web/enmi/Zend/Db/Adapter/Pdo/Ibm.php
changeset 19 1c2f13fd785c
parent 0 4eba9c11703f
equal deleted inserted replaced
18:bd595ad770fc 19:1c2f13fd785c
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     7  * This source file is subject to the new BSD license that is bundled
       
     8  * with this package in the file LICENSE.txt.
       
     9  * It is also available through the world-wide-web at this URL:
       
    10  * http://framework.zend.com/license/new-bsd
       
    11  * If you did not receive a copy of the license and are unable to
       
    12  * obtain it through the world-wide-web, please send an email
       
    13  * to license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_Db
       
    17  * @subpackage Adapter
       
    18  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    19  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    20  * @version    $Id: Ibm.php 20096 2010-01-06 02:05:09Z bkarwin $
       
    21  */
       
    22 
       
    23 
       
    24 /** @see Zend_Db_Adapter_Pdo_Abstract */
       
    25 require_once 'Zend/Db/Adapter/Pdo/Abstract.php';
       
    26 
       
    27 /** @see Zend_Db_Abstract_Pdo_Ibm_Db2 */
       
    28 require_once 'Zend/Db/Adapter/Pdo/Ibm/Db2.php';
       
    29 
       
    30 /** @see Zend_Db_Abstract_Pdo_Ibm_Ids */
       
    31 require_once 'Zend/Db/Adapter/Pdo/Ibm/Ids.php';
       
    32 
       
    33 /** @see Zend_Db_Statement_Pdo_Ibm */
       
    34 require_once 'Zend/Db/Statement/Pdo/Ibm.php';
       
    35 
       
    36 
       
    37 /**
       
    38  * @category   Zend
       
    39  * @package    Zend_Db
       
    40  * @subpackage Adapter
       
    41  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    42  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    43  */
       
    44 class Zend_Db_Adapter_Pdo_Ibm extends Zend_Db_Adapter_Pdo_Abstract
       
    45 {
       
    46     /**
       
    47      * PDO type.
       
    48      *
       
    49      * @var string
       
    50      */
       
    51     protected $_pdoType = 'ibm';
       
    52 
       
    53     /**
       
    54      * The IBM data server connected to
       
    55      *
       
    56      * @var string
       
    57      */
       
    58     protected $_serverType = null;
       
    59 
       
    60     /**
       
    61      * Keys are UPPERCASE SQL datatypes or the constants
       
    62      * Zend_Db::INT_TYPE, Zend_Db::BIGINT_TYPE, or Zend_Db::FLOAT_TYPE.
       
    63      *
       
    64      * Values are:
       
    65      * 0 = 32-bit integer
       
    66      * 1 = 64-bit integer
       
    67      * 2 = float or decimal
       
    68      *
       
    69      * @var array Associative array of datatypes to values 0, 1, or 2.
       
    70      */
       
    71     protected $_numericDataTypes = array(
       
    72                         Zend_Db::INT_TYPE    => Zend_Db::INT_TYPE,
       
    73                         Zend_Db::BIGINT_TYPE => Zend_Db::BIGINT_TYPE,
       
    74                         Zend_Db::FLOAT_TYPE  => Zend_Db::FLOAT_TYPE,
       
    75                         'INTEGER'            => Zend_Db::INT_TYPE,
       
    76                         'SMALLINT'           => Zend_Db::INT_TYPE,
       
    77                         'BIGINT'             => Zend_Db::BIGINT_TYPE,
       
    78                         'DECIMAL'            => Zend_Db::FLOAT_TYPE,
       
    79                         'DEC'                => Zend_Db::FLOAT_TYPE,
       
    80                         'REAL'               => Zend_Db::FLOAT_TYPE,
       
    81                         'NUMERIC'            => Zend_Db::FLOAT_TYPE,
       
    82                         'DOUBLE PRECISION'   => Zend_Db::FLOAT_TYPE,
       
    83                         'FLOAT'              => Zend_Db::FLOAT_TYPE
       
    84                         );
       
    85 
       
    86     /**
       
    87      * Creates a PDO object and connects to the database.
       
    88      *
       
    89      * The IBM data server is set.
       
    90      * Current options are DB2 or IDS
       
    91      * @todo also differentiate between z/OS and i/5
       
    92      *
       
    93      * @return void
       
    94      * @throws Zend_Db_Adapter_Exception
       
    95      */
       
    96     public function _connect()
       
    97     {
       
    98         if ($this->_connection) {
       
    99             return;
       
   100         }
       
   101         parent::_connect();
       
   102 
       
   103         $this->getConnection()->setAttribute(Zend_Db::ATTR_STRINGIFY_FETCHES, true);
       
   104 
       
   105         try {
       
   106             if ($this->_serverType === null) {
       
   107                 $server = substr($this->getConnection()->getAttribute(PDO::ATTR_SERVER_INFO), 0, 3);
       
   108 
       
   109                 switch ($server) {
       
   110                     case 'DB2':
       
   111                         $this->_serverType = new Zend_Db_Adapter_Pdo_Ibm_Db2($this);
       
   112 
       
   113                         // Add DB2-specific numeric types
       
   114                         $this->_numericDataTypes['DECFLOAT'] = Zend_Db::FLOAT_TYPE;
       
   115                         $this->_numericDataTypes['DOUBLE']   = Zend_Db::FLOAT_TYPE;
       
   116                         $this->_numericDataTypes['NUM']      = Zend_Db::FLOAT_TYPE;
       
   117 
       
   118                         break;
       
   119                     case 'IDS':
       
   120                         $this->_serverType = new Zend_Db_Adapter_Pdo_Ibm_Ids($this);
       
   121 
       
   122                         // Add IDS-specific numeric types
       
   123                         $this->_numericDataTypes['SERIAL']       = Zend_Db::INT_TYPE;
       
   124                         $this->_numericDataTypes['SERIAL8']      = Zend_Db::BIGINT_TYPE;
       
   125                         $this->_numericDataTypes['INT8']         = Zend_Db::BIGINT_TYPE;
       
   126                         $this->_numericDataTypes['SMALLFLOAT']   = Zend_Db::FLOAT_TYPE;
       
   127                         $this->_numericDataTypes['MONEY']        = Zend_Db::FLOAT_TYPE;
       
   128 
       
   129                         break;
       
   130                     }
       
   131             }
       
   132         } catch (PDOException $e) {
       
   133             /** @see Zend_Db_Adapter_Exception */
       
   134             require_once 'Zend/Db/Adapter/Exception.php';
       
   135             $error = strpos($e->getMessage(), 'driver does not support that attribute');
       
   136             if ($error) {
       
   137                 throw new Zend_Db_Adapter_Exception("PDO_IBM driver extension is downlevel.  Please use driver release version 1.2.1 or later", 0, $e);
       
   138             } else {
       
   139                 throw new Zend_Db_Adapter_Exception($e->getMessage(), $e->getCode(), $e);
       
   140             }
       
   141         }
       
   142     }
       
   143 
       
   144     /**
       
   145      * Creates a PDO DSN for the adapter from $this->_config settings.
       
   146      *
       
   147      * @return string
       
   148      */
       
   149     protected function _dsn()
       
   150     {
       
   151         $this->_checkRequiredOptions($this->_config);
       
   152 
       
   153         // check if using full connection string
       
   154         if (array_key_exists('host', $this->_config)) {
       
   155             $dsn = ';DATABASE=' . $this->_config['dbname']
       
   156             . ';HOSTNAME=' . $this->_config['host']
       
   157             . ';PORT='     . $this->_config['port']
       
   158             // PDO_IBM supports only DB2 TCPIP protocol
       
   159             . ';PROTOCOL=' . 'TCPIP;';
       
   160         } else {
       
   161             // catalogued connection
       
   162             $dsn = $this->_config['dbname'];
       
   163         }
       
   164         return $this->_pdoType . ': ' . $dsn;
       
   165     }
       
   166 
       
   167     /**
       
   168      * Checks required options
       
   169      *
       
   170      * @param  array $config
       
   171      * @throws Zend_Db_Adapter_Exception
       
   172      * @return void
       
   173      */
       
   174     protected function _checkRequiredOptions(array $config)
       
   175     {
       
   176         parent::_checkRequiredOptions($config);
       
   177 
       
   178         if (array_key_exists('host', $this->_config) &&
       
   179         !array_key_exists('port', $config)) {
       
   180             /** @see Zend_Db_Adapter_Exception */
       
   181             require_once 'Zend/Db/Adapter/Exception.php';
       
   182             throw new Zend_Db_Adapter_Exception("Configuration must have a key for 'port' when 'host' is specified");
       
   183         }
       
   184     }
       
   185 
       
   186     /**
       
   187      * Prepares an SQL statement.
       
   188      *
       
   189      * @param string $sql The SQL statement with placeholders.
       
   190      * @param array $bind An array of data to bind to the placeholders.
       
   191      * @return PDOStatement
       
   192      */
       
   193     public function prepare($sql)
       
   194     {
       
   195         $this->_connect();
       
   196         $stmtClass = $this->_defaultStmtClass;
       
   197         $stmt = new $stmtClass($this, $sql);
       
   198         $stmt->setFetchMode($this->_fetchMode);
       
   199         return $stmt;
       
   200     }
       
   201 
       
   202     /**
       
   203      * Returns a list of the tables in the database.
       
   204      *
       
   205      * @return array
       
   206      */
       
   207     public function listTables()
       
   208     {
       
   209         $this->_connect();
       
   210         return $this->_serverType->listTables();
       
   211     }
       
   212 
       
   213     /**
       
   214      * Returns the column descriptions for a table.
       
   215      *
       
   216      * The return value is an associative array keyed by the column name,
       
   217      * as returned by the RDBMS.
       
   218      *
       
   219      * The value of each array element is an associative array
       
   220      * with the following keys:
       
   221      *
       
   222      * SCHEMA_NAME      => string; name of database or schema
       
   223      * TABLE_NAME       => string;
       
   224      * COLUMN_NAME      => string; column name
       
   225      * COLUMN_POSITION  => number; ordinal position of column in table
       
   226      * DATA_TYPE        => string; SQL datatype name of column
       
   227      * DEFAULT          => string; default expression of column, null if none
       
   228      * NULLABLE         => boolean; true if column can have nulls
       
   229      * LENGTH           => number; length of CHAR/VARCHAR
       
   230      * SCALE            => number; scale of NUMERIC/DECIMAL
       
   231      * PRECISION        => number; precision of NUMERIC/DECIMAL
       
   232      * UNSIGNED         => boolean; unsigned property of an integer type
       
   233      * PRIMARY          => boolean; true if column is part of the primary key
       
   234      * PRIMARY_POSITION => integer; position of column in primary key
       
   235      *
       
   236      * @todo Discover integer unsigned property.
       
   237      *
       
   238      * @param string $tableName
       
   239      * @param string $schemaName OPTIONAL
       
   240      * @return array
       
   241      */
       
   242     public function describeTable($tableName, $schemaName = null)
       
   243     {
       
   244         $this->_connect();
       
   245         return $this->_serverType->describeTable($tableName, $schemaName);
       
   246     }
       
   247 
       
   248     /**
       
   249      * Inserts a table row with specified data.
       
   250      * Special handling for PDO_IBM
       
   251      * remove empty slots
       
   252      *
       
   253      * @param mixed $table The table to insert data into.
       
   254      * @param array $bind Column-value pairs.
       
   255      * @return int The number of affected rows.
       
   256      */
       
   257     public function insert($table, array $bind)
       
   258     {
       
   259         $this->_connect();
       
   260         $newbind = array();
       
   261         if (is_array($bind)) {
       
   262             foreach ($bind as $name => $value) {
       
   263                 if($value !== null) {
       
   264                     $newbind[$name] = $value;
       
   265                 }
       
   266             }
       
   267         }
       
   268 
       
   269         return parent::insert($table, $newbind);
       
   270     }
       
   271 
       
   272     /**
       
   273      * Adds an adapter-specific LIMIT clause to the SELECT statement.
       
   274      *
       
   275      * @param string $sql
       
   276      * @param integer $count
       
   277      * @param integer $offset OPTIONAL
       
   278      * @return string
       
   279      */
       
   280     public function limit($sql, $count, $offset = 0)
       
   281     {
       
   282        $this->_connect();
       
   283        return $this->_serverType->limit($sql, $count, $offset);
       
   284     }
       
   285 
       
   286     /**
       
   287      * Gets the last ID generated automatically by an IDENTITY/AUTOINCREMENT
       
   288      * column.
       
   289      *
       
   290      * @param string $tableName OPTIONAL
       
   291      * @param string $primaryKey OPTIONAL
       
   292      * @return integer
       
   293      */
       
   294     public function lastInsertId($tableName = null, $primaryKey = null)
       
   295     {
       
   296         $this->_connect();
       
   297 
       
   298          if ($tableName !== null) {
       
   299             $sequenceName = $tableName;
       
   300             if ($primaryKey) {
       
   301                 $sequenceName .= "_$primaryKey";
       
   302             }
       
   303             $sequenceName .= '_seq';
       
   304             return $this->lastSequenceId($sequenceName);
       
   305         }
       
   306 
       
   307         $id = $this->getConnection()->lastInsertId();
       
   308 
       
   309         return $id;
       
   310     }
       
   311 
       
   312     /**
       
   313      * Return the most recent value from the specified sequence in the database.
       
   314      *
       
   315      * @param string $sequenceName
       
   316      * @return integer
       
   317      */
       
   318     public function lastSequenceId($sequenceName)
       
   319     {
       
   320         $this->_connect();
       
   321         return $this->_serverType->lastSequenceId($sequenceName);
       
   322     }
       
   323 
       
   324     /**
       
   325      * Generate a new value from the specified sequence in the database,
       
   326      * and return it.
       
   327      *
       
   328      * @param string $sequenceName
       
   329      * @return integer
       
   330      */
       
   331     public function nextSequenceId($sequenceName)
       
   332     {
       
   333         $this->_connect();
       
   334         return $this->_serverType->nextSequenceId($sequenceName);
       
   335     }
       
   336 
       
   337     /**
       
   338      * Retrieve server version in PHP style
       
   339      * Pdo_Idm doesn't support getAttribute(PDO::ATTR_SERVER_VERSION)
       
   340      * @return string
       
   341      */
       
   342     public function getServerVersion()
       
   343     {
       
   344         try {
       
   345             $stmt = $this->query('SELECT service_level, fixpack_num FROM TABLE (sysproc.env_get_inst_info()) as INSTANCEINFO');
       
   346             $result = $stmt->fetchAll(Zend_Db::FETCH_NUM);
       
   347             if (count($result)) {
       
   348                 $matches = null;
       
   349                 if (preg_match('/((?:[0-9]{1,2}\.){1,3}[0-9]{1,2})/', $result[0][0], $matches)) {
       
   350                     return $matches[1];
       
   351                 } else {
       
   352                     return null;
       
   353                 }
       
   354             }
       
   355             return null;
       
   356         } catch (PDOException $e) {
       
   357             return null;
       
   358         }
       
   359     }
       
   360 }