| /** | |
| * Zend Framework | |
| * | |
| * LICENSE | |
| * | |
| * This source file is subject to the new BSD license that is bundled | |
| * with this package in the file LICENSE.txt. | |
| * It is also available through the world-wide-web at this URL: | |
| * http://framework.zend.com/license/new-bsd | |
| * If you did not receive a copy of the license and are unable to | |
| * obtain it through the world-wide-web, please send an email | |
| * to license@zend.com so we can send you a copy immediately. | |
| * | |
| * @category Zend | |
| * @package Zend_Db | |
| * @subpackage Adapter | |
| * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) | |
| * @license http://framework.zend.com/license/new-bsd New BSD License | |
| * @version $Id: Abstract.php 24148 2011-06-21 15:14:00Z yoshida@zend.co.jp $ | |
| */ | |
| /** | |
| * @see Zend_Db | |
| */ | |
| // require_once 'Zend/Db.php'; | |
| /** | |
| * @see Zend_Db_Select | |
| */ | |
| // require_once 'Zend/Db/Select.php'; | |
| /** | |
| * Class for connecting to SQL databases and performing common operations. | |
| * | |
| * @category Zend | |
| * @package Zend_Db | |
| * @subpackage Adapter | |
| * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) | |
| * @license http://framework.zend.com/license/new-bsd New BSD License | |
| */ | |
| abstract class Zend_Db_Adapter_Abstract | |
| { | |
| /** | |
| * User-provided configuration | |
| * | |
| * @var array | |
| */ | |
| protected $_config = array(); | |
| /** | |
| * Fetch mode | |
| * | |
| * @var integer | |
| */ | |
| protected $_fetchMode = Zend_Db::FETCH_ASSOC; | |
| /** | |
| * Query profiler object, of type Zend_Db_Profiler | |
| * or a subclass of that. | |
| * | |
| * @var Zend_Db_Profiler | |
| */ | |
| protected $_profiler; | |
| /** | |
| * Default class name for a DB statement. | |
| * | |
| * @var string | |
| */ | |
| protected $_defaultStmtClass = 'Zend_Db_Statement'; | |
| /** | |
| * Default class name for the profiler object. | |
| * | |
| * @var string | |
| */ | |
| protected $_defaultProfilerClass = 'Zend_Db_Profiler'; | |
| /** | |
| * Database connection | |
| * | |
| * @var object|resource|null | |
| */ | |
| protected $_connection = null; | |
| /** | |
| * Specifies the case of column names retrieved in queries | |
| * Options | |
| * Zend_Db::CASE_NATURAL (default) | |
| * Zend_Db::CASE_LOWER | |
| * Zend_Db::CASE_UPPER | |
| * | |
| * @var integer | |
| */ | |
| protected $_caseFolding = Zend_Db::CASE_NATURAL; | |
| /** | |
| * Specifies whether the adapter automatically quotes identifiers. | |
| * If true, most SQL generated by Zend_Db classes applies | |
| * identifier quoting automatically. | |
| * If false, developer must quote identifiers themselves | |
| * by calling quoteIdentifier(). | |
| * | |
| * @var bool | |
| */ | |
| protected $_autoQuoteIdentifiers = true; | |
| /** | |
| * Keys are UPPERCASE SQL datatypes or the constants | |
| * Zend_Db::INT_TYPE, Zend_Db::BIGINT_TYPE, or Zend_Db::FLOAT_TYPE. | |
| * | |
| * Values are: | |
| * 0 = 32-bit integer | |
| * 1 = 64-bit integer | |
| * 2 = float or decimal | |
| * | |
| * @var array Associative array of datatypes to values 0, 1, or 2. | |
| */ | |
| protected $_numericDataTypes = array( | |
| Zend_Db::INT_TYPE => Zend_Db::INT_TYPE, | |
| Zend_Db::BIGINT_TYPE => Zend_Db::BIGINT_TYPE, | |
| Zend_Db::FLOAT_TYPE => Zend_Db::FLOAT_TYPE | |
| ); | |
| /** Weither or not that object can get serialized | |
| * | |
| * @var bool | |
| */ | |
| protected $_allowSerialization = true; | |
| /** | |
| * Weither or not the database should be reconnected | |
| * to that adapter when waking up | |
| * | |
| * @var bool | |
| */ | |
| protected $_autoReconnectOnUnserialize = false; | |
| /** | |
| * Constructor. | |
| * | |
| * $config is an array of key/value pairs or an instance of Zend_Config | |
| * containing configuration options. These options are common to most adapters: | |
| * | |
| * dbname => (string) The name of the database to user | |
| * username => (string) Connect to the database as this username. | |
| * password => (string) Password associated with the username. | |
| * host => (string) What host to connect to, defaults to localhost | |
| * | |
| * Some options are used on a case-by-case basis by adapters: | |
| * | |
| * port => (string) The port of the database | |
| * persistent => (boolean) Whether to use a persistent connection or not, defaults to false | |
| * protocol => (string) The network protocol, defaults to TCPIP | |
| * caseFolding => (int) style of case-alteration used for identifiers | |
| * | |
| * @param array|Zend_Config $config An array or instance of Zend_Config having configuration data | |
| * @throws Zend_Db_Adapter_Exception | |
| */ | |
| public function __construct( | |
| #[\SensitiveParameter] | |
| $config | |
| ) { | |
| /* | |
| * Verify that adapter parameters are in an array. | |
| */ | |
| if (!is_array($config)) { | |
| /* | |
| * Convert Zend_Config argument to a plain array. | |
| */ | |
| if ($config instanceof Zend_Config) { | |
| $config = $config->toArray(); | |
| } else { | |
| /** | |
| * @see Zend_Db_Adapter_Exception | |
| */ | |
| // require_once 'Zend/Db/Adapter/Exception.php'; | |
| throw new Zend_Db_Adapter_Exception('Adapter parameters must be in an array or a Zend_Config object'); | |
| } | |
| } | |
| $this->_checkRequiredOptions($config); | |
| $options = array( | |
| Zend_Db::CASE_FOLDING => $this->_caseFolding, | |
| Zend_Db::AUTO_QUOTE_IDENTIFIERS => $this->_autoQuoteIdentifiers, | |
| Zend_Db::FETCH_MODE => $this->_fetchMode, | |
| ); | |
| $driverOptions = array(); | |
| /* | |
| * normalize the config and merge it with the defaults | |
| */ | |
| if (array_key_exists('options', $config)) { | |
| // can't use array_merge() because keys might be integers | |
| foreach ((array) $config['options'] as $key => $value) { | |
| $options[$key] = $value; | |
| } | |
| } | |
| if (array_key_exists('driver_options', $config)) { | |
| if (!empty($config['driver_options'])) { | |
| // can't use array_merge() because keys might be integers | |
| foreach ((array) $config['driver_options'] as $key => $value) { | |
| $driverOptions[$key] = $value; | |
| } | |
| } | |
| } | |
| if (!isset($config['charset'])) { | |
| $config['charset'] = null; | |
| } | |
| if (!isset($config['persistent'])) { | |
| $config['persistent'] = false; | |
| } | |
| $this->_config = array_merge($this->_config, $config); | |
| $this->_config['options'] = $options; | |
| $this->_config['driver_options'] = $driverOptions; | |
| // obtain the case setting, if there is one | |
| if (array_key_exists(Zend_Db::CASE_FOLDING, $options)) { | |
| $case = (int) $options[Zend_Db::CASE_FOLDING]; | |
| switch ($case) { | |
| case Zend_Db::CASE_LOWER: | |
| case Zend_Db::CASE_UPPER: | |
| case Zend_Db::CASE_NATURAL: | |
| $this->_caseFolding = $case; | |
| break; | |
| default: | |
| /** @see Zend_Db_Adapter_Exception */ | |
| // require_once 'Zend/Db/Adapter/Exception.php'; | |
| throw new Zend_Db_Adapter_Exception('Case must be one of the following constants: ' | |
| . 'Zend_Db::CASE_NATURAL, Zend_Db::CASE_LOWER, Zend_Db::CASE_UPPER'); | |
| } | |
| } | |
| if (array_key_exists(Zend_Db::FETCH_MODE, $options)) { | |
| if (is_string($options[Zend_Db::FETCH_MODE])) { | |
| $constant = 'Zend_Db::FETCH_' . strtoupper($options[Zend_Db::FETCH_MODE]); | |
| if(defined($constant)) { | |
| $options[Zend_Db::FETCH_MODE] = constant($constant); | |
| } | |
| } | |
| $this->setFetchMode((int) $options[Zend_Db::FETCH_MODE]); | |
| } | |
| // obtain quoting property if there is one | |
| if (array_key_exists(Zend_Db::AUTO_QUOTE_IDENTIFIERS, $options)) { | |
| $this->_autoQuoteIdentifiers = (bool) $options[Zend_Db::AUTO_QUOTE_IDENTIFIERS]; | |
| } | |
| // obtain allow serialization property if there is one | |
| if (array_key_exists(Zend_Db::ALLOW_SERIALIZATION, $options)) { | |
| $this->_allowSerialization = (bool) $options[Zend_Db::ALLOW_SERIALIZATION]; | |
| } | |
| // obtain auto reconnect on unserialize property if there is one | |
| if (array_key_exists(Zend_Db::AUTO_RECONNECT_ON_UNSERIALIZE, $options)) { | |
| $this->_autoReconnectOnUnserialize = (bool) $options[Zend_Db::AUTO_RECONNECT_ON_UNSERIALIZE]; | |
| } | |
| // create a profiler object | |
| $profiler = false; | |
| if (array_key_exists(Zend_Db::PROFILER, $this->_config)) { | |
| $profiler = $this->_config[Zend_Db::PROFILER]; | |
| unset($this->_config[Zend_Db::PROFILER]); | |
| } | |
| $this->setProfiler($profiler); | |
| } | |
| /** | |
| * Check for config options that are mandatory. | |
| * Throw exceptions if any are missing. | |
| * | |
| * @param array $config | |
| * @throws Zend_Db_Adapter_Exception | |
| */ | |
| protected function _checkRequiredOptions( | |
| #[\SensitiveParameter] | |
| array $config | |
| ) { | |
| // we need at least a dbname | |
| if (! array_key_exists('dbname', $config)) { | |
| /** @see Zend_Db_Adapter_Exception */ | |
| // require_once 'Zend/Db/Adapter/Exception.php'; | |
| throw new Zend_Db_Adapter_Exception("Configuration array must have a key for 'dbname' that names the database instance"); | |
| } | |
| if (! array_key_exists('password', $config)) { | |
| /** | |
| * @see Zend_Db_Adapter_Exception | |
| */ | |
| // require_once 'Zend/Db/Adapter/Exception.php'; | |
| throw new Zend_Db_Adapter_Exception("Configuration array must have a key for 'password' for login credentials"); | |
| } | |
| if (! array_key_exists('username', $config)) { | |
| /** | |
| * @see Zend_Db_Adapter_Exception | |
| */ | |
| // require_once 'Zend/Db/Adapter/Exception.php'; | |
| throw new Zend_Db_Adapter_Exception("Configuration array must have a key for 'username' for login credentials"); | |
| } | |
| } | |
| /** | |
| * Returns the underlying database connection object or resource. | |
| * If not presently connected, this initiates the connection. | |
| * | |
| * @return object|resource|null | |
| */ | |
| public function getConnection() | |
| { | |
| $this->_connect(); | |
| return $this->_connection; | |
| } | |
| /** | |
| * Returns the configuration variables in this adapter. | |
| * | |
| * @return array | |
| */ | |
| public function getConfig() | |
| { | |
| return $this->_config; | |
| } | |
| /** | |
| * Set the adapter's profiler object. | |
| * | |
| * The argument may be a boolean, an associative array, an instance of | |
| * Zend_Db_Profiler, or an instance of Zend_Config. | |
| * | |
| * A boolean argument sets the profiler to enabled if true, or disabled if | |
| * false. The profiler class is the adapter's default profiler class, | |
| * Zend_Db_Profiler. | |
| * | |
| * An instance of Zend_Db_Profiler sets the adapter's instance to that | |
| * object. The profiler is enabled and disabled separately. | |
| * | |
| * An associative array argument may contain any of the keys 'enabled', | |
| * 'class', and 'instance'. The 'enabled' and 'instance' keys correspond to the | |
| * boolean and object types documented above. The 'class' key is used to name a | |
| * class to use for a custom profiler. The class must be Zend_Db_Profiler or a | |
| * subclass. The class is instantiated with no constructor arguments. The 'class' | |
| * option is ignored when the 'instance' option is supplied. | |
| * | |
| * An object of type Zend_Config may contain the properties 'enabled', 'class', and | |
| * 'instance', just as if an associative array had been passed instead. | |
| * | |
| * @param Zend_Db_Profiler|Zend_Config|array|boolean $profiler | |
| * @return Zend_Db_Adapter_Abstract Provides a fluent interface | |
| * @throws Zend_Db_Profiler_Exception if the object instance or class specified | |
| * is not Zend_Db_Profiler or an extension of that class. | |
| */ | |
| public function setProfiler($profiler) | |
| { | |
| $enabled = null; | |
| $profilerClass = $this->_defaultProfilerClass; | |
| $profilerInstance = null; | |
| if ($profilerIsObject = is_object($profiler)) { | |
| if ($profiler instanceof Zend_Db_Profiler) { | |
| $profilerInstance = $profiler; | |
| } else if ($profiler instanceof Zend_Config) { | |
| $profiler = $profiler->toArray(); | |
| } else { | |
| /** | |
| * @see Zend_Db_Profiler_Exception | |
| */ | |
| // require_once 'Zend/Db/Profiler/Exception.php'; | |
| throw new Zend_Db_Profiler_Exception('Profiler argument must be an instance of either Zend_Db_Profiler' | |
| . ' or Zend_Config when provided as an object'); | |
| } | |
| } | |
| if (is_array($profiler)) { | |
| if (isset($profiler['enabled'])) { | |
| $enabled = (bool) $profiler['enabled']; | |
| } | |
| if (isset($profiler['class'])) { | |
| $profilerClass = $profiler['class']; | |
| } | |
| if (isset($profiler['instance'])) { | |
| $profilerInstance = $profiler['instance']; | |
| } | |
| } else if (!$profilerIsObject) { | |
| $enabled = (bool) $profiler; | |
| } | |
| if ($profilerInstance === null) { | |
| if (!class_exists($profilerClass)) { | |
| // require_once 'Zend/Loader.php'; | |
| Zend_Loader::loadClass($profilerClass); | |
| } | |
| $profilerInstance = new $profilerClass(); | |
| } | |
| if (!$profilerInstance instanceof Zend_Db_Profiler) { | |
| /** @see Zend_Db_Profiler_Exception */ | |
| // require_once 'Zend/Db/Profiler/Exception.php'; | |
| throw new Zend_Db_Profiler_Exception('Class ' . get_class($profilerInstance) . ' does not extend ' | |
| . 'Zend_Db_Profiler'); | |
| } | |
| if (null !== $enabled) { | |
| $profilerInstance->setEnabled($enabled); | |
| } | |
| $this->_profiler = $profilerInstance; | |
| return $this; | |
| } | |
| /** | |
| * Returns the profiler for this adapter. | |
| * | |
| * @return Zend_Db_Profiler | |
| */ | |
| public function getProfiler() | |
| { | |
| return $this->_profiler; | |
| } | |
| /** | |
| * Get the default statement class. | |
| * | |
| * @return string | |
| */ | |
| public function getStatementClass() | |
| { | |
| return $this->_defaultStmtClass; | |
| } | |
| /** | |
| * Set the default statement class. | |
| * | |
| * @return Zend_Db_Adapter_Abstract Fluent interface | |
| */ | |
| public function setStatementClass($class) | |
| { | |
| $this->_defaultStmtClass = $class; | |
| return $this; | |
| } | |
| /** | |
| * Prepares and executes an SQL statement with bound data. | |
| * | |
| * @param mixed $sql The SQL statement with placeholders. | |
| * May be a string or Zend_Db_Select. | |
| * @param mixed $bind An array of data to bind to the placeholders. | |
| * @return Zend_Db_Statement_Interface | |
| */ | |
| public function query($sql, $bind = array()) | |
| { | |
| // connect to the database if needed | |
| $this->_connect(); | |
| // is the $sql a Zend_Db_Select object? | |
| if ($sql instanceof Zend_Db_Select) { | |
| if (empty($bind)) { | |
| $bind = $sql->getBind(); | |
| } | |
| $sql = $sql->assemble(); | |
| } | |
| // make sure $bind to an array; | |
| // don't use (array) typecasting because | |
| // because $bind may be a Zend_Db_Expr object | |
| if (!is_array($bind)) { | |
| $bind = array($bind); | |
| } | |
| // prepare and execute the statement with profiling | |
| $stmt = $this->prepare($sql); | |
| $stmt->execute($bind); | |
| // return the results embedded in the prepared statement object | |
| $stmt->setFetchMode($this->_fetchMode); | |
| return $stmt; | |
| } | |
| /** | |
| * Leave autocommit mode and begin a transaction. | |
| * | |
| * @return Zend_Db_Adapter_Abstract | |
| */ | |
| public function beginTransaction() | |
| { | |
| $this->_connect(); | |
| $q = $this->_profiler->queryStart('begin', Zend_Db_Profiler::TRANSACTION); | |
| $this->_beginTransaction(); | |
| $this->_profiler->queryEnd($q); | |
| return $this; | |
| } | |
| /** | |
| * Commit a transaction and return to autocommit mode. | |
| * | |
| * @return Zend_Db_Adapter_Abstract | |
| */ | |
| public function commit() | |
| { | |
| $this->_connect(); | |
| $q = $this->_profiler->queryStart('commit', Zend_Db_Profiler::TRANSACTION); | |
| $this->_commit(); | |
| $this->_profiler->queryEnd($q); | |
| return $this; | |
| } | |
| /** | |
| * Roll back a transaction and return to autocommit mode. | |
| * | |
| * @return Zend_Db_Adapter_Abstract | |
| */ | |
| public function rollBack() | |
| { | |
| $this->_connect(); | |
| $q = $this->_profiler->queryStart('rollback', Zend_Db_Profiler::TRANSACTION); | |
| $this->_rollBack(); | |
| $this->_profiler->queryEnd($q); | |
| return $this; | |
| } | |
| /** | |
| * Inserts a table row with specified data. | |
| * | |
| * @param mixed $table The table to insert data into. | |
| * @param array $bind Column-value pairs. | |
| * @return int The number of affected rows. | |
| * @throws Zend_Db_Adapter_Exception | |
| */ | |
| public function insert($table, array $bind) | |
| { | |
| // extract and quote col names from the array keys | |
| $cols = array(); | |
| $vals = array(); | |
| $i = 0; | |
| foreach ($bind as $col => $val) { | |
| $cols[] = $this->quoteIdentifier($col, true); | |
| if ($val instanceof Zend_Db_Expr) { | |
| $vals[] = $val->__toString(); | |
| unset($bind[$col]); | |
| } else { | |
| if ($this->supportsParameters('positional')) { | |
| $vals[] = '?'; | |
| } else { | |
| if ($this->supportsParameters('named')) { | |
| unset($bind[$col]); | |
| $bind[':col'.$i] = $val; | |
| $vals[] = ':col'.$i; | |
| $i++; | |
| } else { | |
| /** @see Zend_Db_Adapter_Exception */ | |
| // require_once 'Zend/Db/Adapter/Exception.php'; | |
| throw new Zend_Db_Adapter_Exception(get_class($this) ." doesn't support positional or named binding"); | |
| } | |
| } | |
| } | |
| } | |
| // build the statement | |
| $sql = "INSERT INTO " | |
| . $this->quoteIdentifier($table, true) | |
| . ' (' . implode(', ', $cols) . ') ' | |
| . 'VALUES (' . implode(', ', $vals) . ')'; | |
| // execute the statement and return the number of affected rows | |
| if ($this->supportsParameters('positional')) { | |
| $bind = array_values($bind); | |
| } | |
| $stmt = $this->query($sql, $bind); | |
| $result = $stmt->rowCount(); | |
| return $result; | |
| } | |
| /** | |
| * Updates table rows with specified data based on a WHERE clause. | |
| * | |
| * @param mixed $table The table to update. | |
| * @param array $bind Column-value pairs. | |
| * @param mixed $where UPDATE WHERE clause(s). | |
| * @return int The number of affected rows. | |
| * @throws Zend_Db_Adapter_Exception | |
| */ | |
| public function update($table, array $bind, $where = '') | |
| { | |
| /** | |
| * Build "col = ?" pairs for the statement, | |
| * except for Zend_Db_Expr which is treated literally. | |
| */ | |
| $set = array(); | |
| $i = 0; | |
| foreach ($bind as $col => $val) { | |
| if ($val instanceof Zend_Db_Expr) { | |
| $val = $val->__toString(); | |
| unset($bind[$col]); | |
| } else { | |
| if ($this->supportsParameters('positional')) { | |
| $val = '?'; | |
| } else { | |
| if ($this->supportsParameters('named')) { | |
| unset($bind[$col]); | |
| $bind[':col'.$i] = $val; | |
| $val = ':col'.$i; | |
| $i++; | |
| } else { | |
| /** @see Zend_Db_Adapter_Exception */ | |
| // require_once 'Zend/Db/Adapter/Exception.php'; | |
| throw new Zend_Db_Adapter_Exception(get_class($this) ." doesn't support positional or named binding"); | |
| } | |
| } | |
| } | |
| $set[] = $this->quoteIdentifier($col, true) . ' = ' . $val; | |
| } | |
| $where = $this->_whereExpr($where); | |
| /** | |
| * Build the UPDATE statement | |
| */ | |
| $sql = "UPDATE " | |
| . $this->quoteIdentifier($table, true) | |
| . ' SET ' . implode(', ', $set) | |
| . (($where) ? " WHERE $where" : ''); | |
| /** | |
| * Execute the statement and return the number of affected rows | |
| */ | |
| if ($this->supportsParameters('positional')) { | |
| $stmt = $this->query($sql, array_values($bind)); | |
| } else { | |
| $stmt = $this->query($sql, $bind); | |
| } | |
| $result = $stmt->rowCount(); | |
| return $result; | |
| } | |
| /** | |
| * Deletes table rows based on a WHERE clause. | |
| * | |
| * @param mixed $table The table to update. | |
| * @param mixed $where DELETE WHERE clause(s). | |
| * @return int The number of affected rows. | |
| */ | |
| public function delete($table, $where = '') | |
| { | |
| $where = $this->_whereExpr($where); | |
| /** | |
| * Build the DELETE statement | |
| */ | |
| $sql = "DELETE FROM " | |
| . $this->quoteIdentifier($table, true) | |
| . (($where) ? " WHERE $where" : ''); | |
| /** | |
| * Execute the statement and return the number of affected rows | |
| */ | |
| $stmt = $this->query($sql); | |
| $result = $stmt->rowCount(); | |
| return $result; | |
| } | |
| /** | |
| * Convert an array, string, or Zend_Db_Expr object | |
| * into a string to put in a WHERE clause. | |
| * | |
| * @param mixed $where | |
| * @return string | |
| */ | |
| protected function _whereExpr($where) | |
| { | |
| if (empty($where)) { | |
| return $where; | |
| } | |
| if (!is_array($where)) { | |
| $where = array($where); | |
| } | |
| foreach ($where as $cond => &$term) { | |
| // is $cond an int? (i.e. Not a condition) | |
| if (is_int($cond)) { | |
| // $term is the full condition | |
| if ($term instanceof Zend_Db_Expr) { | |
| $term = $term->__toString(); | |
| } | |
| } else { | |
| // $cond is the condition with placeholder, | |
| // and $term is quoted into the condition | |
| $term = $this->quoteInto($cond, $term); | |
| } | |
| $term = '(' . $term . ')'; | |
| } | |
| $where = implode(' AND ', $where); | |
| return $where; | |
| } | |
| /** | |
| * Creates and returns a new Zend_Db_Select object for this adapter. | |
| * | |
| * @return Zend_Db_Select | |
| */ | |
| public function select() | |
| { | |
| return new Zend_Db_Select($this); | |
| } | |
| /** | |
| * Get the fetch mode. | |
| * | |
| * @return int | |
| */ | |
| public function getFetchMode() | |
| { | |
| return $this->_fetchMode; | |
| } | |
| /** | |
| * Fetches all SQL result rows as a sequential array. | |
| * Uses the current fetchMode for the adapter. | |
| * | |
| * @param string|Zend_Db_Select $sql An SQL SELECT statement. | |
| * @param mixed $bind Data to bind into SELECT placeholders. | |
| * @param mixed $fetchMode Override current fetch mode. | |
| * @return array | |
| */ | |
| public function fetchAll($sql, $bind = array(), $fetchMode = null) | |
| { | |
| if ($fetchMode === null) { | |
| $fetchMode = $this->_fetchMode; | |
| } | |
| $stmt = $this->query($sql, $bind); | |
| $result = $stmt->fetchAll($fetchMode); | |
| return $result; | |
| } | |
| /** | |
| * Fetches the first row of the SQL result. | |
| * Uses the current fetchMode for the adapter. | |
| * | |
| * @param string|Zend_Db_Select $sql An SQL SELECT statement. | |
| * @param mixed $bind Data to bind into SELECT placeholders. | |
| * @param mixed $fetchMode Override current fetch mode. | |
| * @return array | |
| */ | |
| public function fetchRow($sql, $bind = array(), $fetchMode = null) | |
| { | |
| if ($fetchMode === null) { | |
| $fetchMode = $this->_fetchMode; | |
| } | |
| $stmt = $this->query($sql, $bind); | |
| $result = $stmt->fetch($fetchMode); | |
| return $result; | |
| } | |
| /** | |
| * Fetches all SQL result rows as an associative array. | |
| * | |
| * The first column is the key, the entire row array is the | |
| * value. You should construct the query to be sure that | |
| * the first column contains unique values, or else | |
| * rows with duplicate values in the first column will | |
| * overwrite previous data. | |
| * | |
| * @param string|Zend_Db_Select $sql An SQL SELECT statement. | |
| * @param mixed $bind Data to bind into SELECT placeholders. | |
| * @return array | |
| */ | |
| public function fetchAssoc($sql, $bind = array()) | |
| { | |
| $stmt = $this->query($sql, $bind); | |
| $data = array(); | |
| while ($row = $stmt->fetch(Zend_Db::FETCH_ASSOC)) { | |
| $tmp = array_values(array_slice($row, 0, 1)); | |
| $data[$tmp[0]] = $row; | |
| } | |
| return $data; | |
| } | |
| /** | |
| * Fetches the first column of all SQL result rows as an array. | |
| * | |
| * @param string|Zend_Db_Select $sql An SQL SELECT statement. | |
| * @param mixed $bind Data to bind into SELECT placeholders. | |
| * @return array | |
| */ | |
| public function fetchCol($sql, $bind = array()) | |
| { | |
| $stmt = $this->query($sql, $bind); | |
| $result = $stmt->fetchAll(Zend_Db::FETCH_COLUMN, 0); | |
| return $result; | |
| } | |
| /** | |
| * Fetches all SQL result rows as an array of key-value pairs. | |
| * | |
| * The first column is the key, the second column is the | |
| * value. | |
| * | |
| * @param string|Zend_Db_Select $sql An SQL SELECT statement. | |
| * @param mixed $bind Data to bind into SELECT placeholders. | |
| * @return array | |
| */ | |
| public function fetchPairs($sql, $bind = array()) | |
| { | |
| $stmt = $this->query($sql, $bind); | |
| $data = array(); | |
| while ($row = $stmt->fetch(Zend_Db::FETCH_NUM)) { | |
| $data[$row[0]] = $row[1]; | |
| } | |
| return $data; | |
| } | |
| /** | |
| * Fetches the first column of the first row of the SQL result. | |
| * | |
| * @param string|Zend_Db_Select $sql An SQL SELECT statement. | |
| * @param mixed $bind Data to bind into SELECT placeholders. | |
| * @return string | |
| */ | |
| public function fetchOne($sql, $bind = array()) | |
| { | |
| $stmt = $this->query($sql, $bind); | |
| $result = $stmt->fetchColumn(0); | |
| return $result; | |
| } | |
| /** | |
| * Quote a raw string. | |
| * | |
| * @param string $value Raw string | |
| * @return string Quoted string | |
| */ | |
| protected function _quote($value) | |
| { | |
| if (is_int($value)) { | |
| return $value; | |
| } elseif (is_float($value)) { | |
| return sprintf('%F', $value); | |
| } | |
| return "'" . addcslashes($value, "\000\n\r\\'\"\032") . "'"; | |
| } | |
| /** | |
| * Safely quotes a value for an SQL statement. | |
| * | |
| * If an array is passed as the value, the array values are quoted | |
| * and then returned as a comma-separated string. | |
| * | |
| * @param mixed $value The value to quote. | |
| * @param mixed $type OPTIONAL the SQL datatype name, or constant, or null. | |
| * @return mixed An SQL-safe quoted value (or string of separated values). | |
| */ | |
| public function quote($value, $type = null) | |
| { | |
| $this->_connect(); | |
| if ($value instanceof Zend_Db_Select) { | |
| return '(' . $value->assemble() . ')'; | |
| } | |
| if ($value instanceof Zend_Db_Expr) { | |
| return $value->__toString(); | |
| } | |
| if (is_array($value)) { | |
| foreach ($value as &$val) { | |
| $val = $this->quote($val, $type); | |
| } | |
| return implode(', ', $value); | |
| } | |
| if ($type !== null && array_key_exists($type = strtoupper($type), $this->_numericDataTypes)) { | |
| $quotedValue = '0'; | |
| switch ($this->_numericDataTypes[$type]) { | |
| case Zend_Db::INT_TYPE: // 32-bit integer | |
| $quotedValue = (string) intval($value); | |
| break; | |
| case Zend_Db::BIGINT_TYPE: // 64-bit integer | |
| // ANSI SQL-style hex literals (e.g. x'[\dA-F]+') | |
| // are not supported here, because these are string | |
| // literals, not numeric literals. | |
| if (preg_match('/^( | |
| [+-]? # optional sign | |
| (?: | |
| 0[Xx][\da-fA-F]+ # ODBC-style hexadecimal | |
| |\d+ # decimal or octal, or MySQL ZEROFILL decimal | |
| (?:[eE][+-]?\d+)? # optional exponent on decimals or octals | |
| ) | |
| )/x', | |
| (string) $value, $matches)) { | |
| $quotedValue = $matches[1]; | |
| } | |
| break; | |
| case Zend_Db::FLOAT_TYPE: // float or decimal | |
| $quotedValue = sprintf('%F', $value); | |
| } | |
| return $quotedValue; | |
| } | |
| return $this->_quote($value); | |
| } | |
| /** | |
| * Quotes a value and places into a piece of text at a placeholder. | |
| * | |
| * The placeholder is a question-mark; all placeholders will be replaced | |
| * with the quoted value. For example: | |
| * | |
| * <code> | |
| * $text = "WHERE date < ?"; | |
| * $date = "2005-01-02"; | |
| * $safe = $sql->quoteInto($text, $date); | |
| * // $safe = "WHERE date < '2005-01-02'" | |
| * </code> | |
| * | |
| * @param string $text The text with a placeholder. | |
| * @param mixed $value The value to quote. | |
| * @param string $type OPTIONAL SQL datatype | |
| * @param integer $count OPTIONAL count of placeholders to replace | |
| * @return string An SQL-safe quoted value placed into the original text. | |
| */ | |
| public function quoteInto($text, $value, $type = null, $count = null) | |
| { | |
| if ($count === null) { | |
| return str_replace('?', $this->quote($value, $type), $text); | |
| } else { | |
| while ($count > 0) { | |
| if (strpos($text, '?') !== false) { | |
| $text = substr_replace($text, $this->quote($value, $type), strpos($text, '?'), 1); | |
| } | |
| --$count; | |
| } | |
| return $text; | |
| } | |
| } | |
| /** | |
| * Quotes an identifier. | |
| * | |
| * Accepts a string representing a qualified indentifier. For Example: | |
| * <code> | |
| * $adapter->quoteIdentifier('myschema.mytable') | |
| * </code> | |
| * Returns: "myschema"."mytable" | |
| * | |
| * Or, an array of one or more identifiers that may form a qualified identifier: | |
| * <code> | |
| * $adapter->quoteIdentifier(array('myschema','my.table')) | |
| * </code> | |
| * Returns: "myschema"."my.table" | |
| * | |
| * The actual quote character surrounding the identifiers may vary depending on | |
| * the adapter. | |
| * | |
| * @param string|array|Zend_Db_Expr $ident The identifier. | |
| * @param boolean $auto If true, heed the AUTO_QUOTE_IDENTIFIERS config option. | |
| * @return string The quoted identifier. | |
| */ | |
| public function quoteIdentifier($ident, $auto=false) | |
| { | |
| return $this->_quoteIdentifierAs($ident, null, $auto); | |
| } | |
| /** | |
| * Quote a column identifier and alias. | |
| * | |
| * @param string|array|Zend_Db_Expr $ident The identifier or expression. | |
| * @param string $alias An alias for the column. | |
| * @param boolean $auto If true, heed the AUTO_QUOTE_IDENTIFIERS config option. | |
| * @return string The quoted identifier and alias. | |
| */ | |
| public function quoteColumnAs($ident, $alias, $auto=false) | |
| { | |
| return $this->_quoteIdentifierAs($ident, $alias, $auto); | |
| } | |
| /** | |
| * Quote a table identifier and alias. | |
| * | |
| * @param string|array|Zend_Db_Expr $ident The identifier or expression. | |
| * @param string $alias An alias for the table. | |
| * @param boolean $auto If true, heed the AUTO_QUOTE_IDENTIFIERS config option. | |
| * @return string The quoted identifier and alias. | |
| */ | |
| public function quoteTableAs($ident, $alias = null, $auto = false) | |
| { | |
| return $this->_quoteIdentifierAs($ident, $alias, $auto); | |
| } | |
| /** | |
| * Quote an identifier and an optional alias. | |
| * | |
| * @param string|array|Zend_Db_Expr $ident The identifier or expression. | |
| * @param string $alias An optional alias. | |
| * @param boolean $auto If true, heed the AUTO_QUOTE_IDENTIFIERS config option. | |
| * @param string $as The string to add between the identifier/expression and the alias. | |
| * @return string The quoted identifier and alias. | |
| */ | |
| protected function _quoteIdentifierAs($ident, $alias = null, $auto = false, $as = ' AS ') | |
| { | |
| if ($ident instanceof Zend_Db_Expr) { | |
| $quoted = $ident->__toString(); | |
| } elseif ($ident instanceof Zend_Db_Select) { | |
| $quoted = '(' . $ident->assemble() . ')'; | |
| } else { | |
| if (is_string($ident)) { | |
| $ident = explode('.', $ident); | |
| } | |
| if (is_array($ident)) { | |
| $segments = array(); | |
| foreach ($ident as $segment) { | |
| if ($segment instanceof Zend_Db_Expr) { | |
| $segments[] = $segment->__toString(); | |
| } else { | |
| $segments[] = $this->_quoteIdentifier($segment, $auto); | |
| } | |
| } | |
| if ($alias !== null && end($ident) == $alias) { | |
| $alias = null; | |
| } | |
| $quoted = implode('.', $segments); | |
| } else { | |
| $quoted = $this->_quoteIdentifier($ident, $auto); | |
| } | |
| } | |
| if ($alias !== null) { | |
| $quoted .= $as . $this->_quoteIdentifier($alias, $auto); | |
| } | |
| return $quoted; | |
| } | |
| /** | |
| * Quote an identifier. | |
| * | |
| * @param string $value The identifier or expression. | |
| * @param boolean $auto If true, heed the AUTO_QUOTE_IDENTIFIERS config option. | |
| * @return string The quoted identifier and alias. | |
| */ | |
| protected function _quoteIdentifier($value, $auto=false) | |
| { | |
| if ($auto === false || $this->_autoQuoteIdentifiers === true) { | |
| $q = $this->getQuoteIdentifierSymbol(); | |
| return ($q . str_replace("$q", "$q$q", $value) . $q); | |
| } | |
| return $value; | |
| } | |
| /** | |
| * Returns the symbol the adapter uses for delimited identifiers. | |
| * | |
| * @return string | |
| */ | |
| public function getQuoteIdentifierSymbol() | |
| { | |
| return '"'; | |
| } | |
| /** | |
| * Return the most recent value from the specified sequence in the database. | |
| * This is supported only on RDBMS brands that support sequences | |
| * (e.g. Oracle, PostgreSQL, DB2). Other RDBMS brands return null. | |
| * | |
| * @param string $sequenceName | |
| * @return string | |
| */ | |
| public function lastSequenceId($sequenceName) | |
| { | |
| return null; | |
| } | |
| /** | |
| * Generate a new value from the specified sequence in the database, and return it. | |
| * This is supported only on RDBMS brands that support sequences | |
| * (e.g. Oracle, PostgreSQL, DB2). Other RDBMS brands return null. | |
| * | |
| * @param string $sequenceName | |
| * @return string | |
| */ | |
| public function nextSequenceId($sequenceName) | |
| { | |
| return null; | |
| } | |
| /** | |
| * Helper method to change the case of the strings used | |
| * when returning result sets in FETCH_ASSOC and FETCH_BOTH | |
| * modes. | |
| * | |
| * This is not intended to be used by application code, | |
| * but the method must be public so the Statement class | |
| * can invoke it. | |
| * | |
| * @param string $key | |
| * @return string | |
| */ | |
| public function foldCase($key) | |
| { | |
| switch ($this->_caseFolding) { | |
| case Zend_Db::CASE_LOWER: | |
| $value = strtolower((string) $key); | |
| break; | |
| case Zend_Db::CASE_UPPER: | |
| $value = strtoupper((string) $key); | |
| break; | |
| case Zend_Db::CASE_NATURAL: | |
| default: | |
| $value = (string) $key; | |
| } | |
| return $value; | |
| } | |
| /** | |
| * called when object is getting serialized | |
| * This disconnects the DB object that cant be serialized | |
| * | |
| * @throws Zend_Db_Adapter_Exception | |
| * @return array | |
| */ | |
| public function __sleep() | |
| { | |
| if ($this->_allowSerialization == false) { | |
| /** @see Zend_Db_Adapter_Exception */ | |
| // require_once 'Zend/Db/Adapter/Exception.php'; | |
| throw new Zend_Db_Adapter_Exception(get_class($this) ." is not allowed to be serialized"); | |
| } | |
| $this->_connection = false; | |
| return array_keys(array_diff_key(get_object_vars($this), array('_connection'=>false))); | |
| } | |
| /** | |
| * called when object is getting unserialized | |
| * | |
| * @return void | |
| */ | |
| public function __wakeup() | |
| { | |
| if ($this->_autoReconnectOnUnserialize == true) { | |
| $this->getConnection(); | |
| } | |
| } | |
| /** | |
| * Abstract Methods | |
| */ | |
| /** | |
| * Returns a list of the tables in the database. | |
| * | |
| * @return array | |
| */ | |
| abstract public function listTables(); | |
| /** | |
| * Returns the column descriptions for a table. | |
| * | |
| * The return value is an associative array keyed by the column name, | |
| * as returned by the RDBMS. | |
| * | |
| * The value of each array element is an associative array | |
| * with the following keys: | |
| * | |
| * SCHEMA_NAME => string; name of database or schema | |
| * TABLE_NAME => string; | |
| * COLUMN_NAME => string; column name | |
| * COLUMN_POSITION => number; ordinal position of column in table | |
| * DATA_TYPE => string; SQL datatype name of column | |
| * DEFAULT => string; default expression of column, null if none | |
| * NULLABLE => boolean; true if column can have nulls | |
| * LENGTH => number; length of CHAR/VARCHAR | |
| * SCALE => number; scale of NUMERIC/DECIMAL | |
| * PRECISION => number; precision of NUMERIC/DECIMAL | |
| * UNSIGNED => boolean; unsigned property of an integer type | |
| * PRIMARY => boolean; true if column is part of the primary key | |
| * PRIMARY_POSITION => integer; position of column in primary key | |
| * | |
| * @param string $tableName | |
| * @param string $schemaName OPTIONAL | |
| * @return array | |
| */ | |
| abstract public function describeTable($tableName, $schemaName = null); | |
| /** | |
| * Creates a connection to the database. | |
| * | |
| * @return void | |
| */ | |
| abstract protected function _connect(); | |
| /** | |
| * Test if a connection is active | |
| * | |
| * @return boolean | |
| */ | |
| abstract public function isConnected(); | |
| /** | |
| * Force the connection to close. | |
| * | |
| * @return void | |
| */ | |
| abstract public function closeConnection(); | |
| /** | |
| * Prepare a statement and return a PDOStatement-like object. | |
| * | |
| * @param string|Zend_Db_Select $sql SQL query | |
| * @return Zend_Db_Statement|PDOStatement | |
| */ | |
| abstract public function prepare($sql); | |
| /** | |
| * Gets the last ID generated automatically by an IDENTITY/AUTOINCREMENT column. | |
| * | |
| * As a convention, on RDBMS brands that support sequences | |
| * (e.g. Oracle, PostgreSQL, DB2), this method forms the name of a sequence | |
| * from the arguments and returns the last id generated by that sequence. | |
| * On RDBMS brands that support IDENTITY/AUTOINCREMENT columns, this method | |
| * returns the last value generated for such a column, and the table name | |
| * argument is disregarded. | |
| * | |
| * @param string $tableName OPTIONAL Name of table. | |
| * @param string $primaryKey OPTIONAL Name of primary key column. | |
| * @return string | |
| */ | |
| abstract public function lastInsertId($tableName = null, $primaryKey = null); | |
| /** | |
| * Begin a transaction. | |
| */ | |
| abstract protected function _beginTransaction(); | |
| /** | |
| * Commit a transaction. | |
| */ | |
| abstract protected function _commit(); | |
| /** | |
| * Roll-back a transaction. | |
| */ | |
| abstract protected function _rollBack(); | |
| /** | |
| * Set the fetch mode. | |
| * | |
| * @param integer $mode | |
| * @return void | |
| * @throws Zend_Db_Adapter_Exception | |
| */ | |
| abstract public function setFetchMode($mode); | |
| /** | |
| * Adds an adapter-specific LIMIT clause to the SELECT statement. | |
| * | |
| * @param mixed $sql | |
| * @param integer $count | |
| * @param integer $offset | |
| * @return string | |
| */ | |
| abstract public function limit($sql, $count, $offset = 0); | |
| /** | |
| * Check if the adapter supports real SQL parameters. | |
| * | |
| * @param string $type 'positional' or 'named' | |
| * @return bool | |
| */ | |
| abstract public function supportsParameters($type); | |
| /** | |
| * Retrieve server version in PHP style | |
| * | |
| * @return string | |
| */ | |
| abstract public function getServerVersion(); | |
| } | |