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 / Db2.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
Db2.php
678 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: Db2.php 23775 2011-03-01 17:25:24Z ralph $
23 *
24 */
25 /**
26 * @see Zend_Db
27 */
28 // require_once 'Zend/Db.php';
29 /**
30 * @see Zend_Db_Adapter_Abstract
31 */
32 // require_once 'Zend/Db/Adapter/Abstract.php';
33 /**
34 * @see Zend_Db_Statement_Db2
35 */
36 // require_once 'Zend/Db/Statement/Db2.php';
37 /**
38 * @package Zend_Db
39 * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
40 * @license http://framework.zend.com/license/new-bsd New BSD License
41 */
42 class Zend_Db_Adapter_Db2 extends \Zend_Db_Adapter_Abstract
43 {
44 /**
45 * User-provided configuration.
46 *
47 * Basic keys are:
48 *
49 * username => (string) Connect to the database as this username.
50 * password => (string) Password associated with the username.
51 * host => (string) What host to connect to (default 127.0.0.1)
52 * dbname => (string) The name of the database to user
53 * protocol => (string) Protocol to use, defaults to "TCPIP"
54 * port => (integer) Port number to use for TCP/IP if protocol is "TCPIP"
55 * persistent => (boolean) Set TRUE to use a persistent connection (db2_pconnect)
56 * os => (string) This should be set to 'i5' if the db is on an os400/i5
57 * schema => (string) The default schema the connection should use
58 *
59 * @var array
60 */
61 protected $_config = array('dbname' => null, 'username' => null, 'password' => null, 'host' => 'localhost', 'port' => '50000', 'protocol' => 'TCPIP', 'persistent' => \false, 'os' => null, 'schema' => null);
62 /**
63 * Execution mode
64 *
65 * @var int execution flag (DB2_AUTOCOMMIT_ON or DB2_AUTOCOMMIT_OFF)
66 */
67 protected $_execute_mode = \DB2_AUTOCOMMIT_ON;
68 /**
69 * Default class name for a DB statement.
70 *
71 * @var string
72 */
73 protected $_defaultStmtClass = 'Zend_Db_Statement_Db2';
74 protected $_isI5 = \false;
75 /**
76 * Keys are UPPERCASE SQL datatypes or the constants
77 * Zend_Db::INT_TYPE, Zend_Db::BIGINT_TYPE, or Zend_Db::FLOAT_TYPE.
78 *
79 * Values are:
80 * 0 = 32-bit integer
81 * 1 = 64-bit integer
82 * 2 = float or decimal
83 *
84 * @var array Associative array of datatypes to values 0, 1, or 2.
85 */
86 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, 'INTEGER' => \Zend_Db::INT_TYPE, 'SMALLINT' => \Zend_Db::INT_TYPE, 'BIGINT' => \Zend_Db::BIGINT_TYPE, 'DECIMAL' => \Zend_Db::FLOAT_TYPE, 'NUMERIC' => \Zend_Db::FLOAT_TYPE);
87 /**
88 * Creates a connection resource.
89 *
90 * @return void
91 */
92 protected function _connect()
93 {
94 if (\is_resource($this->_connection)) {
95 // connection already exists
96 return;
97 }
98 if (!\extension_loaded('ibm_db2')) {
99 /**
100 * @see Zend_Db_Adapter_Db2_Exception
101 */
102 // require_once 'Zend/Db/Adapter/Db2/Exception.php';
103 throw new \Zend_Db_Adapter_Db2_Exception('The IBM DB2 extension is required for this adapter but the extension is not loaded');
104 }
105 $this->_determineI5();
106 if ($this->_config['persistent']) {
107 // use persistent connection
108 $conn_func_name = 'db2_pconnect';
109 } else {
110 // use "normal" connection
111 $conn_func_name = 'db2_connect';
112 }
113 if (!isset($this->_config['driver_options']['autocommit'])) {
114 // set execution mode
115 $this->_config['driver_options']['autocommit'] =& $this->_execute_mode;
116 }
117 if (isset($this->_config['options'][\Zend_Db::CASE_FOLDING])) {
118 $caseAttrMap = array(\Zend_Db::CASE_NATURAL => \DB2_CASE_NATURAL, \Zend_Db::CASE_UPPER => \DB2_CASE_UPPER, \Zend_Db::CASE_LOWER => \DB2_CASE_LOWER);
119 $this->_config['driver_options']['DB2_ATTR_CASE'] = $caseAttrMap[$this->_config['options'][\Zend_Db::CASE_FOLDING]];
120 }
121 if ($this->_isI5 && isset($this->_config['driver_options']['i5_naming'])) {
122 if ($this->_config['driver_options']['i5_naming']) {
123 $this->_config['driver_options']['i5_naming'] = \DB2_I5_NAMING_ON;
124 } else {
125 $this->_config['driver_options']['i5_naming'] = \DB2_I5_NAMING_OFF;
126 }
127 }
128 if ($this->_config['host'] !== 'localhost' && !$this->_isI5) {
129 // if the host isn't localhost, use extended connection params
130 $dbname = 'DRIVER={IBM DB2 ODBC DRIVER}' . ';DATABASE=' . $this->_config['dbname'] . ';HOSTNAME=' . $this->_config['host'] . ';PORT=' . $this->_config['port'] . ';PROTOCOL=' . $this->_config['protocol'] . ';UID=' . $this->_config['username'] . ';PWD=' . $this->_config['password'] . ';';
131 $this->_connection = $conn_func_name($dbname, null, null, $this->_config['driver_options']);
132 } else {
133 // host is localhost, so use standard connection params
134 $this->_connection = $conn_func_name($this->_config['dbname'], $this->_config['username'], $this->_config['password'], $this->_config['driver_options']);
135 }
136 // check the connection
137 if (!$this->_connection) {
138 /**
139 * @see Zend_Db_Adapter_Db2_Exception
140 */
141 // require_once 'Zend/Db/Adapter/Db2/Exception.php';
142 throw new \Zend_Db_Adapter_Db2_Exception(\db2_conn_errormsg(), \db2_conn_error());
143 }
144 }
145 /**
146 * Test if a connection is active
147 *
148 * @return boolean
149 */
150 public function isConnected()
151 {
152 return (bool) (\is_resource($this->_connection) && \get_resource_type($this->_connection) == 'DB2 Connection');
153 }
154 /**
155 * Force the connection to close.
156 *
157 * @return void
158 */
159 public function closeConnection()
160 {
161 if ($this->isConnected()) {
162 \db2_close($this->_connection);
163 }
164 $this->_connection = null;
165 }
166 /**
167 * Returns an SQL statement for preparation.
168 *
169 * @param string $sql The SQL statement with placeholders.
170 * @return Zend_Db_Statement_Db2
171 */
172 public function prepare($sql)
173 {
174 $this->_connect();
175 $stmtClass = $this->_defaultStmtClass;
176 if (!\class_exists($stmtClass)) {
177 // require_once 'Zend/Loader.php';
178 \Zend_Loader::loadClass($stmtClass);
179 }
180 $stmt = new $stmtClass($this, $sql);
181 $stmt->setFetchMode($this->_fetchMode);
182 return $stmt;
183 }
184 /**
185 * Gets the execution mode
186 *
187 * @return int the execution mode (DB2_AUTOCOMMIT_ON or DB2_AUTOCOMMIT_OFF)
188 */
189 public function _getExecuteMode()
190 {
191 return $this->_execute_mode;
192 }
193 /**
194 * @param integer $mode
195 * @return void
196 */
197 public function _setExecuteMode($mode)
198 {
199 switch ($mode) {
200 case \DB2_AUTOCOMMIT_OFF:
201 case \DB2_AUTOCOMMIT_ON:
202 $this->_execute_mode = $mode;
203 \db2_autocommit($this->_connection, $mode);
204 break;
205 default:
206 /**
207 * @see Zend_Db_Adapter_Db2_Exception
208 */
209 // require_once 'Zend/Db/Adapter/Db2/Exception.php';
210 throw new \Zend_Db_Adapter_Db2_Exception("execution mode not supported");
211 break;
212 }
213 }
214 /**
215 * Quote a raw string.
216 *
217 * @param string $value Raw string
218 * @return string Quoted string
219 */
220 protected function _quote($value)
221 {
222 if (\is_int($value) || \is_float($value)) {
223 return $value;
224 }
225 /**
226 * Use db2_escape_string() if it is present in the IBM DB2 extension.
227 * But some supported versions of PHP do not include this function,
228 * so fall back to default quoting in the parent class.
229 */
230 if (\function_exists('db2_escape_string')) {
231 return "'" . \db2_escape_string($value) . "'";
232 }
233 return parent::_quote($value);
234 }
235 /**
236 * @return string
237 */
238 public function getQuoteIdentifierSymbol()
239 {
240 $this->_connect();
241 $info = \db2_server_info($this->_connection);
242 if ($info) {
243 $identQuote = $info->IDENTIFIER_QUOTE_CHAR;
244 } else {
245 // db2_server_info() does not return result on some i5 OS version
246 if ($this->_isI5) {
247 $identQuote = "'";
248 }
249 }
250 return $identQuote;
251 }
252 /**
253 * Returns a list of the tables in the database.
254 * @param string $schema OPTIONAL
255 * @return array
256 */
257 public function listTables($schema = null)
258 {
259 $this->_connect();
260 if ($schema === null && $this->_config['schema'] != null) {
261 $schema = $this->_config['schema'];
262 }
263 $tables = array();
264 if (!$this->_isI5) {
265 if ($schema) {
266 $stmt = \db2_tables($this->_connection, null, $schema);
267 } else {
268 $stmt = \db2_tables($this->_connection);
269 }
270 while ($row = \db2_fetch_assoc($stmt)) {
271 $tables[] = $row['TABLE_NAME'];
272 }
273 } else {
274 $tables = $this->_i5listTables($schema);
275 }
276 return $tables;
277 }
278 /**
279 * Returns the column descriptions for a table.
280 *
281 * The return value is an associative array keyed by the column name,
282 * as returned by the RDBMS.
283 *
284 * The value of each array element is an associative array
285 * with the following keys:
286 *
287 * SCHEMA_NAME => string; name of database or schema
288 * TABLE_NAME => string;
289 * COLUMN_NAME => string; column name
290 * COLUMN_POSITION => number; ordinal position of column in table
291 * DATA_TYPE => string; SQL datatype name of column
292 * DEFAULT => string; default expression of column, null if none
293 * NULLABLE => boolean; true if column can have nulls
294 * LENGTH => number; length of CHAR/VARCHAR
295 * SCALE => number; scale of NUMERIC/DECIMAL
296 * PRECISION => number; precision of NUMERIC/DECIMAL
297 * UNSIGNED => boolean; unsigned property of an integer type
298 * DB2 not supports UNSIGNED integer.
299 * PRIMARY => boolean; true if column is part of the primary key
300 * PRIMARY_POSITION => integer; position of column in primary key
301 * IDENTITY => integer; true if column is auto-generated with unique values
302 *
303 * @param string $tableName
304 * @param string $schemaName OPTIONAL
305 * @return array
306 */
307 public function describeTable($tableName, $schemaName = null)
308 {
309 // Ensure the connection is made so that _isI5 is set
310 $this->_connect();
311 if ($schemaName === null && $this->_config['schema'] != null) {
312 $schemaName = $this->_config['schema'];
313 }
314 if (!$this->_isI5) {
315 $sql = "SELECT DISTINCT c.tabschema, c.tabname, c.colname, c.colno,\n c.typename, c.default, c.nulls, c.length, c.scale,\n c.identity, tc.type AS tabconsttype, k.colseq\n FROM syscat.columns c\n LEFT JOIN (syscat.keycoluse k JOIN syscat.tabconst tc\n ON (k.tabschema = tc.tabschema\n AND k.tabname = tc.tabname\n AND tc.type = 'P'))\n ON (c.tabschema = k.tabschema\n AND c.tabname = k.tabname\n AND c.colname = k.colname)\n WHERE " . $this->quoteInto('UPPER(c.tabname) = UPPER(?)', $tableName);
316 if ($schemaName) {
317 $sql .= $this->quoteInto(' AND UPPER(c.tabschema) = UPPER(?)', $schemaName);
318 }
319 $sql .= " ORDER BY c.colno";
320 } else {
321 // DB2 On I5 specific query
322 $sql = "SELECT DISTINCT C.TABLE_SCHEMA, C.TABLE_NAME, C.COLUMN_NAME, C.ORDINAL_POSITION,\n C.DATA_TYPE, C.COLUMN_DEFAULT, C.NULLS ,C.LENGTH, C.SCALE, LEFT(C.IDENTITY,1),\n LEFT(tc.TYPE, 1) AS tabconsttype, k.COLSEQ\n FROM QSYS2.SYSCOLUMNS C\n LEFT JOIN (QSYS2.syskeycst k JOIN QSYS2.SYSCST tc\n ON (k.TABLE_SCHEMA = tc.TABLE_SCHEMA\n AND k.TABLE_NAME = tc.TABLE_NAME\n AND LEFT(tc.type,1) = 'P'))\n ON (C.TABLE_SCHEMA = k.TABLE_SCHEMA\n AND C.TABLE_NAME = k.TABLE_NAME\n AND C.COLUMN_NAME = k.COLUMN_NAME)\n WHERE " . $this->quoteInto('UPPER(C.TABLE_NAME) = UPPER(?)', $tableName);
323 if ($schemaName) {
324 $sql .= $this->quoteInto(' AND UPPER(C.TABLE_SCHEMA) = UPPER(?)', $schemaName);
325 }
326 $sql .= " ORDER BY C.ORDINAL_POSITION FOR FETCH ONLY";
327 }
328 $desc = array();
329 $stmt = $this->query($sql);
330 /**
331 * To avoid case issues, fetch using FETCH_NUM
332 */
333 $result = $stmt->fetchAll(\Zend_Db::FETCH_NUM);
334 /**
335 * The ordering of columns is defined by the query so we can map
336 * to variables to improve readability
337 */
338 $tabschema = 0;
339 $tabname = 1;
340 $colname = 2;
341 $colno = 3;
342 $typename = 4;
343 $default = 5;
344 $nulls = 6;
345 $length = 7;
346 $scale = 8;
347 $identityCol = 9;
348 $tabconstType = 10;
349 $colseq = 11;
350 foreach ($result as $key => $row) {
351 list($primary, $primaryPosition, $identity) = array(\false, null, \false);
352 if ($row[$tabconstType] == 'P') {
353 $primary = \true;
354 $primaryPosition = $row[$colseq];
355 }
356 /**
357 * In IBM DB2, an column can be IDENTITY
358 * even if it is not part of the PRIMARY KEY.
359 */
360 if ($row[$identityCol] == 'Y') {
361 $identity = \true;
362 }
363 // only colname needs to be case adjusted
364 $desc[$this->foldCase($row[$colname])] = array('SCHEMA_NAME' => $this->foldCase($row[$tabschema]), 'TABLE_NAME' => $this->foldCase($row[$tabname]), 'COLUMN_NAME' => $this->foldCase($row[$colname]), 'COLUMN_POSITION' => !$this->_isI5 ? $row[$colno] + 1 : $row[$colno], 'DATA_TYPE' => $row[$typename], 'DEFAULT' => $row[$default], 'NULLABLE' => (bool) ($row[$nulls] == 'Y'), 'LENGTH' => $row[$length], 'SCALE' => $row[$scale], 'PRECISION' => $row[$typename] == 'DECIMAL' ? $row[$length] : 0, 'UNSIGNED' => \false, 'PRIMARY' => $primary, 'PRIMARY_POSITION' => $primaryPosition, 'IDENTITY' => $identity);
365 }
366 return $desc;
367 }
368 /**
369 * Return the most recent value from the specified sequence in the database.
370 * This is supported only on RDBMS brands that support sequences
371 * (e.g. Oracle, PostgreSQL, DB2). Other RDBMS brands return null.
372 *
373 * @param string $sequenceName
374 * @return string
375 */
376 public function lastSequenceId($sequenceName)
377 {
378 $this->_connect();
379 if (!$this->_isI5) {
380 $quotedSequenceName = $this->quoteIdentifier($sequenceName, \true);
381 $sql = 'SELECT PREVVAL FOR ' . $quotedSequenceName . ' AS VAL FROM SYSIBM.SYSDUMMY1';
382 } else {
383 $quotedSequenceName = $sequenceName;
384 $sql = 'SELECT PREVVAL FOR ' . $this->quoteIdentifier($sequenceName, \true) . ' AS VAL FROM QSYS2.QSQPTABL';
385 }
386 $value = $this->fetchOne($sql);
387 return (string) $value;
388 }
389 /**
390 * Generate a new value from the specified sequence in the database, and return it.
391 * This is supported only on RDBMS brands that support sequences
392 * (e.g. Oracle, PostgreSQL, DB2). Other RDBMS brands return null.
393 *
394 * @param string $sequenceName
395 * @return string
396 */
397 public function nextSequenceId($sequenceName)
398 {
399 $this->_connect();
400 $sql = 'SELECT NEXTVAL FOR ' . $this->quoteIdentifier($sequenceName, \true) . ' AS VAL FROM SYSIBM.SYSDUMMY1';
401 $value = $this->fetchOne($sql);
402 return (string) $value;
403 }
404 /**
405 * Gets the last ID generated automatically by an IDENTITY/AUTOINCREMENT column.
406 *
407 * As a convention, on RDBMS brands that support sequences
408 * (e.g. Oracle, PostgreSQL, DB2), this method forms the name of a sequence
409 * from the arguments and returns the last id generated by that sequence.
410 * On RDBMS brands that support IDENTITY/AUTOINCREMENT columns, this method
411 * returns the last value generated for such a column, and the table name
412 * argument is disregarded.
413 *
414 * The IDENTITY_VAL_LOCAL() function gives the last generated identity value
415 * in the current process, even if it was for a GENERATED column.
416 *
417 * @param string $tableName OPTIONAL
418 * @param string $primaryKey OPTIONAL
419 * @param string $idType OPTIONAL used for i5 platform to define sequence/idenity unique value
420 * @return string
421 */
422 public function lastInsertId($tableName = null, $primaryKey = null, $idType = null)
423 {
424 $this->_connect();
425 if ($this->_isI5) {
426 return (string) $this->_i5LastInsertId($tableName, $idType);
427 }
428 if ($tableName !== null) {
429 $sequenceName = $tableName;
430 if ($primaryKey) {
431 $sequenceName .= "_{$primaryKey}";
432 }
433 $sequenceName .= '_seq';
434 return $this->lastSequenceId($sequenceName);
435 }
436 $sql = 'SELECT IDENTITY_VAL_LOCAL() AS VAL FROM SYSIBM.SYSDUMMY1';
437 $value = $this->fetchOne($sql);
438 return (string) $value;
439 }
440 /**
441 * Begin a transaction.
442 *
443 * @return void
444 */
445 protected function _beginTransaction()
446 {
447 $this->_setExecuteMode(\DB2_AUTOCOMMIT_OFF);
448 }
449 /**
450 * Commit a transaction.
451 *
452 * @return void
453 */
454 protected function _commit()
455 {
456 if (!\db2_commit($this->_connection)) {
457 /**
458 * @see Zend_Db_Adapter_Db2_Exception
459 */
460 // require_once 'Zend/Db/Adapter/Db2/Exception.php';
461 throw new \Zend_Db_Adapter_Db2_Exception(\db2_conn_errormsg($this->_connection), \db2_conn_error($this->_connection));
462 }
463 $this->_setExecuteMode(\DB2_AUTOCOMMIT_ON);
464 }
465 /**
466 * Rollback a transaction.
467 *
468 * @return void
469 */
470 protected function _rollBack()
471 {
472 if (!\db2_rollback($this->_connection)) {
473 /**
474 * @see Zend_Db_Adapter_Db2_Exception
475 */
476 // require_once 'Zend/Db/Adapter/Db2/Exception.php';
477 throw new \Zend_Db_Adapter_Db2_Exception(\db2_conn_errormsg($this->_connection), \db2_conn_error($this->_connection));
478 }
479 $this->_setExecuteMode(\DB2_AUTOCOMMIT_ON);
480 }
481 /**
482 * Set the fetch mode.
483 *
484 * @param integer $mode
485 * @return void
486 * @throws Zend_Db_Adapter_Db2_Exception
487 */
488 public function setFetchMode($mode)
489 {
490 switch ($mode) {
491 case \Zend_Db::FETCH_NUM:
492 // seq array
493 case \Zend_Db::FETCH_ASSOC:
494 // assoc array
495 case \Zend_Db::FETCH_BOTH:
496 // seq+assoc array
497 case \Zend_Db::FETCH_OBJ:
498 // object
499 $this->_fetchMode = $mode;
500 break;
501 case \Zend_Db::FETCH_BOUND:
502 // bound to PHP variable
503 /**
504 * @see Zend_Db_Adapter_Db2_Exception
505 */
506 // require_once 'Zend/Db/Adapter/Db2/Exception.php';
507 throw new \Zend_Db_Adapter_Db2_Exception('FETCH_BOUND is not supported yet');
508 break;
509 default:
510 /**
511 * @see Zend_Db_Adapter_Db2_Exception
512 */
513 // require_once 'Zend/Db/Adapter/Db2/Exception.php';
514 throw new \Zend_Db_Adapter_Db2_Exception("Invalid fetch mode '{$mode}' specified");
515 break;
516 }
517 }
518 /**
519 * Adds an adapter-specific LIMIT clause to the SELECT statement.
520 *
521 * @param string $sql
522 * @param integer $count
523 * @param integer $offset OPTIONAL
524 * @return string
525 */
526 public function limit($sql, $count, $offset = 0)
527 {
528 $count = \intval($count);
529 if ($count <= 0) {
530 /**
531 * @see Zend_Db_Adapter_Db2_Exception
532 */
533 // require_once 'Zend/Db/Adapter/Db2/Exception.php';
534 throw new \Zend_Db_Adapter_Db2_Exception("LIMIT argument count={$count} is not valid");
535 }
536 $offset = \intval($offset);
537 if ($offset < 0) {
538 /**
539 * @see Zend_Db_Adapter_Db2_Exception
540 */
541 // require_once 'Zend/Db/Adapter/Db2/Exception.php';
542 throw new \Zend_Db_Adapter_Db2_Exception("LIMIT argument offset={$offset} is not valid");
543 }
544 if ($offset == 0) {
545 $limit_sql = $sql . " FETCH FIRST {$count} ROWS ONLY";
546 return $limit_sql;
547 }
548 /**
549 * DB2 does not implement the LIMIT clause as some RDBMS do.
550 * We have to simulate it with subqueries and ROWNUM.
551 * Unfortunately because we use the column wildcard "*",
552 * this puts an extra column into the query result set.
553 */
554 $limit_sql = "SELECT z2.*\n FROM (\n SELECT ROW_NUMBER() OVER() AS \"ZEND_DB_ROWNUM\", z1.*\n FROM (\n " . $sql . "\n ) z1\n ) z2\n WHERE z2.zend_db_rownum BETWEEN " . ($offset + 1) . " AND " . ($offset + $count);
555 return $limit_sql;
556 }
557 /**
558 * Check if the adapter supports real SQL parameters.
559 *
560 * @param string $type 'positional' or 'named'
561 * @return bool
562 */
563 public function supportsParameters($type)
564 {
565 if ($type == 'positional') {
566 return \true;
567 }
568 // if its 'named' or anything else
569 return \false;
570 }
571 /**
572 * Retrieve server version in PHP style
573 *
574 * @return string
575 */
576 public function getServerVersion()
577 {
578 $this->_connect();
579 $server_info = \db2_server_info($this->_connection);
580 if ($server_info !== \false) {
581 $version = $server_info->DBMS_VER;
582 if ($this->_isI5) {
583 $version = (int) \substr($version, 0, 2) . '.' . (int) \substr($version, 2, 2) . '.' . (int) \substr($version, 4);
584 }
585 return $version;
586 } else {
587 return null;
588 }
589 }
590 /**
591 * Return whether or not this is running on i5
592 *
593 * @return bool
594 */
595 public function isI5()
596 {
597 if ($this->_isI5 === null) {
598 $this->_determineI5();
599 }
600 return (bool) $this->_isI5;
601 }
602 /**
603 * Check the connection parameters according to verify
604 * type of used OS
605 *
606 * @return void
607 */
608 protected function _determineI5()
609 {
610 // first us the compiled flag.
611 $this->_isI5 = \php_uname('s') == 'OS400' ? \true : \false;
612 // if this is set, then us it
613 if (isset($this->_config['os'])) {
614 if (\strtolower($this->_config['os']) === 'i5') {
615 $this->_isI5 = \true;
616 } else {
617 // any other value passed in, its null
618 $this->_isI5 = \false;
619 }
620 }
621 }
622 /**
623 * Db2 On I5 specific method
624 *
625 * Returns a list of the tables in the database .
626 * Used only for DB2/400.
627 *
628 * @return array
629 */
630 protected function _i5listTables($schema = null)
631 {
632 //list of i5 libraries.
633 $tables = array();
634 if ($schema) {
635 $tablesStatement = \db2_tables($this->_connection, null, $schema);
636 while ($rowTables = \db2_fetch_assoc($tablesStatement)) {
637 if ($rowTables['TABLE_NAME'] !== null) {
638 $tables[] = $rowTables['TABLE_NAME'];
639 }
640 }
641 } else {
642 $schemaStatement = \db2_tables($this->_connection);
643 while ($schema = \db2_fetch_assoc($schemaStatement)) {
644 if ($schema['TABLE_SCHEM'] !== null) {
645 // list of the tables which belongs to the selected library
646 $tablesStatement = \db2_tables($this->_connection, NULL, $schema['TABLE_SCHEM']);
647 if (\is_resource($tablesStatement)) {
648 while ($rowTables = \db2_fetch_assoc($tablesStatement)) {
649 if ($rowTables['TABLE_NAME'] !== null) {
650 $tables[] = $rowTables['TABLE_NAME'];
651 }
652 }
653 }
654 }
655 }
656 }
657 return $tables;
658 }
659 protected function _i5LastInsertId($objectName = null, $idType = null)
660 {
661 if ($objectName === null) {
662 $sql = 'SELECT IDENTITY_VAL_LOCAL() AS VAL FROM QSYS2.QSQPTABL';
663 $value = $this->fetchOne($sql);
664 return $value;
665 }
666 if (\strtoupper($idType) === 'S') {
667 //check i5_lib option
668 $sequenceName = $objectName;
669 return $this->lastSequenceId($sequenceName);
670 }
671 //returns last identity value for the specified table
672 //if (strtoupper($idType) === 'I') {
673 $tableName = $objectName;
674 return $this->fetchOne('SELECT IDENTITY_VAL_LOCAL() from ' . $this->quoteIdentifier($tableName));
675 }
676 }
677 }
678