1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Yajra\Oci8; |
4
|
|
|
|
5
|
|
|
use Doctrine\DBAL\Connection as DoctrineConnection; |
6
|
|
|
use Doctrine\DBAL\Driver\OCI8\Driver as DoctrineDriver; |
7
|
|
|
use Illuminate\Database\Connection; |
8
|
|
|
use Illuminate\Database\Grammar; |
9
|
|
|
use PDO; |
10
|
|
|
use Yajra\Oci8\Query\Grammars\OracleGrammar as QueryGrammar; |
11
|
|
|
use Yajra\Oci8\Query\OracleBuilder as QueryBuilder; |
12
|
|
|
use Yajra\Oci8\Query\Processors\OracleProcessor as Processor; |
13
|
|
|
use Yajra\Oci8\Schema\Grammars\OracleGrammar as SchemaGrammar; |
14
|
|
|
use Yajra\Oci8\Schema\OracleBuilder as SchemaBuilder; |
15
|
|
|
use Yajra\Oci8\Schema\Sequence; |
16
|
|
|
use Yajra\Oci8\Schema\Trigger; |
17
|
|
|
|
18
|
|
|
class Oci8Connection extends Connection |
19
|
|
|
{ |
20
|
|
|
/** |
21
|
|
|
* @var string |
22
|
|
|
*/ |
23
|
|
|
protected $schema; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* @var \Yajra\Oci8\Schema\Sequence |
27
|
|
|
*/ |
28
|
|
|
protected $sequence; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* @var \Yajra\Oci8\Schema\Trigger |
32
|
|
|
*/ |
33
|
|
|
protected $trigger; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* @param PDO|\Closure $pdo |
37
|
|
|
* @param string $database |
38
|
|
|
* @param string $tablePrefix |
39
|
|
|
* @param array $config |
40
|
|
|
*/ |
41
|
|
|
public function __construct($pdo, $database = '', $tablePrefix = '', array $config = []) |
42
|
|
|
{ |
43
|
|
|
parent::__construct($pdo, $database, $tablePrefix, $config); |
44
|
|
|
$this->sequence = new Sequence($this); |
45
|
|
|
$this->trigger = new Trigger($this); |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* Get current schema. |
50
|
|
|
* |
51
|
|
|
* @return string |
52
|
|
|
*/ |
53
|
|
|
public function getSchema() |
54
|
|
|
{ |
55
|
|
|
return $this->schema; |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* Set current schema. |
60
|
|
|
* |
61
|
|
|
* @param string $schema |
62
|
|
|
* |
63
|
|
|
* @return $this |
64
|
|
|
*/ |
65
|
|
|
public function setSchema($schema) |
66
|
|
|
{ |
67
|
|
|
$this->schema = $schema; |
68
|
|
|
$sessionVars = [ |
69
|
|
|
'CURRENT_SCHEMA' => $schema, |
70
|
|
|
]; |
71
|
|
|
|
72
|
|
|
return $this->setSessionVars($sessionVars); |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* Update oracle session variables. |
77
|
|
|
* |
78
|
|
|
* @param array $sessionVars |
79
|
|
|
* |
80
|
|
|
* @return $this |
81
|
|
|
*/ |
82
|
|
|
public function setSessionVars(array $sessionVars) |
83
|
|
|
{ |
84
|
|
|
$vars = []; |
85
|
|
|
foreach ($sessionVars as $option => $value) { |
86
|
|
|
if (strtoupper($option) == 'CURRENT_SCHEMA') { |
87
|
|
|
$vars[] = "$option = $value"; |
88
|
|
|
} else { |
89
|
|
|
$vars[] = "$option = '$value'"; |
90
|
|
|
} |
91
|
|
|
} |
92
|
|
|
if ($vars) { |
|
|
|
|
93
|
|
|
$sql = 'ALTER SESSION SET '.implode(' ', $vars); |
94
|
|
|
$this->statement($sql); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
return $this; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* Get sequence class. |
102
|
|
|
* |
103
|
|
|
* @return \Yajra\Oci8\Schema\Sequence |
104
|
|
|
*/ |
105
|
|
|
public function getSequence() |
106
|
|
|
{ |
107
|
|
|
return $this->sequence; |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
/** |
111
|
|
|
* Set sequence class. |
112
|
|
|
* |
113
|
|
|
* @param \Yajra\Oci8\Schema\Sequence $sequence |
114
|
|
|
* |
115
|
|
|
* @return \Yajra\Oci8\Schema\Sequence |
116
|
|
|
*/ |
117
|
|
|
public function setSequence(Sequence $sequence) |
118
|
|
|
{ |
119
|
|
|
return $this->sequence = $sequence; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* Get oracle trigger class. |
124
|
|
|
* |
125
|
|
|
* @return \Yajra\Oci8\Schema\Trigger |
126
|
|
|
*/ |
127
|
|
|
public function getTrigger() |
128
|
|
|
{ |
129
|
|
|
return $this->trigger; |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* Set oracle trigger class. |
134
|
|
|
* |
135
|
|
|
* @param \Yajra\Oci8\Schema\Trigger $trigger |
136
|
|
|
* |
137
|
|
|
* @return \Yajra\Oci8\Schema\Trigger |
138
|
|
|
*/ |
139
|
|
|
public function setTrigger(Trigger $trigger) |
140
|
|
|
{ |
141
|
|
|
return $this->trigger = $trigger; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* Get a schema builder instance for the connection. |
146
|
|
|
* |
147
|
|
|
* @return \Yajra\Oci8\Schema\OracleBuilder |
148
|
|
|
*/ |
149
|
|
|
public function getSchemaBuilder() |
150
|
|
|
{ |
151
|
|
|
if (is_null($this->schemaGrammar)) { |
152
|
|
|
$this->useDefaultSchemaGrammar(); |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
return new SchemaBuilder($this); |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
/** |
159
|
|
|
* Begin a fluent query against a database table. |
160
|
|
|
* |
161
|
|
|
* @param string $table |
162
|
|
|
* |
163
|
|
|
* @return \Yajra\Oci8\Query\OracleBuilder |
164
|
|
|
*/ |
165
|
|
|
public function table($table) |
166
|
|
|
{ |
167
|
|
|
$processor = $this->getPostProcessor(); |
168
|
|
|
|
169
|
|
|
$query = new QueryBuilder($this, $this->getQueryGrammar(), $processor); |
170
|
|
|
|
171
|
|
|
return $query->from($table); |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
/** |
175
|
|
|
* Set oracle session date format. |
176
|
|
|
* |
177
|
|
|
* @param string $format |
178
|
|
|
* |
179
|
|
|
* @return $this |
180
|
|
|
*/ |
181
|
|
|
public function setDateFormat($format = 'YYYY-MM-DD HH24:MI:SS') |
182
|
|
|
{ |
183
|
|
|
$sessionVars = [ |
184
|
|
|
'NLS_DATE_FORMAT' => $format, |
185
|
|
|
'NLS_TIMESTAMP_FORMAT' => $format, |
186
|
|
|
]; |
187
|
|
|
|
188
|
|
|
return $this->setSessionVars($sessionVars); |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
/** |
192
|
|
|
* Get doctrine connection. |
193
|
|
|
* |
194
|
|
|
* @return \Doctrine\DBAL\Connection |
195
|
|
|
*/ |
196
|
|
|
public function getDoctrineConnection() |
197
|
|
|
{ |
198
|
|
|
$driver = $this->getDoctrineDriver(); |
199
|
|
|
|
200
|
|
|
$data = ['pdo' => $this->getPdo(), 'user' => $this->getConfig('username')]; |
201
|
|
|
|
202
|
|
|
return new DoctrineConnection($data, $driver); |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
/** |
206
|
|
|
* Get doctrine driver. |
207
|
|
|
* |
208
|
|
|
* @return \Doctrine\DBAL\Driver\OCI8\Driver |
209
|
|
|
*/ |
210
|
|
|
protected function getDoctrineDriver() |
211
|
|
|
{ |
212
|
|
|
return new DoctrineDriver(); |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
/** |
216
|
|
|
* Execute a PL/SQL Function and return its value. |
217
|
|
|
* Usage: DB::executeFunction('function_name(:binding_1,:binding_n)', [':binding_1' => 'hi', ':binding_n' => |
218
|
|
|
* 'bye'], PDO::PARAM_LOB). |
219
|
|
|
* |
220
|
|
|
* @author Tylerian - [email protected] |
221
|
|
|
* |
222
|
|
|
* @param string $sql (mixed) |
223
|
|
|
* @param array $bindings (kvp array) |
224
|
|
|
* @param int $returnType (PDO::PARAM_*) |
225
|
|
|
* |
226
|
|
|
* @return mixed $returnType |
227
|
|
|
*/ |
228
|
|
|
public function executeFunction($sql, array $bindings = [], $returnType = PDO::PARAM_STR) |
229
|
|
|
{ |
230
|
|
|
$query = $this->getPdo()->prepare('begin :result := '.$sql.'; end;'); |
231
|
|
|
|
232
|
|
|
foreach ($bindings as $key => &$value) { |
233
|
|
|
if (!preg_match('/^:(.*)$/i', $key)) { |
234
|
|
|
$key = ':'.$key; |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
$query->bindParam($key, $value); |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
$query->bindParam(':result', $result, $returnType); |
241
|
|
|
$query->execute(); |
242
|
|
|
|
243
|
|
|
return $result; |
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
/** |
247
|
|
|
* Execute a PL/SQL Procedure and return its result. |
248
|
|
|
* Usage: DB::executeProcedure($procedureName, $bindings). |
249
|
|
|
* |
250
|
|
|
* $bindings looks like: |
251
|
|
|
* $bindings = [ |
252
|
|
|
* 'p_userid' => $id |
253
|
|
|
* ]; |
254
|
|
|
* |
255
|
|
|
* @param string $procedureName |
256
|
|
|
* @param array $bindings |
257
|
|
|
* @param mixed $returnType |
258
|
|
|
* |
259
|
|
|
* @return array |
260
|
|
|
*/ |
261
|
|
|
public function executeProcedure($procedureName, $bindings, $returnType = PDO::PARAM_STMT) |
262
|
|
|
{ |
263
|
|
|
$command = sprintf('begin %s(:%s, :cursor); end;', $procedureName, implode(', :', array_keys($bindings))); |
264
|
|
|
|
265
|
|
|
$stmt = $this->getPdo()->prepare($command); |
266
|
|
|
|
267
|
|
|
foreach ($bindings as $bindingName => &$bindingValue) { |
268
|
|
|
$stmt->bindParam(':'.$bindingName, $bindingValue, $this->suggestValueType($bindingValue)); |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
$cursor = null; |
272
|
|
|
|
273
|
|
|
$stmt->bindParam(':cursor', $cursor, $returnType); |
274
|
|
|
$stmt->execute(); |
275
|
|
|
|
276
|
|
|
if ($returnType === PDO::PARAM_STMT) { |
277
|
|
|
oci_execute($cursor, OCI_NO_AUTO_COMMIT); |
278
|
|
|
oci_fetch_all($cursor, $results, 0, -1, OCI_FETCHSTATEMENT_BY_ROW + OCI_ASSOC); |
279
|
|
|
oci_free_cursor($cursor); |
280
|
|
|
|
281
|
|
|
return $results; |
282
|
|
|
} |
283
|
|
|
|
284
|
|
|
return $cursor; |
285
|
|
|
} |
286
|
|
|
|
287
|
|
|
/** |
288
|
|
|
* Bind values to their parameters in the given statement. |
289
|
|
|
* |
290
|
|
|
* @param \PDOStatement $statement |
291
|
|
|
* @param array $bindings |
292
|
|
|
*/ |
293
|
|
|
public function bindValues($statement, $bindings) |
294
|
|
|
{ |
295
|
|
|
foreach ($bindings as $key => $value) { |
296
|
|
|
$statement->bindParam( |
297
|
|
|
$key, |
298
|
|
|
$bindings[$key], |
299
|
|
|
$this->suggestValueType($value) |
300
|
|
|
); |
301
|
|
|
} |
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
/** |
305
|
|
|
* Get the default query grammar instance. |
306
|
|
|
* |
307
|
|
|
* @return \Illuminate\Database\Grammar|\Yajra\Oci8\Query\Grammars\OracleGrammar |
308
|
|
|
*/ |
309
|
|
|
protected function getDefaultQueryGrammar() |
310
|
|
|
{ |
311
|
|
|
return $this->withTablePrefix(new QueryGrammar()); |
312
|
|
|
} |
313
|
|
|
|
314
|
|
|
/** |
315
|
|
|
* Set the table prefix and return the grammar. |
316
|
|
|
* |
317
|
|
|
* @param \Illuminate\Database\Grammar|\Yajra\Oci8\Query\Grammars\OracleGrammar|\Yajra\Oci8\Schema\Grammars\OracleGrammar $grammar |
318
|
|
|
* |
319
|
|
|
* @return \Illuminate\Database\Grammar |
320
|
|
|
*/ |
321
|
|
|
public function withTablePrefix(Grammar $grammar) |
322
|
|
|
{ |
323
|
|
|
return $this->withSchemaPrefix(parent::withTablePrefix($grammar)); |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
/** |
327
|
|
|
* Set the schema prefix and return the grammar. |
328
|
|
|
* |
329
|
|
|
* @param \Illuminate\Database\Grammar|\Yajra\Oci8\Query\Grammars\OracleGrammar|\Yajra\Oci8\Schema\Grammars\OracleGrammar $grammar |
330
|
|
|
* |
331
|
|
|
* @return \Illuminate\Database\Grammar |
332
|
|
|
*/ |
333
|
|
|
public function withSchemaPrefix(Grammar $grammar) |
334
|
|
|
{ |
335
|
|
|
$grammar->setSchemaPrefix($this->getConfigSchemaPrefix()); |
|
|
|
|
336
|
|
|
|
337
|
|
|
return $grammar; |
338
|
|
|
} |
339
|
|
|
|
340
|
|
|
/** |
341
|
|
|
* Get config schema prefix. |
342
|
|
|
* |
343
|
|
|
* @return string |
344
|
|
|
*/ |
345
|
|
|
protected function getConfigSchemaPrefix() |
346
|
|
|
{ |
347
|
|
|
return isset($this->config['prefix_schema']) ? $this->config['prefix_schema'] : ''; |
348
|
|
|
} |
349
|
|
|
|
350
|
|
|
/** |
351
|
|
|
* Get the default schema grammar instance. |
352
|
|
|
* |
353
|
|
|
* @return \Illuminate\Database\Grammar|\Yajra\Oci8\Schema\Grammars\OracleGrammar |
354
|
|
|
*/ |
355
|
|
|
protected function getDefaultSchemaGrammar() |
356
|
|
|
{ |
357
|
|
|
return $this->withTablePrefix(new SchemaGrammar()); |
358
|
|
|
} |
359
|
|
|
|
360
|
|
|
/** |
361
|
|
|
* Get the default post processor instance. |
362
|
|
|
* |
363
|
|
|
* @return \Yajra\Oci8\Query\Processors\OracleProcessor |
364
|
|
|
*/ |
365
|
|
|
protected function getDefaultPostProcessor() |
366
|
|
|
{ |
367
|
|
|
return new Processor(); |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
/** |
371
|
|
|
* Returns PDO constant based on value type. |
372
|
|
|
* |
373
|
|
|
* @param string|int $value |
374
|
|
|
* |
375
|
|
|
* @return int |
376
|
|
|
*/ |
377
|
|
|
protected function suggestValueType($value) |
378
|
|
|
{ |
379
|
|
|
return !is_string($value) && is_numeric($value) ? PDO::PARAM_INT : PDO::PARAM_STR; |
380
|
|
|
} |
381
|
|
|
} |
382
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.