Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Db2.php
Go to the documentation of this file.
1 <?php
27 #require_once 'Zend/Db.php';
28 
32 #require_once 'Zend/Db/Adapter/Abstract.php';
33 
37 #require_once 'Zend/Db/Statement/Db2.php';
38 
39 
47 {
65  protected $_config = array(
66  'dbname' => null,
67  'username' => null,
68  'password' => null,
69  'host' => 'localhost',
70  'port' => '50000',
71  'protocol' => 'TCPIP',
72  'persistent' => false,
73  'os' => null,
74  'schema' => null
75  );
76 
82  protected $_execute_mode = DB2_AUTOCOMMIT_ON;
83 
89  protected $_defaultStmtClass = 'Zend_Db_Statement_Db2';
90  protected $_isI5 = false;
91 
103  protected $_numericDataTypes = array(
107  'INTEGER' => Zend_Db::INT_TYPE,
108  'SMALLINT' => Zend_Db::INT_TYPE,
109  'BIGINT' => Zend_Db::BIGINT_TYPE,
110  'DECIMAL' => Zend_Db::FLOAT_TYPE,
111  'NUMERIC' => Zend_Db::FLOAT_TYPE
112  );
113 
119  protected function _connect()
120  {
121  if (is_resource($this->_connection)) {
122  // connection already exists
123  return;
124  }
125 
126  if (!extension_loaded('ibm_db2')) {
130  #require_once 'Zend/Db/Adapter/Db2/Exception.php';
131  throw new Zend_Db_Adapter_Db2_Exception('The IBM DB2 extension is required for this adapter but the extension is not loaded');
132  }
133 
134  $this->_determineI5();
135  if ($this->_config['persistent']) {
136  // use persistent connection
137  $conn_func_name = 'db2_pconnect';
138  } else {
139  // use "normal" connection
140  $conn_func_name = 'db2_connect';
141  }
142 
143  if (!isset($this->_config['driver_options']['autocommit'])) {
144  // set execution mode
145  $this->_config['driver_options']['autocommit'] = &$this->_execute_mode;
146  }
147 
148  if (isset($this->_config['options'][Zend_Db::CASE_FOLDING])) {
149  $caseAttrMap = array(
150  Zend_Db::CASE_NATURAL => DB2_CASE_NATURAL,
151  Zend_Db::CASE_UPPER => DB2_CASE_UPPER,
152  Zend_Db::CASE_LOWER => DB2_CASE_LOWER
153  );
154  $this->_config['driver_options']['DB2_ATTR_CASE'] = $caseAttrMap[$this->_config['options'][Zend_Db::CASE_FOLDING]];
155  }
156 
157  if ($this->_isI5 && isset($this->_config['driver_options']['i5_naming'])) {
158  if ($this->_config['driver_options']['i5_naming']) {
159  $this->_config['driver_options']['i5_naming'] = DB2_I5_NAMING_ON;
160  } else {
161  $this->_config['driver_options']['i5_naming'] = DB2_I5_NAMING_OFF;
162  }
163  }
164 
165  if ($this->_config['host'] !== 'localhost' && !$this->_isI5) {
166  // if the host isn't localhost, use extended connection params
167  $dbname = 'DRIVER={IBM DB2 ODBC DRIVER}' .
168  ';DATABASE=' . $this->_config['dbname'] .
169  ';HOSTNAME=' . $this->_config['host'] .
170  ';PORT=' . $this->_config['port'] .
171  ';PROTOCOL=' . $this->_config['protocol'] .
172  ';UID=' . $this->_config['username'] .
173  ';PWD=' . $this->_config['password'] .';';
174  $this->_connection = $conn_func_name(
175  $dbname,
176  null,
177  null,
178  $this->_config['driver_options']
179  );
180  } else {
181  // host is localhost, so use standard connection params
182  $this->_connection = $conn_func_name(
183  $this->_config['dbname'],
184  $this->_config['username'],
185  $this->_config['password'],
186  $this->_config['driver_options']
187  );
188  }
189 
190  // check the connection
191  if (!$this->_connection) {
195  #require_once 'Zend/Db/Adapter/Db2/Exception.php';
196  throw new Zend_Db_Adapter_Db2_Exception(db2_conn_errormsg(), db2_conn_error());
197  }
198  }
199 
205  public function isConnected()
206  {
207  return ((bool) (is_resource($this->_connection)
208  && get_resource_type($this->_connection) == 'DB2 Connection'));
209  }
210 
216  public function closeConnection()
217  {
218  if ($this->isConnected()) {
219  db2_close($this->_connection);
220  }
221  $this->_connection = null;
222  }
223 
230  public function prepare($sql)
231  {
232  $this->_connect();
233  $stmtClass = $this->_defaultStmtClass;
234  if (!class_exists($stmtClass)) {
235  #require_once 'Zend/Loader.php';
236  Zend_Loader::loadClass($stmtClass);
237  }
238  $stmt = new $stmtClass($this, $sql);
239  $stmt->setFetchMode($this->_fetchMode);
240  return $stmt;
241  }
242 
248  public function _getExecuteMode()
249  {
250  return $this->_execute_mode;
251  }
252 
257  public function _setExecuteMode($mode)
258  {
259  switch ($mode) {
260  case DB2_AUTOCOMMIT_OFF:
261  case DB2_AUTOCOMMIT_ON:
262  $this->_execute_mode = $mode;
263  db2_autocommit($this->_connection, $mode);
264  break;
265  default:
269  #require_once 'Zend/Db/Adapter/Db2/Exception.php';
270  throw new Zend_Db_Adapter_Db2_Exception("execution mode not supported");
271  break;
272  }
273  }
274 
281  protected function _quote($value)
282  {
283  if (is_int($value) || is_float($value)) {
284  return $value;
285  }
291  if (function_exists('db2_escape_string')) {
292  return "'" . db2_escape_string($value) . "'";
293  }
294  return parent::_quote($value);
295  }
296 
300  public function getQuoteIdentifierSymbol()
301  {
302  $this->_connect();
303  $info = db2_server_info($this->_connection);
304  if ($info) {
305  $identQuote = $info->IDENTIFIER_QUOTE_CHAR;
306  } else {
307  // db2_server_info() does not return result on some i5 OS version
308  if ($this->_isI5) {
309  $identQuote ="'";
310  }
311  }
312  return $identQuote;
313  }
314 
320  public function listTables($schema = null)
321  {
322  $this->_connect();
323 
324  if ($schema === null && $this->_config['schema'] != null) {
325  $schema = $this->_config['schema'];
326  }
327 
328  $tables = array();
329 
330  if (!$this->_isI5) {
331  if ($schema) {
332  $stmt = db2_tables($this->_connection, null, $schema);
333  } else {
334  $stmt = db2_tables($this->_connection);
335  }
336  while ($row = db2_fetch_assoc($stmt)) {
337  $tables[] = $row['TABLE_NAME'];
338  }
339  } else {
340  $tables = $this->_i5listTables($schema);
341  }
342 
343  return $tables;
344  }
345 
346 
376  public function describeTable($tableName, $schemaName = null)
377  {
378  // Ensure the connection is made so that _isI5 is set
379  $this->_connect();
380 
381  if ($schemaName === null && $this->_config['schema'] != null) {
382  $schemaName = $this->_config['schema'];
383  }
384 
385  if (!$this->_isI5) {
386 
387  $sql = "SELECT DISTINCT c.tabschema, c.tabname, c.colname, c.colno,
388  c.typename, c.default, c.nulls, c.length, c.scale,
389  c.identity, tc.type AS tabconsttype, k.colseq
390  FROM syscat.columns c
391  LEFT JOIN (syscat.keycoluse k JOIN syscat.tabconst tc
392  ON (k.tabschema = tc.tabschema
393  AND k.tabname = tc.tabname
394  AND tc.type = 'P'))
395  ON (c.tabschema = k.tabschema
396  AND c.tabname = k.tabname
397  AND c.colname = k.colname)
398  WHERE "
399  . $this->quoteInto('UPPER(c.tabname) = UPPER(?)', $tableName);
400 
401  if ($schemaName) {
402  $sql .= $this->quoteInto(' AND UPPER(c.tabschema) = UPPER(?)', $schemaName);
403  }
404 
405  $sql .= " ORDER BY c.colno";
406 
407  } else {
408 
409  // DB2 On I5 specific query
410  $sql = "SELECT DISTINCT C.TABLE_SCHEMA, C.TABLE_NAME, C.COLUMN_NAME, C.ORDINAL_POSITION,
411  C.DATA_TYPE, C.COLUMN_DEFAULT, C.NULLS ,C.LENGTH, C.SCALE, LEFT(C.IDENTITY,1),
412  LEFT(tc.TYPE, 1) AS tabconsttype, k.COLSEQ
413  FROM QSYS2.SYSCOLUMNS C
414  LEFT JOIN (QSYS2.syskeycst k JOIN QSYS2.SYSCST tc
415  ON (k.TABLE_SCHEMA = tc.TABLE_SCHEMA
416  AND k.TABLE_NAME = tc.TABLE_NAME
417  AND LEFT(tc.type,1) = 'P'))
418  ON (C.TABLE_SCHEMA = k.TABLE_SCHEMA
419  AND C.TABLE_NAME = k.TABLE_NAME
420  AND C.COLUMN_NAME = k.COLUMN_NAME)
421  WHERE "
422  . $this->quoteInto('UPPER(C.TABLE_NAME) = UPPER(?)', $tableName);
423 
424  if ($schemaName) {
425  $sql .= $this->quoteInto(' AND UPPER(C.TABLE_SCHEMA) = UPPER(?)', $schemaName);
426  }
427 
428  $sql .= " ORDER BY C.ORDINAL_POSITION FOR FETCH ONLY";
429  }
430 
431  $desc = array();
432  $stmt = $this->query($sql);
433 
437  $result = $stmt->fetchAll(Zend_Db::FETCH_NUM);
438 
443  $tabschema = 0;
444  $tabname = 1;
445  $colname = 2;
446  $colno = 3;
447  $typename = 4;
448  $default = 5;
449  $nulls = 6;
450  $length = 7;
451  $scale = 8;
452  $identityCol = 9;
453  $tabconstType = 10;
454  $colseq = 11;
455 
456  foreach ($result as $key => $row) {
457  list ($primary, $primaryPosition, $identity) = array(false, null, false);
458  if ($row[$tabconstType] == 'P') {
459  $primary = true;
460  $primaryPosition = $row[$colseq];
461  }
466  if ($row[$identityCol] == 'Y') {
467  $identity = true;
468  }
469 
470  // only colname needs to be case adjusted
471  $desc[$this->foldCase($row[$colname])] = array(
472  'SCHEMA_NAME' => $this->foldCase($row[$tabschema]),
473  'TABLE_NAME' => $this->foldCase($row[$tabname]),
474  'COLUMN_NAME' => $this->foldCase($row[$colname]),
475  'COLUMN_POSITION' => (!$this->_isI5) ? $row[$colno]+1 : $row[$colno],
476  'DATA_TYPE' => $row[$typename],
477  'DEFAULT' => $row[$default],
478  'NULLABLE' => (bool) ($row[$nulls] == 'Y'),
479  'LENGTH' => $row[$length],
480  'SCALE' => $row[$scale],
481  'PRECISION' => ($row[$typename] == 'DECIMAL' ? $row[$length] : 0),
482  'UNSIGNED' => false,
483  'PRIMARY' => $primary,
484  'PRIMARY_POSITION' => $primaryPosition,
485  'IDENTITY' => $identity
486  );
487  }
488 
489  return $desc;
490  }
491 
500  public function lastSequenceId($sequenceName)
501  {
502  $this->_connect();
503 
504  if (!$this->_isI5) {
505  $quotedSequenceName = $this->quoteIdentifier($sequenceName, true);
506  $sql = 'SELECT PREVVAL FOR ' . $quotedSequenceName . ' AS VAL FROM SYSIBM.SYSDUMMY1';
507  } else {
508  $quotedSequenceName = $sequenceName;
509  $sql = 'SELECT PREVVAL FOR ' . $this->quoteIdentifier($sequenceName, true) . ' AS VAL FROM QSYS2.QSQPTABL';
510  }
511 
512  $value = $this->fetchOne($sql);
513  return (string) $value;
514  }
515 
524  public function nextSequenceId($sequenceName)
525  {
526  $this->_connect();
527  $sql = 'SELECT NEXTVAL FOR '.$this->quoteIdentifier($sequenceName, true).' AS VAL FROM SYSIBM.SYSDUMMY1';
528  $value = $this->fetchOne($sql);
529  return (string) $value;
530  }
531 
551  public function lastInsertId($tableName = null, $primaryKey = null, $idType = null)
552  {
553  $this->_connect();
554 
555  if ($this->_isI5) {
556  return (string) $this->_i5LastInsertId($tableName, $idType);
557  }
558 
559  if ($tableName !== null) {
560  $sequenceName = $tableName;
561  if ($primaryKey) {
562  $sequenceName .= "_$primaryKey";
563  }
564  $sequenceName .= '_seq';
565  return $this->lastSequenceId($sequenceName);
566  }
567 
568  $sql = 'SELECT IDENTITY_VAL_LOCAL() AS VAL FROM SYSIBM.SYSDUMMY1';
569  $value = $this->fetchOne($sql);
570  return (string) $value;
571  }
572 
578  protected function _beginTransaction()
579  {
580  $this->_setExecuteMode(DB2_AUTOCOMMIT_OFF);
581  }
582 
588  protected function _commit()
589  {
590  if (!db2_commit($this->_connection)) {
594  #require_once 'Zend/Db/Adapter/Db2/Exception.php';
596  db2_conn_errormsg($this->_connection),
597  db2_conn_error($this->_connection));
598  }
599 
600  $this->_setExecuteMode(DB2_AUTOCOMMIT_ON);
601  }
602 
608  protected function _rollBack()
609  {
610  if (!db2_rollback($this->_connection)) {
614  #require_once 'Zend/Db/Adapter/Db2/Exception.php';
616  db2_conn_errormsg($this->_connection),
617  db2_conn_error($this->_connection));
618  }
619  $this->_setExecuteMode(DB2_AUTOCOMMIT_ON);
620  }
621 
629  public function setFetchMode($mode)
630  {
631  switch ($mode) {
632  case Zend_Db::FETCH_NUM: // seq array
633  case Zend_Db::FETCH_ASSOC: // assoc array
634  case Zend_Db::FETCH_BOTH: // seq+assoc array
635  case Zend_Db::FETCH_OBJ: // object
636  $this->_fetchMode = $mode;
637  break;
638  case Zend_Db::FETCH_BOUND: // bound to PHP variable
642  #require_once 'Zend/Db/Adapter/Db2/Exception.php';
643  throw new Zend_Db_Adapter_Db2_Exception('FETCH_BOUND is not supported yet');
644  break;
645  default:
649  #require_once 'Zend/Db/Adapter/Db2/Exception.php';
650  throw new Zend_Db_Adapter_Db2_Exception("Invalid fetch mode '$mode' specified");
651  break;
652  }
653  }
654 
663  public function limit($sql, $count, $offset = 0)
664  {
665  $count = intval($count);
666  if ($count <= 0) {
670  #require_once 'Zend/Db/Adapter/Db2/Exception.php';
671  throw new Zend_Db_Adapter_Db2_Exception("LIMIT argument count=$count is not valid");
672  }
673 
674  $offset = intval($offset);
675  if ($offset < 0) {
679  #require_once 'Zend/Db/Adapter/Db2/Exception.php';
680  throw new Zend_Db_Adapter_Db2_Exception("LIMIT argument offset=$offset is not valid");
681  }
682 
683  if ($offset == 0) {
684  $limit_sql = $sql . " FETCH FIRST $count ROWS ONLY";
685  return $limit_sql;
686  }
687 
694  $limit_sql = "SELECT z2.*
695  FROM (
696  SELECT ROW_NUMBER() OVER() AS \"ZEND_DB_ROWNUM\", z1.*
697  FROM (
698  " . $sql . "
699  ) z1
700  ) z2
701  WHERE z2.zend_db_rownum BETWEEN " . ($offset+1) . " AND " . ($offset+$count);
702  return $limit_sql;
703  }
704 
711  public function supportsParameters($type)
712  {
713  if ($type == 'positional') {
714  return true;
715  }
716 
717  // if its 'named' or anything else
718  return false;
719  }
720 
726  public function getServerVersion()
727  {
728  $this->_connect();
729  $server_info = db2_server_info($this->_connection);
730  if ($server_info !== false) {
731  $version = $server_info->DBMS_VER;
732  if ($this->_isI5) {
733  $version = (int) substr($version, 0, 2) . '.' . (int) substr($version, 2, 2) . '.' . (int) substr($version, 4);
734  }
735  return $version;
736  } else {
737  return null;
738  }
739  }
740 
746  public function isI5()
747  {
748  if ($this->_isI5 === null) {
749  $this->_determineI5();
750  }
751 
752  return (bool) $this->_isI5;
753  }
754 
761  protected function _determineI5()
762  {
763  // first us the compiled flag.
764  $this->_isI5 = (php_uname('s') == 'OS400') ? true : false;
765 
766  // if this is set, then us it
767  if (isset($this->_config['os'])){
768  if (strtolower($this->_config['os']) === 'i5') {
769  $this->_isI5 = true;
770  } else {
771  // any other value passed in, its null
772  $this->_isI5 = false;
773  }
774  }
775 
776  }
777 
786  protected function _i5listTables($schema = null)
787  {
788  //list of i5 libraries.
789  $tables = array();
790  if ($schema) {
791  $tablesStatement = db2_tables($this->_connection, null, $schema);
792  while ($rowTables = db2_fetch_assoc($tablesStatement) ) {
793  if ($rowTables['TABLE_NAME'] !== null) {
794  $tables[] = $rowTables['TABLE_NAME'];
795  }
796  }
797  } else {
798  $schemaStatement = db2_tables($this->_connection);
799  while ($schema = db2_fetch_assoc($schemaStatement)) {
800  if ($schema['TABLE_SCHEM'] !== null) {
801  // list of the tables which belongs to the selected library
802  $tablesStatement = db2_tables($this->_connection, NULL, $schema['TABLE_SCHEM']);
803  if (is_resource($tablesStatement)) {
804  while ($rowTables = db2_fetch_assoc($tablesStatement) ) {
805  if ($rowTables['TABLE_NAME'] !== null) {
806  $tables[] = $rowTables['TABLE_NAME'];
807  }
808  }
809  }
810  }
811  }
812  }
813 
814  return $tables;
815  }
816 
817  protected function _i5LastInsertId($objectName = null, $idType = null)
818  {
819 
820  if ($objectName === null) {
821  $sql = 'SELECT IDENTITY_VAL_LOCAL() AS VAL FROM QSYS2.QSQPTABL';
822  $value = $this->fetchOne($sql);
823  return $value;
824  }
825 
826  if (strtoupper($idType) === 'S'){
827  //check i5_lib option
828  $sequenceName = $objectName;
829  return $this->lastSequenceId($sequenceName);
830  }
831 
832  //returns last identity value for the specified table
833  //if (strtoupper($idType) === 'I') {
834  $tableName = $objectName;
835  return $this->fetchOne('SELECT IDENTITY_VAL_LOCAL() from ' . $this->quoteIdentifier($tableName));
836  }
837 
838 }
839 
840 
setFetchMode($mode)
Definition: Db2.php:629
describeTable($tableName, $schemaName=null)
Definition: Db2.php:376
$tableName
Definition: trigger.php:13
fetchOne($sql, $bind=array())
Definition: Abstract.php:826
listTables($schema=null)
Definition: Db2.php:320
static loadClass($class, $dirs=null)
Definition: Loader.php:52
const BIGINT_TYPE
Definition: Db.php:69
const INT_TYPE
Definition: Db.php:68
$count
Definition: recent.phtml:13
const FETCH_BOUND
Definition: Db.php:144
const FETCH_ASSOC
Definition: Db.php:142
lastInsertId($tableName=null, $primaryKey=null, $idType=null)
Definition: Db2.php:551
_quote($value)
Definition: Db2.php:281
const FLOAT_TYPE
Definition: Db.php:70
$type
Definition: item.phtml:13
const FETCH_BOTH
Definition: Db.php:143
$value
Definition: gender.phtml:16
const FETCH_NUM
Definition: Db.php:153
quoteInto($text, $value, $type=null, $count=null)
Definition: Abstract.php:928
supportsParameters($type)
Definition: Db2.php:711
if($exist=($block->getProductCollection() && $block->getProductCollection() ->getSize())) $mode
Definition: grid.phtml:15
_i5listTables($schema=null)
Definition: Db2.php:786
const FETCH_OBJ
Definition: Db.php:154
lastSequenceId($sequenceName)
Definition: Db2.php:500
_i5LastInsertId($objectName=null, $idType=null)
Definition: Db2.php:817
const CASE_UPPER
Definition: Db.php:125
const CASE_NATURAL
Definition: Db.php:124
query($sql, $bind=array())
Definition: Abstract.php:457
foreach( $_productCollection as $_product)() ?>" class $info
Definition: listing.phtml:52
_setExecuteMode($mode)
Definition: Db2.php:257
quoteIdentifier($ident, $auto=false)
Definition: Abstract.php:959
limit($sql, $count, $offset=0)
Definition: Db2.php:663
const CASE_FOLDING
Definition: Db.php:43
nextSequenceId($sequenceName)
Definition: Db2.php:524
getQuoteIdentifierSymbol()
Definition: Db2.php:300
const CASE_LOWER
Definition: Db.php:123