File indexing completed on 2025-01-26 05:24:56
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 /** 0025 * @see Zend_Db_Adapter_Pdo_Abstract 0026 */ 0027 // require_once 'Zend/Db/Adapter/Pdo/Abstract.php'; 0028 0029 0030 /** 0031 * Class for connecting to MySQL databases and performing common operations. 0032 * 0033 * @category Zend 0034 * @package Zend_Db 0035 * @subpackage Adapter 0036 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0037 * @license http://framework.zend.com/license/new-bsd New BSD License 0038 */ 0039 class Zend_Db_Adapter_Pdo_Mysql extends Zend_Db_Adapter_Pdo_Abstract 0040 { 0041 0042 /** 0043 * PDO type. 0044 * 0045 * @var string 0046 */ 0047 protected $_pdoType = 'mysql'; 0048 0049 /** 0050 * Keys are UPPERCASE SQL datatypes or the constants 0051 * Zend_Db::INT_TYPE, Zend_Db::BIGINT_TYPE, or Zend_Db::FLOAT_TYPE. 0052 * 0053 * Values are: 0054 * 0 = 32-bit integer 0055 * 1 = 64-bit integer 0056 * 2 = float or decimal 0057 * 0058 * @var array Associative array of datatypes to values 0, 1, or 2. 0059 */ 0060 protected $_numericDataTypes = array( 0061 Zend_Db::INT_TYPE => Zend_Db::INT_TYPE, 0062 Zend_Db::BIGINT_TYPE => Zend_Db::BIGINT_TYPE, 0063 Zend_Db::FLOAT_TYPE => Zend_Db::FLOAT_TYPE, 0064 'INT' => Zend_Db::INT_TYPE, 0065 'INTEGER' => Zend_Db::INT_TYPE, 0066 'MEDIUMINT' => Zend_Db::INT_TYPE, 0067 'SMALLINT' => Zend_Db::INT_TYPE, 0068 'TINYINT' => Zend_Db::INT_TYPE, 0069 'BIGINT' => Zend_Db::BIGINT_TYPE, 0070 'SERIAL' => Zend_Db::BIGINT_TYPE, 0071 'DEC' => Zend_Db::FLOAT_TYPE, 0072 'DECIMAL' => Zend_Db::FLOAT_TYPE, 0073 'DOUBLE' => Zend_Db::FLOAT_TYPE, 0074 'DOUBLE PRECISION' => Zend_Db::FLOAT_TYPE, 0075 'FIXED' => Zend_Db::FLOAT_TYPE, 0076 'FLOAT' => Zend_Db::FLOAT_TYPE 0077 ); 0078 0079 /** 0080 * Override _dsn() and ensure that charset is incorporated in mysql 0081 * @see Zend_Db_Adapter_Pdo_Abstract::_dsn() 0082 */ 0083 protected function _dsn() 0084 { 0085 $dsn = parent::_dsn(); 0086 if (isset($this->_config['charset'])) { 0087 $dsn .= ';charset=' . $this->_config['charset']; 0088 } 0089 return $dsn; 0090 } 0091 0092 /** 0093 * Creates a PDO object and connects to the database. 0094 * 0095 * @return void 0096 * @throws Zend_Db_Adapter_Exception 0097 */ 0098 protected function _connect() 0099 { 0100 if ($this->_connection) { 0101 return; 0102 } 0103 0104 if (!empty($this->_config['charset']) 0105 && version_compare(PHP_VERSION, '5.3.6', '<') 0106 ) { 0107 $initCommand = "SET NAMES '" . $this->_config['charset'] . "'"; 0108 $this->_config['driver_options'][1002] = $initCommand; // 1002 = PDO::MYSQL_ATTR_INIT_COMMAND 0109 } 0110 0111 parent::_connect(); 0112 } 0113 0114 /** 0115 * @return string 0116 */ 0117 public function getQuoteIdentifierSymbol() 0118 { 0119 return "`"; 0120 } 0121 0122 /** 0123 * Returns a list of the tables in the database. 0124 * 0125 * @return array 0126 */ 0127 public function listTables() 0128 { 0129 return $this->fetchCol('SHOW TABLES'); 0130 } 0131 0132 /** 0133 * Returns the column descriptions for a table. 0134 * 0135 * The return value is an associative array keyed by the column name, 0136 * as returned by the RDBMS. 0137 * 0138 * The value of each array element is an associative array 0139 * with the following keys: 0140 * 0141 * SCHEMA_NAME => string; name of database or schema 0142 * TABLE_NAME => string; 0143 * COLUMN_NAME => string; column name 0144 * COLUMN_POSITION => number; ordinal position of column in table 0145 * DATA_TYPE => string; SQL datatype name of column 0146 * DEFAULT => string; default expression of column, null if none 0147 * NULLABLE => boolean; true if column can have nulls 0148 * LENGTH => number; length of CHAR/VARCHAR 0149 * SCALE => number; scale of NUMERIC/DECIMAL 0150 * PRECISION => number; precision of NUMERIC/DECIMAL 0151 * UNSIGNED => boolean; unsigned property of an integer type 0152 * PRIMARY => boolean; true if column is part of the primary key 0153 * PRIMARY_POSITION => integer; position of column in primary key 0154 * IDENTITY => integer; true if column is auto-generated with unique values 0155 * 0156 * @param string $tableName 0157 * @param string $schemaName OPTIONAL 0158 * @return array 0159 */ 0160 public function describeTable($tableName, $schemaName = null) 0161 { 0162 // @todo use INFORMATION_SCHEMA someday when MySQL's 0163 // implementation has reasonably good performance and 0164 // the version with this improvement is in wide use. 0165 0166 if ($schemaName) { 0167 $sql = 'DESCRIBE ' . $this->quoteIdentifier("$schemaName.$tableName", true); 0168 } else { 0169 $sql = 'DESCRIBE ' . $this->quoteIdentifier($tableName, true); 0170 } 0171 $stmt = $this->query($sql); 0172 0173 // Use FETCH_NUM so we are not dependent on the CASE attribute of the PDO connection 0174 $result = $stmt->fetchAll(Zend_Db::FETCH_NUM); 0175 0176 $field = 0; 0177 $type = 1; 0178 $null = 2; 0179 $key = 3; 0180 $default = 4; 0181 $extra = 5; 0182 0183 $desc = array(); 0184 $i = 1; 0185 $p = 1; 0186 foreach ($result as $row) { 0187 list($length, $scale, $precision, $unsigned, $primary, $primaryPosition, $identity) 0188 = array(null, null, null, null, false, null, false); 0189 if (preg_match('/unsigned/', $row[$type])) { 0190 $unsigned = true; 0191 } 0192 if (preg_match('/^((?:var)?char)\((\d+)\)/', $row[$type], $matches)) { 0193 $row[$type] = $matches[1]; 0194 $length = $matches[2]; 0195 } else if (preg_match('/^decimal\((\d+),(\d+)\)/', $row[$type], $matches)) { 0196 $row[$type] = 'decimal'; 0197 $precision = $matches[1]; 0198 $scale = $matches[2]; 0199 } else if (preg_match('/^float\((\d+),(\d+)\)/', $row[$type], $matches)) { 0200 $row[$type] = 'float'; 0201 $precision = $matches[1]; 0202 $scale = $matches[2]; 0203 } else if (preg_match('/^((?:big|medium|small|tiny)?int)\((\d+)\)/', $row[$type], $matches)) { 0204 $row[$type] = $matches[1]; 0205 // The optional argument of a MySQL int type is not precision 0206 // or length; it is only a hint for display width. 0207 } 0208 if (strtoupper($row[$key]) == 'PRI') { 0209 $primary = true; 0210 $primaryPosition = $p; 0211 if ($row[$extra] == 'auto_increment') { 0212 $identity = true; 0213 } else { 0214 $identity = false; 0215 } 0216 ++$p; 0217 } 0218 $desc[$this->foldCase($row[$field])] = array( 0219 'SCHEMA_NAME' => null, // @todo 0220 'TABLE_NAME' => $this->foldCase($tableName), 0221 'COLUMN_NAME' => $this->foldCase($row[$field]), 0222 'COLUMN_POSITION' => $i, 0223 'DATA_TYPE' => $row[$type], 0224 'DEFAULT' => $row[$default], 0225 'NULLABLE' => (bool) ($row[$null] == 'YES'), 0226 'LENGTH' => $length, 0227 'SCALE' => $scale, 0228 'PRECISION' => $precision, 0229 'UNSIGNED' => $unsigned, 0230 'PRIMARY' => $primary, 0231 'PRIMARY_POSITION' => $primaryPosition, 0232 'IDENTITY' => $identity 0233 ); 0234 ++$i; 0235 } 0236 return $desc; 0237 } 0238 0239 /** 0240 * Adds an adapter-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 } 0256 0257 $offset = intval($offset); 0258 if ($offset < 0) { 0259 /** @see Zend_Db_Adapter_Exception */ 0260 // require_once 'Zend/Db/Adapter/Exception.php'; 0261 throw new Zend_Db_Adapter_Exception("LIMIT argument offset=$offset is not valid"); 0262 } 0263 0264 $sql .= " LIMIT $count"; 0265 if ($offset > 0) { 0266 $sql .= " OFFSET $offset"; 0267 } 0268 0269 return $sql; 0270 } 0271 0272 }