1 | <?php |
||
2 | |||
3 | namespace Doctrine\DBAL\Driver\OCI8; |
||
4 | |||
5 | use Doctrine\DBAL\Driver\Connection; |
||
6 | use Doctrine\DBAL\Driver\ServerInfoAwareConnection; |
||
7 | use Doctrine\DBAL\ParameterType; |
||
8 | use UnexpectedValueException; |
||
9 | use const OCI_COMMIT_ON_SUCCESS; |
||
10 | use const OCI_DEFAULT; |
||
11 | use const OCI_NO_AUTO_COMMIT; |
||
12 | use function addcslashes; |
||
13 | use function func_get_args; |
||
14 | use function is_float; |
||
15 | use function is_int; |
||
16 | use function oci_commit; |
||
17 | use function oci_connect; |
||
18 | use function oci_error; |
||
19 | use function oci_pconnect; |
||
20 | use function oci_rollback; |
||
21 | use function oci_server_version; |
||
22 | use function preg_match; |
||
23 | use function sprintf; |
||
24 | use function str_replace; |
||
25 | |||
26 | /** |
||
27 | * OCI8 implementation of the Connection interface. |
||
28 | */ |
||
29 | class OCI8Connection implements Connection, ServerInfoAwareConnection |
||
30 | { |
||
31 | /** @var resource */ |
||
32 | protected $dbh; |
||
33 | |||
34 | /** @var int */ |
||
35 | protected $executeMode = OCI_COMMIT_ON_SUCCESS; |
||
36 | |||
37 | /** |
||
38 | * Creates a Connection to an Oracle Database using oci8 extension. |
||
39 | * |
||
40 | * @param string $username |
||
41 | * @param string $password |
||
42 | * @param string $db |
||
43 | * @param string $charset |
||
44 | * @param int $sessionMode |
||
45 | * @param bool $persistent |
||
46 | * |
||
47 | * @throws OCI8Exception |
||
48 | */ |
||
49 | 30 | public function __construct( |
|
50 | $username, |
||
51 | $password, |
||
52 | $db, |
||
53 | $charset = '', |
||
54 | $sessionMode = OCI_DEFAULT, |
||
55 | $persistent = false |
||
56 | ) { |
||
57 | 30 | $dbh = $persistent |
|
58 | ? @oci_pconnect($username, $password, $db, $charset, $sessionMode) |
||
59 | 30 | : @oci_connect($username, $password, $db, $charset, $sessionMode); |
|
60 | |||
61 | 30 | if ($dbh === false) { |
|
0 ignored issues
–
show
introduced
by
Loading history...
|
|||
62 | 3 | throw OCI8Exception::fromErrorInfo(oci_error()); |
|
63 | } |
||
64 | |||
65 | 27 | $this->dbh = $dbh; |
|
66 | 27 | } |
|
67 | |||
68 | /** |
||
69 | * {@inheritdoc} |
||
70 | * |
||
71 | * @throws UnexpectedValueException If the version string returned by the database server |
||
72 | * does not contain a parsable version number. |
||
73 | */ |
||
74 | public function getServerVersion() |
||
75 | { |
||
76 | $version = oci_server_version($this->dbh); |
||
77 | |||
78 | if ($version === false) { |
||
79 | throw OCI8Exception::fromErrorInfo(oci_error($this->dbh)); |
||
80 | } |
||
81 | |||
82 | if (! preg_match('/\s+(\d+\.\d+\.\d+\.\d+\.\d+)\s+/', $version, $matches)) { |
||
83 | throw new UnexpectedValueException( |
||
84 | sprintf( |
||
85 | 'Unexpected database version string "%s". Cannot parse an appropriate version number from it. ' . |
||
86 | 'Please report this database version string to the Doctrine team.', |
||
87 | $version |
||
88 | ) |
||
89 | ); |
||
90 | } |
||
91 | |||
92 | return $matches[1]; |
||
93 | } |
||
94 | |||
95 | /** |
||
96 | * {@inheritdoc} |
||
97 | */ |
||
98 | 2 | public function requiresQueryForServerVersion() |
|
99 | { |
||
100 | 2 | return false; |
|
101 | } |
||
102 | |||
103 | /** |
||
104 | * {@inheritdoc} |
||
105 | */ |
||
106 | 262 | public function prepare($prepareString) |
|
107 | { |
||
108 | 262 | return new OCI8Statement($this->dbh, $prepareString, $this); |
|
109 | } |
||
110 | |||
111 | /** |
||
112 | * {@inheritdoc} |
||
113 | */ |
||
114 | 173 | public function query() |
|
115 | { |
||
116 | 173 | $args = func_get_args(); |
|
117 | 173 | $sql = $args[0]; |
|
118 | //$fetchMode = $args[1]; |
||
119 | 173 | $stmt = $this->prepare($sql); |
|
120 | 173 | $stmt->execute(); |
|
121 | |||
122 | 170 | return $stmt; |
|
123 | } |
||
124 | |||
125 | /** |
||
126 | * {@inheritdoc} |
||
127 | */ |
||
128 | 4 | public function quote($value, $type = ParameterType::STRING) |
|
129 | { |
||
130 | 4 | if (is_int($value) || is_float($value)) { |
|
131 | 2 | return $value; |
|
132 | } |
||
133 | 3 | $value = str_replace("'", "''", $value); |
|
134 | |||
135 | 3 | return "'" . addcslashes($value, "\000\n\r\\\032") . "'"; |
|
136 | } |
||
137 | |||
138 | /** |
||
139 | * {@inheritdoc} |
||
140 | */ |
||
141 | 174 | public function exec($statement) |
|
142 | { |
||
143 | 174 | $stmt = $this->prepare($statement); |
|
144 | 174 | $stmt->execute(); |
|
145 | |||
146 | 168 | return $stmt->rowCount(); |
|
147 | } |
||
148 | |||
149 | /** |
||
150 | * {@inheritdoc} |
||
151 | */ |
||
152 | 4 | public function lastInsertId($name = null) |
|
153 | { |
||
154 | 4 | if ($name === null) { |
|
155 | 1 | return false; |
|
156 | } |
||
157 | |||
158 | 3 | $sql = 'SELECT ' . $name . '.CURRVAL FROM DUAL'; |
|
159 | 3 | $stmt = $this->query($sql); |
|
160 | 3 | $result = $stmt->fetchColumn(); |
|
161 | |||
162 | 3 | if ($result === false) { |
|
163 | throw new OCI8Exception('lastInsertId failed: Query was executed but no result was returned.'); |
||
164 | } |
||
165 | |||
166 | 3 | return (int) $result; |
|
167 | } |
||
168 | |||
169 | /** |
||
170 | * Returns the current execution mode. |
||
171 | * |
||
172 | * @return int |
||
173 | */ |
||
174 | 257 | public function getExecuteMode() |
|
175 | { |
||
176 | 257 | return $this->executeMode; |
|
177 | } |
||
178 | |||
179 | /** |
||
180 | * {@inheritdoc} |
||
181 | */ |
||
182 | 15 | public function beginTransaction() |
|
183 | { |
||
184 | 15 | $this->executeMode = OCI_NO_AUTO_COMMIT; |
|
185 | |||
186 | 15 | return true; |
|
187 | } |
||
188 | |||
189 | /** |
||
190 | * {@inheritdoc} |
||
191 | */ |
||
192 | 7 | public function commit() |
|
193 | { |
||
194 | 7 | if (! oci_commit($this->dbh)) { |
|
195 | throw OCI8Exception::fromErrorInfo($this->errorInfo()); |
||
196 | } |
||
197 | 7 | $this->executeMode = OCI_COMMIT_ON_SUCCESS; |
|
198 | |||
199 | 7 | return true; |
|
200 | } |
||
201 | |||
202 | /** |
||
203 | * {@inheritdoc} |
||
204 | */ |
||
205 | 9 | public function rollBack() |
|
206 | { |
||
207 | 9 | if (! oci_rollback($this->dbh)) { |
|
208 | throw OCI8Exception::fromErrorInfo($this->errorInfo()); |
||
209 | } |
||
210 | 9 | $this->executeMode = OCI_COMMIT_ON_SUCCESS; |
|
211 | |||
212 | 9 | return true; |
|
213 | } |
||
214 | |||
215 | /** |
||
216 | * {@inheritdoc} |
||
217 | */ |
||
218 | public function errorCode() |
||
219 | { |
||
220 | $error = oci_error($this->dbh); |
||
221 | if ($error !== false) { |
||
222 | $error = $error['code']; |
||
223 | } |
||
224 | |||
225 | return $error; |
||
226 | } |
||
227 | |||
228 | /** |
||
229 | * {@inheritdoc} |
||
230 | */ |
||
231 | public function errorInfo() |
||
232 | { |
||
233 | $error = oci_error($this->dbh); |
||
234 | |||
235 | if ($error === false) { |
||
236 | return []; |
||
237 | } |
||
238 | |||
239 | return $error; |
||
240 | } |
||
241 | } |
||
242 |