• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • Examples
  • File List

E:/E/GEAMP/www/openbiz/openbiz/others/Zend/Db/Adapter/Db2.php

00001 <?php
00027 require_once 'Zend/Db.php';
00028 
00032 require_once 'Zend/Db/Adapter/Abstract.php';
00033 
00037 require_once 'Zend/Db/Statement/Db2.php';
00038 
00039 
00046 class Zend_Db_Adapter_Db2 extends Zend_Db_Adapter_Abstract
00047 {
00065     protected $_config = array(
00066         'dbname'       => null,
00067         'username'     => null,
00068         'password'     => null,
00069         'host'         => 'localhost',
00070         'port'         => '50000',
00071         'protocol'     => 'TCPIP',
00072         'persistent'   => false,
00073         'os'           => null,
00074         'schema'       => null
00075     );
00076 
00082     protected $_execute_mode = DB2_AUTOCOMMIT_ON;
00083 
00089     protected $_defaultStmtClass = 'Zend_Db_Statement_Db2';
00090     protected $_isI5 = false;
00091 
00103     protected $_numericDataTypes = array(
00104         Zend_Db::INT_TYPE    => Zend_Db::INT_TYPE,
00105         Zend_Db::BIGINT_TYPE => Zend_Db::BIGINT_TYPE,
00106         Zend_Db::FLOAT_TYPE  => Zend_Db::FLOAT_TYPE,
00107         'INTEGER'            => Zend_Db::INT_TYPE,
00108         'SMALLINT'           => Zend_Db::INT_TYPE,
00109         'BIGINT'             => Zend_Db::BIGINT_TYPE,
00110         'DECIMAL'            => Zend_Db::FLOAT_TYPE,
00111         'NUMERIC'            => Zend_Db::FLOAT_TYPE
00112     );
00113 
00119     protected function _connect()
00120     {
00121         if (is_resource($this->_connection)) {
00122             // connection already exists
00123             return;
00124         }
00125 
00126         if (!extension_loaded('ibm_db2')) {
00130             require_once 'Zend/Db/Adapter/Db2/Exception.php';
00131             throw new Zend_Db_Adapter_Db2_Exception('The IBM DB2 extension is required for this adapter but the extension is not loaded');
00132         }
00133 
00134         $this->_determineI5();
00135         if ($this->_config['persistent']) {
00136             // use persistent connection
00137             $conn_func_name = 'db2_pconnect';
00138         } else {
00139             // use "normal" connection
00140             $conn_func_name = 'db2_connect';
00141         }
00142 
00143         if (!isset($this->_config['driver_options']['autocommit'])) {
00144             // set execution mode
00145             $this->_config['driver_options']['autocommit'] = &$this->_execute_mode;
00146         }
00147 
00148         if (isset($this->_config['options'][Zend_Db::CASE_FOLDING])) {
00149             $caseAttrMap = array(
00150                 Zend_Db::CASE_NATURAL => DB2_CASE_NATURAL,
00151                 Zend_Db::CASE_UPPER   => DB2_CASE_UPPER,
00152                 Zend_Db::CASE_LOWER   => DB2_CASE_LOWER
00153             );
00154             $this->_config['driver_options']['DB2_ATTR_CASE'] = $caseAttrMap[$this->_config['options'][Zend_Db::CASE_FOLDING]];
00155         }
00156 
00157         if ($this->_config['host'] !== 'localhost' && !$this->_isI5) {
00158             // if the host isn't localhost, use extended connection params
00159             $dbname = 'DRIVER={IBM DB2 ODBC DRIVER}' .
00160                      ';DATABASE=' . $this->_config['dbname'] .
00161                      ';HOSTNAME=' . $this->_config['host'] .
00162                      ';PORT='     . $this->_config['port'] .
00163                      ';PROTOCOL=' . $this->_config['protocol'] .
00164                      ';UID='      . $this->_config['username'] .
00165                      ';PWD='      . $this->_config['password'] .';';
00166             $this->_connection = $conn_func_name(
00167                 $dbname,
00168                 null,
00169                 null,
00170                 $this->_config['driver_options']
00171             );
00172         } else {
00173             // host is localhost, so use standard connection params
00174             $this->_connection = $conn_func_name(
00175                 $this->_config['dbname'],
00176                 $this->_config['username'],
00177                 $this->_config['password'],
00178                 $this->_config['driver_options']
00179             );
00180         }
00181 
00182         // check the connection
00183         if (!$this->_connection) {
00187             require_once 'Zend/Db/Adapter/Db2/Exception.php';
00188             throw new Zend_Db_Adapter_Db2_Exception(db2_conn_errormsg(), db2_conn_error());
00189         }
00190     }
00191 
00197     public function isConnected()
00198     {
00199         return ((bool) (is_resource($this->_connection)
00200                      && get_resource_type($this->_connection) == 'DB2 Connection'));
00201     }
00202 
00208     public function closeConnection()
00209     {
00210         if ($this->isConnected()) {
00211             db2_close($this->_connection);
00212         }
00213         $this->_connection = null;
00214     }
00215 
00222     public function prepare($sql)
00223     {
00224         $this->_connect();
00225         $stmtClass = $this->_defaultStmtClass;
00226         if (!class_exists($stmtClass)) {
00227             require_once 'Zend/Loader.php';
00228             Zend_Loader::loadClass($stmtClass);
00229         }
00230         $stmt = new $stmtClass($this, $sql);
00231         $stmt->setFetchMode($this->_fetchMode);
00232         return $stmt;
00233     }
00234 
00240     public function _getExecuteMode()
00241     {
00242         return $this->_execute_mode;
00243     }
00244 
00249     public function _setExecuteMode($mode)
00250     {
00251         switch ($mode) {
00252             case DB2_AUTOCOMMIT_OFF:
00253             case DB2_AUTOCOMMIT_ON:
00254                 $this->_execute_mode = $mode;
00255                 db2_autocommit($this->_connection, $mode);
00256                 break;
00257             default:
00261                 require_once 'Zend/Db/Adapter/Db2/Exception.php';
00262                 throw new Zend_Db_Adapter_Db2_Exception("execution mode not supported");
00263                 break;
00264         }
00265     }
00266 
00273     protected function _quote($value)
00274     {
00275         if (is_int($value) || is_float($value)) {
00276             return $value;
00277         }
00283         if (function_exists('db2_escape_string')) {
00284             return "'" . db2_escape_string($value) . "'";
00285         }
00286         return parent::_quote($value);
00287     }
00288 
00292     public function getQuoteIdentifierSymbol()
00293     {
00294         $this->_connect();
00295         $info = db2_server_info($this->_connection);
00296         if ($info) {
00297             $identQuote = $info->IDENTIFIER_QUOTE_CHAR;
00298         } else {
00299             // db2_server_info() does not return result on some i5 OS version
00300             if ($this->_isI5) {
00301                 $identQuote ="'";
00302             }
00303         }
00304         return $identQuote;
00305     }
00306 
00312     public function listTables($schema = null)
00313     {
00314         $this->_connect();
00315 
00316         if ($schema === null && $this->_config['schema'] != null) {
00317             $schema = $this->_config['schema'];
00318         }
00319 
00320         $tables = array();
00321 
00322         if (!$this->_isI5) {
00323             if ($schema) {
00324                 $stmt = db2_tables($this->_connection, null, $schema);
00325             } else {
00326                 $stmt = db2_tables($this->_connection);
00327             }
00328             while ($row = db2_fetch_assoc($stmt)) {
00329                 $tables[] = $row['TABLE_NAME'];
00330             }
00331         } else {
00332             $tables = $this->_i5listTables($schema);
00333         }
00334 
00335         return $tables;
00336     }
00337 
00338 
00368     public function describeTable($tableName, $schemaName = null)
00369     {
00370         // Ensure the connection is made so that _isI5 is set
00371         $this->_connect();
00372 
00373         if ($schemaName === null && $this->_config['schema'] != null) {
00374             $schemaName = $this->_config['schema'];
00375         }
00376 
00377         if (!$this->_isI5) {
00378 
00379             $sql = "SELECT DISTINCT c.tabschema, c.tabname, c.colname, c.colno,
00380                 c.typename, c.default, c.nulls, c.length, c.scale,
00381                 c.identity, tc.type AS tabconsttype, k.colseq
00382                 FROM syscat.columns c
00383                 LEFT JOIN (syscat.keycoluse k JOIN syscat.tabconst tc
00384                 ON (k.tabschema = tc.tabschema
00385                     AND k.tabname = tc.tabname
00386                     AND tc.type = 'P'))
00387                 ON (c.tabschema = k.tabschema
00388                     AND c.tabname = k.tabname
00389                     AND c.colname = k.colname)
00390                 WHERE "
00391                 . $this->quoteInto('UPPER(c.tabname) = UPPER(?)', $tableName);
00392 
00393             if ($schemaName) {
00394                $sql .= $this->quoteInto(' AND UPPER(c.tabschema) = UPPER(?)', $schemaName);
00395             }
00396 
00397             $sql .= " ORDER BY c.colno";
00398 
00399         } else {
00400 
00401             // DB2 On I5 specific query
00402             $sql = "SELECT DISTINCT C.TABLE_SCHEMA, C.TABLE_NAME, C.COLUMN_NAME, C.ORDINAL_POSITION,
00403                 C.DATA_TYPE, C.COLUMN_DEFAULT, C.NULLS ,C.LENGTH, C.SCALE, LEFT(C.IDENTITY,1),
00404                 LEFT(tc.TYPE, 1) AS tabconsttype, k.COLSEQ
00405                 FROM QSYS2.SYSCOLUMNS C
00406                 LEFT JOIN (QSYS2.syskeycst k JOIN QSYS2.SYSCST tc
00407                     ON (k.TABLE_SCHEMA = tc.TABLE_SCHEMA
00408                       AND k.TABLE_NAME = tc.TABLE_NAME
00409                       AND LEFT(tc.type,1) = 'P'))
00410                     ON (C.TABLE_SCHEMA = k.TABLE_SCHEMA
00411                        AND C.TABLE_NAME = k.TABLE_NAME
00412                        AND C.COLUMN_NAME = k.COLUMN_NAME)
00413                 WHERE "
00414                  . $this->quoteInto('UPPER(C.TABLE_NAME) = UPPER(?)', $tableName);
00415 
00416             if ($schemaName) {
00417                 $sql .= $this->quoteInto(' AND UPPER(C.TABLE_SCHEMA) = UPPER(?)', $schemaName);
00418             }
00419 
00420             $sql .= " ORDER BY C.ORDINAL_POSITION FOR FETCH ONLY";
00421         }
00422 
00423         $desc = array();
00424         $stmt = $this->query($sql);
00425 
00429         $result = $stmt->fetchAll(Zend_Db::FETCH_NUM);
00430 
00435         $tabschema      = 0;
00436         $tabname        = 1;
00437         $colname        = 2;
00438         $colno          = 3;
00439         $typename       = 4;
00440         $default        = 5;
00441         $nulls          = 6;
00442         $length         = 7;
00443         $scale          = 8;
00444         $identityCol    = 9;
00445         $tabconstType   = 10;
00446         $colseq         = 11;
00447 
00448         foreach ($result as $key => $row) {
00449             list ($primary, $primaryPosition, $identity) = array(false, null, false);
00450             if ($row[$tabconstType] == 'P') {
00451                 $primary = true;
00452                 $primaryPosition = $row[$colseq];
00453             }
00458             if ($row[$identityCol] == 'Y') {
00459                 $identity = true;
00460             }
00461 
00462             // only colname needs to be case adjusted
00463             $desc[$this->foldCase($row[$colname])] = array(
00464                 'SCHEMA_NAME'      => $this->foldCase($row[$tabschema]),
00465                 'TABLE_NAME'       => $this->foldCase($row[$tabname]),
00466                 'COLUMN_NAME'      => $this->foldCase($row[$colname]),
00467                 'COLUMN_POSITION'  => (!$this->_isI5) ? $row[$colno]+1 : $row[$colno],
00468                 'DATA_TYPE'        => $row[$typename],
00469                 'DEFAULT'          => $row[$default],
00470                 'NULLABLE'         => (bool) ($row[$nulls] == 'Y'),
00471                 'LENGTH'           => $row[$length],
00472                 'SCALE'            => $row[$scale],
00473                 'PRECISION'        => ($row[$typename] == 'DECIMAL' ? $row[$length] : 0),
00474                 'UNSIGNED'         => false,
00475                 'PRIMARY'          => $primary,
00476                 'PRIMARY_POSITION' => $primaryPosition,
00477                 'IDENTITY'         => $identity
00478             );
00479         }
00480 
00481         return $desc;
00482     }
00483 
00492     public function lastSequenceId($sequenceName)
00493     {
00494         $this->_connect();
00495 
00496         if (!$this->_isI5) {
00497             $quotedSequenceName = $this->quoteIdentifier($sequenceName, true);
00498             $sql = 'SELECT PREVVAL FOR ' . $quotedSequenceName . ' AS VAL FROM SYSIBM.SYSDUMMY1';
00499         } else {
00500             $quotedSequenceName = $sequenceName;
00501             $sql = 'SELECT PREVVAL FOR ' . $this->quoteIdentifier($sequenceName, true) . ' AS VAL FROM QSYS2.QSQPTABL';
00502         }
00503 
00504         $value = $this->fetchOne($sql);
00505         return (string) $value;
00506     }
00507 
00516     public function nextSequenceId($sequenceName)
00517     {
00518         $this->_connect();
00519         $sql = 'SELECT NEXTVAL FOR '.$this->quoteIdentifier($sequenceName, true).' AS VAL FROM SYSIBM.SYSDUMMY1';
00520         $value = $this->fetchOne($sql);
00521         return (string) $value;
00522     }
00523 
00543     public function lastInsertId($tableName = null, $primaryKey = null, $idType = null)
00544     {
00545         $this->_connect();
00546 
00547         if ($this->_isI5) {
00548             return (string) $this->_i5LastInsertId($tableName, $idType);
00549         }
00550 
00551         if ($tableName !== null) {
00552             $sequenceName = $tableName;
00553             if ($primaryKey) {
00554                 $sequenceName .= "_$primaryKey";
00555             }
00556             $sequenceName .= '_seq';
00557             return $this->lastSequenceId($sequenceName);
00558         }
00559 
00560         $sql = 'SELECT IDENTITY_VAL_LOCAL() AS VAL FROM SYSIBM.SYSDUMMY1';
00561         $value = $this->fetchOne($sql);
00562         return (string) $value;
00563     }
00564 
00570     protected function _beginTransaction()
00571     {
00572         $this->_setExecuteMode(DB2_AUTOCOMMIT_OFF);
00573     }
00574 
00580     protected function _commit()
00581     {
00582         if (!db2_commit($this->_connection)) {
00586             require_once 'Zend/Db/Adapter/Db2/Exception.php';
00587             throw new Zend_Db_Adapter_Db2_Exception(
00588                 db2_conn_errormsg($this->_connection),
00589                 db2_conn_error($this->_connection));
00590         }
00591 
00592         $this->_setExecuteMode(DB2_AUTOCOMMIT_ON);
00593     }
00594 
00600     protected function _rollBack()
00601     {
00602         if (!db2_rollback($this->_connection)) {
00606             require_once 'Zend/Db/Adapter/Db2/Exception.php';
00607             throw new Zend_Db_Adapter_Db2_Exception(
00608                 db2_conn_errormsg($this->_connection),
00609                 db2_conn_error($this->_connection));
00610         }
00611         $this->_setExecuteMode(DB2_AUTOCOMMIT_ON);
00612     }
00613 
00621     public function setFetchMode($mode)
00622     {
00623         switch ($mode) {
00624             case Zend_Db::FETCH_NUM:   // seq array
00625             case Zend_Db::FETCH_ASSOC: // assoc array
00626             case Zend_Db::FETCH_BOTH:  // seq+assoc array
00627             case Zend_Db::FETCH_OBJ:   // object
00628                 $this->_fetchMode = $mode;
00629                 break;
00630             case Zend_Db::FETCH_BOUND:   // bound to PHP variable
00634                 require_once 'Zend/Db/Adapter/Db2/Exception.php';
00635                 throw new Zend_Db_Adapter_Db2_Exception('FETCH_BOUND is not supported yet');
00636                 break;
00637             default:
00641                 require_once 'Zend/Db/Adapter/Db2/Exception.php';
00642                 throw new Zend_Db_Adapter_Db2_Exception("Invalid fetch mode '$mode' specified");
00643                 break;
00644         }
00645     }
00646 
00655     public function limit($sql, $count, $offset = 0)
00656     {
00657         $count = intval($count);
00658         if ($count <= 0) {
00662             require_once 'Zend/Db/Adapter/Db2/Exception.php';
00663             throw new Zend_Db_Adapter_Db2_Exception("LIMIT argument count=$count is not valid");
00664         }
00665 
00666         $offset = intval($offset);
00667         if ($offset < 0) {
00671             require_once 'Zend/Db/Adapter/Db2/Exception.php';
00672             throw new Zend_Db_Adapter_Db2_Exception("LIMIT argument offset=$offset is not valid");
00673         }
00674 
00675         if ($offset == 0) {
00676             $limit_sql = $sql . " FETCH FIRST $count ROWS ONLY";
00677             return $limit_sql;
00678         }
00679 
00686         $limit_sql = "SELECT z2.*
00687             FROM (
00688                 SELECT ROW_NUMBER() OVER() AS \"ZEND_DB_ROWNUM\", z1.*
00689                 FROM (
00690                     " . $sql . "
00691                 ) z1
00692             ) z2
00693             WHERE z2.zend_db_rownum BETWEEN " . ($offset+1) . " AND " . ($offset+$count);
00694         return $limit_sql;
00695     }
00696 
00703     public function supportsParameters($type)
00704     {
00705         if ($type == 'positional') {
00706             return true;
00707         }
00708 
00709         // if its 'named' or anything else
00710         return false;
00711     }
00712 
00718     public function getServerVersion()
00719     {
00720         $this->_connect();
00721         $server_info = db2_server_info($this->_connection);
00722         if ($server_info !== false) {
00723             $version = $server_info->DBMS_VER;
00724             if ($this->_isI5) {
00725                 $version = (int) substr($version, 0, 2) . '.' . (int) substr($version, 2, 2) . '.' . (int) substr($version, 4);
00726             }
00727             return $version;
00728         } else {
00729             return null;
00730         }
00731     }
00732 
00738     public function isI5()
00739     {
00740         if ($this->_isI5 === null) {
00741             $this->_determineI5();
00742         }
00743 
00744         return (bool) $this->_isI5;
00745     }
00746 
00753     protected function _determineI5()
00754     {
00755         // first us the compiled flag.
00756         $this->_isI5 = (php_uname('s') == 'OS400') ? true : false;
00757 
00758         // if this is set, then us it
00759         if (isset($this->_config['os'])){
00760             if (strtolower($this->_config['os']) === 'i5') {
00761                 $this->_isI5 = true;
00762             } else {
00763                 // any other value passed in, its null
00764                 $this->_isI5 = false;
00765             }
00766         }
00767 
00768     }
00769 
00778     protected function _i5listTables($schema = null)
00779     {
00780         //list of i5 libraries.
00781         $tables = array();
00782         if ($schema) {
00783             $tablesStatement = db2_tables($this->_connection, null, $schema);
00784             while ($rowTables = db2_fetch_assoc($tablesStatement) ) {
00785                 if ($rowTables['TABLE_NAME'] !== null) {
00786                     $tables[] = $rowTables['TABLE_NAME'];
00787                 }
00788             }
00789         } else {
00790             $schemaStatement = db2_tables($this->_connection);
00791             while ($schema = db2_fetch_assoc($schemaStatement)) {
00792                 if ($schema['TABLE_SCHEM'] !== null) {
00793                     // list of the tables which belongs to the selected library
00794                     $tablesStatement = db2_tables($this->_connection, NULL, $schema['TABLE_SCHEM']);
00795                     if (is_resource($tablesStatement)) {
00796                         while ($rowTables = db2_fetch_assoc($tablesStatement) ) {
00797                             if ($rowTables['TABLE_NAME'] !== null) {
00798                                 $tables[] = $rowTables['TABLE_NAME'];
00799                             }
00800                         }
00801                     }
00802                 }
00803             }
00804         }
00805 
00806         return $tables;
00807     }
00808 
00809     protected function _i5LastInsertId($objectName = null, $idType = null)
00810     {
00811 
00812         if ($objectName === null) {
00813             $sql = 'SELECT IDENTITY_VAL_LOCAL() AS VAL FROM QSYS2.QSQPTABL';
00814             $value = $this->fetchOne($sql);
00815             return $value;
00816         }
00817 
00818         if (strtoupper($idType) === 'S'){
00819             //check i5_lib option
00820             $sequenceName = $objectName;
00821             return $this->lastSequenceId($sequenceName);
00822         }
00823 
00824             //returns last identity value for the specified table
00825         //if (strtoupper($idType) === 'I') {
00826         $tableName = $objectName;
00827         return $this->fetchOne('SELECT IDENTITY_VAL_LOCAL() from ' . $this->quoteIdentifier($tableName));
00828     }
00829 
00830 }
00831 
00832 

Generated on Thu Apr 19 2012 17:01:17 for openbiz by  doxygen 1.7.2