File indexing completed on 2025-01-19 05:21:01
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Db 0017 * @subpackage Adapter 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 * @version $Id$ 0021 */ 0022 0023 0024 /** @see Zend_Db_Adapter_Pdo_Ibm */ 0025 // require_once 'Zend/Db/Adapter/Pdo/Ibm.php'; 0026 0027 /** @see Zend_Db_Statement_Pdo_Ibm */ 0028 // require_once 'Zend/Db/Statement/Pdo/Ibm.php'; 0029 0030 0031 /** 0032 * @category Zend 0033 * @package Zend_Db 0034 * @subpackage Adapter 0035 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0036 * @license http://framework.zend.com/license/new-bsd New BSD License 0037 */ 0038 class Zend_Db_Adapter_Pdo_Ibm_Ids 0039 { 0040 /** 0041 * @var Zend_Db_Adapter_Abstract 0042 */ 0043 protected $_adapter = null; 0044 0045 /** 0046 * Construct the data server class. 0047 * 0048 * It will be used to generate non-generic SQL 0049 * for a particular data server 0050 * 0051 * @param Zend_Db_Adapter_Abstract $adapter 0052 */ 0053 public function __construct($adapter) 0054 { 0055 $this->_adapter = $adapter; 0056 } 0057 0058 /** 0059 * Returns a list of the tables in the database. 0060 * 0061 * @return array 0062 */ 0063 public function listTables() 0064 { 0065 $sql = "SELECT tabname " 0066 . "FROM systables "; 0067 0068 return $this->_adapter->fetchCol($sql); 0069 } 0070 0071 /** 0072 * IDS catalog lookup for describe table 0073 * 0074 * @param string $tableName 0075 * @param string $schemaName OPTIONAL 0076 * @return array 0077 */ 0078 public function describeTable($tableName, $schemaName = null) 0079 { 0080 // this is still a work in progress 0081 0082 $sql= "SELECT DISTINCT t.owner, t.tabname, c.colname, c.colno, c.coltype, 0083 d.default, c.collength, t.tabid 0084 FROM syscolumns c 0085 JOIN systables t ON c.tabid = t.tabid 0086 LEFT JOIN sysdefaults d ON c.tabid = d.tabid AND c.colno = d.colno 0087 WHERE " 0088 . $this->_adapter->quoteInto('UPPER(t.tabname) = UPPER(?)', $tableName); 0089 if ($schemaName) { 0090 $sql .= $this->_adapter->quoteInto(' AND UPPER(t.owner) = UPPER(?)', $schemaName); 0091 } 0092 $sql .= " ORDER BY c.colno"; 0093 0094 $desc = array(); 0095 $stmt = $this->_adapter->query($sql); 0096 0097 $result = $stmt->fetchAll(Zend_Db::FETCH_NUM); 0098 0099 /** 0100 * The ordering of columns is defined by the query so we can map 0101 * to variables to improve readability 0102 */ 0103 $tabschema = 0; 0104 $tabname = 1; 0105 $colname = 2; 0106 $colno = 3; 0107 $typename = 4; 0108 $default = 5; 0109 $length = 6; 0110 $tabid = 7; 0111 0112 $primaryCols = null; 0113 0114 foreach ($result as $key => $row) { 0115 $primary = false; 0116 $primaryPosition = null; 0117 0118 if (!$primaryCols) { 0119 $primaryCols = $this->_getPrimaryInfo($row[$tabid]); 0120 } 0121 0122 if (array_key_exists($row[$colno], $primaryCols)) { 0123 $primary = true; 0124 $primaryPosition = $primaryCols[$row[$colno]]; 0125 } 0126 0127 $identity = false; 0128 if ($row[$typename] == 6 + 256 || 0129 $row[$typename] == 18 + 256) { 0130 $identity = true; 0131 } 0132 0133 $desc[$this->_adapter->foldCase($row[$colname])] = array ( 0134 'SCHEMA_NAME' => $this->_adapter->foldCase($row[$tabschema]), 0135 'TABLE_NAME' => $this->_adapter->foldCase($row[$tabname]), 0136 'COLUMN_NAME' => $this->_adapter->foldCase($row[$colname]), 0137 'COLUMN_POSITION' => $row[$colno], 0138 'DATA_TYPE' => $this->_getDataType($row[$typename]), 0139 'DEFAULT' => $row[$default], 0140 'NULLABLE' => (bool) !($row[$typename] - 256 >= 0), 0141 'LENGTH' => $row[$length], 0142 'SCALE' => ($row[$typename] == 5 ? $row[$length]&255 : 0), 0143 'PRECISION' => ($row[$typename] == 5 ? (int)($row[$length]/256) : 0), 0144 'UNSIGNED' => false, 0145 'PRIMARY' => $primary, 0146 'PRIMARY_POSITION' => $primaryPosition, 0147 'IDENTITY' => $identity 0148 ); 0149 } 0150 0151 return $desc; 0152 } 0153 0154 /** 0155 * Map number representation of a data type 0156 * to a string 0157 * 0158 * @param int $typeNo 0159 * @return string 0160 */ 0161 protected function _getDataType($typeNo) 0162 { 0163 $typemap = array( 0164 0 => "CHAR", 0165 1 => "SMALLINT", 0166 2 => "INTEGER", 0167 3 => "FLOAT", 0168 4 => "SMALLFLOAT", 0169 5 => "DECIMAL", 0170 6 => "SERIAL", 0171 7 => "DATE", 0172 8 => "MONEY", 0173 9 => "NULL", 0174 10 => "DATETIME", 0175 11 => "BYTE", 0176 12 => "TEXT", 0177 13 => "VARCHAR", 0178 14 => "INTERVAL", 0179 15 => "NCHAR", 0180 16 => "NVARCHAR", 0181 17 => "INT8", 0182 18 => "SERIAL8", 0183 19 => "SET", 0184 20 => "MULTISET", 0185 21 => "LIST", 0186 22 => "Unnamed ROW", 0187 40 => "Variable-length opaque type", 0188 4118 => "Named ROW" 0189 ); 0190 0191 if ($typeNo - 256 >= 0) { 0192 $typeNo = $typeNo - 256; 0193 } 0194 0195 return $typemap[$typeNo]; 0196 } 0197 0198 /** 0199 * Helper method to retrieve primary key column 0200 * and column location 0201 * 0202 * @param int $tabid 0203 * @return array 0204 */ 0205 protected function _getPrimaryInfo($tabid) 0206 { 0207 $sql = "SELECT i.part1, i.part2, i.part3, i.part4, i.part5, i.part6, 0208 i.part7, i.part8, i.part9, i.part10, i.part11, i.part12, 0209 i.part13, i.part14, i.part15, i.part16 0210 FROM sysindexes i 0211 JOIN sysconstraints c ON c.idxname = i.idxname 0212 WHERE i.tabid = " . $tabid . " AND c.constrtype = 'P'"; 0213 0214 $stmt = $this->_adapter->query($sql); 0215 $results = $stmt->fetchAll(); 0216 0217 $cols = array(); 0218 0219 // this should return only 1 row 0220 // unless there is no primary key, 0221 // in which case, the empty array is returned 0222 if ($results) { 0223 $row = $results[0]; 0224 } else { 0225 return $cols; 0226 } 0227 0228 $position = 0; 0229 foreach ($row as $key => $colno) { 0230 $position++; 0231 if ($colno == 0) { 0232 return $cols; 0233 } else { 0234 $cols[$colno] = $position; 0235 } 0236 } 0237 } 0238 0239 /** 0240 * Adds an IDS-specific LIMIT clause to the SELECT statement. 0241 * 0242 * @param string $sql 0243 * @param integer $count 0244 * @param integer $offset OPTIONAL 0245 * @throws Zend_Db_Adapter_Exception 0246 * @return string 0247 */ 0248 public function limit($sql, $count, $offset = 0) 0249 { 0250 $count = intval($count); 0251 if ($count < 0) { 0252 /** @see Zend_Db_Adapter_Exception */ 0253 // require_once 'Zend/Db/Adapter/Exception.php'; 0254 throw new Zend_Db_Adapter_Exception("LIMIT argument count=$count is not valid"); 0255 } else if ($count == 0) { 0256 $limit_sql = str_ireplace("SELECT", "SELECT * FROM (SELECT", $sql); 0257 $limit_sql .= ") WHERE 0 = 1"; 0258 } else { 0259 $offset = intval($offset); 0260 if ($offset < 0) { 0261 /** @see Zend_Db_Adapter_Exception */ 0262 // require_once 'Zend/Db/Adapter/Exception.php'; 0263 throw new Zend_Db_Adapter_Exception("LIMIT argument offset=$offset is not valid"); 0264 } 0265 if ($offset == 0) { 0266 $limit_sql = str_ireplace("SELECT", "SELECT FIRST $count", $sql); 0267 } else { 0268 $limit_sql = str_ireplace("SELECT", "SELECT SKIP $offset LIMIT $count", $sql); 0269 } 0270 } 0271 return $limit_sql; 0272 } 0273 0274 /** 0275 * IDS-specific last sequence id 0276 * 0277 * @param string $sequenceName 0278 * @return integer 0279 */ 0280 public function lastSequenceId($sequenceName) 0281 { 0282 $sql = 'SELECT '.$this->_adapter->quoteIdentifier($sequenceName).'.CURRVAL FROM ' 0283 .'systables WHERE tabid = 1'; 0284 $value = $this->_adapter->fetchOne($sql); 0285 return $value; 0286 } 0287 0288 /** 0289 * IDS-specific sequence id value 0290 * 0291 * @param string $sequenceName 0292 * @return integer 0293 */ 0294 public function nextSequenceId($sequenceName) 0295 { 0296 $sql = 'SELECT '.$this->_adapter->quoteIdentifier($sequenceName).'.NEXTVAL FROM ' 0297 .'systables WHERE tabid = 1'; 0298 $value = $this->_adapter->fetchOne($sql); 0299 return $value; 0300 } 0301 }