PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.2.0
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.2.0
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / libs / Zend / Db / Adapter / Oracle.php
matomo / app / libs / Zend / Db / Adapter Last commit date
Db2 1 year ago Mysqli 2 years ago Oracle 2 years ago Pdo 1 year ago Sqlsrv 2 years ago Abstract.php 2 years ago Db2.php 2 years ago Exception.php 1 year ago Mysqli.php 1 year ago Oracle.php 2 years ago Sqlsrv.php 2 years ago
Oracle.php
568 lines
1 <?php
2
3 namespace {
4 /**
5 * Zend Framework
6 *
7 * LICENSE
8 *
9 * This source file is subject to the new BSD license that is bundled
10 * with this package in the file LICENSE.txt.
11 * It is also available through the world-wide-web at this URL:
12 * http://framework.zend.com/license/new-bsd
13 * If you did not receive a copy of the license and are unable to
14 * obtain it through the world-wide-web, please send an email
15 * to license@zend.com so we can send you a copy immediately.
16 *
17 * @category Zend
18 * @package Zend_Db
19 * @subpackage Adapter
20 * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
21 * @license http://framework.zend.com/license/new-bsd New BSD License
22 * @version $Id: Oracle.php 23775 2011-03-01 17:25:24Z ralph $
23 */
24 /**
25 * @see Zend_Db_Adapter_Abstract
26 */
27 // require_once 'Zend/Db/Adapter/Abstract.php';
28 /**
29 * @see Zend_Db_Statement_Oracle
30 */
31 // require_once 'Zend/Db/Statement/Oracle.php';
32 /**
33 * @category Zend
34 * @package Zend_Db
35 * @subpackage Adapter
36 * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
37 * @license http://framework.zend.com/license/new-bsd New BSD License
38 */
39 class Zend_Db_Adapter_Oracle extends \Zend_Db_Adapter_Abstract
40 {
41 /**
42 * User-provided configuration.
43 *
44 * Basic keys are:
45 *
46 * username => (string) Connect to the database as this username.
47 * password => (string) Password associated with the username.
48 * dbname => Either the name of the local Oracle instance, or the
49 * name of the entry in tnsnames.ora to which you want to connect.
50 * persistent => (boolean) Set TRUE to use a persistent connection
51 * @var array
52 */
53 protected $_config = array('dbname' => null, 'username' => null, 'password' => null, 'persistent' => \false);
54 /**
55 * Keys are UPPERCASE SQL datatypes or the constants
56 * Zend_Db::INT_TYPE, Zend_Db::BIGINT_TYPE, or Zend_Db::FLOAT_TYPE.
57 *
58 * Values are:
59 * 0 = 32-bit integer
60 * 1 = 64-bit integer
61 * 2 = float or decimal
62 *
63 * @var array Associative array of datatypes to values 0, 1, or 2.
64 */
65 protected $_numericDataTypes = array(\Zend_Db::INT_TYPE => \Zend_Db::INT_TYPE, \Zend_Db::BIGINT_TYPE => \Zend_Db::BIGINT_TYPE, \Zend_Db::FLOAT_TYPE => \Zend_Db::FLOAT_TYPE, 'BINARY_DOUBLE' => \Zend_Db::FLOAT_TYPE, 'BINARY_FLOAT' => \Zend_Db::FLOAT_TYPE, 'NUMBER' => \Zend_Db::FLOAT_TYPE);
66 /**
67 * @var integer
68 */
69 protected $_execute_mode = null;
70 /**
71 * Default class name for a DB statement.
72 *
73 * @var string
74 */
75 protected $_defaultStmtClass = 'Zend_Db_Statement_Oracle';
76 /**
77 * Check if LOB field are returned as string
78 * instead of OCI-Lob object
79 *
80 * @var boolean
81 */
82 protected $_lobAsString = null;
83 /**
84 * Creates a connection resource.
85 *
86 * @return void
87 * @throws Zend_Db_Adapter_Oracle_Exception
88 */
89 protected function _connect()
90 {
91 if (\is_resource($this->_connection)) {
92 // connection already exists
93 return;
94 }
95 if (!\extension_loaded('oci8')) {
96 /**
97 * @see Zend_Db_Adapter_Oracle_Exception
98 */
99 // require_once 'Zend/Db/Adapter/Oracle/Exception.php';
100 throw new \Zend_Db_Adapter_Oracle_Exception('The OCI8 extension is required for this adapter but the extension is not loaded');
101 }
102 $this->_setExecuteMode(\OCI_COMMIT_ON_SUCCESS);
103 $connectionFuncName = $this->_config['persistent'] == \true ? 'oci_pconnect' : 'oci_connect';
104 $this->_connection = @$connectionFuncName($this->_config['username'], $this->_config['password'], $this->_config['dbname'], $this->_config['charset']);
105 // check the connection
106 if (!$this->_connection) {
107 /**
108 * @see Zend_Db_Adapter_Oracle_Exception
109 */
110 // require_once 'Zend/Db/Adapter/Oracle/Exception.php';
111 throw new \Zend_Db_Adapter_Oracle_Exception(\oci_error());
112 }
113 }
114 /**
115 * Test if a connection is active
116 *
117 * @return boolean
118 */
119 public function isConnected()
120 {
121 return (bool) (\is_resource($this->_connection) && (\get_resource_type($this->_connection) == 'oci8 connection' || \get_resource_type($this->_connection) == 'oci8 persistent connection'));
122 }
123 /**
124 * Force the connection to close.
125 *
126 * @return void
127 */
128 public function closeConnection()
129 {
130 if ($this->isConnected()) {
131 \oci_close($this->_connection);
132 }
133 $this->_connection = null;
134 }
135 /**
136 * Activate/deactivate return of LOB as string
137 *
138 * @param string $lob_as_string
139 * @return Zend_Db_Adapter_Oracle
140 */
141 public function setLobAsString($lobAsString)
142 {
143 $this->_lobAsString = (bool) $lobAsString;
144 return $this;
145 }
146 /**
147 * Return whether or not LOB are returned as string
148 *
149 * @return boolean
150 */
151 public function getLobAsString()
152 {
153 if ($this->_lobAsString === null) {
154 // if never set by user, we use driver option if it exists otherwise false
155 if (isset($this->_config['driver_options']) && isset($this->_config['driver_options']['lob_as_string'])) {
156 $this->_lobAsString = (bool) $this->_config['driver_options']['lob_as_string'];
157 } else {
158 $this->_lobAsString = \false;
159 }
160 }
161 return $this->_lobAsString;
162 }
163 /**
164 * Returns an SQL statement for preparation.
165 *
166 * @param string $sql The SQL statement with placeholders.
167 * @return Zend_Db_Statement_Oracle
168 */
169 public function prepare($sql)
170 {
171 $this->_connect();
172 $stmtClass = $this->_defaultStmtClass;
173 if (!\class_exists($stmtClass)) {
174 // require_once 'Zend/Loader.php';
175 \Zend_Loader::loadClass($stmtClass);
176 }
177 $stmt = new $stmtClass($this, $sql);
178 if ($stmt instanceof \Zend_Db_Statement_Oracle) {
179 $stmt->setLobAsString($this->getLobAsString());
180 }
181 $stmt->setFetchMode($this->_fetchMode);
182 return $stmt;
183 }
184 /**
185 * Quote a raw string.
186 *
187 * @param string $value Raw string
188 * @return string Quoted string
189 */
190 protected function _quote($value)
191 {
192 if (\is_int($value) || \is_float($value)) {
193 return $value;
194 }
195 $value = \str_replace("'", "''", $value);
196 return "'" . \addcslashes($value, "\x00\n\r\\\x1a") . "'";
197 }
198 /**
199 * Quote a table identifier and alias.
200 *
201 * @param string|array|Zend_Db_Expr $ident The identifier or expression.
202 * @param string $alias An alias for the table.
203 * @param boolean $auto If true, heed the AUTO_QUOTE_IDENTIFIERS config option.
204 * @return string The quoted identifier and alias.
205 */
206 public function quoteTableAs($ident, $alias = null, $auto = \false)
207 {
208 // Oracle doesn't allow the 'AS' keyword between the table identifier/expression and alias.
209 return $this->_quoteIdentifierAs($ident, $alias, $auto, ' ');
210 }
211 /**
212 * Return the most recent value from the specified sequence in the database.
213 * This is supported only on RDBMS brands that support sequences
214 * (e.g. Oracle, PostgreSQL, DB2). Other RDBMS brands return null.
215 *
216 * @param string $sequenceName
217 * @return string
218 */
219 public function lastSequenceId($sequenceName)
220 {
221 $this->_connect();
222 $sql = 'SELECT ' . $this->quoteIdentifier($sequenceName, \true) . '.CURRVAL FROM dual';
223 $value = $this->fetchOne($sql);
224 return $value;
225 }
226 /**
227 * Generate a new value from the specified sequence in the database, and return it.
228 * This is supported only on RDBMS brands that support sequences
229 * (e.g. Oracle, PostgreSQL, DB2). Other RDBMS brands return null.
230 *
231 * @param string $sequenceName
232 * @return string
233 */
234 public function nextSequenceId($sequenceName)
235 {
236 $this->_connect();
237 $sql = 'SELECT ' . $this->quoteIdentifier($sequenceName, \true) . '.NEXTVAL FROM dual';
238 $value = $this->fetchOne($sql);
239 return $value;
240 }
241 /**
242 * Gets the last ID generated automatically by an IDENTITY/AUTOINCREMENT column.
243 *
244 * As a convention, on RDBMS brands that support sequences
245 * (e.g. Oracle, PostgreSQL, DB2), this method forms the name of a sequence
246 * from the arguments and returns the last id generated by that sequence.
247 * On RDBMS brands that support IDENTITY/AUTOINCREMENT columns, this method
248 * returns the last value generated for such a column, and the table name
249 * argument is disregarded.
250 *
251 * Oracle does not support IDENTITY columns, so if the sequence is not
252 * specified, this method returns null.
253 *
254 * @param string $tableName OPTIONAL Name of table.
255 * @param string $primaryKey OPTIONAL Name of primary key column.
256 * @return string
257 */
258 public function lastInsertId($tableName = null, $primaryKey = null)
259 {
260 if ($tableName !== null) {
261 $sequenceName = $tableName;
262 if ($primaryKey) {
263 $sequenceName .= "_{$primaryKey}";
264 }
265 $sequenceName .= '_seq';
266 return $this->lastSequenceId($sequenceName);
267 }
268 // No support for IDENTITY columns; return null
269 return null;
270 }
271 /**
272 * Returns a list of the tables in the database.
273 *
274 * @return array
275 */
276 public function listTables()
277 {
278 $this->_connect();
279 $data = $this->fetchCol('SELECT table_name FROM all_tables');
280 return $data;
281 }
282 /**
283 * Returns the column descriptions for a table.
284 *
285 * The return value is an associative array keyed by the column name,
286 * as returned by the RDBMS.
287 *
288 * The value of each array element is an associative array
289 * with the following keys:
290 *
291 * SCHEMA_NAME => string; name of schema
292 * TABLE_NAME => string;
293 * COLUMN_NAME => string; column name
294 * COLUMN_POSITION => number; ordinal position of column in table
295 * DATA_TYPE => string; SQL datatype name of column
296 * DEFAULT => string; default expression of column, null if none
297 * NULLABLE => boolean; true if column can have nulls
298 * LENGTH => number; length of CHAR/VARCHAR
299 * SCALE => number; scale of NUMERIC/DECIMAL
300 * PRECISION => number; precision of NUMERIC/DECIMAL
301 * UNSIGNED => boolean; unsigned property of an integer type
302 * PRIMARY => boolean; true if column is part of the primary key
303 * PRIMARY_POSITION => integer; position of column in primary key
304 * IDENTITY => integer; true if column is auto-generated with unique values
305 *
306 * @todo Discover integer unsigned property.
307 *
308 * @param string $tableName
309 * @param string $schemaName OPTIONAL
310 * @return array
311 */
312 public function describeTable($tableName, $schemaName = null)
313 {
314 $version = $this->getServerVersion();
315 if ($version === null || \version_compare($version, '9.0.0', '>=')) {
316 $sql = "SELECT TC.TABLE_NAME, TC.OWNER, TC.COLUMN_NAME, TC.DATA_TYPE,\n TC.DATA_DEFAULT, TC.NULLABLE, TC.COLUMN_ID, TC.DATA_LENGTH,\n TC.DATA_SCALE, TC.DATA_PRECISION, C.CONSTRAINT_TYPE, CC.POSITION\n FROM ALL_TAB_COLUMNS TC\n LEFT JOIN (ALL_CONS_COLUMNS CC JOIN ALL_CONSTRAINTS C\n ON (CC.CONSTRAINT_NAME = C.CONSTRAINT_NAME AND CC.TABLE_NAME = C.TABLE_NAME AND CC.OWNER = C.OWNER AND C.CONSTRAINT_TYPE = 'P'))\n ON TC.TABLE_NAME = CC.TABLE_NAME AND TC.COLUMN_NAME = CC.COLUMN_NAME\n WHERE UPPER(TC.TABLE_NAME) = UPPER(:TBNAME)";
317 $bind[':TBNAME'] = $tableName;
318 if ($schemaName) {
319 $sql .= ' AND UPPER(TC.OWNER) = UPPER(:SCNAME)';
320 $bind[':SCNAME'] = $schemaName;
321 }
322 $sql .= ' ORDER BY TC.COLUMN_ID';
323 } else {
324 $subSql = "SELECT AC.OWNER, AC.TABLE_NAME, ACC.COLUMN_NAME, AC.CONSTRAINT_TYPE, ACC.POSITION\n from ALL_CONSTRAINTS AC, ALL_CONS_COLUMNS ACC\n WHERE ACC.CONSTRAINT_NAME = AC.CONSTRAINT_NAME\n AND ACC.TABLE_NAME = AC.TABLE_NAME\n AND ACC.OWNER = AC.OWNER\n AND AC.CONSTRAINT_TYPE = 'P'\n AND UPPER(AC.TABLE_NAME) = UPPER(:TBNAME)";
325 $bind[':TBNAME'] = $tableName;
326 if ($schemaName) {
327 $subSql .= ' AND UPPER(ACC.OWNER) = UPPER(:SCNAME)';
328 $bind[':SCNAME'] = $schemaName;
329 }
330 $sql = "SELECT TC.TABLE_NAME, TC.OWNER, TC.COLUMN_NAME, TC.DATA_TYPE,\n TC.DATA_DEFAULT, TC.NULLABLE, TC.COLUMN_ID, TC.DATA_LENGTH,\n TC.DATA_SCALE, TC.DATA_PRECISION, CC.CONSTRAINT_TYPE, CC.POSITION\n FROM ALL_TAB_COLUMNS TC, ({$subSql}) CC\n WHERE UPPER(TC.TABLE_NAME) = UPPER(:TBNAME)\n AND TC.OWNER = CC.OWNER(+) AND TC.TABLE_NAME = CC.TABLE_NAME(+) AND TC.COLUMN_NAME = CC.COLUMN_NAME(+)";
331 if ($schemaName) {
332 $sql .= ' AND UPPER(TC.OWNER) = UPPER(:SCNAME)';
333 }
334 $sql .= ' ORDER BY TC.COLUMN_ID';
335 }
336 $stmt = $this->query($sql, $bind);
337 /**
338 * Use FETCH_NUM so we are not dependent on the CASE attribute of the PDO connection
339 */
340 $result = $stmt->fetchAll(\Zend_Db::FETCH_NUM);
341 $table_name = 0;
342 $owner = 1;
343 $column_name = 2;
344 $data_type = 3;
345 $data_default = 4;
346 $nullable = 5;
347 $column_id = 6;
348 $data_length = 7;
349 $data_scale = 8;
350 $data_precision = 9;
351 $constraint_type = 10;
352 $position = 11;
353 $desc = array();
354 foreach ($result as $key => $row) {
355 list($primary, $primaryPosition, $identity) = array(\false, null, \false);
356 if ($row[$constraint_type] == 'P') {
357 $primary = \true;
358 $primaryPosition = $row[$position];
359 /**
360 * Oracle does not support auto-increment keys.
361 */
362 $identity = \false;
363 }
364 $desc[$this->foldCase($row[$column_name])] = array(
365 'SCHEMA_NAME' => $this->foldCase($row[$owner]),
366 'TABLE_NAME' => $this->foldCase($row[$table_name]),
367 'COLUMN_NAME' => $this->foldCase($row[$column_name]),
368 'COLUMN_POSITION' => $row[$column_id],
369 'DATA_TYPE' => $row[$data_type],
370 'DEFAULT' => $row[$data_default],
371 'NULLABLE' => (bool) ($row[$nullable] == 'Y'),
372 'LENGTH' => $row[$data_length],
373 'SCALE' => $row[$data_scale],
374 'PRECISION' => $row[$data_precision],
375 'UNSIGNED' => null,
376 // @todo
377 'PRIMARY' => $primary,
378 'PRIMARY_POSITION' => $primaryPosition,
379 'IDENTITY' => $identity,
380 );
381 }
382 return $desc;
383 }
384 /**
385 * Leave autocommit mode and begin a transaction.
386 *
387 * @return void
388 */
389 protected function _beginTransaction()
390 {
391 $this->_setExecuteMode(\OCI_DEFAULT);
392 }
393 /**
394 * Commit a transaction and return to autocommit mode.
395 *
396 * @return void
397 * @throws Zend_Db_Adapter_Oracle_Exception
398 */
399 protected function _commit()
400 {
401 if (!\oci_commit($this->_connection)) {
402 /**
403 * @see Zend_Db_Adapter_Oracle_Exception
404 */
405 // require_once 'Zend/Db/Adapter/Oracle/Exception.php';
406 throw new \Zend_Db_Adapter_Oracle_Exception(\oci_error($this->_connection));
407 }
408 $this->_setExecuteMode(\OCI_COMMIT_ON_SUCCESS);
409 }
410 /**
411 * Roll back a transaction and return to autocommit mode.
412 *
413 * @return void
414 * @throws Zend_Db_Adapter_Oracle_Exception
415 */
416 protected function _rollBack()
417 {
418 if (!\oci_rollback($this->_connection)) {
419 /**
420 * @see Zend_Db_Adapter_Oracle_Exception
421 */
422 // require_once 'Zend/Db/Adapter/Oracle/Exception.php';
423 throw new \Zend_Db_Adapter_Oracle_Exception(\oci_error($this->_connection));
424 }
425 $this->_setExecuteMode(\OCI_COMMIT_ON_SUCCESS);
426 }
427 /**
428 * Set the fetch mode.
429 *
430 * @todo Support FETCH_CLASS and FETCH_INTO.
431 *
432 * @param integer $mode A fetch mode.
433 * @return void
434 * @throws Zend_Db_Adapter_Oracle_Exception
435 */
436 public function setFetchMode($mode)
437 {
438 switch ($mode) {
439 case \Zend_Db::FETCH_NUM:
440 // seq array
441 case \Zend_Db::FETCH_ASSOC:
442 // assoc array
443 case \Zend_Db::FETCH_BOTH:
444 // seq+assoc array
445 case \Zend_Db::FETCH_OBJ:
446 // object
447 $this->_fetchMode = $mode;
448 break;
449 case \Zend_Db::FETCH_BOUND:
450 // bound to PHP variable
451 /**
452 * @see Zend_Db_Adapter_Oracle_Exception
453 */
454 // require_once 'Zend/Db/Adapter/Oracle/Exception.php';
455 throw new \Zend_Db_Adapter_Oracle_Exception('FETCH_BOUND is not supported yet');
456 break;
457 default:
458 /**
459 * @see Zend_Db_Adapter_Oracle_Exception
460 */
461 // require_once 'Zend/Db/Adapter/Oracle/Exception.php';
462 throw new \Zend_Db_Adapter_Oracle_Exception("Invalid fetch mode '{$mode}' specified");
463 break;
464 }
465 }
466 /**
467 * Adds an adapter-specific LIMIT clause to the SELECT statement.
468 *
469 * @param string $sql
470 * @param integer $count
471 * @param integer $offset OPTIONAL
472 * @return string
473 * @throws Zend_Db_Adapter_Oracle_Exception
474 */
475 public function limit($sql, $count, $offset = 0)
476 {
477 $count = \intval($count);
478 if ($count <= 0) {
479 /**
480 * @see Zend_Db_Adapter_Oracle_Exception
481 */
482 // require_once 'Zend/Db/Adapter/Oracle/Exception.php';
483 throw new \Zend_Db_Adapter_Oracle_Exception("LIMIT argument count={$count} is not valid");
484 }
485 $offset = \intval($offset);
486 if ($offset < 0) {
487 /**
488 * @see Zend_Db_Adapter_Oracle_Exception
489 */
490 // require_once 'Zend/Db/Adapter/Oracle/Exception.php';
491 throw new \Zend_Db_Adapter_Oracle_Exception("LIMIT argument offset={$offset} is not valid");
492 }
493 /**
494 * Oracle does not implement the LIMIT clause as some RDBMS do.
495 * We have to simulate it with subqueries and ROWNUM.
496 * Unfortunately because we use the column wildcard "*",
497 * this puts an extra column into the query result set.
498 */
499 $limit_sql = "SELECT z2.*\n FROM (\n SELECT z1.*, ROWNUM AS \"zend_db_rownum\"\n FROM (\n " . $sql . "\n ) z1\n ) z2\n WHERE z2.\"zend_db_rownum\" BETWEEN " . ($offset + 1) . " AND " . ($offset + $count);
500 return $limit_sql;
501 }
502 /**
503 * @param integer $mode
504 * @throws Zend_Db_Adapter_Oracle_Exception
505 */
506 private function _setExecuteMode($mode)
507 {
508 switch ($mode) {
509 case \OCI_COMMIT_ON_SUCCESS:
510 case \OCI_DEFAULT:
511 case \OCI_DESCRIBE_ONLY:
512 $this->_execute_mode = $mode;
513 break;
514 default:
515 /**
516 * @see Zend_Db_Adapter_Oracle_Exception
517 */
518 // require_once 'Zend/Db/Adapter/Oracle/Exception.php';
519 throw new \Zend_Db_Adapter_Oracle_Exception("Invalid execution mode '{$mode}' specified");
520 break;
521 }
522 }
523 /**
524 * @return int
525 */
526 public function _getExecuteMode()
527 {
528 return $this->_execute_mode;
529 }
530 /**
531 * Check if the adapter supports real SQL parameters.
532 *
533 * @param string $type 'positional' or 'named'
534 * @return bool
535 */
536 public function supportsParameters($type)
537 {
538 switch ($type) {
539 case 'named':
540 return \true;
541 case 'positional':
542 default:
543 return \false;
544 }
545 }
546 /**
547 * Retrieve server version in PHP style
548 *
549 * @return string
550 */
551 public function getServerVersion()
552 {
553 $this->_connect();
554 $version = \oci_server_version($this->_connection);
555 if ($version !== \false) {
556 $matches = null;
557 if (\preg_match('/((?:[0-9]{1,2}\\.){1,3}[0-9]{1,2})/', $version, $matches)) {
558 return $matches[1];
559 } else {
560 return null;
561 }
562 } else {
563 return null;
564 }
565 }
566 }
567 }
568