diff options
Diffstat (limited to 'system/database')
57 files changed, 6586 insertions, 6698 deletions
diff --git a/system/database/DB.php b/system/database/DB.php index ed6afd7ed..00d14b43e 100755..100644 --- a/system/database/DB.php +++ b/system/database/DB.php @@ -2,7 +2,7 @@ /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE * @@ -32,16 +32,16 @@ * @author EllisLab Dev Team * @link http://codeigniter.com/user_guide/database/ * @param string - * @param bool Determines if active record should be used or not + * @param bool Determines if query builder should be used or not */ -function &DB($params = '', $active_record_override = NULL) +function &DB($params = '', $query_builder_override = NULL) { // Load the DB config file if a DSN string wasn't passed - if (is_string($params) AND strpos($params, '://') === FALSE) + if (is_string($params) && strpos($params, '://') === FALSE) { // Is the config file in the environment folder? if (( ! defined('ENVIRONMENT') OR ! file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/database.php')) - AND ! file_exists($file_path = APPPATH.'config/database.php')) + && ! file_exists($file_path = APPPATH.'config/database.php')) { show_error('The configuration file database.php does not exist.'); } @@ -53,7 +53,7 @@ function &DB($params = '', $active_record_override = NULL) show_error('No database connection settings were found in the database config file.'); } - if ($params != '') + if ($params !== '') { $active_group = $params; } @@ -74,33 +74,30 @@ function &DB($params = '', $active_record_override = NULL) * parameter. DSNs must have this prototype: * $dsn = 'driver://username:password@hostname/database'; */ - if (($dns = @parse_url($params)) === FALSE) + if (($dsn = @parse_url($params)) === FALSE) { show_error('Invalid DB Connection String'); } $params = array( - 'dbdriver' => $dns['scheme'], - 'hostname' => (isset($dns['host'])) ? rawurldecode($dns['host']) : '', - 'username' => (isset($dns['user'])) ? rawurldecode($dns['user']) : '', - 'password' => (isset($dns['pass'])) ? rawurldecode($dns['pass']) : '', - 'database' => (isset($dns['path'])) ? rawurldecode(substr($dns['path'], 1)) : '' + 'dbdriver' => $dsn['scheme'], + 'hostname' => isset($dsn['host']) ? rawurldecode($dsn['host']) : '', + 'port' => isset($dsn['port']) ? rawurldecode($dsn['port']) : '', + 'username' => isset($dsn['user']) ? rawurldecode($dsn['user']) : '', + 'password' => isset($dsn['pass']) ? rawurldecode($dsn['pass']) : '', + 'database' => isset($dsn['path']) ? rawurldecode(substr($dsn['path'], 1)) : '' ); // were additional config items set? - if (isset($dns['query'])) + if (isset($dsn['query'])) { - parse_str($dns['query'], $extra); + parse_str($dsn['query'], $extra); + foreach ($extra as $key => $val) { - // booleans please - if (strtoupper($val) === 'TRUE') - { - $val = TRUE; - } - elseif (strtoupper($val) === 'FALSE') + if (is_string($val) && in_array(strtoupper($val), array('TRUE', 'FALSE', 'NULL'))) { - $val = FALSE; + $val = var_export($val); } $params[$key] = $val; @@ -109,27 +106,34 @@ function &DB($params = '', $active_record_override = NULL) } // No DB specified yet? Beat them senseless... - if ( ! isset($params['dbdriver']) OR $params['dbdriver'] == '') + if (empty($params['dbdriver'])) { show_error('You have not selected a database type to connect to.'); } - // Load the DB classes. Note: Since the active record class is optional + // Load the DB classes. Note: Since the query builder class is optional // we need to dynamically create a class that extends proper parent class - // based on whether we're using the active record class or not. - if ($active_record_override !== NULL) + // based on whether we're using the query builder class or not. + if ($query_builder_override !== NULL) { - $active_record = $active_record_override; + $query_builder = $query_builder_override; + } + // Backwards compatibility work-around for keeping the + // $active_record config variable working. Should be + // removed in v3.1 + elseif ( ! isset($query_builder) && isset($active_record)) + { + $query_builder = $active_record; } require_once(BASEPATH.'database/DB_driver.php'); - if ( ! isset($active_record) OR $active_record == TRUE) + if ( ! isset($query_builder) OR $query_builder === TRUE) { - require_once(BASEPATH.'database/DB_active_rec.php'); + require_once(BASEPATH.'database/DB_query_builder.php'); if ( ! class_exists('CI_DB')) { - class CI_DB extends CI_DB_active_record { } + class CI_DB extends CI_DB_query_builder { } } } elseif ( ! class_exists('CI_DB')) @@ -137,18 +141,23 @@ function &DB($params = '', $active_record_override = NULL) class CI_DB extends CI_DB_driver { } } - require_once(BASEPATH.'database/drivers/'.$params['dbdriver'].'/'.$params['dbdriver'].'_driver.php'); + // Load the DB driver + $driver_file = BASEPATH.'database/drivers/'.$params['dbdriver'].'/'.$params['dbdriver'].'_driver.php'; + + if ( ! file_exists($driver_file)) show_error('Invalid DB driver'); + + require_once($driver_file); // Instantiate the DB adapter $driver = 'CI_DB_'.$params['dbdriver'].'_driver'; $DB = new $driver($params); - if ($DB->autoinit == TRUE) + if ($DB->autoinit === TRUE) { $DB->initialize(); } - if (isset($params['stricton']) && $params['stricton'] == TRUE) + if ( ! empty($params['stricton'])) { $DB->query('SET SESSION sql_mode="STRICT_ALL_TABLES"'); } @@ -157,4 +166,4 @@ function &DB($params = '', $active_record_override = NULL) } /* End of file DB.php */ -/* Location: ./system/database/DB.php */ +/* Location: ./system/database/DB.php */
\ No newline at end of file diff --git a/system/database/DB_cache.php b/system/database/DB_cache.php index 79651fcb0..ba9110382 100644 --- a/system/database/DB_cache.php +++ b/system/database/DB_cache.php @@ -2,7 +2,7 @@ /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE * @@ -55,9 +55,9 @@ class CI_DB_Cache { */ public function check_path($path = '') { - if ($path == '') + if ($path === '') { - if ($this->db->cachedir == '') + if ($this->db->cachedir === '') { return $this->db->cache_off(); } @@ -99,7 +99,7 @@ class CI_DB_Cache { $segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2); $filepath = $this->db->cachedir.$segment_one.'+'.$segment_two.'/'.md5($sql); - if (FALSE === ($cachedata = read_file($filepath))) + if (FALSE === ($cachedata = file_get_contents($filepath))) { return FALSE; } @@ -154,12 +154,12 @@ class CI_DB_Cache { */ public function delete($segment_one = '', $segment_two = '') { - if ($segment_one == '') + if ($segment_one === '') { $segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1); } - if ($segment_two == '') + if ($segment_two === '') { $segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2); } @@ -177,10 +177,10 @@ class CI_DB_Cache { */ public function delete_all() { - delete_files($this->db->cachedir, TRUE); + delete_files($this->db->cachedir, TRUE, 0, TRUE); } } /* End of file DB_cache.php */ -/* Location: ./system/database/DB_cache.php */ +/* Location: ./system/database/DB_cache.php */
\ No newline at end of file diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php index 7445a5069..079ee8d05 100644 --- a/system/database/DB_driver.php +++ b/system/database/DB_driver.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,8 +25,6 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * Database Driver Class * @@ -40,57 +38,46 @@ * @author EllisLab Dev Team * @link http://codeigniter.com/user_guide/database/ */ -class CI_DB_driver { - - var $username; - var $password; - var $hostname; - var $database; - var $dbdriver = 'mysql'; - var $dbprefix = ''; - var $char_set = 'utf8'; - var $dbcollat = 'utf8_general_ci'; - var $autoinit = TRUE; // Whether to automatically initialize the DB - var $swap_pre = ''; - var $port = ''; - var $pconnect = FALSE; - var $conn_id = FALSE; - var $result_id = FALSE; - var $db_debug = FALSE; - var $benchmark = 0; - var $query_count = 0; - var $bind_marker = '?'; - var $save_queries = TRUE; - var $queries = array(); - var $query_times = array(); - var $data_cache = array(); - var $trans_enabled = TRUE; - var $trans_strict = TRUE; - var $_trans_depth = 0; - var $_trans_status = TRUE; // Used with transactions to determine if a rollback should occur - var $cache_on = FALSE; - var $cachedir = ''; - var $cache_autodel = FALSE; - var $CACHE; // The cache class object - - // Private variables - var $_protect_identifiers = TRUE; - var $_reserved_identifiers = array('*'); // Identifiers that should NOT be escaped - - // These are use with Oracle - var $stmt_id; - var $curs_id; - var $limit_used; - - - - /** - * Constructor. Accepts one parameter containing the database - * connection settings. - * - * @param array - */ - function __construct($params) +abstract class CI_DB_driver { + + public $dsn; + public $username; + public $password; + public $hostname; + public $database; + public $dbdriver = 'mysql'; + public $dbprefix = ''; + public $char_set = 'utf8'; + public $dbcollat = 'utf8_general_ci'; + public $autoinit = TRUE; // Whether to automatically initialize the DB + public $swap_pre = ''; + public $port = ''; + public $pconnect = FALSE; + public $conn_id = FALSE; + public $result_id = FALSE; + public $db_debug = FALSE; + public $benchmark = 0; + public $query_count = 0; + public $bind_marker = '?'; + public $save_queries = TRUE; + public $queries = array(); + public $query_times = array(); + public $data_cache = array(); + + public $trans_enabled = TRUE; + public $trans_strict = TRUE; + protected $_trans_depth = 0; + protected $_trans_status = TRUE; // Used with transactions to determine if a rollback should occur + + public $cache_on = FALSE; + public $cachedir = ''; + public $cache_autodel = FALSE; + public $CACHE; // The cache class object + + protected $_protect_identifiers = TRUE; + protected $_reserved_identifiers = array('*'); // Identifiers that should NOT be escaped + + public function __construct($params) { if (is_array($params)) { @@ -108,15 +95,17 @@ class CI_DB_driver { /** * Initialize Database Settings * - * @access private Called by the constructor - * @param mixed - * @return void + * @return bool */ - function initialize() + public function initialize() { - // If an existing connection resource is available - // there is no need to connect and select the database - if (is_resource($this->conn_id) OR is_object($this->conn_id)) + /* If an established connection is available, then there's + * no need to connect and select the database. + * + * Depending on the database driver, conn_id can be either + * boolean TRUE, a resource or an object. + */ + if ($this->conn_id) { return TRUE; } @@ -124,9 +113,9 @@ class CI_DB_driver { // ---------------------------------------------------------------- // Connect to the database and set the connection ID - $this->conn_id = ($this->pconnect == FALSE) ? $this->db_connect() : $this->db_pconnect(); + $this->conn_id = ($this->pconnect === FALSE) ? $this->db_connect() : $this->db_pconnect(); - // No connection resource? Check if there is a failover else throw an error + // No connection resource? Check if there is a failover else throw an error if ( ! $this->conn_id) { // Check if there is a failover set @@ -142,7 +131,7 @@ class CI_DB_driver { } // Try to connect - $this->conn_id = ($this->pconnect == FALSE) ? $this->db_connect() : $this->db_pconnect(); + $this->conn_id = ($this->pconnect === FALSE) ? $this->db_connect() : $this->db_pconnect(); // If a connection is made break the foreach loop if ($this->conn_id) @@ -168,30 +157,50 @@ class CI_DB_driver { // ---------------------------------------------------------------- // Select the DB... assuming a database name is specified in the config file - if ($this->database != '') + if ($this->database !== '' && ! $this->db_select()) { - if ( ! $this->db_select()) - { - log_message('error', 'Unable to select database: '.$this->database); + log_message('error', 'Unable to select database: '.$this->database); - if ($this->db_debug) - { - $this->display_error('db_unable_to_select', $this->database); - } - return FALSE; - } - else + if ($this->db_debug) { - // We've selected the DB. Now we set the character set - if ( ! $this->db_set_charset($this->char_set, $this->dbcollat)) - { - return FALSE; - } - - return TRUE; + $this->display_error('db_unable_to_select', $this->database); } + return FALSE; } + // Now we set the character set and that's all + return $this->db_set_charset($this->char_set); + } + + // -------------------------------------------------------------------- + + /** + * Reconnect + * + * Keep / reestablish the db connection if no queries have been + * sent for a length of time exceeding the server's idle timeout. + * + * This is just a dummy method to allow drivers without such + * functionality to not declare it, while others will override it. + * + * @return void + */ + public function reconnect() + { + } + + // -------------------------------------------------------------------- + + /** + * Select database + * + * This is just a dummy method to allow drivers without such + * functionality to not declare it, while others will override it. + * + * @return bool + */ + public function db_select() + { return TRUE; } @@ -200,20 +209,18 @@ class CI_DB_driver { /** * Set client character set * - * @access public * @param string - * @param string - * @return resource + * @return bool */ - function db_set_charset($charset, $collation) + public function db_set_charset($charset) { - if ( ! $this->_db_set_charset($this->char_set, $this->dbcollat)) + if (method_exists($this, '_db_set_charset') && ! $this->_db_set_charset($charset)) { - log_message('error', 'Unable to set database connection charset: '.$this->char_set); + log_message('error', 'Unable to set database connection charset: '.$charset); if ($this->db_debug) { - $this->display_error('db_unable_to_set_charset', $this->char_set); + $this->display_error('db_unable_to_set_charset', $charset); } return FALSE; @@ -227,10 +234,9 @@ class CI_DB_driver { /** * The name of the platform in use (mysql, mssql, etc...) * - * @access public * @return string */ - function platform() + public function platform() { return $this->dbdriver; } @@ -238,36 +244,40 @@ class CI_DB_driver { // -------------------------------------------------------------------- /** - * Database Version Number. Returns a string containing the - * version of the database being used + * Database version number + * + * Returns a string containing the version of the database being used. + * Most drivers will override this method. * - * @access public * @return string */ - function version() + public function version() { - if (FALSE === ($sql = $this->_version())) + if (isset($this->data_cache['version'])) { - if ($this->db_debug) - { - return $this->display_error('db_unsupported_function'); - } - return FALSE; + return $this->data_cache['version']; } - // Some DBs have functions that return the version, and don't run special - // SQL queries per se. In these instances, just return the result. - $driver_version_exceptions = array('oci8', 'sqlite', 'cubrid', 'pdo', 'mysqli'); - - if (in_array($this->dbdriver, $driver_version_exceptions)) - { - return $sql; - } - else + if (FALSE === ($sql = $this->_version())) { - $query = $this->query($sql); - return $query->row('ver'); + return ($this->db_debug) ? $this->display_error('db_unsupported_function') : FALSE; } + + $query = $this->query($sql); + $query = $query->row(); + return $this->data_cache['version'] = $query->ver; + } + + // -------------------------------------------------------------------- + + /** + * Version number query string + * + * @return string + */ + protected function _version() + { + return 'SELECT VERSION() AS ver'; } // -------------------------------------------------------------------- @@ -276,69 +286,61 @@ class CI_DB_driver { * Execute the query * * Accepts an SQL string as input and returns a result object upon - * successful execution of a "read" type query. Returns boolean TRUE + * successful execution of a "read" type query. Returns boolean TRUE * upon successful execution of a "write" type query. Returns boolean * FALSE upon failure, and if the $db_debug variable is set to TRUE * will raise an error. * - * @access public * @param string An SQL query string * @param array An array of binding data * @return mixed */ - function query($sql, $binds = FALSE, $return_object = TRUE) + public function query($sql, $binds = FALSE, $return_object = TRUE) { - if ($sql == '') + if ($sql === '') { log_message('error', 'Invalid query: '.$sql); - if ($this->db_debug) - { - return $this->display_error('db_invalid_query'); - } - return FALSE; + return ($this->db_debug) ? $this->display_error('db_invalid_query') : FALSE; } // Verify table prefix and replace if necessary - if ( ($this->dbprefix != '' AND $this->swap_pre != '') AND ($this->dbprefix != $this->swap_pre) ) + if ($this->dbprefix !== '' && $this->swap_pre !== '' && $this->dbprefix !== $this->swap_pre) { - $sql = preg_replace("/(\W)".$this->swap_pre."(\S+?)/", "\\1".$this->dbprefix."\\2", $sql); + $sql = preg_replace('/(\W)'.$this->swap_pre.'(\S+?)/', '\\1'.$this->dbprefix.'\\2', $sql); } - // Is query caching enabled? If the query is a "read type" + // Compile binds if needed + if ($binds !== FALSE) + { + $sql = $this->compile_binds($sql, $binds); + } + + // Is query caching enabled? If the query is a "read type" // we will load the caching class and return the previously // cached query if it exists - if ($this->cache_on == TRUE AND stristr($sql, 'SELECT')) + if ($this->cache_on === TRUE && stripos($sql, 'SELECT') !== FALSE && $this->_cache_init()) { - if ($this->_cache_init()) + $this->load_rdriver(); + if (FALSE !== ($cache = $this->CACHE->read($sql))) { - $this->load_rdriver(); - if (FALSE !== ($cache = $this->CACHE->read($sql))) - { - return $cache; - } + return $cache; } } - // Compile binds if needed - if ($binds !== FALSE) - { - $sql = $this->compile_binds($sql, $binds); - } - // Save the query for debugging - if ($this->save_queries == TRUE) + if ($this->save_queries === TRUE) { $this->queries[] = $sql; } // Start the Query Timer - $time_start = list($sm, $ss) = explode(' ', microtime()); + $time_start = microtime(TRUE); // Run the Query if (FALSE === ($this->result_id = $this->simple_query($sql))) { - if ($this->save_queries == TRUE) + if ($this->save_queries === TRUE) { $this->query_times[] = 0; } @@ -346,42 +348,34 @@ class CI_DB_driver { // This will trigger a rollback if transactions are being used $this->_trans_status = FALSE; - // Grab the error number and message now, as we might run some - // additional queries before displaying the error - $error_no = $this->_error_number(); - $error_msg = $this->_error_message(); + // Grab the error now, as we might run some additional queries before displaying the error + $error = $this->error(); // Log errors - log_message('error', 'Query error: '.$error_msg); + log_message('error', 'Query error: '.$error['message']); if ($this->db_debug) { // We call this function in order to roll-back queries - // if transactions are enabled. If we don't call this here + // if transactions are enabled. If we don't call this here // the error message will trigger an exit, causing the // transactions to remain in limbo. $this->trans_complete(); // Display errors - return $this->display_error( - array( - 'Error Number: '.$error_no, - $error_msg, - $sql - ) - ); + return $this->display_error(array('Error Number: '.$error['code'], $error['message'], $sql)); } return FALSE; } // Stop and aggregate the query time results - $time_end = list($em, $es) = explode(' ', microtime()); - $this->benchmark += ($em + $es) - ($sm + $ss); + $time_end = microtime(TRUE); + $this->benchmark += $time_end - $time_start; - if ($this->save_queries == TRUE) + if ($this->save_queries === TRUE) { - $this->query_times[] = ($em + $es) - ($sm + $ss); + $this->query_times[] = $time_end - $time_start; } // Increment the query counter @@ -393,7 +387,7 @@ class CI_DB_driver { { // If caching is enabled we'll auto-cleanup any // existing files related to this particular URI - if ($this->cache_on == TRUE AND $this->cache_autodel == TRUE AND $this->_cache_init()) + if ($this->cache_on === TRUE && $this->cache_autodel === TRUE && $this->_cache_init()) { $this->CACHE->delete(); } @@ -410,26 +404,12 @@ class CI_DB_driver { } // Load and instantiate the result driver + $driver = $this->load_rdriver(); + $RES = new $driver($this); - $driver = $this->load_rdriver(); - $RES = new $driver(); - $RES->conn_id = $this->conn_id; - $RES->result_id = $this->result_id; - - if ($this->dbdriver == 'oci8') - { - $RES->stmt_id = $this->stmt_id; - $RES->curs_id = NULL; - $RES->limit_used = $this->limit_used; - $this->stmt_id = FALSE; - } - - // oci8 vars must be set before calling this - $RES->num_rows = $RES->num_rows(); - - // Is query caching enabled? If so, we'll serialize the + // Is query caching enabled? If so, we'll serialize the // result object and save it to a cache file. - if ($this->cache_on == TRUE AND $this->_cache_init()) + if ($this->cache_on === TRUE && $this->_cache_init()) { // We'll create a new instance of the result object // only without the platform specific driver since @@ -438,9 +418,9 @@ class CI_DB_driver { // result object, so we'll have to compile the data // and save it) $CR = new CI_DB_result(); - $CR->num_rows = $RES->num_rows(); $CR->result_object = $RES->result_object(); $CR->result_array = $RES->result_array(); + $CR->num_rows = $RES->num_rows(); // Reset these since cached objects can not utilize resource IDs. $CR->conn_id = NULL; @@ -457,10 +437,9 @@ class CI_DB_driver { /** * Load the result drivers * - * @access public * @return string the name of the result class */ - function load_rdriver() + public function load_rdriver() { $driver = 'CI_DB_'.$this->dbdriver.'_result'; @@ -477,15 +456,14 @@ class CI_DB_driver { /** * Simple Query - * This is a simplified version of the query() function. Internally + * This is a simplified version of the query() function. Internally * we only use it when running transaction commands since they do * not require all the features of the main query() function. * - * @access public * @param string the sql query * @return mixed */ - function simple_query($sql) + public function simple_query($sql) { if ( ! $this->conn_id) { @@ -501,10 +479,9 @@ class CI_DB_driver { * Disable Transactions * This permits transactions to be disabled at run-time. * - * @access public * @return void */ - function trans_off() + public function trans_off() { $this->trans_enabled = FALSE; } @@ -518,10 +495,9 @@ class CI_DB_driver { * If strict mode is disabled, each group is treated autonomously, meaning * a failure of one group will not affect any others * - * @access public * @return void */ - function trans_strict($mode = TRUE) + public function trans_strict($mode = TRUE) { $this->trans_strict = is_bool($mode) ? $mode : TRUE; } @@ -531,10 +507,9 @@ class CI_DB_driver { /** * Start Transaction * - * @access public * @return void */ - function trans_start($test_mode = FALSE) + public function trans_start($test_mode = FALSE) { if ( ! $this->trans_enabled) { @@ -557,10 +532,9 @@ class CI_DB_driver { /** * Complete Transaction * - * @access public * @return bool */ - function trans_complete() + public function trans_complete() { if ( ! $this->trans_enabled) { @@ -604,10 +578,9 @@ class CI_DB_driver { /** * Lets you retrieve the transaction flag to determine if it has failed * - * @access public * @return bool */ - function trans_status() + public function trans_status() { return $this->_trans_status; } @@ -617,12 +590,11 @@ class CI_DB_driver { /** * Compile Bindings * - * @access public * @param string the sql statement * @param array an array of bind data * @return string */ - function compile_binds($sql, $binds) + public function compile_binds($sql, $binds) { if (strpos($sql, $this->bind_marker) === FALSE) { @@ -639,7 +611,8 @@ class CI_DB_driver { // The count of bind should be 1 less then the count of segments // If there are more bind arguments trim it down - if (count($binds) >= count($segments)) { + if (count($binds) >= count($segments)) + { $binds = array_slice($binds, 0, count($segments)-1); } @@ -648,8 +621,7 @@ class CI_DB_driver { $i = 0; foreach ($binds as $bind) { - $result .= $this->escape($bind); - $result .= $segments[++$i]; + $result .= $this->escape($bind).$segments[++$i]; } return $result; @@ -660,17 +632,12 @@ class CI_DB_driver { /** * Determines if a query is a "write" type. * - * @access public * @param string An SQL query string - * @return boolean + * @return bool */ - function is_write_type($sql) + public function is_write_type($sql) { - if ( ! preg_match('/^\s*"?(SET|INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD DATA|COPY|ALTER|GRANT|REVOKE|LOCK|UNLOCK)\s+/i', $sql)) - { - return FALSE; - } - return TRUE; + return (bool) preg_match('/^\s*"?(SET|INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD DATA|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX)\s+/i', $sql); } // -------------------------------------------------------------------- @@ -678,11 +645,10 @@ class CI_DB_driver { /** * Calculate the aggregate query elapsed time * - * @access public - * @param integer The number of decimal places - * @return integer + * @param int The number of decimal places + * @return int */ - function elapsed_time($decimals = 6) + public function elapsed_time($decimals = 6) { return number_format($this->benchmark, $decimals); } @@ -692,10 +658,9 @@ class CI_DB_driver { /** * Returns the total number of queries * - * @access public - * @return integer + * @return int */ - function total_queries() + public function total_queries() { return $this->query_count; } @@ -705,10 +670,9 @@ class CI_DB_driver { /** * Returns the last query that was executed * - * @access public - * @return void + * @return string */ - function last_query() + public function last_query() { return end($this->queries); } @@ -721,23 +685,22 @@ class CI_DB_driver { * Escapes data based on type * Sets boolean and null types * - * @access public * @param string * @return mixed */ - function escape($str) + public function escape($str) { - if (is_string($str)) + if (is_string($str) OR method_exists($str, '__toString')) { - $str = "'".$this->escape_str($str)."'"; + return "'".$this->escape_str($str)."'"; } elseif (is_bool($str)) { - $str = ($str === FALSE) ? 0 : 1; + return ($str === FALSE) ? 0 : 1; } elseif (is_null($str)) { - $str = 'NULL'; + return 'NULL'; } return $str; @@ -751,11 +714,10 @@ class CI_DB_driver { * Calls the individual driver for platform * specific escaping for LIKE conditions * - * @access public * @param string * @return mixed */ - function escape_like_str($str) + public function escape_like_str($str) { return $this->escape_str($str, TRUE); } @@ -765,23 +727,45 @@ class CI_DB_driver { /** * Primary * - * Retrieves the primary key. It assumes that the row in the first + * Retrieves the primary key. It assumes that the row in the first * position is the primary key * - * @access public * @param string the table name * @return string */ - function primary($table = '') + public function primary($table = '') { $fields = $this->list_fields($table); + return is_array($fields) ? current($fields) : FALSE; + } + + // -------------------------------------------------------------------- + + /** + * "Count All" query + * + * Generates a platform-specific query string that counts all records in + * the specified database + * + * @param string + * @return int + */ + public function count_all($table = '') + { + if ($table === '') + { + return 0; + } - if ( ! is_array($fields)) + $query = $this->query($this->_count_string.$this->escape_identifiers('numrows').' FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE)); + if ($query->num_rows() === 0) { - return FALSE; + return 0; } - return current($fields); + $query = $query->row(); + $this->_reset_select(); + return (int) $query->numrows; } // -------------------------------------------------------------------- @@ -789,10 +773,9 @@ class CI_DB_driver { /** * Returns an array of table names * - * @access public * @return array */ - function list_tables($constrain_by_prefix = FALSE) + public function list_tables($constrain_by_prefix = FALSE) { // Is there a cached result? if (isset($this->data_cache['table_names'])) @@ -802,32 +785,40 @@ class CI_DB_driver { if (FALSE === ($sql = $this->_list_tables($constrain_by_prefix))) { - if ($this->db_debug) - { - return $this->display_error('db_unsupported_function'); - } - return FALSE; + return ($this->db_debug) ? $this->display_error('db_unsupported_function') : FALSE; } - $retval = array(); + $this->data_cache['table_names'] = array(); $query = $this->query($sql); - if ($query->num_rows() > 0) + foreach ($query->result_array() as $row) { - foreach ($query->result_array() as $row) + // Do we know from which column to get the table name? + if ( ! isset($key)) { - if (isset($row['TABLE_NAME'])) + if (isset($row['table_name'])) { - $retval[] = $row['TABLE_NAME']; + $key = 'table_name'; + } + elseif (isset($row['TABLE_NAME'])) + { + $key = 'TABLE_NAME'; } else { - $retval[] = array_shift($row); + /* We have no other choice but to just get the first element's key. + * Due to array_shift() accepting it's argument by reference, if + * E_STRICT is on, this would trigger a warning. So we'll have to + * assign it first. + */ + $key = array_keys($row); + $key = array_shift($key); } } + + $this->data_cache['table_names'][] = $row[$key]; } - $this->data_cache['table_names'] = $retval; return $this->data_cache['table_names']; } @@ -835,12 +826,12 @@ class CI_DB_driver { /** * Determine if a particular table exists - * @access public - * @return boolean + * + * @return bool */ - function table_exists($table_name) + public function table_exists($table_name) { - return ( ! in_array($this->_protect_identifiers($table_name, TRUE, FALSE, FALSE), $this->list_tables())) ? FALSE : TRUE; + return in_array($this->protect_identifiers($table_name, TRUE, FALSE, FALSE), $this->list_tables()); } // -------------------------------------------------------------------- @@ -848,11 +839,10 @@ class CI_DB_driver { /** * Fetch MySQL Field Names * - * @access public * @param string the table name * @return array */ - function list_fields($table = '') + public function list_fields($table = '') { // Is there a cached result? if (isset($this->data_cache['field_names'][$table])) @@ -860,40 +850,47 @@ class CI_DB_driver { return $this->data_cache['field_names'][$table]; } - if ($table == '') + if ($table === '') { - if ($this->db_debug) - { - return $this->display_error('db_field_param_missing'); - } - return FALSE; + return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE; } if (FALSE === ($sql = $this->_list_columns($table))) { - if ($this->db_debug) - { - return $this->display_error('db_unsupported_function'); - } - return FALSE; + return ($this->db_debug) ? $this->display_error('db_unsupported_function') : FALSE; } $query = $this->query($sql); + $this->data_cache['field_names'][$table] = array(); - $retval = array(); foreach ($query->result_array() as $row) { - if (isset($row['COLUMN_NAME'])) - { - $retval[] = $row['COLUMN_NAME']; - } - else + // Do we know from where to get the column's name? + if ( ! isset($key)) { - $retval[] = current($row); + if (isset($row['column_name'])) + { + $key = 'column_name'; + } + elseif (isset($row['COLUMN_NAME'])) + { + $key = 'COLUMN_NAME'; + } + else + { + /* We have no other choice but to just get the first element's key. + * Due to array_shift() accepting it's argument by reference, if + * E_STRICT is on, this would trigger a warning. So we'll have to + * assign it first. + */ + $key = array_keys($row); + $key = array_shift($key); + } } + + $this->data_cache['field_names'][$table][] = $row[$key]; } - $this->data_cache['field_names'][$table] = $retval; return $this->data_cache['field_names'][$table]; } @@ -901,14 +898,14 @@ class CI_DB_driver { /** * Determine if a particular field exists - * @access public + * * @param string * @param string - * @return boolean + * @return bool */ - function field_exists($field_name, $table_name) + public function field_exists($field_name, $table_name) { - return ( ! in_array($field_name, $this->list_fields($table_name))) ? FALSE : TRUE; + return in_array($field_name, $this->list_fields($table_name)); } // -------------------------------------------------------------------- @@ -916,24 +913,69 @@ class CI_DB_driver { /** * Returns an object with field data * - * @access public * @param string the table name * @return object */ - function field_data($table = '') + public function field_data($table = '') { - if ($table == '') + if ($table === '') { - if ($this->db_debug) + return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE; + } + + $query = $this->query($this->_field_data($this->protect_identifiers($table, TRUE, NULL, FALSE))); + return $query->field_data(); + } + + // -------------------------------------------------------------------- + + /** + * Escape the SQL Identifiers + * + * This function escapes column and table names + * + * @param mixed + * @return mixed + */ + public function escape_identifiers($item) + { + if ($this->_escape_char === '') + { + return $item; + } + elseif (is_array($item)) + { + foreach ($item as $key => $value) { - return $this->display_error('db_field_param_missing'); + $item[$key] = $this->escape_identifiers($value); } - return FALSE; + + return $item; } - $query = $this->query($this->_field_data($this->_protect_identifiers($table, TRUE, NULL, FALSE))); + static $preg_ec = array(); - return $query->field_data(); + if (empty($preg_ec)) + { + if (is_array($this->_escape_char)) + { + $preg_ec = array(preg_quote($this->_escape_char[0]), preg_quote($this->_escape_char[1])); + } + else + { + $preg_ec[0] = $preg_ec[1] = preg_quote($this->_escape_char); + } + } + + foreach ($this->_reserved_identifiers as $id) + { + if (strpos($item, '.'.$id) !== FALSE) + { + return preg_replace('/'.$preg_ec[0].'?([^'.$preg_ec[1].'\.]+)'.$preg_ec[1].'?\./i', $preg_ec[0].'$1'.$preg_ec[1].'.', $item); + } + } + + return preg_replace('/'.$preg_ec[0].'?([^'.$preg_ec[1].'\.]+)'.$preg_ec[1].'?(\.)?/i', $preg_ec[0].'$1'.$preg_ec[1].'$2', $item); } // -------------------------------------------------------------------- @@ -941,23 +983,21 @@ class CI_DB_driver { /** * Generate an insert string * - * @access public * @param string the table upon which the query will be performed * @param array an associative array data of key/values * @return string */ - function insert_string($table, $data) + public function insert_string($table, $data) { - $fields = array(); - $values = array(); + $fields = $values = array(); foreach ($data as $key => $val) { - $fields[] = $this->_escape_identifiers($key); + $fields[] = $this->escape_identifiers($key); $values[] = $this->escape($val); } - return $this->_insert($this->_protect_identifiers($table, TRUE, NULL, FALSE), $fields, $values); + return $this->_insert($this->protect_identifiers($table, TRUE, NULL, FALSE), $fields, $values); } // -------------------------------------------------------------------- @@ -965,23 +1005,22 @@ class CI_DB_driver { /** * Generate an update string * - * @access public * @param string the table upon which the query will be performed * @param array an associative array data of key/values * @param mixed the "where" statement * @return string */ - function update_string($table, $data, $where) + public function update_string($table, $data, $where) { - if ($where == '') + if ($where === '') { - return false; + return FALSE; } $fields = array(); foreach ($data as $key => $val) { - $fields[$this->_protect_identifiers($key)] = $this->escape($val); + $fields[$this->protect_identifiers($key)] = $this->escape($val); } if ( ! is_array($where)) @@ -993,8 +1032,8 @@ class CI_DB_driver { $dest = array(); foreach ($where as $key => $val) { - $prefix = (count($dest) == 0) ? '' : ' AND '; - $key = $this->_protect_identifiers($key); + $prefix = (count($dest) === 0) ? '' : ' AND '; + $key = $this->protect_identifiers($key); if ($val !== '') { @@ -1010,7 +1049,7 @@ class CI_DB_driver { } } - return $this->_update($this->_protect_identifiers($table, TRUE, NULL, FALSE), $fields, $dest); + return $this->_update($this->protect_identifiers($table, TRUE, NULL, FALSE), $fields, $dest); } // -------------------------------------------------------------------- @@ -1018,19 +1057,12 @@ class CI_DB_driver { /** * Tests whether the string has an SQL operator * - * @access private * @param string * @return bool */ - function _has_operator($str) + protected function _has_operator($str) { - $str = trim($str); - if ( ! preg_match("/(\s|<|>|!|=|is null|is not null)/i", $str)) - { - return FALSE; - } - - return TRUE; + return (bool) preg_match('/(\s|<|>|!|=|IS NULL|IS NOT NULL|BETWEEN)/i', trim($str)); } // -------------------------------------------------------------------- @@ -1038,14 +1070,13 @@ class CI_DB_driver { /** * Enables a native PHP function to be run, using a platform agnostic wrapper. * - * @access public * @param string the function name * @param mixed any parameters needed by the function * @return mixed */ - function call_function($function) + public function call_function($function) { - $driver = ($this->dbdriver == 'postgre') ? 'pg_' : $this->dbdriver.'_'; + $driver = ($this->dbdriver === 'postgre') ? 'pg_' : $this->dbdriver.'_'; if (FALSE === strpos($driver, $function)) { @@ -1054,25 +1085,12 @@ class CI_DB_driver { if ( ! function_exists($function)) { - if ($this->db_debug) - { - return $this->display_error('db_unsupported_function'); - } - return FALSE; + return ($this->db_debug) ? $this->display_error('db_unsupported_function') : FALSE; } - else - { - $args = (func_num_args() > 1) ? array_splice(func_get_args(), 1) : null; - if (is_null($args)) - { - return call_user_func($function); - } - else - { - return call_user_func_array($function, $args); - } - } + return (func_num_args() > 1) + ? call_user_func_array($function, array_splice(func_get_args(), 1)) + : call_user_func($function); } // -------------------------------------------------------------------- @@ -1080,11 +1098,10 @@ class CI_DB_driver { /** * Set Cache Directory Path * - * @access public * @param string the path to the cache directory * @return void */ - function cache_set_path($path = '') + public function cache_set_path($path = '') { $this->cachedir = $path; } @@ -1094,13 +1111,11 @@ class CI_DB_driver { /** * Enable Query Caching * - * @access public - * @return void + * @return bool cache_on value */ - function cache_on() + public function cache_on() { - $this->cache_on = TRUE; - return TRUE; + return $this->cache_on = TRUE; } // -------------------------------------------------------------------- @@ -1108,13 +1123,11 @@ class CI_DB_driver { /** * Disable Query Caching * - * @access public - * @return void + * @return bool cache_on value */ - function cache_off() + public function cache_off() { - $this->cache_on = FALSE; - return FALSE; + return $this->cache_on = FALSE; } @@ -1123,16 +1136,13 @@ class CI_DB_driver { /** * Delete the cache files associated with a particular URI * - * @access public - * @return void + * @return bool */ - function cache_delete($segment_one = '', $segment_two = '') + public function cache_delete($segment_one = '', $segment_two = '') { - if ( ! $this->_cache_init()) - { - return FALSE; - } - return $this->CACHE->delete($segment_one, $segment_two); + return ($this->_cache_init()) + ? $this->CACHE->delete($segment_one, $segment_two) + : FALSE; } // -------------------------------------------------------------------- @@ -1140,17 +1150,13 @@ class CI_DB_driver { /** * Delete All cache files * - * @access public - * @return void + * @return bool */ - function cache_delete_all() + public function cache_delete_all() { - if ( ! $this->_cache_init()) - { - return FALSE; - } - - return $this->CACHE->delete_all(); + return ($this->_cache_init()) + ? $this->CACHE->delete_all() + : FALSE; } // -------------------------------------------------------------------- @@ -1158,23 +1164,21 @@ class CI_DB_driver { /** * Initialize the Cache Class * - * @access private - * @return void + * @return bool */ - function _cache_init() + protected function _cache_init() { - if (is_object($this->CACHE) AND class_exists('CI_DB_Cache')) + if (class_exists('CI_DB_Cache')) { - return TRUE; - } - - if ( ! class_exists('CI_DB_Cache')) - { - if ( ! @include(BASEPATH.'database/DB_cache.php')) + if (is_object($this->CACHE)) { - return $this->cache_off(); + return TRUE; } } + elseif ( ! @include_once(BASEPATH.'database/DB_cache.php')) + { + return $this->cache_off(); + } $this->CACHE = new CI_DB_Cache($this); // pass db object to support multiple db connections and returned db objects return TRUE; @@ -1185,15 +1189,28 @@ class CI_DB_driver { /** * Close DB Connection * - * @access public * @return void */ - function close() + public function close() { - if (is_resource($this->conn_id) OR is_object($this->conn_id)) + if ($this->conn_id) { - $this->_close($this->conn_id); + $this->_close(); + $this->conn_id = FALSE; } + } + + // -------------------------------------------------------------------- + + /** + * Close DB Connection + * + * This method would be overriden by most of the drivers. + * + * @return void + */ + protected function _close() + { $this->conn_id = FALSE; } @@ -1202,20 +1219,19 @@ class CI_DB_driver { /** * Display an error message * - * @access public * @param string the error message * @param string any "swap" values - * @param boolean whether to localize the message + * @param bool whether to localize the message * @return string sends the application/error_db.php template */ - function display_error($error = '', $swap = '', $native = FALSE) + public function display_error($error = '', $swap = '', $native = FALSE) { $LANG =& load_class('Lang', 'core'); $LANG->load('db'); $heading = $LANG->line('db_error_heading'); - if ($native == TRUE) + if ($native === TRUE) { $message = (array) $error; } @@ -1227,9 +1243,7 @@ class CI_DB_driver { // Find the most likely culprit of the error by going through // the backtrace until the source file is no longer in the // database folder. - $trace = debug_backtrace(); - foreach ($trace as $call) { if (isset($call['file']) && strpos($call['file'], BASEPATH.'database') === FALSE) @@ -1237,7 +1251,6 @@ class CI_DB_driver { // Found it - use a relative path for safety $message[] = 'Filename: '.str_replace(array(BASEPATH, APPPATH), '', $call['file']); $message[] = 'Line Number: '.$call['line']; - break; } } @@ -1252,27 +1265,11 @@ class CI_DB_driver { /** * Protect Identifiers * - * This function adds backticks if appropriate based on db type - * - * @access private - * @param mixed the item to escape - * @return mixed the item with backticks - */ - function protect_identifiers($item, $prefix_single = FALSE) - { - return $this->_protect_identifiers($item, $prefix_single); - } - - // -------------------------------------------------------------------- - - /** - * Protect Identifiers - * - * This function is used extensively by the Active Record class, and by + * This function is used extensively by the Query Builder class, and by * a couple functions in this class. * It takes a column or table name (optionally with an alias) and inserts - * the table prefix onto it. Some logic is necessary in order to deal with - * column names that include the path. Consider a query like this: + * the table prefix onto it. Some logic is necessary in order to deal with + * column names that include the path. Consider a query like this: * * SELECT * FROM hostname.database.table.column AS c FROM hostname.database.table * @@ -1285,14 +1282,13 @@ class CI_DB_driver { * insert the table prefix (if it exists) in the proper position, and escape only * the correct identifiers. * - * @access private * @param string * @param bool * @param mixed * @param bool * @return string */ - function _protect_identifiers($item, $prefix_single = FALSE, $protect_identifiers = NULL, $field_exists = TRUE) + public function protect_identifiers($item, $prefix_single = FALSE, $protect_identifiers = NULL, $field_exists = TRUE) { if ( ! is_bool($protect_identifiers)) { @@ -1302,34 +1298,63 @@ class CI_DB_driver { if (is_array($item)) { $escaped_array = array(); - foreach ($item as $k => $v) { - $escaped_array[$this->_protect_identifiers($k)] = $this->_protect_identifiers($v); + $escaped_array[$this->protect_identifiers($k)] = $this->protect_identifiers($v, $prefix_single, $protect_identifiers, $field_exists); } return $escaped_array; } + // This is basically a bug fix for queries that use MAX, MIN, etc. + // If a parenthesis is found we know that we do not need to + // escape the data or add a prefix. There's probably a more graceful + // way to deal with this, but I'm not thinking of it -- Rick + if (strpos($item, '(') !== FALSE) + { + return $item; + } + // Convert tabs or multiple spaces into single spaces - $item = preg_replace('/[\t ]+/', ' ', $item); + $item = preg_replace('/\s+/', ' ', $item); + + static $preg_ec = array(); + + if (empty($preg_ec)) + { + if (is_array($this->_escape_char)) + { + $preg_ec = array(preg_quote($this->_escape_char[0]), preg_quote($this->_escape_char[1])); + } + else + { + $preg_ec[0] = $preg_ec[1] = preg_quote($this->_escape_char); + } + } // If the item has an alias declaration we remove it and set it aside. // Basically we remove everything to the right of the first space - $alias = ''; - if (strpos($item, ' ') !== FALSE) + preg_match('/^(('.$preg_ec[0].'[^'.$preg_ec[1].']+'.$preg_ec[1].')|([^'.$preg_ec[0].'][^\s]+))( AS)*(.+)*$/i', $item, $matches); + + if (isset($matches[4])) { - $alias = strstr($item, " "); - $item = substr($item, 0, - strlen($alias)); - } + $item = $matches[1]; - // This is basically a bug fix for queries that use MAX, MIN, etc. - // If a parenthesis is found we know that we do not need to - // escape the data or add a prefix. There's probably a more graceful - // way to deal with this, but I'm not thinking of it -- Rick - if (strpos($item, '(') !== FALSE) + // Escape the alias, if needed + if ($protect_identifiers === TRUE) + { + $alias = empty($matches[5]) + ? ' '.$this->escape_identifiers(ltrim($matches[4])) + : $matches[4].' '.$this->escape_identifiers(ltrim($matches[5])); + } + else + { + $alias = $matches[4].$matches[5]; + } + } + else { - return $item.$alias; + $alias = ''; } // Break the string apart if it contains periods, then insert the table prefix @@ -1340,9 +1365,9 @@ class CI_DB_driver { $parts = explode('.', $item); // Does the first segment of the exploded item match - // one of the aliases previously identified? If so, + // one of the aliases previously identified? If so, // we have nothing more to do other than escape the item - if (in_array($parts[0], $this->ar_aliased_tables)) + if (in_array($parts[0], $this->qb_aliased_tables)) { if ($protect_identifiers === TRUE) { @@ -1350,17 +1375,18 @@ class CI_DB_driver { { if ( ! in_array($val, $this->_reserved_identifiers)) { - $parts[$key] = $this->_escape_identifiers($val); + $parts[$key] = $this->escape_identifiers($val); } } $item = implode('.', $parts); } + return $item.$alias; } - // Is there a table prefix defined in the config file? If not, no need to do anything - if ($this->dbprefix != '') + // Is there a table prefix defined in the config file? If not, no need to do anything + if ($this->dbprefix !== '') { // We now add the table prefix based on some logic. // Do we have 4 segments (hostname.database.table.column)? @@ -1384,19 +1410,18 @@ class CI_DB_driver { // This flag is set when the supplied $item does not contain a field name. // This can happen when this function is being called from a JOIN. - if ($field_exists == FALSE) + if ($field_exists === FALSE) { $i++; } // Verify table prefix and replace if necessary - if ($this->swap_pre != '' && strncmp($parts[$i], $this->swap_pre, strlen($this->swap_pre)) === 0) + if ($this->swap_pre !== '' && strpos($parts[$i], $this->swap_pre) === 0) { - $parts[$i] = preg_replace("/^".$this->swap_pre."(\S+?)/", $this->dbprefix."\\1", $parts[$i]); + $parts[$i] = preg_replace('/^'.$this->swap_pre.'(\S+?)/', $this->dbprefix.'\\1', $parts[$i]); } - // We only add the table prefix if it does not already exist - if (substr($parts[$i], 0, strlen($this->dbprefix)) != $this->dbprefix) + elseif (strpos($parts[$i], $this->dbprefix) !== 0) { $parts[$i] = $this->dbprefix.$parts[$i]; } @@ -1407,39 +1432,48 @@ class CI_DB_driver { if ($protect_identifiers === TRUE) { - $item = $this->_escape_identifiers($item); + $item = $this->escape_identifiers($item); } return $item.$alias; } - // Is there a table prefix? If not, no need to insert it - if ($this->dbprefix != '') + // Is there a table prefix? If not, no need to insert it + if ($this->dbprefix !== '') { // Verify table prefix and replace if necessary - if ($this->swap_pre != '' && strncmp($item, $this->swap_pre, strlen($this->swap_pre)) === 0) + if ($this->swap_pre !== '' && strpos($item, $this->swap_pre) === 0) { - $item = preg_replace("/^".$this->swap_pre."(\S+?)/", $this->dbprefix."\\1", $item); + $item = preg_replace('/^'.$this->swap_pre.'(\S+?)/', $this->dbprefix.'\\1', $item); } - // Do we prefix an item with no segments? - if ($prefix_single == TRUE AND substr($item, 0, strlen($this->dbprefix)) != $this->dbprefix) + elseif ($prefix_single === TRUE && strpos($item, $this->dbprefix) !== 0) { $item = $this->dbprefix.$item; } } - if ($protect_identifiers === TRUE AND ! in_array($item, $this->_reserved_identifiers)) + if ($protect_identifiers === TRUE && ! in_array($item, $this->_reserved_identifiers)) { - $item = $this->_escape_identifiers($item); + $item = $this->escape_identifiers($item); } return $item.$alias; } + // -------------------------------------------------------------------- -} + /** + * Dummy method that allows Query Builder class to be disabled + * and keep count_all() working. + * + * @return void + */ + protected function _reset_select() + { + } +} /* End of file DB_driver.php */ -/* Location: ./system/database/DB_driver.php */ +/* Location: ./system/database/DB_driver.php */
\ No newline at end of file diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php index 336e9497d..9b7639289 100644 --- a/system/database/DB_forge.php +++ b/system/database/DB_forge.php @@ -2,7 +2,7 @@ /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE * @@ -25,22 +25,26 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** - * Database Utility Class + * Database Forge Class * * @category Database * @author EllisLab Dev Team * @link http://codeigniter.com/user_guide/database/ */ -class CI_DB_forge { +abstract class CI_DB_forge { public $fields = array(); public $keys = array(); public $primary_keys = array(); public $db_char_set = ''; + // Platform specific SQL strings + protected $_create_database = 'CREATE DATABASE %s'; + protected $_drop_database = 'DROP DATABASE %s'; + protected $_drop_table = 'DROP TABLE IF EXISTS %s'; + protected $_rename_table = 'ALTER TABLE %s RENAME TO %s'; + public function __construct() { // Assign the main database object to $this->db @@ -59,8 +63,21 @@ class CI_DB_forge { */ public function create_database($db_name) { - $sql = $this->_create_database($db_name); - return is_bool($sql) ? $sql : $this->db->query($sql); + if ($this->_create_database === FALSE) + { + return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE; + } + elseif ( ! $this->db->query(sprintf($this->_create_database, $db_name, $this->db->char_set, $this->db->dbcollat))) + { + return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE; + } + + if ( ! empty($this->db->data_cache['db_names'])) + { + $this->db->data_cache['db_names'][] = $db_name; + } + + return TRUE; } // -------------------------------------------------------------------- @@ -73,8 +90,30 @@ class CI_DB_forge { */ public function drop_database($db_name) { - $sql = $this->_drop_database($db_name); - return is_bool($sql) ? $sql : $this->db->query($sql); + if ($db_name === '') + { + show_error('A table name is required for that operation.'); + return FALSE; + } + elseif ($this->_drop_database === FALSE) + { + return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE; + } + elseif ( ! $this->db->query(sprintf($this->_drop_database, $db_name))) + { + return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE; + } + + if ( ! empty($this->db->data_cache['db_names'])) + { + $key = array_search(strtolower($db_name), array_map('strtolower', $this->db->data_cache['db_names']), TRUE); + if ($key !== FALSE) + { + unset($this->db->data_cache['db_names'][$key]); + } + } + + return TRUE; } // -------------------------------------------------------------------- @@ -98,7 +137,7 @@ class CI_DB_forge { return; } - if ($key == '') + if ($key === '') { show_error('Key information is required for that operation.'); } @@ -125,7 +164,7 @@ class CI_DB_forge { */ public function add_field($field = '') { - if ($field == '') + if ($field === '') { show_error('Field information is required.'); } @@ -172,7 +211,7 @@ class CI_DB_forge { */ public function create_table($table = '', $if_not_exists = FALSE) { - if ($table == '') + if ($table === '') { show_error('A table name is required for that operation.'); } @@ -184,7 +223,18 @@ class CI_DB_forge { $sql = $this->_create_table($this->db->dbprefix.$table, $this->fields, $this->primary_keys, $this->keys, $if_not_exists); $this->_reset(); - return is_bool($sql) ? $sql : $this->db->query($sql); + + if (is_bool($sql)) + { + return $sql; + } + + if (($result = $this->db->query($sql)) !== FALSE && ! empty($this->db->data_cache['table_names'])) + { + $this->db->data_cache['table_names'][] = $$this->db->dbprefix.$table; + } + + return $result; } // -------------------------------------------------------------------- @@ -197,8 +247,28 @@ class CI_DB_forge { */ public function drop_table($table_name) { - $sql = $this->_drop_table($this->db->dbprefix.$table_name); - return is_bool($sql) ? $sql : $this->db->query($sql); + if ($table_name === '') + { + return ($this->db->db_debug) ? $this->db->display_error('db_table_name_required') : FALSE; + } + elseif ($this->_drop_table === FALSE) + { + return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE; + } + + $result = $this->db->query(sprintf($this->_drop_table, $this->db->escape_identifiers($this->db->dbprefix.$table_name))); + + // Update table list cache + if ($result && ! empty($this->db->data_cache['table_names'])) + { + $key = array_search(strtolower($this->db->dbprefix.$table_name), array_map('strtolower', $this->db->data_cache['table_names']), TRUE); + if ($key !== FALSE) + { + unset($this->db->data_cache['table_names'][$key]); + } + } + + return $result; } // -------------------------------------------------------------------- @@ -212,12 +282,31 @@ class CI_DB_forge { */ public function rename_table($table_name, $new_table_name) { - if ($table_name == '' OR $new_table_name == '') + if ($table_name === '' OR $new_table_name === '') { show_error('A table name is required for that operation.'); + return FALSE; } + elseif ($this->_rename_table === FALSE) + { + return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE; + } + + $result = $this->db->query(sprintf($this->_rename_table, + $this->db->escape_identifiers($this->db->dbprefix.$table_name), + $this->db->escape_identifiers($this->db->dbprefix.$new_table_name)) + ); - return $this->db->query($this->_rename_table($this->db->dbprefix.$table_name, $this->db->dbprefix.$new_table_name)); + if ($result && ! empty($this->db->data_cache['table_names'])) + { + $key = array_search(strtolower($this->db->dbprefix.$table_name), array_map('strtolower', $this->db->data_cache['table_names']), TRUE); + if ($key !== FALSE) + { + $this->db->data_cache['table_names'][$key] = $this->db->dbprefix.$new_table_name; + } + } + + return $result; } // -------------------------------------------------------------------- @@ -232,7 +321,7 @@ class CI_DB_forge { */ public function add_column($table = '', $field = array(), $after_field = '') { - if ($table == '') + if ($table === '') { show_error('A table name is required for that operation.'); } @@ -243,7 +332,7 @@ class CI_DB_forge { { $this->add_field(array($k => $field[$k])); - if (count($this->fields) == 0) + if (count($this->fields) === 0) { show_error('Field information is required.'); } @@ -271,12 +360,12 @@ class CI_DB_forge { */ public function drop_column($table = '', $column_name = '') { - if ($table == '') + if ($table === '') { show_error('A table name is required for that operation.'); } - if ($column_name == '') + if ($column_name === '') { show_error('A column name is required for that operation.'); } @@ -296,7 +385,7 @@ class CI_DB_forge { */ public function modify_column($table = '', $field = array()) { - if ($table == '') + if ($table === '') { show_error('A table name is required for that operation.'); } @@ -346,4 +435,4 @@ class CI_DB_forge { } /* End of file DB_forge.php */ -/* Location: ./system/database/DB_forge.php */ +/* Location: ./system/database/DB_forge.php */
\ No newline at end of file diff --git a/system/database/DB_active_rec.php b/system/database/DB_query_builder.php index 424735157..488b294e4 100644 --- a/system/database/DB_active_rec.php +++ b/system/database/DB_query_builder.php @@ -2,7 +2,7 @@ /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE * @@ -25,12 +25,10 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** - * Active Record Class + * Query Builder Class * - * This is the platform-independent base Active Record implementation class. + * This is the platform-independent base Query Builder implementation class. * * @package CodeIgniter * @subpackage Drivers @@ -38,46 +36,46 @@ * @author EllisLab Dev Team * @link http://codeigniter.com/user_guide/database/ */ -class CI_DB_active_record extends CI_DB_driver { + +abstract class CI_DB_query_builder extends CI_DB_driver { protected $return_delete_sql = FALSE; protected $reset_delete_data = FALSE; - protected $ar_select = array(); - protected $ar_distinct = FALSE; - protected $ar_from = array(); - protected $ar_join = array(); - protected $ar_where = array(); - protected $ar_like = array(); - protected $ar_groupby = array(); - protected $ar_having = array(); - protected $ar_keys = array(); - protected $ar_limit = FALSE; - protected $ar_offset = FALSE; - protected $ar_order = FALSE; - protected $ar_orderby = array(); - protected $ar_set = array(); - protected $ar_wherein = array(); - protected $ar_aliased_tables = array(); - protected $ar_store_array = array(); - protected $ar_where_group_started = FALSE; - protected $ar_where_group_count = 0; - - // Active Record Caching variables - protected $ar_caching = FALSE; - protected $ar_cache_exists = array(); - protected $ar_cache_select = array(); - protected $ar_cache_from = array(); - protected $ar_cache_join = array(); - protected $ar_cache_where = array(); - protected $ar_cache_like = array(); - protected $ar_cache_groupby = array(); - protected $ar_cache_having = array(); - protected $ar_cache_orderby = array(); - protected $ar_cache_set = array(); - - protected $ar_no_escape = array(); - protected $ar_cache_no_escape = array(); + protected $qb_select = array(); + protected $qb_distinct = FALSE; + protected $qb_from = array(); + protected $qb_join = array(); + protected $qb_where = array(); + protected $qb_like = array(); + protected $qb_groupby = array(); + protected $qb_having = array(); + protected $qb_keys = array(); + protected $qb_limit = FALSE; + protected $qb_offset = FALSE; + protected $qb_orderby = array(); + protected $qb_set = array(); + protected $qb_wherein = array(); + protected $qb_aliased_tables = array(); + protected $qb_store_array = array(); + protected $qb_where_group_started = FALSE; + protected $qb_where_group_count = 0; + + // Query Builder Caching variables + protected $qb_caching = FALSE; + protected $qb_cache_exists = array(); + protected $qb_cache_select = array(); + protected $qb_cache_from = array(); + protected $qb_cache_join = array(); + protected $qb_cache_where = array(); + protected $qb_cache_like = array(); + protected $qb_cache_groupby = array(); + protected $qb_cache_having = array(); + protected $qb_cache_orderby = array(); + protected $qb_cache_set = array(); + + protected $qb_no_escape = array(); + protected $qb_cache_no_escape = array(); /** * Select @@ -85,6 +83,7 @@ class CI_DB_active_record extends CI_DB_driver { * Generates the SELECT portion of the query * * @param string + * @param mixed * @return object */ public function select($select = '*', $escape = NULL) @@ -94,20 +93,23 @@ class CI_DB_active_record extends CI_DB_driver { $select = explode(',', $select); } + // If the escape value was not set will will base it on the global setting + is_bool($escape) OR $escape = $this->_protect_identifiers; + foreach ($select as $val) { $val = trim($val); - if ($val != '') + if ($val !== '') { - $this->ar_select[] = $val; - $this->ar_no_escape[] = $escape; + $this->qb_select[] = $val; + $this->qb_no_escape[] = $escape; - if ($this->ar_caching === TRUE) + if ($this->qb_caching === TRUE) { - $this->ar_cache_select[] = $val; - $this->ar_cache_exists[] = 'select'; - $this->ar_cache_no_escape[] = $escape; + $this->qb_cache_select[] = $val; + $this->qb_cache_exists[] = 'select'; + $this->qb_cache_no_escape[] = $escape; } } } @@ -195,7 +197,7 @@ class CI_DB_active_record extends CI_DB_driver { */ protected function _max_min_avg_sum($select = '', $alias = '', $type = 'MAX') { - if ( ! is_string($select) OR $select == '') + if ( ! is_string($select) OR $select === '') { $this->display_error('db_invalid_query'); } @@ -207,18 +209,20 @@ class CI_DB_active_record extends CI_DB_driver { show_error('Invalid function type: '.$type); } - if ($alias == '') + if ($alias === '') { $alias = $this->_create_alias_from_table(trim($select)); } - $sql = $this->_protect_identifiers($type.'('.trim($select).')').' AS '.$this->_protect_identifiers(trim($alias)); - $this->ar_select[] = $sql; + $sql = $this->protect_identifiers($type.'('.trim($select).')').' AS '.$this->escape_identifiers(trim($alias)); - if ($this->ar_caching === TRUE) + $this->qb_select[] = $sql; + $this->qb_no_escape[] = NULL; + + if ($this->qb_caching === TRUE) { - $this->ar_cache_select[] = $sql; - $this->ar_cache_exists[] = 'select'; + $this->qb_cache_select[] = $sql; + $this->qb_cache_exists[] = 'select'; } return $this; @@ -236,7 +240,8 @@ class CI_DB_active_record extends CI_DB_driver { { if (strpos($item, '.') !== FALSE) { - return end(explode('.', $item)); + $item = explode('.', $item); + return end($item); } return $item; @@ -254,7 +259,7 @@ class CI_DB_active_record extends CI_DB_driver { */ public function distinct($val = TRUE) { - $this->ar_distinct = (is_bool($val)) ? $val : TRUE; + $this->qb_distinct = is_bool($val) ? $val : TRUE; return $this; } @@ -270,7 +275,7 @@ class CI_DB_active_record extends CI_DB_driver { */ public function from($from) { - foreach ((array)$from as $val) + foreach ((array) $from as $val) { if (strpos($val, ',') !== FALSE) { @@ -278,12 +283,13 @@ class CI_DB_active_record extends CI_DB_driver { { $v = trim($v); $this->_track_aliases($v); - $v = $this->ar_from[] = $this->_protect_identifiers($v, TRUE, NULL, FALSE); - if ($this->ar_caching === TRUE) + $this->qb_from[] = $v = $this->protect_identifiers($v, TRUE, NULL, FALSE); + + if ($this->qb_caching === TRUE) { - $this->ar_cache_from[] = $v; - $this->ar_cache_exists[] = 'from'; + $this->qb_cache_from[] = $v; + $this->qb_cache_exists[] = 'from'; } } } @@ -292,14 +298,15 @@ class CI_DB_active_record extends CI_DB_driver { $val = trim($val); // Extract any aliases that might exist. We use this information - // in the _protect_identifiers to know whether to add a table prefix + // in the protect_identifiers to know whether to add a table prefix $this->_track_aliases($val); - $this->ar_from[] = $val = $this->_protect_identifiers($val, TRUE, NULL, FALSE); - if ($this->ar_caching === TRUE) + $this->qb_from[] = $val = $this->protect_identifiers($val, TRUE, NULL, FALSE); + + if ($this->qb_caching === TRUE) { - $this->ar_cache_from[] = $val; - $this->ar_cache_exists[] = 'from'; + $this->qb_cache_from[] = $val; + $this->qb_cache_exists[] = 'from'; } } } @@ -317,15 +324,16 @@ class CI_DB_active_record extends CI_DB_driver { * @param string * @param string the join condition * @param string the type of join + * @param string wether not to try to escape identifiers * @return object */ - public function join($table, $cond, $type = '') + public function join($table, $cond, $type = '', $escape = TRUE) { - if ($type != '') + if ($type !== '') { $type = strtoupper(trim($type)); - if ( ! in_array($type, array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER'))) + if ( ! in_array($type, array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER'), TRUE)) { $type = ''; } @@ -336,22 +344,49 @@ class CI_DB_active_record extends CI_DB_driver { } // Extract any aliases that might exist. We use this information - // in the _protect_identifiers to know whether to add a table prefix + // in the protect_identifiers to know whether to add a table prefix $this->_track_aliases($table); - // Strip apart the condition and protect the identifiers - if (preg_match('/([\w\.]+)([\W\s]+)(.+)/', $cond, $match)) + // Split multiple conditions + if ($escape === TRUE && preg_match_all('/\sAND\s|\sOR\s/i', $cond, $m, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) + { + $newcond = ''; + $m[0][] = array('', strlen($cond)); + + for ($i = 0, $c = count($m[0]), $s = 0; + $i < $c; + $s += $m[0][$i][1] + strlen($m[0][$i][0]), $i++) + { + $temp = substr($cond, $s, $m[0][$i][1]); + + $newcond .= preg_match('/([\[\w\.-]+)([\W\s]+)(.+)/i', $temp, $match) + ? $this->protect_identifiers($match[1]).$match[2].$this->protect_identifiers($match[3]) + : $temp; + + $newcond .= $m[0][$i][0]; + } + + $cond = $newcond; + } + // Split apart the condition and protect the identifiers + elseif ($escape === TRUE && preg_match('/([\[\w\.-]+)([\W\s]+)(.+)/i', $cond, $match)) + { + $cond = $this->protect_identifiers($match[1]).$match[2].$this->protect_identifiers($match[3]); + } + + // Do we want to escape the table name? + if ($escape === TRUE) { - $cond = $this->_protect_identifiers($match[1]).$match[2].$this->_protect_identifiers($match[3]); + $table = $this->protect_identifiers($table, TRUE, NULL, FALSE); } // Assemble the JOIN statement - $this->ar_join[] = $join = $type.'JOIN '.$this->_protect_identifiers($table, TRUE, NULL, FALSE).' ON '.$cond; + $this->qb_join[] = $join = $type.'JOIN '.$this->protect_identifiers($table, TRUE, NULL, FALSE).' ON '.$cond; - if ($this->ar_caching === TRUE) + if ($this->qb_caching === TRUE) { - $this->ar_cache_join[] = $join; - $this->ar_cache_exists[] = 'join'; + $this->qb_cache_join[] = $join; + $this->qb_cache_exists[] = 'join'; } return $this; @@ -367,6 +402,7 @@ class CI_DB_active_record extends CI_DB_driver { * * @param mixed * @param mixed + * @param bool * @return object */ public function where($key, $value = NULL, $escape = TRUE) @@ -384,6 +420,7 @@ class CI_DB_active_record extends CI_DB_driver { * * @param mixed * @param mixed + * @param bool * @return object */ public function or_where($key, $value = NULL, $escape = TRUE) @@ -401,6 +438,7 @@ class CI_DB_active_record extends CI_DB_driver { * @param mixed * @param mixed * @param string + * @param mixed * @return object */ protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL) @@ -413,14 +451,15 @@ class CI_DB_active_record extends CI_DB_driver { } // If the escape value was not set will will base it on the global setting - if ( ! is_bool($escape)) - { - $escape = $this->_protect_identifiers; - } + $escape = $this->_protect_identifiers; foreach ($key as $k => $v) { - $prefix = (count($this->ar_where) === 0 AND count($this->ar_cache_where) === 0) ? '' : $type; + $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) ? '' : $type; + + $k = $this->_has_operator($k) + ? $this->protect_identifiers(substr($k, 0, strpos(rtrim($k), ' ')), FALSE, $escape).strchr(rtrim($k), ' ') + : $this->protect_identifiers($k, FALSE, $escape); if (is_null($v) && ! $this->_has_operator($k)) { @@ -432,7 +471,6 @@ class CI_DB_active_record extends CI_DB_driver { { if ($escape === TRUE) { - $k = $this->_protect_identifiers($k, FALSE, $escape); $v = ' '.$this->escape($v); } @@ -441,16 +479,12 @@ class CI_DB_active_record extends CI_DB_driver { $k .= ' = '; } } - else - { - $k = $this->_protect_identifiers($k, FALSE, $escape); - } - $this->ar_where[] = $prefix.$k.$v; - if ($this->ar_caching === TRUE) + $this->qb_where[] = $prefix.$k.$v; + if ($this->qb_caching === TRUE) { - $this->ar_cache_where[] = $prefix.$k.$v; - $this->ar_cache_exists[] = 'where'; + $this->qb_cache_where[] = $prefix.$k.$v; + $this->qb_cache_exists[] = 'where'; } } @@ -535,7 +569,7 @@ class CI_DB_active_record extends CI_DB_driver { * * @param string The field to search * @param array The values searched on - * @param boolean If the statement would be IN or NOT IN + * @param bool If the statement would be IN or NOT IN * @param string * @return object */ @@ -543,7 +577,7 @@ class CI_DB_active_record extends CI_DB_driver { { if ($key === NULL OR $values === NULL) { - return; + return $this; } $type = $this->_group_get_type($type); @@ -557,20 +591,20 @@ class CI_DB_active_record extends CI_DB_driver { foreach ($values as $value) { - $this->ar_wherein[] = $this->escape($value); + $this->qb_wherein[] = $this->escape($value); } - $prefix = (count($this->ar_where) === 0) ? '' : $type; - $this->ar_where[] = $where_in = $prefix.$this->_protect_identifiers($key).$not.' IN ('.implode(', ', $this->ar_wherein).') '; + $prefix = (count($this->qb_where) === 0) ? '' : $type; + $this->qb_where[] = $where_in = $prefix.$this->protect_identifiers($key).$not.' IN ('.implode(', ', $this->qb_wherein).') '; - if ($this->ar_caching === TRUE) + if ($this->qb_caching === TRUE) { - $this->ar_cache_where[] = $where_in; - $this->ar_cache_exists[] = 'where'; + $this->qb_cache_where[] = $where_in; + $this->qb_cache_exists[] = 'where'; } // reset the array for multiple calls - $this->ar_wherein = array(); + $this->qb_wherein = array(); return $this; } @@ -665,38 +699,38 @@ class CI_DB_active_record extends CI_DB_driver { foreach ($field as $k => $v) { - $k = $this->_protect_identifiers($k); - $prefix = (count($this->ar_like) === 0) ? '' : $type; + $k = $this->protect_identifiers($k); + $prefix = (count($this->qb_like) === 0) ? '' : $type; $v = $this->escape_like_str($v); if ($side === 'none') { - $like_statement = $prefix." $k $not LIKE '{$v}'"; + $like_statement = "{$prefix} $k $not LIKE '{$v}'"; } elseif ($side === 'before') { - $like_statement = $prefix." $k $not LIKE '%{$v}'"; + $like_statement = "{$prefix} $k $not LIKE '%{$v}'"; } elseif ($side === 'after') { - $like_statement = $prefix." $k $not LIKE '{$v}%'"; + $like_statement = "{$prefix} $k $not LIKE '{$v}%'"; } else { - $like_statement = $prefix." $k $not LIKE '%{$v}%'"; + $like_statement = "{$prefix} $k $not LIKE '%{$v}%'"; } // some platforms require an escape sequence definition for LIKE wildcards - if ($this->_like_escape_str != '') + if ($this->_like_escape_str !== '') { $like_statement = $like_statement.sprintf($this->_like_escape_str, $this->_like_escape_chr); } - $this->ar_like[] = $like_statement; - if ($this->ar_caching === TRUE) + $this->qb_like[] = $like_statement; + if ($this->qb_caching === TRUE) { - $this->ar_cache_like[] = $like_statement; - $this->ar_cache_exists[] = 'like'; + $this->qb_cache_like[] = $like_statement; + $this->qb_cache_exists[] = 'like'; } } @@ -716,13 +750,14 @@ class CI_DB_active_record extends CI_DB_driver { public function group_start($not = '', $type = 'AND ') { $type = $this->_group_get_type($type); - $this->ar_where_group_started = TRUE; - $prefix = (count($this->ar_where) === 0 AND count($this->ar_cache_where) === 0) ? '' : $type; - $this->ar_where[] = $value = $prefix.$not.str_repeat(' ', ++$this->ar_where_group_count).' ('; - if ($this->ar_caching) + $this->qb_where_group_started = TRUE; + $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) ? '' : $type; + $this->qb_where[] = $value = $prefix.$not.str_repeat(' ', ++$this->qb_where_group_count).' ('; + + if ($this->qb_caching) { - $this->ar_cache_where[] = $value; + $this->qb_cache_where[] = $value; } return $this; @@ -773,12 +808,12 @@ class CI_DB_active_record extends CI_DB_driver { */ public function group_end() { - $this->ar_where_group_started = FALSE; - $this->ar_where[] = $value = str_repeat(' ', $this->ar_where_group_count--) . ')'; + $this->qb_where_group_started = FALSE; + $this->qb_where[] = $value = str_repeat(' ', $this->qb_where_group_count--) . ')'; - if ($this->ar_caching) + if ($this->qb_caching) { - $this->ar_cache_where[] = $value; + $this->qb_cache_where[] = $value; } return $this; @@ -796,10 +831,10 @@ class CI_DB_active_record extends CI_DB_driver { */ protected function _group_get_type($type) { - if ($this->ar_where_group_started) + if ($this->qb_where_group_started) { $type = ''; - $this->ar_where_group_started = FALSE; + $this->qb_where_group_started = FALSE; } return $type; @@ -824,14 +859,14 @@ class CI_DB_active_record extends CI_DB_driver { { $val = trim($val); - if ($val != '') + if ($val !== '') { - $this->ar_groupby[] = $val = $this->_protect_identifiers($val); + $this->qb_groupby[] = $val = $this->protect_identifiers($val); - if ($this->ar_caching === TRUE) + if ($this->qb_caching === TRUE) { - $this->ar_cache_groupby[] = $val; - $this->ar_cache_exists[] = 'groupby'; + $this->qb_cache_groupby[] = $val; + $this->qb_cache_exists[] = 'groupby'; } } } @@ -848,6 +883,7 @@ class CI_DB_active_record extends CI_DB_driver { * * @param string * @param string + * @param bool * @return object */ public function having($key, $value = '', $escape = TRUE) @@ -864,6 +900,7 @@ class CI_DB_active_record extends CI_DB_driver { * * @param string * @param string + * @param bool * @return object */ public function or_having($key, $value = '', $escape = TRUE) @@ -880,6 +917,8 @@ class CI_DB_active_record extends CI_DB_driver { * * @param string * @param string + * @param string + * @param bool * @return object */ protected function _having($key, $value = '', $type = 'AND ', $escape = TRUE) @@ -891,11 +930,11 @@ class CI_DB_active_record extends CI_DB_driver { foreach ($key as $k => $v) { - $prefix = (count($this->ar_having) === 0) ? '' : $type; + $prefix = (count($this->qb_having) === 0) ? '' : $type; if ($escape === TRUE) { - $k = $this->_protect_identifiers($k); + $k = $this->protect_identifiers($k); } if ( ! $this->_has_operator($k)) @@ -903,16 +942,16 @@ class CI_DB_active_record extends CI_DB_driver { $k .= ' = '; } - if ($v != '') + if ($v !== '') { $v = ' '.$this->escape($v); } - $this->ar_having[] = $prefix.$k.$v; - if ($this->ar_caching === TRUE) + $this->qb_having[] = $prefix.$k.$v; + if ($this->qb_caching === TRUE) { - $this->ar_cache_having[] = $prefix.$k.$v; - $this->ar_cache_exists[] = 'having'; + $this->qb_cache_having[] = $prefix.$k.$v; + $this->qb_cache_exists[] = 'having'; } } @@ -936,9 +975,9 @@ class CI_DB_active_record extends CI_DB_driver { $orderby = ''; // Random results want or don't need a field name $direction = $this->_random_keyword; } - elseif (trim($direction) != '') + elseif (trim($direction) !== '') { - $direction = (in_array(strtoupper(trim($direction)), array('ASC', 'DESC'), TRUE)) ? ' '.$direction : ' ASC'; + $direction = in_array(strtoupper(trim($direction)), array('ASC', 'DESC'), TRUE) ? ' '.$direction : ' ASC'; } @@ -948,9 +987,11 @@ class CI_DB_active_record extends CI_DB_driver { foreach (explode(',', $orderby) as $part) { $part = trim($part); - if ( ! in_array($part, $this->ar_aliased_tables)) + if ( ! in_array($part, $this->qb_aliased_tables)) { - $part = $this->_protect_identifiers(trim($part)); + $part = preg_match('/^(.+)\s+(ASC|DESC)$/i', $part, $matches) + ? $this->protect_identifiers(rtrim($matches[1])).' '.$matches[2] + : $this->protect_identifiers($part); } $temp[] = $part; @@ -958,20 +999,19 @@ class CI_DB_active_record extends CI_DB_driver { $orderby = implode(', ', $temp); } - elseif ($direction != $this->_random_keyword) + elseif ($direction !== $this->_random_keyword && $escape === TRUE) { - if ($escape === TRUE) - { - $orderby = $this->_protect_identifiers($orderby); - } + $orderby = preg_match('/^(.+)\s+(ASC|DESC)$/i', $orderby, $matches) + ? $this->protect_identifiers(rtrim($matches[1])).' '.$matches[2] + : $this->protect_identifiers($orderby); } - $this->ar_orderby[] = $orderby_statement = $orderby.$direction; + $this->qb_orderby[] = $orderby_statement = $orderby.$direction; - if ($this->ar_caching === TRUE) + if ($this->qb_caching === TRUE) { - $this->ar_cache_orderby[] = $orderby_statement; - $this->ar_cache_exists[] = 'orderby'; + $this->qb_cache_orderby[] = $orderby_statement; + $this->qb_cache_exists[] = 'orderby'; } return $this; @@ -982,17 +1022,17 @@ class CI_DB_active_record extends CI_DB_driver { /** * Sets the LIMIT value * - * @param integer the limit value - * @param integer the offset value + * @param int the limit value + * @param int the offset value * @return object */ public function limit($value, $offset = NULL) { - $this->ar_limit = (int) $value; + $this->qb_limit = (int) $value; - if ( ! is_null($offset)) + if ( ! empty($offset)) { - $this->ar_offset = (int) $offset; + $this->qb_offset = (int) $offset; } return $this; @@ -1003,12 +1043,12 @@ class CI_DB_active_record extends CI_DB_driver { /** * Sets the OFFSET value * - * @param integer the offset value + * @param int the offset value * @return object */ public function offset($offset) { - $this->ar_offset = (int) $offset; + $this->qb_offset = (int) $offset; return $this; } @@ -1019,7 +1059,7 @@ class CI_DB_active_record extends CI_DB_driver { * * @param mixed * @param string - * @param boolean + * @param bool * @return object */ public function set($key, $value = '', $escape = TRUE) @@ -1035,11 +1075,11 @@ class CI_DB_active_record extends CI_DB_driver { { if ($escape === FALSE) { - $this->ar_set[$this->_protect_identifiers($k)] = $v; + $this->qb_set[$this->protect_identifiers($k)] = $v; } else { - $this->ar_set[$this->_protect_identifiers($k, FALSE, TRUE)] = $this->escape($v); + $this->qb_set[$this->protect_identifiers($k, FALSE, TRUE)] = $this->escape($v); } } @@ -1053,20 +1093,19 @@ class CI_DB_active_record extends CI_DB_driver { * * Compiles a SELECT query string and returns the sql. * - * @access public * @param string the table name to select from (optional) - * @param boolean TRUE: resets AR values; FALSE: leave AR vaules alone + * @param bool TRUE: resets QB values; FALSE: leave QB vaules alone * @return string */ public function get_compiled_select($table = '', $reset = TRUE) { - if ($table != '') + if ($table !== '') { $this->_track_aliases($table); $this->from($table); } - $select = $this->_compile_select(); + $select = $this->_compile_select(); if ($reset === TRUE) { @@ -1089,15 +1128,15 @@ class CI_DB_active_record extends CI_DB_driver { * @param string the offset clause * @return object */ - public function get($table = '', $limit = null, $offset = null) + public function get($table = '', $limit = NULL, $offset = NULL) { - if ($table != '') + if ($table !== '') { $this->_track_aliases($table); $this->from($table); } - if ( ! is_null($limit)) + if ( ! empty($limit)) { $this->limit($limit, $offset); } @@ -1107,24 +1146,26 @@ class CI_DB_active_record extends CI_DB_driver { return $result; } + // -------------------------------------------------------------------- + /** * "Count All Results" query * * Generates a platform-specific query string that counts all records - * returned by an Active Record query. + * returned by an Query Builder query. * * @param string * @return string */ public function count_all_results($table = '') { - if ($table != '') + if ($table !== '') { $this->_track_aliases($table); $this->from($table); } - $result = $this->query($this->_compile_select($this->_count_string.$this->_protect_identifiers('numrows'))); + $result = $this->query($this->_compile_select($this->_count_string.$this->protect_identifiers('numrows'))); $this->_reset_select(); if ($result->num_rows() === 0) @@ -1135,6 +1176,7 @@ class CI_DB_active_record extends CI_DB_driver { $row = $result->row(); return (int) $row->numrows; } + // -------------------------------------------------------------------- /** @@ -1149,7 +1191,7 @@ class CI_DB_active_record extends CI_DB_driver { */ public function get_where($table = '', $where = null, $limit = null, $offset = null) { - if ($table != '') + if ($table !== '') { $this->from($table); } @@ -1159,7 +1201,7 @@ class CI_DB_active_record extends CI_DB_driver { $this->where($where); } - if ( ! is_null($limit)) + if ( ! empty($limit)) { $this->limit($limit, $offset); } @@ -1187,7 +1229,7 @@ class CI_DB_active_record extends CI_DB_driver { $this->set_insert_batch($set); } - if (count($this->ar_set) === 0) + if (count($this->qb_set) === 0) { if ($this->db_debug) { @@ -1197,20 +1239,20 @@ class CI_DB_active_record extends CI_DB_driver { return FALSE; } - if ($table == '') + if ($table === '') { - if ( ! isset($this->ar_from[0])) + if ( ! isset($this->qb_from[0])) { return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE; } - $table = $this->ar_from[0]; + $table = $this->qb_from[0]; } // Batch this baby - for ($i = 0, $total = count($this->ar_set); $i < $total; $i += 100) + for ($i = 0, $total = count($this->qb_set); $i < $total; $i += 100) { - $this->query($this->_insert_batch($this->_protect_identifiers($table, TRUE, NULL, FALSE), $this->ar_keys, array_slice($this->ar_set, $i, 100))); + $this->query($this->_insert_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), $this->qb_keys, array_slice($this->qb_set, $i, 100))); } $this->_reset_write(); @@ -1220,11 +1262,28 @@ class CI_DB_active_record extends CI_DB_driver { // -------------------------------------------------------------------- /** + * Insert_batch statement + * + * Generates a platform-specific insert string from the supplied data. + * + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + protected function _insert_batch($table, $keys, $values) + { + return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES '.implode(', ', $values); + } + + // -------------------------------------------------------------------- + + /** * The "set_insert_batch" function. Allows key/value pairs to be set for batch inserts * * @param mixed * @param string - * @param boolean + * @param bool * @return object */ public function set_insert_batch($key, $value = '', $escape = TRUE) @@ -1236,25 +1295,22 @@ class CI_DB_active_record extends CI_DB_driver { $key = array($key => $value); } - $keys = array_keys(current($key)); + $keys = array_keys($this->_object_to_array(current($key))); sort($keys); foreach ($key as $row) { + $row = $this->_object_to_array($row); if (count(array_diff($keys, array_keys($row))) > 0 OR count(array_diff(array_keys($row), $keys)) > 0) { // batch function above returns an error on an empty array - $this->ar_set[] = array(); + $this->qb_set[] = array(); return; } ksort($row); // puts $row in the same order as our keys - if ($escape === FALSE) - { - $this->ar_set[] = '('.implode(',', $row).')'; - } - else + if ($escape !== FALSE) { $clean = array(); foreach ($row as $value) @@ -1262,13 +1318,15 @@ class CI_DB_active_record extends CI_DB_driver { $clean[] = $this->escape($value); } - $this->ar_set[] = '('.implode(',', $clean).')'; + $row = $clean; } + + $this->qb_set[] = '('.implode(',', $row).')'; } foreach ($keys as $k) { - $this->ar_keys[] = $this->_protect_identifiers($k); + $this->qb_keys[] = $this->protect_identifiers($k); } return $this; @@ -1281,9 +1339,8 @@ class CI_DB_active_record extends CI_DB_driver { * * Compiles an insert query and returns the sql * - * @access public * @param string the table to insert into - * @param boolean TRUE: reset AR values; FALSE: leave AR values alone + * @param bool TRUE: reset QB values; FALSE: leave QB values alone * @return string */ public function get_compiled_insert($table = '', $reset = TRUE) @@ -1294,11 +1351,11 @@ class CI_DB_active_record extends CI_DB_driver { } $sql = $this->_insert( - $this->_protect_identifiers( - $this->ar_from[0], TRUE, NULL, FALSE + $this->protect_identifiers( + $this->qb_from[0], TRUE, NULL, FALSE ), - array_keys($this->ar_set), - array_values($this->ar_set) + array_keys($this->qb_set), + array_values($this->qb_set) ); if ($reset === TRUE) @@ -1316,7 +1373,6 @@ class CI_DB_active_record extends CI_DB_driver { * * Compiles an insert string and runs the query * - * @access public * @param string the table to insert data into * @param array an associative array of insert values * @return object @@ -1334,11 +1390,11 @@ class CI_DB_active_record extends CI_DB_driver { } $sql = $this->_insert( - $this->_protect_identifiers( - $this->ar_from[0], TRUE, NULL, FALSE + $this->protect_identifiers( + $this->qb_from[0], TRUE, NULL, FALSE ), - array_keys($this->ar_set), - array_values($this->ar_set) + array_keys($this->qb_set), + array_values($this->qb_set) ); $this->_reset_write(); @@ -1348,33 +1404,46 @@ class CI_DB_active_record extends CI_DB_driver { // -------------------------------------------------------------------- /** + * Insert statement + * + * Generates a platform-specific insert string from the supplied data + * + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + protected function _insert($table, $keys, $values) + { + return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')'; + } + + // -------------------------------------------------------------------- + + /** * Validate Insert * * This method is used by both insert() and get_compiled_insert() to * validate that the there data is actually being set and that table * has been chosen to be inserted into. * - * @access public * @param string the table to insert data into * @return string */ protected function _validate_insert($table = '') { - if (count($this->ar_set) === 0) + if (count($this->qb_set) === 0) { return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE; } - if ($table == '') + if ($table !== '') { - if ( ! isset($this->ar_from[0])) - { - return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE; - } + $this->qb_from[0] = $table; } - else + elseif ( ! isset($this->qb_from[0])) { - $this->ar_from[0] = $table; + return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE; } return TRUE; @@ -1398,22 +1467,23 @@ class CI_DB_active_record extends CI_DB_driver { $this->set($set); } - if (count($this->ar_set) === 0) + if (count($this->qb_set) === 0) { return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE; } - if ($table == '') + if ($table === '') { - if ( ! isset($this->ar_from[0])) + if ( ! isset($this->qb_from[0])) { return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE; } - $table = $this->ar_from[0]; + $table = $this->qb_from[0]; } - $sql = $this->_replace($this->_protect_identifiers($table, TRUE, NULL, FALSE), array_keys($this->ar_set), array_values($this->ar_set)); + $sql = $this->_replace($this->protect_identifiers($table, TRUE, NULL, FALSE), array_keys($this->qb_set), array_values($this->qb_set)); + $this->_reset_write(); return $this->query($sql); } @@ -1421,13 +1491,47 @@ class CI_DB_active_record extends CI_DB_driver { // -------------------------------------------------------------------- /** + * Replace statement + * + * Generates a platform-specific replace string from the supplied data + * + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + protected function _replace($table, $keys, $values) + { + return 'REPLACE INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')'; + } + + // -------------------------------------------------------------------- + + /** + * From Tables + * + * This public function implicitly groups FROM tables so there is no confusion + * about operator precedence in harmony with SQL standards + * + * @param array + * @return string + */ + protected function _from_tables($tables) + { + is_array($tables) OR $tables = array($tables); + + return (count($tables) === 1) ? $tables[0] : '('.implode(', ', $tables).')'; + } + + // -------------------------------------------------------------------- + + /** * Get UPDATE query string * * Compiles an update query and returns the sql * - * @access public * @param string the table to update - * @param boolean TRUE: reset AR values; FALSE: leave AR values alone + * @param bool TRUE: reset QB values; FALSE: leave QB values alone * @return string */ public function get_compiled_update($table = '', $reset = TRUE) @@ -1440,7 +1544,7 @@ class CI_DB_active_record extends CI_DB_driver { return FALSE; } - $sql = $this->_update($this->_protect_identifiers($this->ar_from[0], TRUE, NULL, FALSE), $this->ar_set, $this->ar_where, $this->ar_orderby, $this->ar_limit); + $sql = $this->_update($this->protect_identifiers($this->qb_from[0], TRUE, NULL, FALSE), $this->qb_set, $this->qb_where, $this->qb_orderby, $this->qb_limit); if ($reset === TRUE) { @@ -1477,17 +1581,18 @@ class CI_DB_active_record extends CI_DB_driver { return FALSE; } - if ($where != NULL) + if ($where !== NULL) { $this->where($where); } - if ($limit != NULL) + if ( ! empty($limit)) { $this->limit($limit); } - $sql = $this->_update($this->_protect_identifiers($this->ar_from[0], TRUE, NULL, FALSE), $this->ar_set, $this->ar_where, $this->ar_orderby, $this->ar_limit, $this->ar_like); + $sql = $this->_update($this->protect_identifiers($this->qb_from[0], TRUE, NULL, FALSE), $this->qb_set, $this->qb_where, $this->qb_orderby, $this->qb_limit, $this->qb_like); + $this->_reset_write(); return $this->query($sql); } @@ -1495,33 +1600,64 @@ class CI_DB_active_record extends CI_DB_driver { // -------------------------------------------------------------------- /** + * Update statement + * + * Generates a platform-specific update string from the supplied data + * + * @param string the table name + * @param array the update data + * @param array the where clause + * @param array the orderby clause + * @param array the limit clause + * @param array the like clause + * @return string + */ + protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array()) + { + foreach ($values as $key => $val) + { + $valstr[] = $key.' = '.$val; + } + + $where = empty($where) ? '' : ' WHERE '.implode(' ', $where); + + if ( ! empty($like)) + { + $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like); + } + + return 'UPDATE '.$table.' SET '.implode(', ', $valstr) + .$where + .(count($orderby) > 0 ? ' ORDER BY '.implode(', ', $orderby) : '') + .($limit ? ' LIMIT '.$limit : ''); + } + + // -------------------------------------------------------------------- + + /** * Validate Update * * This method is used by both update() and get_compiled_update() to * validate that data is actually being set and that a table has been * chosen to be update. * - * @access public * @param string the table to update data on * @return bool */ protected function _validate_update($table = '') { - if (count($this->ar_set) == 0) + if (count($this->qb_set) === 0) { return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE; } - if ($table == '') + if ($table !== '') { - if ( ! isset($this->ar_from[0])) - { - return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE; - } + $this->qb_from[0] = $table; } - else + elseif ( ! isset($this->qb_from[0])) { - $this->ar_from[0] = $table; + return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE; } return TRUE; @@ -1554,25 +1690,25 @@ class CI_DB_active_record extends CI_DB_driver { $this->set_update_batch($set, $index); } - if (count($this->ar_set) === 0) + if (count($this->qb_set) === 0) { return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE; } - if ($table == '') + if ($table === '') { - if ( ! isset($this->ar_from[0])) + if ( ! isset($this->qb_from[0])) { return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE; } - $table = $this->ar_from[0]; + $table = $this->qb_from[0]; } // Batch this baby - for ($i = 0, $total = count($this->ar_set); $i < $total; $i += 100) + for ($i = 0, $total = count($this->qb_set); $i < $total; $i += 100) { - $this->query($this->_update_batch($this->_protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->ar_set, $i, 100), $this->_protect_identifiers($index), $this->ar_where)); + $this->query($this->_update_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->qb_set, $i, 100), $this->protect_identifiers($index), $this->qb_where)); } $this->_reset_write(); @@ -1586,7 +1722,7 @@ class CI_DB_active_record extends CI_DB_driver { * * @param array * @param string - * @param boolean + * @param bool * @return object */ public function set_update_batch($key, $index = '', $escape = TRUE) @@ -1604,24 +1740,20 @@ class CI_DB_active_record extends CI_DB_driver { $clean = array(); foreach ($v as $k2 => $v2) { - if ($k2 == $index) + if ($k2 === $index) { $index_set = TRUE; } - else - { - $not[] = $k.'-'.$v; - } - $clean[$this->_protect_identifiers($k2)] = ($escape === FALSE) ? $v2 : $this->escape($v2); + $clean[$this->protect_identifiers($k2)] = ($escape === FALSE) ? $v2 : $this->escape($v2); } - if ($index_set == FALSE) + if ($index_set === FALSE) { return $this->display_error('db_batch_missing_index'); } - $this->ar_set[] = $clean; + $this->qb_set[] = $clean; } return $this; @@ -1639,18 +1771,18 @@ class CI_DB_active_record extends CI_DB_driver { */ public function empty_table($table = '') { - if ($table == '') + if ($table === '') { - if ( ! isset($this->ar_from[0])) + if ( ! isset($this->qb_from[0])) { return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE; } - $table = $this->ar_from[0]; + $table = $this->qb_from[0]; } else { - $table = $this->_protect_identifiers($table, TRUE, NULL, FALSE); + $table = $this->protect_identifiers($table, TRUE, NULL, FALSE); } $sql = $this->_delete($table); @@ -1672,18 +1804,18 @@ class CI_DB_active_record extends CI_DB_driver { */ public function truncate($table = '') { - if ($table == '') + if ($table === '') { - if ( ! isset($this->ar_from[0])) + if ( ! isset($this->qb_from[0])) { return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE; } - $table = $this->ar_from[0]; + $table = $this->qb_from[0]; } else { - $table = $this->_protect_identifiers($table, TRUE, NULL, FALSE); + $table = $this->protect_identifiers($table, TRUE, NULL, FALSE); } $sql = $this->_truncate($table); @@ -1694,13 +1826,30 @@ class CI_DB_active_record extends CI_DB_driver { // -------------------------------------------------------------------- /** + * Truncate statement + * + * Generates a platform-specific truncate string from the supplied data + * + * If the database does not support the truncate() command, + * then this method maps to 'DELETE FROM table' + * + * @param string the table name + * @return string + */ + protected function _truncate($table) + { + return 'TRUNCATE '.$table; + } + + // -------------------------------------------------------------------- + + /** * Get DELETE query string * * Compiles a delete query string and returns the sql * - * @access public * @param string the table to delete from - * @param boolean TRUE: reset AR values; FALSE: leave AR values alone + * @param bool TRUE: reset QB values; FALSE: leave QB values alone * @return string */ public function get_compiled_delete($table = '', $reset = TRUE) @@ -1721,7 +1870,7 @@ class CI_DB_active_record extends CI_DB_driver { * @param mixed the table(s) to delete from. String or array * @param mixed the where clause * @param mixed the limit clause - * @param boolean + * @param bool * @return object */ public function delete($table = '', $where = '', $limit = NULL, $reset_data = TRUE) @@ -1729,14 +1878,14 @@ class CI_DB_active_record extends CI_DB_driver { // Combine any cached components with the current statements $this->_merge_cache(); - if ($table == '') + if ($table === '') { - if ( ! isset($this->ar_from[0])) + if ( ! isset($this->qb_from[0])) { return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE; } - $table = $this->ar_from[0]; + $table = $this->qb_from[0]; } elseif (is_array($table)) { @@ -1750,25 +1899,25 @@ class CI_DB_active_record extends CI_DB_driver { } else { - $table = $this->_protect_identifiers($table, TRUE, NULL, FALSE); + $table = $this->protect_identifiers($table, TRUE, NULL, FALSE); } - if ($where != '') + if ($where !== '') { $this->where($where); } - if ($limit != NULL) + if ( ! empty($limit)) { $this->limit($limit); } - if (count($this->ar_where) === 0 && count($this->ar_wherein) === 0 && count($this->ar_like) === 0) + if (count($this->qb_where) === 0 && count($this->qb_wherein) === 0 && count($this->qb_like) === 0) { return ($this->db_debug) ? $this->display_error('db_del_must_use_where') : FALSE; } - $sql = $this->_delete($table, $this->ar_where, $this->ar_like, $this->ar_limit); + $sql = $this->_delete($table, $this->qb_where, $this->qb_like, $this->qb_limit); if ($reset_data) { $this->_reset_write(); @@ -1780,6 +1929,31 @@ class CI_DB_active_record extends CI_DB_driver { // -------------------------------------------------------------------- /** + * Delete statement + * + * Generates a platform-specific delete string from the supplied data + * + * @param string the table name + * @param array the where clause + * @param array the like clause + * @param string the limit clause + * @return string + */ + protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) + { + $conditions = array(); + + empty($where) OR $conditions[] = implode(' ', $where); + empty($like) OR $conditions[] = implode(' ', $like); + + return 'DELETE FROM '.$table + .(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : '') + .($limit ? ' LIMIT '.(int) $limit : ''); + } + + // -------------------------------------------------------------------- + + /** * DB Prefix * * Prepends a database prefix if one exists in configuration @@ -1789,7 +1963,7 @@ class CI_DB_active_record extends CI_DB_driver { */ public function dbprefix($table = '') { - if ($table == '') + if ($table === '') { $this->display_error('db_table_name_required'); } @@ -1844,15 +2018,15 @@ class CI_DB_active_record extends CI_DB_driver { if (strpos($table, ' ') !== FALSE) { // if the alias is written with the AS keyword, remove it - $table = preg_replace('/ AS /i', ' ', $table); + $table = preg_replace('/\s+AS\s+/i', ' ', $table); // Grab the alias $table = trim(strrchr($table, ' ')); // Store the alias, if it doesn't already exist - if ( ! in_array($table, $this->ar_aliased_tables)) + if ( ! in_array($table, $this->qb_aliased_tables)) { - $this->ar_aliased_tables[] = $table; + $this->qb_aliased_tables[] = $table; } } } @@ -1879,9 +2053,9 @@ class CI_DB_active_record extends CI_DB_driver { } else { - $sql = ( ! $this->ar_distinct) ? 'SELECT ' : 'SELECT DISTINCT '; + $sql = ( ! $this->qb_distinct) ? 'SELECT ' : 'SELECT DISTINCT '; - if (count($this->ar_select) === 0) + if (count($this->qb_select) === 0) { $sql .= '*'; } @@ -1890,73 +2064,69 @@ class CI_DB_active_record extends CI_DB_driver { // Cycle through the "select" portion of the query and prep each column name. // The reason we protect identifiers here rather then in the select() function // is because until the user calls the from() function we don't know if there are aliases - foreach ($this->ar_select as $key => $val) + foreach ($this->qb_select as $key => $val) { - $no_escape = isset($this->ar_no_escape[$key]) ? $this->ar_no_escape[$key] : NULL; - $this->ar_select[$key] = $this->_protect_identifiers($val, FALSE, $no_escape); + $no_escape = isset($this->qb_no_escape[$key]) ? $this->qb_no_escape[$key] : NULL; + $this->qb_select[$key] = $this->protect_identifiers($val, FALSE, $no_escape); } - $sql .= implode(', ', $this->ar_select); + $sql .= implode(', ', $this->qb_select); } } // Write the "FROM" portion of the query - if (count($this->ar_from) > 0) + if (count($this->qb_from) > 0) { - $sql .= "\nFROM ".$this->_from_tables($this->ar_from); + $sql .= "\nFROM ".$this->_from_tables($this->qb_from); } // Write the "JOIN" portion of the query - if (count($this->ar_join) > 0) + if (count($this->qb_join) > 0) { - $sql .= "\n".implode("\n", $this->ar_join); + $sql .= "\n".implode("\n", $this->qb_join); } // Write the "WHERE" portion of the query - if (count($this->ar_where) > 0 OR count($this->ar_like) > 0) + if (count($this->qb_where) > 0 OR count($this->qb_like) > 0) { $sql .= "\nWHERE "; } - $sql .= implode("\n", $this->ar_where); + $sql .= implode("\n", $this->qb_where); // Write the "LIKE" portion of the query - if (count($this->ar_like) > 0) + if (count($this->qb_like) > 0) { - if (count($this->ar_where) > 0) + if (count($this->qb_where) > 0) { $sql .= "\nAND "; } - $sql .= implode("\n", $this->ar_like); + $sql .= implode("\n", $this->qb_like); } // Write the "GROUP BY" portion of the query - if (count($this->ar_groupby) > 0) + if (count($this->qb_groupby) > 0) { - $sql .= "\nGROUP BY ".implode(', ', $this->ar_groupby); + $sql .= "\nGROUP BY ".implode(', ', $this->qb_groupby); } // Write the "HAVING" portion of the query - if (count($this->ar_having) > 0) + if (count($this->qb_having) > 0) { - $sql .= "\nHAVING ".implode("\n", $this->ar_having); + $sql .= "\nHAVING ".implode("\n", $this->qb_having); } // Write the "ORDER BY" portion of the query - if (count($this->ar_orderby) > 0) + if (count($this->qb_orderby) > 0) { - $sql .= "\nORDER BY ".implode(', ', $this->ar_orderby); - if ($this->ar_order !== FALSE) - { - $sql .= ($this->ar_order == 'desc') ? ' DESC' : ' ASC'; - } + $sql .= "\nORDER BY ".implode(', ', $this->qb_orderby); } // Write the "LIMIT" portion of the query - if (is_numeric($this->ar_limit)) + if (is_numeric($this->qb_limit)) { - return $this->_limit($sql."\n", $this->ar_limit, $this->ar_offset); + return $this->_limit($sql."\n", $this->qb_limit, $this->qb_offset); } return $sql; @@ -1972,7 +2142,7 @@ class CI_DB_active_record extends CI_DB_driver { * @param object * @return array */ - public function _object_to_array($object) + protected function _object_to_array($object) { if ( ! is_object($object)) { @@ -1983,7 +2153,7 @@ class CI_DB_active_record extends CI_DB_driver { foreach (get_object_vars($object) as $key => $val) { // There are some built in keys we need to ignore for this conversion - if ( ! is_object($val) && ! is_array($val) && $key != '_parent_name') + if ( ! is_object($val) && ! is_array($val) && $key !== '_parent_name') { $array[$key] = $val; } @@ -2002,7 +2172,7 @@ class CI_DB_active_record extends CI_DB_driver { * @param object * @return array */ - public function _object_to_array_batch($object) + protected function _object_to_array_batch($object) { if ( ! is_object($object)) { @@ -2034,13 +2204,13 @@ class CI_DB_active_record extends CI_DB_driver { /** * Start Cache * - * Starts AR caching + * Starts QB caching * * @return void */ public function start_cache() { - $this->ar_caching = TRUE; + $this->qb_caching = TRUE; } // -------------------------------------------------------------------- @@ -2048,13 +2218,13 @@ class CI_DB_active_record extends CI_DB_driver { /** * Stop Cache * - * Stops AR caching + * Stops QB caching * * @return void */ public function stop_cache() { - $this->ar_caching = FALSE; + $this->qb_caching = FALSE; } // -------------------------------------------------------------------- @@ -2062,25 +2232,24 @@ class CI_DB_active_record extends CI_DB_driver { /** * Flush Cache * - * Empties the AR cache + * Empties the QB cache * - * @access public * @return void */ public function flush_cache() { $this->_reset_run(array( - 'ar_cache_select' => array(), - 'ar_cache_from' => array(), - 'ar_cache_join' => array(), - 'ar_cache_where' => array(), - 'ar_cache_like' => array(), - 'ar_cache_groupby' => array(), - 'ar_cache_having' => array(), - 'ar_cache_orderby' => array(), - 'ar_cache_set' => array(), - 'ar_cache_exists' => array(), - 'ar_cache_no_escape' => array() + 'qb_cache_select' => array(), + 'qb_cache_from' => array(), + 'qb_cache_join' => array(), + 'qb_cache_where' => array(), + 'qb_cache_like' => array(), + 'qb_cache_groupby' => array(), + 'qb_cache_having' => array(), + 'qb_cache_orderby' => array(), + 'qb_cache_set' => array(), + 'qb_cache_exists' => array(), + 'qb_cache_no_escape' => array() )); } @@ -2089,47 +2258,47 @@ class CI_DB_active_record extends CI_DB_driver { /** * Merge Cache * - * When called, this function merges any cached AR arrays with + * When called, this function merges any cached QB arrays with * locally called ones. * * @return void */ protected function _merge_cache() { - if (count($this->ar_cache_exists) === 0) + if (count($this->qb_cache_exists) === 0) { return; } - foreach ($this->ar_cache_exists as $val) + foreach ($this->qb_cache_exists as $val) { - $ar_variable = 'ar_'.$val; - $ar_cache_var = 'ar_cache_'.$val; + $qb_variable = 'qb_'.$val; + $qb_cache_var = 'qb_cache_'.$val; - if (count($this->$ar_cache_var) === 0) + if (count($this->$qb_cache_var) === 0) { continue; } - $this->$ar_variable = array_unique(array_merge($this->$ar_cache_var, $this->$ar_variable)); + $this->$qb_variable = array_unique(array_merge($this->$qb_cache_var, $this->$qb_variable)); } // If we are "protecting identifiers" we need to examine the "from" // portion of the query to determine if there are any aliases - if ($this->_protect_identifiers === TRUE AND count($this->ar_cache_from) > 0) + if ($this->_protect_identifiers === TRUE && count($this->qb_cache_from) > 0) { - $this->_track_aliases($this->ar_from); + $this->_track_aliases($this->qb_from); } - $this->ar_no_escape = $this->ar_cache_no_escape; + $this->qb_no_escape = $this->qb_cache_no_escape; } // -------------------------------------------------------------------- /** - * Reset Active Record values. + * Reset Query Builder values. * - * Publicly-visible method to reset the AR values. + * Publicly-visible method to reset the QB values. * * @return void */ @@ -2142,16 +2311,16 @@ class CI_DB_active_record extends CI_DB_driver { // -------------------------------------------------------------------- /** - * Resets the active record values. Called by the get() function + * Resets the query builder values. Called by the get() function * * @param array An array of fields to reset * @return void */ - protected function _reset_run($ar_reset_items) + protected function _reset_run($qb_reset_items) { - foreach ($ar_reset_items as $item => $default_value) + foreach ($qb_reset_items as $item => $default_value) { - if ( ! in_array($item, $this->ar_store_array)) + if ( ! in_array($item, $this->qb_store_array)) { $this->$item = $default_value; } @@ -2161,28 +2330,27 @@ class CI_DB_active_record extends CI_DB_driver { // -------------------------------------------------------------------- /** - * Resets the active record values. Called by the get() function + * Resets the query builder values. Called by the get() function * * @return void */ protected function _reset_select() { $this->_reset_run(array( - 'ar_select' => array(), - 'ar_from' => array(), - 'ar_join' => array(), - 'ar_where' => array(), - 'ar_like' => array(), - 'ar_groupby' => array(), - 'ar_having' => array(), - 'ar_orderby' => array(), - 'ar_wherein' => array(), - 'ar_aliased_tables' => array(), - 'ar_no_escape' => array(), - 'ar_distinct' => FALSE, - 'ar_limit' => FALSE, - 'ar_offset' => FALSE, - 'ar_order' => FALSE + 'qb_select' => array(), + 'qb_from' => array(), + 'qb_join' => array(), + 'qb_where' => array(), + 'qb_like' => array(), + 'qb_groupby' => array(), + 'qb_having' => array(), + 'qb_orderby' => array(), + 'qb_wherein' => array(), + 'qb_aliased_tables' => array(), + 'qb_no_escape' => array(), + 'qb_distinct' => FALSE, + 'qb_limit' => FALSE, + 'qb_offset' => FALSE ) ); } @@ -2190,7 +2358,7 @@ class CI_DB_active_record extends CI_DB_driver { // -------------------------------------------------------------------- /** - * Resets the active record "write" values. + * Resets the query builder "write" values. * * Called by the insert() update() insert_batch() update_batch() and delete() functions * @@ -2199,19 +2367,18 @@ class CI_DB_active_record extends CI_DB_driver { protected function _reset_write() { $this->_reset_run(array( - 'ar_set' => array(), - 'ar_from' => array(), - 'ar_where' => array(), - 'ar_like' => array(), - 'ar_orderby' => array(), - 'ar_keys' => array(), - 'ar_limit' => FALSE, - 'ar_order' => FALSE - ) - ); + 'qb_set' => array(), + 'qb_from' => array(), + 'qb_where' => array(), + 'qb_like' => array(), + 'qb_orderby' => array(), + 'qb_keys' => array(), + 'qb_limit' => FALSE + ) + ); } } -/* End of file DB_active_rec.php */ -/* Location: ./system/database/DB_active_rec.php */ +/* End of file DB_query_builder.php */ +/* Location: ./system/database/DB_query_builder.php */
\ No newline at end of file diff --git a/system/database/DB_result.php b/system/database/DB_result.php index 730443222..991f6ba94 100644 --- a/system/database/DB_result.php +++ b/system/database/DB_result.php @@ -2,7 +2,7 @@ /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE * @@ -47,11 +47,17 @@ class CI_DB_result { public $num_rows = 0; public $row_data = NULL; + public function __construct(&$driver_object) + { + $this->conn_id = $driver_object->conn_id; + $this->result_id = $driver_object->result_id; + } + /** * Query result. Acts as a wrapper function for the following functions. * * @param string can be "object" or "array" - * @return mixed either a result object or array + * @return object */ public function result($type = 'object') { @@ -75,7 +81,7 @@ class CI_DB_result { return $this->custom_result_object[$class_name]; } - if ($this->result_id === FALSE OR $this->num_rows() == 0) + if ($this->result_id === FALSE OR $this->num_rows() === 0) { return array(); } @@ -102,9 +108,9 @@ class CI_DB_result { // -------------------------------------------------------------------- /** - * Query result. "object" version. + * Query result. "object" version. * - * @return object + * @return array */ public function result_object() { @@ -116,7 +122,7 @@ class CI_DB_result { // In the event that query caching is on the result_id variable // will return FALSE since there isn't a valid SQL resource so // we'll simply return an empty array. - if ($this->result_id === FALSE OR $this->num_rows() == 0) + if ($this->result_id === FALSE OR $this->num_rows() === 0) { return array(); } @@ -147,7 +153,7 @@ class CI_DB_result { // In the event that query caching is on the result_id variable // will return FALSE since there isn't a valid SQL resource so // we'll simply return an empty array. - if ($this->result_id === FALSE OR $this->num_rows() == 0) + if ($this->result_id === FALSE OR $this->num_rows() === 0) { return array(); } @@ -218,7 +224,7 @@ class CI_DB_result { return; } - if ($key != '' AND ! is_null($value)) + if ($key !== '' && ! is_null($value)) { $this->row_data[$key] = $value; } @@ -236,10 +242,10 @@ class CI_DB_result { $result = $this->custom_result_object($type); if (count($result) === 0) { - return $result; + return NULL; } - if ($n != $this->current_row AND isset($result[$n])) + if ($n !== $this->current_row && isset($result[$n])) { $this->current_row = $n; } @@ -247,6 +253,8 @@ class CI_DB_result { return $result[$this->current_row]; } + // -------------------------------------------------------------------- + /** * Returns a single result row - object version * @@ -257,10 +265,10 @@ class CI_DB_result { $result = $this->result_object(); if (count($result) === 0) { - return $result; + return NULL; } - if ($n != $this->current_row AND isset($result[$n])) + if ($n !== $this->current_row && isset($result[$n])) { $this->current_row = $n; } @@ -280,10 +288,10 @@ class CI_DB_result { $result = $this->result_array(); if (count($result) === 0) { - return $result; + return NULL; } - if ($n != $this->current_row AND isset($result[$n])) + if ($n !== $this->current_row && isset($result[$n])) { $this->current_row = $n; } @@ -291,7 +299,6 @@ class CI_DB_result { return $result[$this->current_row]; } - // -------------------------------------------------------------------- /** @@ -302,7 +309,7 @@ class CI_DB_result { public function first_row($type = 'object') { $result = $this->result($type); - return (count($result) === 0) ? $result : $result[0]; + return (count($result) === 0) ? NULL : $result[0]; } // -------------------------------------------------------------------- @@ -315,7 +322,7 @@ class CI_DB_result { public function last_row($type = 'object') { $result = $this->result($type); - return (count($result) === 0) ? $result : $result[count($result) - 1]; + return (count($result) === 0) ? NULL : $result[count($result) - 1]; } // -------------------------------------------------------------------- @@ -330,7 +337,7 @@ class CI_DB_result { $result = $this->result($type); if (count($result) === 0) { - return $result; + return NULL; } if (isset($result[$this->current_row + 1])) @@ -353,7 +360,7 @@ class CI_DB_result { $result = $this->result($type); if (count($result) === 0) { - return $result; + return NULL; } if (isset($result[$this->current_row - 1])) @@ -366,11 +373,23 @@ class CI_DB_result { // -------------------------------------------------------------------- /** + * Returns an unbuffered row and move pointer to next row + * + * @return mixed either a result object or array + */ + public function unbuffered_row($type = 'object') + { + return ($type !== 'array') ? $this->_fetch_object() : $this->_fetch_assoc(); + } + + // -------------------------------------------------------------------- + + /** * The following functions are normally overloaded by the identically named * methods in the platform-specific driver -- except when query caching - * is used. When caching is enabled we do not load the other driver. + * is used. When caching is enabled we do not load the other driver. * These functions are primarily here to prevent undefined function errors - * when a cached result object is in use. They are not otherwise fully + * when a cached result object is in use. They are not otherwise fully * operational due to the unavailability of the database resource IDs with * cached results. */ @@ -378,12 +397,12 @@ class CI_DB_result { public function num_fields() { return 0; } public function list_fields() { return array(); } public function field_data() { return array(); } - public function free_result() { return TRUE; } - protected function _data_seek() { return TRUE; } + public function free_result() { $this->result_id = FALSE; } + protected function _data_seek() { return FALSE; } protected function _fetch_assoc() { return array(); } protected function _fetch_object() { return array(); } } /* End of file DB_result.php */ -/* Location: ./system/database/DB_result.php */ +/* Location: ./system/database/DB_result.php */
\ No newline at end of file diff --git a/system/database/DB_utility.php b/system/database/DB_utility.php index 4c881d8a1..6a3b40779 100644 --- a/system/database/DB_utility.php +++ b/system/database/DB_utility.php @@ -2,7 +2,7 @@ /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE * @@ -32,10 +32,14 @@ * @author EllisLab Dev Team * @link http://codeigniter.com/user_guide/database/ */ -class CI_DB_utility extends CI_DB_forge { +abstract class CI_DB_utility extends CI_DB_forge { public $db; - public $data_cache = array(); + + // Platform specific SQL strings + // Just setting those defaults to FALSE as they are mostly MySQL-specific + protected $_optimize_table = FALSE; + protected $_repair_table = FALSE; public function __construct() { @@ -50,27 +54,34 @@ class CI_DB_utility extends CI_DB_forge { /** * List databases * - * @return bool + * @return array */ public function list_databases() { // Is there a cached result? - if (isset($this->data_cache['db_names'])) + if (isset($this->db->data_cache['db_names'])) + { + return $this->db->data_cache['db_names']; + } + elseif ($this->_list_databases === FALSE) { - return $this->data_cache['db_names']; + return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE; } - $query = $this->db->query($this->_list_databases()); - $dbs = array(); - if ($query->num_rows() > 0) + $this->db->data_cache['db_names'] = array(); + + $query = $this->db->query($this->_list_databases); + if ($query === FALSE) { - foreach ($query->result_array() as $row) - { - $dbs[] = current($row); - } + return $this->db->data_cache['db_names']; } - return $this->data_cache['db_names'] = $dbs; + for ($i = 0, $c = count($query); $i < $c; $i++) + { + $this->db->data_cache['db_names'] = current($query[$i]); + } + + return $this->db->data_cache['db_names']; } // -------------------------------------------------------------------- @@ -79,48 +90,36 @@ class CI_DB_utility extends CI_DB_forge { * Determine if a particular database exists * * @param string - * @return boolean + * @return bool */ public function database_exists($database_name) { - // Some databases won't have access to the list_databases() function, so - // this is intended to allow them to override with their own functions as - // defined in $driver_utility.php - if (method_exists($this, '_database_exists')) - { - return $this->_database_exists($database_name); - } - else - { - return ( ! in_array($database_name, $this->list_databases())) ? FALSE : TRUE; - } + return in_array($database_name, $this->list_databases()); } - // -------------------------------------------------------------------- /** * Optimize Table * * @param string the table name - * @return bool + * @return mixed */ public function optimize_table($table_name) { - $sql = $this->_optimize_table($table_name); - - if (is_bool($sql)) + if ($this->_optimize_table === FALSE) { - show_error('db_must_use_set'); - return FALSE; + return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE; } - $query = $this->db->query($sql); - $res = $query->result_array(); + $query = $this->db->query(sprintf($this->_optimize_table, $this->db->escape_identifiers($table_name))); + if ($query !== FALSE) + { + $query = $query->result_array(); + return current($res); + } - // Note: Due to a bug in current() that affects some versions - // of PHP we can not pass function call directly into it - return current($res); + return FALSE; } // -------------------------------------------------------------------- @@ -128,26 +127,26 @@ class CI_DB_utility extends CI_DB_forge { /** * Optimize Database * - * @return array + * @return mixed */ public function optimize_database() { + if ($this->_optimize_table === FALSE) + { + return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE; + } + $result = array(); foreach ($this->db->list_tables() as $table_name) { - $sql = $this->_optimize_table($table_name); - - if (is_bool($sql)) + $res = $this->db->query(sprintf($this->_optimize_table, $this->db->escape_identifiers($table_name))); + if (is_bool($res)) { - return $sql; + return $res; } - $query = $this->db->query($sql); - // Build the result array... - // Note: Due to a bug in current() that affects some versions - // of PHP we can not pass function call directly into it - $res = $query->result_array(); + $res = $res->result_array(); $res = current($res); $key = str_replace($this->db->database.'.', '', current($res)); $keys = array_keys($res); @@ -165,23 +164,23 @@ class CI_DB_utility extends CI_DB_forge { * Repair Table * * @param string the table name - * @return bool + * @return mixed */ public function repair_table($table_name) { - $sql = $this->_repair_table($table_name); - - if (is_bool($sql)) + if ($this->_repair_table === FALSE) { - return $sql; + return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE; } - $query = $this->db->query($sql); + $query = $this->db->query(sprintf($this->_repair_table, $this->db->escape_identifiers($table_name))); + if (is_bool($query)) + { + return $query; + } - // Note: Due to a bug in current() that affects some versions - // of PHP we can not pass function call directly into it - $res = $query->result_array(); - return current($res); + $query = $query->result_array(); + return current($query); } // -------------------------------------------------------------------- @@ -212,7 +211,7 @@ class CI_DB_utility extends CI_DB_forge { $out = rtrim($out).$newline; // Next blast through the result array and build out the rows - foreach ($query->result_array() as $row) + while ($row = $query->unbuffered_row('array')) { foreach ($row as $item) { @@ -257,18 +256,18 @@ class CI_DB_utility extends CI_DB_forge { $CI->load->helper('xml'); // Generate the result - $xml = "<{$root}>".$newline; - foreach ($query->result_array() as $row) + $xml = '<'.$root.'>'.$newline; + while ($row = $query->unbuffered_row()) { - $xml .= $tab."<{$element}>".$newline; + $xml .= $tab.'<'.$element.'>'.$newline; foreach ($row as $key => $val) { - $xml .= $tab.$tab."<{$key}>".xml_convert($val)."</{$key}>".$newline; + $xml .= $tab.$tab.'<'.$key.'>'.xml_convert($val).'</'.$key.'>'.$newline; } - $xml .= $tab."</{$element}>".$newline; + $xml .= $tab.'</'.$element.'>'.$newline; } - return $xml .= "</$root>".$newline; + return $xml.'</'.$root.'>'.$newline; } // -------------------------------------------------------------------- @@ -328,8 +327,8 @@ class CI_DB_utility extends CI_DB_forge { // Is the encoder supported? If not, we'll either issue an // error or use plain text depending on the debug settings - if (($prefs['format'] === 'gzip' AND ! @function_exists('gzencode')) - OR ($prefs['format'] === 'zip' AND ! @function_exists('gzcompress'))) + if (($prefs['format'] === 'gzip' && ! @function_exists('gzencode')) + OR ($prefs['format'] === 'zip' && ! @function_exists('gzcompress'))) { if ($this->db->db_debug) { @@ -343,7 +342,7 @@ class CI_DB_utility extends CI_DB_forge { if ($prefs['format'] === 'zip') { // Set the filename if not provided (only needed with Zip files) - if ($prefs['filename'] == '') + if ($prefs['filename'] === '') { $prefs['filename'] = (count($prefs['tables']) === 1 ? $prefs['tables'] : $this->db->database) .date('Y-m-d_H-i', time()).'.sql'; @@ -369,7 +368,7 @@ class CI_DB_utility extends CI_DB_forge { $CI->zip->add_data($prefs['filename'], $this->_backup($prefs)); return $CI->zip->get_zip(); } - elseif ($prefs['format'] == 'txt') // Was a text file requested? + elseif ($prefs['format'] === 'txt') // Was a text file requested? { return $this->_backup($prefs); } @@ -384,4 +383,4 @@ class CI_DB_utility extends CI_DB_forge { } /* End of file DB_utility.php */ -/* Location: ./system/database/DB_utility.php */ +/* Location: ./system/database/DB_utility.php */
\ No newline at end of file diff --git a/system/database/drivers/cubrid/cubrid_driver.php b/system/database/drivers/cubrid/cubrid_driver.php index cde719eae..6b67b7546 100644 --- a/system/database/drivers/cubrid/cubrid_driver.php +++ b/system/database/drivers/cubrid/cubrid_driver.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -21,17 +21,15 @@ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com - * @since Version 2.0.2 + * @since Version 2.1 * @filesource */ -// ------------------------------------------------------------------------ - /** * CUBRID Database Adapter Class * * Note: _DB is an extender class that the app controller - * creates dynamically based on whether the active record + * creates dynamically based on whether the query builder * class is being used or not. * * @package CodeIgniter @@ -42,151 +40,134 @@ */ class CI_DB_cubrid_driver extends CI_DB { - // Default CUBRID Broker port. Will be used unless user - // explicitly specifies another one. - const DEFAULT_PORT = 33000; - - var $dbdriver = 'cubrid'; + public $dbdriver = 'cubrid'; // The character used for escaping - no need in CUBRID - var $_escape_char = ''; + protected $_escape_char = '`'; // clause and character used for LIKE escape sequences - not used in CUBRID - var $_like_escape_str = ''; - var $_like_escape_chr = ''; + protected $_like_escape_str = ''; + protected $_like_escape_chr = ''; /** * The syntax to count rows is slightly different across different * database engines, so this string appears in each driver and is * used for the count_all() and count_all_results() functions. */ - var $_count_string = 'SELECT COUNT(*) AS '; - var $_random_keyword = ' RAND()'; // database specific random keyword + protected $_count_string = 'SELECT COUNT(*) AS '; + protected $_random_keyword = ' RAND()'; // database specific random keyword - /** - * Non-persistent database connection - * - * @access private called by the base class - * @return resource - */ - function db_connect() - { - // If no port is defined by the user, use the default value - if ($this->port == '') - { - $this->port = self::DEFAULT_PORT; - } + // CUBRID-specific properties + public $auto_commit = TRUE; - $conn = cubrid_connect($this->hostname, $this->port, $this->database, $this->username, $this->password); + public function __construct($params) + { + parent::__construct($params); - if ($conn) + if (preg_match('/^CUBRID:[^:]+(:[0-9][1-9]{0,4})?:[^:]+:[^:]*:[^:]*:(\?.+)?$/', $this->dsn, $matches)) { - // Check if a user wants to run queries in dry, i.e. run the - // queries but not commit them. - if (isset($this->auto_commit) && ! $this->auto_commit) - { - cubrid_set_autocommit($conn, CUBRID_AUTOCOMMIT_FALSE); - } - else + if (stripos($matches[2], 'autocommit=off') !== FALSE) { - cubrid_set_autocommit($conn, CUBRID_AUTOCOMMIT_TRUE); - $this->auto_commit = TRUE; + $this->auto_commit = FALSE; } } + else + { + // If no port is defined by the user, use the default value + empty($this->port) OR $this->port = 33000; + } + } - return $conn; + /** + * Non-persistent database connection + * + * @return resource + */ + public function db_connect() + { + return $this->_cubrid_connect(); } // -------------------------------------------------------------------- /** * Persistent database connection + * * In CUBRID persistent DB connection is supported natively in CUBRID * engine which can be configured in the CUBRID Broker configuration * file by setting the CCI_PCONNECT parameter to ON. In that case, all * connections established between the client application and the - * server will become persistent. This is calling the same - * @cubrid_connect function will establish persisten connection - * considering that the CCI_PCONNECT is ON. + * server will become persistent. * - * @access private called by the base class * @return resource */ - function db_pconnect() + public function db_pconnect() { - return $this->db_connect(); + return $this->_cubrid_connect(TRUE); } // -------------------------------------------------------------------- /** - * Reconnect + * CUBRID connection * - * Keep / reestablish the db connection if no queries have been - * sent for a length of time exceeding the server's idle timeout + * A CUBRID-specific method to create a connection to the database. + * Except for determining if a persistent connection should be used, + * the rest of the logic is the same for db_connect() and db_pconnect(). * - * @access public - * @return void + * @param bool + * @return resource */ - function reconnect() + protected function _cubrid_connect($persistent = FALSE) { - if (cubrid_ping($this->conn_id) === FALSE) + if (preg_match('/^CUBRID:[^:]+(:[0-9][1-9]{0,4})?:[^:]+:([^:]*):([^:]*):(\?.+)?$/', $this->dsn, $matches)) { - $this->conn_id = FALSE; + $_temp = ($persistent !== TRUE) ? 'cubrid_connect_with_url' : 'cubrid_pconnect_with_url'; + $conn_id = ($matches[2] === '' && $matches[3] === '' && $this->username !== '' && $this->password !== '') + ? $_temp($this->dsn, $this->username, $this->password) + : $_temp($this->dsn); + } + else + { + $_temp = ($persistent !== TRUE) ? 'cubrid_connect' : 'cubrid_pconnect'; + $conn_id = ($this->username !== '') + ? $_temp($this->hostname, $this->port, $this->database, $this->username, $this->password) + : $_temp($this->hostname, $this->port, $this->database); } - } - - // -------------------------------------------------------------------- - /** - * Select the database - * - * @access private called by the base class - * @return resource - */ - function db_select() - { - // In CUBRID there is no need to select a database as the database - // is chosen at the connection time. - // So, to determine if the database is "selected", all we have to - // do is ping the server and return that value. - return cubrid_ping($this->conn_id); + return $conn_id; } // -------------------------------------------------------------------- /** - * Set client character set + * Reconnect * - * @access public - * @param string - * @param string - * @return resource + * Keep / reestablish the db connection if no queries have been + * sent for a length of time exceeding the server's idle timeout + * + * @return void */ - function db_set_charset($charset, $collation) + public function reconnect() { - // In CUBRID, there is no need to set charset or collation. - // This is why returning true will allow the application continue - // its normal process. - return TRUE; + if (cubrid_ping($this->conn_id) === FALSE) + { + $this->conn_id = FALSE; + } } // -------------------------------------------------------------------- /** - * Version number query string + * Database version number * - * @access public * @return string */ - function _version() + public function version() { - // To obtain the CUBRID Server version, no need to run the SQL query. - // CUBRID PHP API provides a function to determin this value. - // This is why we also need to add 'cubrid' value to the list of - // $driver_version_exceptions array in DB_driver class in - // version() function. - return cubrid_get_server_info($this->conn_id); + return isset($this->data_cache['version']) + ? $this->data_cache['version'] + : $this->data_cache['version'] = cubrid_get_server_info($this->conn_id); } // -------------------------------------------------------------------- @@ -194,50 +175,25 @@ class CI_DB_cubrid_driver extends CI_DB { /** * Execute the query * - * @access private called by the base class * @param string an SQL query * @return resource */ - function _execute($sql) + protected function _execute($sql) { - $sql = $this->_prep_query($sql); return @cubrid_query($sql, $this->conn_id); } // -------------------------------------------------------------------- /** - * Prep the query - * - * If needed, each database adapter can prep the query string - * - * @access private called by execute() - * @param string an SQL query - * @return string - */ - function _prep_query($sql) - { - // No need to prepare - return $sql; - } - - // -------------------------------------------------------------------- - - /** * Begin Transaction * - * @access public * @return bool */ - function trans_begin($test_mode = FALSE) + public function trans_begin($test_mode = FALSE) { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } @@ -245,7 +201,7 @@ class CI_DB_cubrid_driver extends CI_DB { // Reset the transaction failure flag. // If the $test_mode flag is set to TRUE transactions will be rolled back // even if the queries produce a successful result. - $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE; + $this->_trans_failure = ($test_mode === TRUE); if (cubrid_get_autocommit($this->conn_id)) { @@ -260,18 +216,12 @@ class CI_DB_cubrid_driver extends CI_DB { /** * Commit Transaction * - * @access public * @return bool */ - function trans_commit() + public function trans_commit() { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } @@ -291,18 +241,12 @@ class CI_DB_cubrid_driver extends CI_DB { /** * Rollback Transaction * - * @access public * @return bool */ - function trans_rollback() + public function trans_rollback() { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } @@ -322,12 +266,11 @@ class CI_DB_cubrid_driver extends CI_DB { /** * Escape String * - * @access public * @param string * @param bool whether or not the string will be used in a LIKE condition * @return string */ - function escape_str($str, $like = FALSE) + public function escape_str($str, $like = FALSE) { if (is_array($str)) { @@ -339,7 +282,9 @@ class CI_DB_cubrid_driver extends CI_DB { return $str; } - if (function_exists('cubrid_real_escape_string') AND is_resource($this->conn_id)) + if (function_exists('cubrid_real_escape_string') && + (is_resource($this->conn_id) + OR (get_resource_type($this->conn_id) === 'Unknown' && preg_match('/Resource id #/', strval($this->conn_id))))) { $str = cubrid_real_escape_string($str, $this->conn_id); } @@ -351,7 +296,7 @@ class CI_DB_cubrid_driver extends CI_DB { // escape LIKE condition wildcards if ($like === TRUE) { - $str = str_replace(array('%', '_'), array('\\%', '\\_'), $str); + return str_replace(array('%', '_'), array('\\%', '\\_'), $str); } return $str; @@ -362,12 +307,11 @@ class CI_DB_cubrid_driver extends CI_DB { /** * Affected Rows * - * @access public - * @return integer + * @return int */ - function affected_rows() + public function affected_rows() { - return @cubrid_affected_rows($this->conn_id); + return @cubrid_affected_rows(); } // -------------------------------------------------------------------- @@ -375,10 +319,9 @@ class CI_DB_cubrid_driver extends CI_DB { /** * Insert ID * - * @access public - * @return integer + * @return int */ - function insert_id() + public function insert_id() { return @cubrid_insert_id($this->conn_id); } @@ -386,52 +329,20 @@ class CI_DB_cubrid_driver extends CI_DB { // -------------------------------------------------------------------- /** - * "Count All" query - * - * Generates a platform-specific query string that counts all records in - * the specified table - * - * @access public - * @param string - * @return string - */ - function count_all($table = '') - { - if ($table == '') - { - return 0; - } - - $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE)); - - if ($query->num_rows() == 0) - { - return 0; - } - - $row = $query->row(); - $this->_reset_select(); - return (int) $row->numrows; - } - - // -------------------------------------------------------------------- - - /** * List table query * * Generates a platform-specific query string so that the table names can be fetched * - * @access private - * @param boolean + * @param bool * @return string */ - function _list_tables($prefix_limit = FALSE) + protected function _list_tables($prefix_limit = FALSE) { - $sql = "SHOW TABLES"; + $sql = 'SHOW TABLES'; - if ($prefix_limit !== FALSE AND $this->dbprefix != '') + if ($prefix_limit !== FALSE && $this->dbprefix !== '') { - $sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%'"; + return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'"; } return $sql; @@ -444,13 +355,12 @@ class CI_DB_cubrid_driver extends CI_DB { * * Generates a platform-specific query string so that the column names can be fetched * - * @access public * @param string the table name * @return string */ - function _list_columns($table = '') + protected function _list_columns($table = '') { - return "SHOW COLUMNS FROM ".$this->_protect_identifiers($table, TRUE, NULL, FALSE); + return 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE); } // -------------------------------------------------------------------- @@ -460,300 +370,68 @@ class CI_DB_cubrid_driver extends CI_DB { * * Generates a platform-specific query so that the column data can be retrieved * - * @access public * @param string the table name - * @return object - */ - function _field_data($table) - { - return "SELECT * FROM ".$table." LIMIT 1"; - } - - // -------------------------------------------------------------------- - - /** - * The error message string - * - * @access private * @return string */ - function _error_message() + protected function _field_data($table) { - return cubrid_error($this->conn_id); + return 'SELECT * FROM '.$table.' LIMIT 1'; } // -------------------------------------------------------------------- /** - * The error message number + * Error * - * @access private - * @return integer - */ - function _error_number() - { - return cubrid_errno($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * Escape the SQL Identifiers - * - * This function escapes column and table names + * Returns an array containing code and message of the last + * database error that has occured. * - * @access private - * @param string - * @return string + * @return array */ - function _escape_identifiers($item) + public function error() { - if ($this->_escape_char == '') - { - return $item; - } - - foreach ($this->_reserved_identifiers as $id) - { - if (strpos($item, '.'.$id) !== FALSE) - { - $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item); - - // remove duplicates if the user already included the escape - return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); - } - } - - if (strpos($item, '.') !== FALSE) - { - $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char; - } - else - { - $str = $this->_escape_char.$item.$this->_escape_char; - } - - // remove duplicates if the user already included the escape - return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); - } - - // -------------------------------------------------------------------- - - /** - * From Tables - * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards - * - * @access public - * @param type - * @return type - */ - function _from_tables($tables) - { - if ( ! is_array($tables)) - { - $tables = array($tables); - } - - return '('.implode(', ', $tables).')'; - } - - // -------------------------------------------------------------------- - - /** - * Insert statement - * - * Generates a platform-specific insert string from the supplied data - * - * @access public - * @param string the table name - * @param array the insert keys - * @param array the insert values - * @return string - */ - function _insert($table, $keys, $values) - { - return "INSERT INTO ".$table." (\"".implode('", "', $keys)."\") VALUES (".implode(', ', $values).")"; - } - - // -------------------------------------------------------------------- - - - /** - * Replace statement - * - * Generates a platform-specific replace string from the supplied data - * - * @access public - * @param string the table name - * @param array the insert keys - * @param array the insert values - * @return string - */ - function _replace($table, $keys, $values) - { - return "REPLACE INTO ".$table." (\"".implode('", "', $keys)."\") VALUES (".implode(', ', $values).")"; - } - - // -------------------------------------------------------------------- - - /** - * Insert_batch statement - * - * Generates a platform-specific insert string from the supplied data - * - * @access public - * @param string the table name - * @param array the insert keys - * @param array the insert values - * @return string - */ - function _insert_batch($table, $keys, $values) - { - return "INSERT INTO ".$table." (\"".implode('", "', $keys)."\") VALUES ".implode(', ', $values); - } - - // -------------------------------------------------------------------- - - - /** - * Update statement - * - * Generates a platform-specific update string from the supplied data - * - * @access public - * @param string the table name - * @param array the update data - * @param array the where clause - * @param array the orderby clause - * @param array the limit clause - * @return string - */ - function _update($table, $values, $where, $orderby = array(), $limit = FALSE) - { - foreach ($values as $key => $val) - { - $valstr[] = sprintf('"%s" = %s', $key, $val); - } - - $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; - - $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):''; - - $sql = "UPDATE ".$table." SET ".implode(', ', $valstr); - - $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : ''; - - $sql .= $orderby.$limit; - - return $sql; + return array('code' => cubrid_errno($this->conn_id), 'message' => cubrid_error($this->conn_id)); } // -------------------------------------------------------------------- - /** * Update_Batch statement * * Generates a platform-specific batch update string from the supplied data * - * @access public * @param string the table name * @param array the update data * @param array the where clause * @return string */ - function _update_batch($table, $values, $index, $where = NULL) + protected function _update_batch($table, $values, $index, $where = NULL) { $ids = array(); - $where = ($where != '' AND count($where) >=1) ? implode(" ", $where).' AND ' : ''; - foreach ($values as $key => $val) { $ids[] = $val[$index]; foreach (array_keys($val) as $field) { - if ($field != $index) + if ($field !== $index) { $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field]; } } } - $sql = "UPDATE ".$table." SET "; $cases = ''; - foreach ($final as $k => $v) { - $cases .= $k.' = CASE '."\n"; - foreach ($v as $row) - { - $cases .= $row."\n"; - } - - $cases .= 'ELSE '.$k.' END, '; - } - - $sql .= substr($cases, 0, -2); - - $sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')'; - - return $sql; - } - - // -------------------------------------------------------------------- - - - /** - * Truncate statement - * - * Generates a platform-specific truncate string from the supplied data - * If the database does not support the truncate() command - * This function maps to "DELETE FROM table" - * - * @access public - * @param string the table name - * @return string - */ - function _truncate($table) - { - return "TRUNCATE ".$table; - } - - // -------------------------------------------------------------------- - - /** - * Delete statement - * - * Generates a platform-specific delete string from the supplied data - * - * @access public - * @param string the table name - * @param array the where clause - * @param string the limit clause - * @return string - */ - function _delete($table, $where = array(), $like = array(), $limit = FALSE) - { - $conditions = ''; - - if (count($where) > 0 OR count($like) > 0) - { - $conditions = "\nWHERE "; - $conditions .= implode("\n", $this->ar_where); - - if (count($where) > 0 && count($like) > 0) - { - $conditions .= " AND "; - } - $conditions .= implode("\n", $like); + $cases .= $k." = CASE \n" + .implode("\n", $v) + .'ELSE '.$k.' END, '; } - $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; - - return "DELETE FROM ".$table.$conditions.$limit; + return 'UPDATE '.$table.' SET '.substr($cases, 0, -2) + .' WHERE '.(($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '') + .$index.' IN ('.implode(',', $ids).')'; } // -------------------------------------------------------------------- @@ -763,24 +441,14 @@ class CI_DB_cubrid_driver extends CI_DB { * * Generates a platform-specific LIMIT clause * - * @access public * @param string the sql query string - * @param integer the number of rows to limit the query to - * @param integer the offset value + * @param int the number of rows to limit the query to + * @param int the offset value * @return string */ - function _limit($sql, $limit, $offset) + protected function _limit($sql, $limit, $offset) { - if ($offset == 0) - { - $offset = ''; - } - else - { - $offset .= ", "; - } - - return $sql."LIMIT ".$offset.$limit; + return $sql.'LIMIT '.($offset == 0 ? '' : $offset.', ').$limit; } // -------------------------------------------------------------------- @@ -788,17 +456,14 @@ class CI_DB_cubrid_driver extends CI_DB { /** * Close DB Connection * - * @access public - * @param resource * @return void */ - function _close($conn_id) + protected function _close() { - @cubrid_close($conn_id); + @cubrid_close($this->conn_id); } } - /* End of file cubrid_driver.php */ /* Location: ./system/database/drivers/cubrid/cubrid_driver.php */
\ No newline at end of file diff --git a/system/database/drivers/cubrid/cubrid_forge.php b/system/database/drivers/cubrid/cubrid_forge.php index 85e740057..d328aa241 100644 --- a/system/database/drivers/cubrid/cubrid_forge.php +++ b/system/database/drivers/cubrid/cubrid_forge.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -21,12 +21,10 @@ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com - * @since Version 1.0 + * @since Version 2.1 * @filesource */ -// ------------------------------------------------------------------------ - /** * CUBRID Forge Class * @@ -36,86 +34,54 @@ */ class CI_DB_cubrid_forge extends CI_DB_forge { - /** - * Create database - * - * @access private - * @param string the database name - * @return bool - */ - function _create_database($name) - { - // CUBRID does not allow to create a database in SQL. The GUI tools - // have to be used for this purpose. - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Drop database - * - * @access private - * @param string the database name - * @return bool - */ - function _drop_database($name) - { - // CUBRID does not allow to drop a database in SQL. The GUI tools - // have to be used for this purpose. - return FALSE; - } - - // -------------------------------------------------------------------- + protected $_create_database = FALSE; + protected $_drop_database = FALSE; /** * Process Fields * - * @access private * @param mixed the fields * @return string */ - function _process_fields($fields) + protected function _process_fields($fields) { $current_field_count = 0; $sql = ''; - foreach ($fields as $field=>$attributes) + foreach ($fields as $field => $attributes) { // Numeric field names aren't allowed in databases, so if the key is // numeric, we know it was assigned by PHP and the developer manually // entered the field information, so we'll simply add it to the list if (is_numeric($field)) { - $sql .= "\n\t$attributes"; + $sql .= "\n\t".$attributes; } else { $attributes = array_change_key_case($attributes, CASE_UPPER); - $sql .= "\n\t\"" . $this->db->_protect_identifiers($field) . "\""; + $sql .= "\n\t".$this->db->escape_identifiers($field); - if (array_key_exists('NAME', $attributes)) - { - $sql .= ' '.$this->db->_protect_identifiers($attributes['NAME']).' '; - } + empty($attributes['NAME']) OR $sql .= ' '.$this->db->escape_identifiers($attributes['NAME']).' '; - if (array_key_exists('TYPE', $attributes)) + if ( ! empty($attributes['TYPE'])) { $sql .= ' '.$attributes['TYPE']; - if (array_key_exists('CONSTRAINT', $attributes)) + if ( ! empty($attributes['CONSTRAINT'])) { - switch ($attributes['TYPE']) + switch (strtolower($attributes['TYPE'])) { case 'decimal': case 'float': case 'numeric': $sql .= '('.implode(',', $attributes['CONSTRAINT']).')'; break; - case 'enum': // As of version 8.4.0 CUBRID does not support - // enum data type. - break; + case 'enum': + // Will be supported in the future as part a part of + // MySQL compatibility features. + break; case 'set': $sql .= '("'.implode('","', $attributes['CONSTRAINT']).'")'; break; @@ -125,33 +91,29 @@ class CI_DB_cubrid_forge extends CI_DB_forge { } } - if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE) + /* As of version 8.4.1 CUBRID does not support UNSIGNED INTEGER data type. + * Will be supported in the next release as a part of MySQL Compatibility. + * + if (isset($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE) { - //$sql .= ' UNSIGNED'; - // As of version 8.4.0 CUBRID does not support UNSIGNED INTEGER data type. - // Will be supported in the next release as a part of MySQL Compatibility. + $sql .= ' UNSIGNED'; } + */ - if (array_key_exists('DEFAULT', $attributes)) + if (isset($attributes['DEFAULT'])) { - $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\''; + $sql .= " DEFAULT '".$attributes['DEFAULT']."'"; } - if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE) - { - $sql .= ' NULL'; - } - else - { - $sql .= ' NOT NULL'; - } + $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE) + ? ' NULL' : ' NOT NULL'; - if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE) + if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE) { $sql .= ' AUTO_INCREMENT'; } - if (array_key_exists('UNIQUE', $attributes) && $attributes['UNIQUE'] === TRUE) + if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE) { $sql .= ' UNIQUE'; } @@ -172,36 +134,31 @@ class CI_DB_cubrid_forge extends CI_DB_forge { /** * Create Table * - * @access private * @param string the table name * @param mixed the fields * @param mixed primary key(s) * @param mixed key(s) - * @param boolean should 'IF NOT EXISTS' be added to the SQL + * @param bool should 'IF NOT EXISTS' be added to the SQL * @return bool */ - function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) + protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) { $sql = 'CREATE TABLE '; + /* As of version 8.4.1 CUBRID does not support this SQL syntax. if ($if_not_exists === TRUE) { - //$sql .= 'IF NOT EXISTS '; - // As of version 8.4.0 CUBRID does not support this SQL syntax. + $sql .= 'IF NOT EXISTS '; } + */ - $sql .= $this->db->_escape_identifiers($table)." ("; - - $sql .= $this->_process_fields($fields); + $sql .= $this->db->escape_identifiers($table).' ('.$this->_process_fields($fields); // If there is a PK defined if (count($primary_keys) > 0) { - $key_name = "pk_" . $table . "_" . - $this->db->_protect_identifiers(implode('_', $primary_keys)); - - $primary_keys = $this->db->_protect_identifiers($primary_keys); - $sql .= ",\n\tCONSTRAINT " . $key_name . " PRIMARY KEY(" . implode(', ', $primary_keys) . ")"; + $key_name = $this->db->escape_identifiers('pk_'.$table.'_'.implode('_', $primary_keys)); + $sql .= ",\n\tCONSTRAINT ".$key_name.' PRIMARY KEY('.implode(', ', $this->db->escape_identifiers($primary_keys)).')'; } if (is_array($keys) && count($keys) > 0) @@ -210,35 +167,20 @@ class CI_DB_cubrid_forge extends CI_DB_forge { { if (is_array($key)) { - $key_name = $this->db->_protect_identifiers(implode('_', $key)); - $key = $this->db->_protect_identifiers($key); + $key_name = $this->db->escape_identifiers('idx_'.$table.implode('_', $key)); + $key = $this->db->escape_identifiers($key); } else { - $key_name = $this->db->_protect_identifiers($key); + $key_name = $this->db->escape_identifiers('idx_'.$table.$key); $key = array($key_name); } - - $sql .= ",\n\tKEY \"{$key_name}\" (" . implode(', ', $key) . ")"; + + $sql .= ",\n\tKEY ".$key_name.' ('.implode(', ', $key).')'; } } - $sql .= "\n);"; - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Drop Table - * - * @access private - * @return string - */ - function _drop_table($table) - { - return "DROP TABLE IF EXISTS ".$this->db->_escape_identifiers($table); + return $sql."\n);"; } // -------------------------------------------------------------------- @@ -249,49 +191,24 @@ class CI_DB_cubrid_forge extends CI_DB_forge { * Generates a platform-specific query so that a table can be altered * Called by add_column(), drop_column(), and column_alter(), * - * @access private * @param string the ALTER type (ADD, DROP, CHANGE) * @param string the column name * @param array fields * @param string the field after which we should add the new field - * @return object + * @return string */ - function _alter_table($alter_type, $table, $fields, $after_field = '') + protected function _alter_table($alter_type, $table, $fields, $after_field = '') { - $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type "; + $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '; // DROP has everything it needs now. - if ($alter_type == 'DROP') + if ($alter_type === 'DROP') { - return $sql.$this->db->_protect_identifiers($fields); + return $sql.$this->db->escape_identifiers($fields); } - $sql .= $this->_process_fields($fields); - - if ($after_field != '') - { - $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field); - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Rename a table - * - * Generates a platform-specific query so that a table can be renamed - * - * @access private - * @param string the old table name - * @param string the new table name - * @return string - */ - function _rename_table($table_name, $new_table_name) - { - $sql = 'RENAME TABLE '.$this->db->_protect_identifiers($table_name)." AS ".$this->db->_protect_identifiers($new_table_name); - return $sql; + return $sql.$this->_process_fields($fields) + .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : ''); } } diff --git a/system/database/drivers/cubrid/cubrid_result.php b/system/database/drivers/cubrid/cubrid_result.php index 4c0fede10..3eb9f7e3d 100644 --- a/system/database/drivers/cubrid/cubrid_result.php +++ b/system/database/drivers/cubrid/cubrid_result.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -21,12 +21,10 @@ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com - * @since Version 2.0.2 + * @since Version 2.1 * @filesource */ -// -------------------------------------------------------------------- - /** * CUBRID Result Class * @@ -41,10 +39,9 @@ class CI_DB_cubrid_result extends CI_DB_result { /** * Number of rows in the result set * - * @access public - * @return integer + * @return int */ - function num_rows() + public function num_rows() { return @cubrid_num_rows($this->result_id); } @@ -54,10 +51,9 @@ class CI_DB_cubrid_result extends CI_DB_result { /** * Number of fields in the result set * - * @access public - * @return integer + * @return int */ - function num_fields() + public function num_fields() { return @cubrid_num_fields($this->result_id); } @@ -69,10 +65,9 @@ class CI_DB_cubrid_result extends CI_DB_result { * * Generates an array of column names * - * @access public * @return array */ - function list_fields() + public function list_fields() { return cubrid_column_names($this->result_id); } @@ -84,59 +79,25 @@ class CI_DB_cubrid_result extends CI_DB_result { * * Generates an array of objects containing field meta-data * - * @access public * @return array */ - function field_data() + public function field_data() { $retval = array(); - - $tablePrimaryKeys = array(); + $i = 0; while ($field = cubrid_fetch_field($this->result_id)) { - $F = new stdClass(); - $F->name = $field->name; - $F->type = $field->type; - $F->default = $field->def; - $F->max_length = $field->max_length; - - // At this moment primary_key property is not returned when - // cubrid_fetch_field is called. The following code will - // provide a patch for it. primary_key property will be added - // in the next release. - - // TODO: later version of CUBRID will provide primary_key - // property. - // When PK is defined in CUBRID, an index is automatically - // created in the db_index system table in the form of - // pk_tblname_fieldname. So the following will count how many - // columns are there which satisfy this format. - // The query will search for exact single columns, thus - // compound PK is not supported. - $res = cubrid_query($this->conn_id, - "SELECT COUNT(*) FROM db_index WHERE class_name = '" . $field->table . - "' AND is_primary_key = 'YES' AND index_name = 'pk_" . - $field->table . "_" . $field->name . "'" - ); - - if ($res) - { - $row = cubrid_fetch_array($res, CUBRID_NUM); - $F->primary_key = ($row[0] > 0 ? 1 : null); - } - else - { - $F->primary_key = null; - } - - if (is_resource($res)) - { - cubrid_close_request($res); - $this->result_id = FALSE; - } - - $retval[] = $F; + $retval[$i] = new stdClass(); + $retval[$i]->name = $field->name; + // CUBRID returns type as e.g. varchar(100), + // so we need to remove all digits and brackets. + $retval[$i]->type = preg_replace('/[\d()]/', '', $field->type); + $retval[$i]->default = $field->def; + // Use CUBRID's native API to obtain column's max_length, + // otherwise $field->max_length has incorrect info + $retval[$i]->max_length = cubrid_field_len($this->result_id, $i); + $retval[$i++]->primary_key = $field->primary_key; } return $retval; @@ -147,13 +108,12 @@ class CI_DB_cubrid_result extends CI_DB_result { /** * Free the result * - * @return null + * @return void */ - function free_result() + public function free_result() { - if(is_resource($this->result_id) || - get_resource_type($this->result_id) == "Unknown" && - preg_match('/Resource id #/', strval($this->result_id))) + if (is_resource($this->result_id) OR + (get_resource_type($this->result_id) === 'Unknown' && preg_match('/Resource id #/', strval($this->result_id)))) { cubrid_close_request($this->result_id); $this->result_id = FALSE; @@ -169,10 +129,9 @@ class CI_DB_cubrid_result extends CI_DB_result { * this internally before fetching results to make sure the * result set starts at zero * - * @access private - * @return array + * @return bool */ - function _data_seek($n = 0) + protected function _data_seek($n = 0) { return cubrid_data_seek($this->result_id, $n); } @@ -184,10 +143,9 @@ class CI_DB_cubrid_result extends CI_DB_result { * * Returns the result set as an array * - * @access private * @return array */ - function _fetch_assoc() + protected function _fetch_assoc() { return cubrid_fetch_assoc($this->result_id); } @@ -199,16 +157,14 @@ class CI_DB_cubrid_result extends CI_DB_result { * * Returns the result set as an object * - * @access private * @return object */ - function _fetch_object() + protected function _fetch_object() { return cubrid_fetch_object($this->result_id); } } - /* End of file cubrid_result.php */ /* Location: ./system/database/drivers/cubrid/cubrid_result.php */
\ No newline at end of file diff --git a/system/database/drivers/cubrid/cubrid_utility.php b/system/database/drivers/cubrid/cubrid_utility.php index 750c0d8dd..ea8feb4e2 100644 --- a/system/database/drivers/cubrid/cubrid_utility.php +++ b/system/database/drivers/cubrid/cubrid_utility.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -21,12 +21,10 @@ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com - * @since Version 1.0 + * @since Version 2.1 * @filesource */ -// ------------------------------------------------------------------------ - /** * CUBRID Utility Class * @@ -39,75 +37,27 @@ class CI_DB_cubrid_utility extends CI_DB_utility { /** * List databases * - * @access private * @return array */ - function _list_databases() + public function list_databases() { - // CUBRID does not allow to see the list of all databases on the - // server. It is the way its architecture is designed. Every - // database is independent and isolated. - // For this reason we can return only the name of the currect - // connected database. - if ($this->conn_id) + if (isset($this->db->data_cache['db_names'])) { - return "SELECT '" . $this->database . "'"; + return $this->db->data_cache['db_names']; } - else - { - return FALSE; - } - } - // -------------------------------------------------------------------- - - /** - * Optimize table query - * - * Generates a platform-specific query so that a table can be optimized - * - * @access private - * @param string the table name - * @return object - * @link http://www.cubrid.org/manual/840/en/Optimize%20Database - */ - function _optimize_table($table) - { - // No SQL based support in CUBRID as of version 8.4.0. Database or - // table optimization can be performed using CUBRID Manager - // database administration tool. See the link above for more info. - return FALSE; + return $this->db->data_cache['db_names'] = cubrid_list_dbs($this->db->conn_id); } // -------------------------------------------------------------------- /** - * Repair table query - * - * Generates a platform-specific query so that a table can be repaired - * - * @access private - * @param string the table name - * @return object - * @link http://www.cubrid.org/manual/840/en/Checking%20Database%20Consistency - */ - function _repair_table($table) - { - // Not supported in CUBRID as of version 8.4.0. Database or - // table consistency can be checked using CUBRID Manager - // database administration tool. See the link above for more info. - return FALSE; - } - - // -------------------------------------------------------------------- - /** * CUBRID Export * - * @access private * @param array Preferences * @return mixed */ - function _backup($params = array()) + protected function _backup($params = array()) { // No SQL based support in CUBRID as of version 8.4.0. Database or // table backup can be performed using CUBRID Manager diff --git a/system/database/drivers/interbase/index.html b/system/database/drivers/interbase/index.html new file mode 100644 index 000000000..c942a79ce --- /dev/null +++ b/system/database/drivers/interbase/index.html @@ -0,0 +1,10 @@ +<html> +<head> + <title>403 Forbidden</title> +</head> +<body> + +<p>Directory access is forbidden.</p> + +</body> +</html>
\ No newline at end of file diff --git a/system/database/drivers/interbase/interbase_driver.php b/system/database/drivers/interbase/interbase_driver.php new file mode 100644 index 000000000..5a03607ee --- /dev/null +++ b/system/database/drivers/interbase/interbase_driver.php @@ -0,0 +1,450 @@ +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +/** + * CodeIgniter + * + * An open source application development framework for PHP 5.2.4 or newer + * + * NOTICE OF LICENSE + * + * Licensed under the Open Software License version 3.0 + * + * This source file is subject to the Open Software License (OSL 3.0) that is + * bundled with this package in the files license.txt / license.rst. It is + * also available through the world wide web at this URL: + * http://opensource.org/licenses/OSL-3.0 + * 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 + * licensing@ellislab.com so we can send you a copy immediately. + * + * @package CodeIgniter + * @author EllisLab Dev Team + * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) + * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * @link http://codeigniter.com + * @since Version 3.0 + * @filesource + */ + +/** + * Firebird/Interbase Database Adapter Class + * + * Note: _DB is an extender class that the app controller + * creates dynamically based on whether the query builder + * class is being used or not. + * + * @package CodeIgniter + * @subpackage Drivers + * @category Database + * @author EllisLab Dev Team + * @link http://codeigniter.com/user_guide/database/ + */ +class CI_DB_interbase_driver extends CI_DB { + + public $dbdriver = 'interbase'; + + // The character used to escape with + protected $_escape_char = '"'; + + // clause and character used for LIKE escape sequences + protected $_like_escape_str = " ESCAPE '%s' "; + protected $_like_escape_chr = '!'; + + /** + * The syntax to count rows is slightly different across different + * database engines, so this string appears in each driver and is + * used for the count_all() and count_all_results() functions. + */ + protected $_count_string = 'SELECT COUNT(*) AS '; + protected $_random_keyword = ' Random()'; // database specific random keyword + + // Keeps track of the resource for the current transaction + protected $trans; + + /** + * Non-persistent database connection + * + * @return resource + */ + public function db_connect() + { + return @ibase_connect($this->hostname.':'.$this->database, $this->username, $this->password, $this->char_set); + } + + // -------------------------------------------------------------------- + + /** + * Persistent database connection + * + * @return resource + */ + public function db_pconnect() + { + return @ibase_pconnect($this->hostname.':'.$this->database, $this->username, $this->password, $this->char_set); + } + + // -------------------------------------------------------------------- + + /** + * Database version number + * + * @return string + */ + public function version() + { + if (isset($this->data_cache['version'])) + { + return $this->data_cache['version']; + } + + if (($service = ibase_service_attach($this->hostname, $this->username, $this->password))) + { + $this->data_cache['version'] = ibase_server_info($service, IBASE_SVC_SERVER_VERSION); + + // Don't keep the service open + ibase_service_detach($service); + return $this->data_cache['version']; + } + + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Execute the query + * + * @param string an SQL query + * @return resource + */ + protected function _execute($sql) + { + return @ibase_query($this->conn_id, $sql); + } + + // -------------------------------------------------------------------- + + /** + * Begin Transaction + * + * @return bool + */ + public function trans_begin($test_mode = FALSE) + { + // When transactions are nested we only begin/commit/rollback the outermost ones + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) + { + return TRUE; + } + + // Reset the transaction failure flag. + // If the $test_mode flag is set to TRUE transactions will be rolled back + // even if the queries produce a successful result. + $this->_trans_failure = ($test_mode === TRUE); + + $this->trans = @ibase_trans($this->conn_id); + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Commit Transaction + * + * @return bool + */ + public function trans_commit() + { + // When transactions are nested we only begin/commit/rollback the outermost ones + if ( ! $this->trans_enabled OR $this->_trans->depth > 0) + { + return TRUE; + } + + return @ibase_commit($this->trans); + } + + // -------------------------------------------------------------------- + + /** + * Rollback Transaction + * + * @return bool + */ + public function trans_rollback() + { + // When transactions are nested we only begin/commit/rollback the outermost ones + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) + { + return TRUE; + } + + return @ibase_rollback($this->trans); + } + + // -------------------------------------------------------------------- + + /** + * Escape String + * + * @param string + * @param bool whether or not the string will be used in a LIKE condition + * @return string + */ + public function escape_str($str, $like = FALSE) + { + if (is_array($str)) + { + foreach ($str as $key => $val) + { + $str[$key] = $this->escape_str($val, $like); + } + + return $str; + } + + // escape LIKE condition wildcards + if ($like === TRUE) + { + return str_replace(array($this->_like_escape_chr, '%', '_'), + array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'), + $str); + } + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Affected Rows + * + * @return int + */ + public function affected_rows() + { + return @ibase_affected_rows($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Insert ID + * + * @param string $generator_name + * @param int $inc_by + * @return int + */ + public function insert_id($generator_name, $inc_by=0) + { + //If a generator hasn't been used before it will return 0 + return ibase_gen_id('"'.$generator_name.'"', $inc_by); + } + + // -------------------------------------------------------------------- + + /** + * List table query + * + * Generates a platform-specific query string so that the table names can be fetched + * + * @param bool + * @return string + */ + protected function _list_tables($prefix_limit = FALSE) + { + $sql = 'SELECT "RDB$RELATION_NAME" FROM "RDB$RELATIONS" WHERE "RDB$RELATION_NAME" NOT LIKE \'RDB$%\' AND "RDB$RELATION_NAME" NOT LIKE \'MON$%\''; + + if ($prefix_limit !== FALSE && $this->dbprefix !== '') + { + return $sql.' AND "RDB$RELATION_NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Show column query + * + * Generates a platform-specific query string so that the column names can be fetched + * + * @param string the table name + * @return string + */ + protected function _list_columns($table = '') + { + return 'SELECT "RDB$FIELD_NAME" FROM "RDB$RELATION_FIELDS" WHERE "RDB$RELATION_NAME" = \''.$this->escape_str($table)."'"; + } + + // -------------------------------------------------------------------- + + /** + * Field data query + * + * Generates a platform-specific query so that the column data can be retrieved + * + * @param string the table name + * @return string + */ + protected function _field_data($table) + { + // Need to find a more efficient way to do this + // but Interbase/Firebird seems to lack the + // limit clause + return 'SELECT * FROM '.$table; + } + + // -------------------------------------------------------------------- + + /** + * Error + * + * Returns an array containing code and message of the last + * database error that has occured. + * + * @return array + */ + public function error() + { + return array('code' => ibase_errcode(), 'message' => ibase_errmsg()); + } + + // -------------------------------------------------------------------- + + /** + * From Tables + * + * This public function implicitly groups FROM tables so there is no confusion + * about operator precedence in harmony with SQL standards + * + * @param array + * @return string + */ + protected function _from_tables($tables) + { + return is_array($tables) ? implode(', ', $tables) : $tables; + } + + // -------------------------------------------------------------------- + + /** + * Update statement + * + * Generates a platform-specific update string from the supplied data + * + * @param string the table name + * @param array the update data + * @param array the where clause + * @param array the orderby clause + * @param array the limit clause (ignored) + * @param array the like clause + * @return string + */ + protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array()) + { + foreach ($values as $key => $val) + { + $valstr[] = $key.' = '.$val; + } + + $where = empty($where) ? '' : ' WHERE '.implode(' ', $where); + + if ( ! empty($like)) + { + $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like); + } + + return 'UPDATE '.$table.' SET '.implode(', ', $valstr) + .$where + .(count($orderby) > 0 ? ' ORDER BY '.implode(', ', $orderby) : ''); + } + + + // -------------------------------------------------------------------- + + /** + * Truncate statement + * + * Generates a platform-specific truncate string from the supplied data + * + * If the database does not support the truncate() command, + * then this method maps to 'DELETE FROM table' + * + * @param string the table name + * @return string + */ + protected function _truncate($table) + { + return 'DELETE FROM '.$table; + } + + // -------------------------------------------------------------------- + + /** + * Delete statement + * + * Generates a platform-specific delete string from the supplied data + * + * @param string the table name + * @param array the where clause + * @param array the like clause + * @param string the limit clause (ignored) + * @return string + */ + protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) + { + $conditions = array(); + + empty($where) OR $conditions[] = implode(' ', $where); + empty($like) OR $conditions[] = implode(' ', $like); + + return 'DELETE FROM '.$table.(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : ''); + } + + // -------------------------------------------------------------------- + + /** + * Limit string + * + * Generates a platform-specific LIMIT clause + * + * @param string the sql query string + * @param int the number of rows to limit the query to + * @param int the offset value + * @return string + */ + protected function _limit($sql, $limit, $offset) + { + // Limit clause depends on if Interbase or Firebird + if (stripos($this->version(), 'firebird') !== FALSE) + { + $select = 'FIRST '. (int) $limit + .($offset > 0 ? ' SKIP '. (int) $offset : ''); + } + else + { + $select = 'ROWS ' + .($offset > 0 ? (int) $offset.' TO '.($limit + $offset) : (int) $limit); + } + + return preg_replace('`SELECT`i', 'SELECT '.$select, $sql); + } + + // -------------------------------------------------------------------- + + /** + * Close DB Connection + * + * @return void + */ + protected function _close() + { + @ibase_close($this->conn_id); + } + +} + +/* End of file interbase_driver.php */ +/* Location: ./system/database/drivers/interbase/interbase_driver.php */
\ No newline at end of file diff --git a/system/database/drivers/interbase/interbase_forge.php b/system/database/drivers/interbase/interbase_forge.php new file mode 100644 index 000000000..d1b006e80 --- /dev/null +++ b/system/database/drivers/interbase/interbase_forge.php @@ -0,0 +1,194 @@ +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +/** + * CodeIgniter + * + * An open source application development framework for PHP 5.2.4 or newer + * + * NOTICE OF LICENSE + * + * Licensed under the Open Software License version 3.0 + * + * This source file is subject to the Open Software License (OSL 3.0) that is + * bundled with this package in the files license.txt / license.rst. It is + * also available through the world wide web at this URL: + * http://opensource.org/licenses/OSL-3.0 + * 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 + * licensing@ellislab.com so we can send you a copy immediately. + * + * @package CodeIgniter + * @author EllisLab Dev Team + * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) + * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * @link http://codeigniter.com + * @since Version 3.0 + * @filesource + */ + +/** + * Interbase/Firebird Forge Class + * + * @category Database + * @author EllisLab Dev Team + * @link http://codeigniter.com/user_guide/database/ + */ +class CI_DB_interbase_forge extends CI_DB_forge { + + protected $_drop_table = 'DROP TABLE %s'; + + /** + * Create database + * + * @param string the database name + * @return string + */ + public function create_database($db_name) + { + // Firebird databases are flat files, so a path is required + + // Hostname is needed for remote access + empty($this->db->hostname) OR $db_name = $this->hostname.':'.$db_name; + + return parent::create_database('"'.$db_name.'"'); + } + + // -------------------------------------------------------------------- + + /** + * Drop database + * + * @param string the database name + * - not used in this driver, the current db is dropped + * @return bool + */ + public function drop_database($db_name = '') + { + if ( ! ibase_drop_db($this->conn_id)) + { + return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE; + } + elseif ( ! empty($this->db->data_cache['db_names'])) + { + $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE); + if ($key !== FALSE) + { + unset($this->db->data_cache['db_names'][$key]); + } + } + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Create Table + * + * @param string the table name + * @param array the fields + * @param mixed primary key(s) + * @param mixed key(s) + * @param bool should 'IF NOT EXISTS' be added to the SQL + * @return string + */ + protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) + { + $sql = 'CREATE TABLE '; + + $sql .= $this->db->escape_identifiers($table).'('; + $current_field_count = 0; + + foreach ($fields as $field => $attributes) + { + // Numeric field names aren't allowed in databases, so if the key is + // numeric, we know it was assigned by PHP and the developer manually + // entered the field information, so we'll simply add it to the list + if (is_numeric($field)) + { + $sql .= "\n\t".$attributes; + } + else + { + $attributes = array_change_key_case($attributes, CASE_UPPER); + + $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE']; + + empty($attributes['CONSTRAINT']) OR $sql .= '('.$attributes['CONSTRAINT'].')'; + + if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE) + { + $sql .= ' UNSIGNED'; + } + + if (isset($attributes['DEFAULT'])) + { + $sql .= " DEFAULT '".$attributes['DEFAULT']."'"; + } + + $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE) + ? ' NULL' : ' NOT NULL'; + + if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE) + { + $sql .= ' AUTO_INCREMENT'; + } + } + + // don't add a comma on the end of the last field + if (++$current_field_count < count($fields)) + { + $sql .= ','; + } + } + + if (count($primary_keys) > 0) + { + $primary_keys = $this->db->escape_identifiers($primary_keys); + $sql .= ",\n\tPRIMARY KEY (".implode(', ', $primary_keys).')'; + } + + if (is_array($keys) && count($keys) > 0) + { + foreach ($keys as $key) + { + $key = is_array($key) + ? $this->db->escape_identifiers($key) + : array($this->db->escape_identifiers($key)); + + $sql .= ",\n\tUNIQUE (".implode(', ', $key).')'; + } + } + + return $sql."\n)"; + } + + // -------------------------------------------------------------------- + + /** + * Alter table query + * + * Generates a platform-specific query so that a table can be altered + * Called by add_column(), drop_column(), and column_alter(), + * + * @param string the ALTER type (ADD, DROP, CHANGE) + * @param string the column name + * @param string the table name + * @param string the column definition + * @param string the default value + * @param bool should 'NOT NULL' be added + * @param string the field after which we should add the new field + * @return string + */ + protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') + { + return 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name) + .' '.$column_definition + .($default_value !== '' ? ' DEFAULT "'.$default_value.'"' : '') + .($null === NULL ? ' NULL' : ' NOT NULL') + .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : ''); + } + +} + +/* End of file interbase_forge.php */ +/* Location: ./system/database/drivers/interbase/interbase_forge.php */
\ No newline at end of file diff --git a/system/database/drivers/interbase/interbase_result.php b/system/database/drivers/interbase/interbase_result.php new file mode 100644 index 000000000..5ddb6fa47 --- /dev/null +++ b/system/database/drivers/interbase/interbase_result.php @@ -0,0 +1,260 @@ +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +/** + * CodeIgniter + * + * An open source application development framework for PHP 5.2.4 or newer + * + * NOTICE OF LICENSE + * + * Licensed under the Open Software License version 3.0 + * + * This source file is subject to the Open Software License (OSL 3.0) that is + * bundled with this package in the files license.txt / license.rst. It is + * also available through the world wide web at this URL: + * http://opensource.org/licenses/OSL-3.0 + * 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 + * licensing@ellislab.com so we can send you a copy immediately. + * + * @package CodeIgniter + * @author EllisLab Dev Team + * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) + * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * @link http://codeigniter.com + * @since Version 3.0 + * @filesource + */ + +/** + * Interbase/Firebird Result Class + * + * This class extends the parent result class: CI_DB_result + * + * @category Database + * @author EllisLab Dev Team + * @link http://codeigniter.com/user_guide/database/ + */ +class CI_DB_interbase_result extends CI_DB_result { + + public $num_rows; + + /** + * Number of rows in the result set + * + * @return int + */ + public function num_rows() + { + if (is_int($this->num_rows)) + { + return $this->num_rows; + } + + // Get the results so that you can get an accurate rowcount + $this->result(); + + return $this->num_rows; + } + + // -------------------------------------------------------------------- + + /** + * Number of fields in the result set + * + * @return int + */ + public function num_fields() + { + return @ibase_num_fields($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Fetch Field Names + * + * Generates an array of column names + * + * @return array + */ + public function list_fields() + { + $field_names = array(); + for ($i = 0, $num_fields = $this->num_fields(); $i < $num_fields; $i++) + { + $info = ibase_field_info($this->result_id, $i); + $field_names[] = $info['name']; + } + + return $field_names; + } + + // -------------------------------------------------------------------- + + /** + * Field data + * + * Generates an array of objects containing field meta-data + * + * @return array + */ + public function field_data() + { + $retval = array(); + for ($i = 0, $c = $this->num_fields(); $i < $c; $i++) + { + $info = ibase_field_info($this->result_id, $i); + + $retval[$i] = new stdClass(); + $retval[$i]->name = $info['name']; + $retval[$i]->type = $info['type']; + $retval[$i]->max_length = $info['length']; + $retval[$i]->primary_key = 0; + $retval[$i]->default = ''; + } + + return $retval; + } + + // -------------------------------------------------------------------- + + /** + * Free the result + * + * @return void + */ + public function free_result() + { + @ibase_free_result($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Result - associative array + * + * Returns the result set as an array + * + * @return array + */ + protected function _fetch_assoc() + { + if (($row = @ibase_fetch_assoc($this->result_id, IBASE_FETCH_BLOBS)) !== FALSE) + { + //Increment row count + $this->num_rows++; + } + + return $row; + } + + // -------------------------------------------------------------------- + + /** + * Result - object + * + * Returns the result set as an object + * + * @return object + */ + protected function _fetch_object() + { + if (($row = @ibase_fetch_object($this->result_id, IBASE_FETCH_BLOBS)) !== FALSE) + { + //Increment row count + $this->num_rows++; + } + + return $row; + } + + // -------------------------------------------------------------------- + + /** + * Query result. "object" version. + * + * @return object + */ + public function result_object() + { + if (count($this->result_object) === $this->num_rows) + { + return $this->result_object; + } + + // Convert result array to object so that + // We don't have to get the result again + if (($c = count($this->result_array)) > 0) + { + for ($i = 0; $i < $c; $i++) + { + $this->result_object[$i] = (object) $this->result_array[$i]; + } + + return $this->result_object; + } + + // In the event that query caching is on the result_id variable + // will return FALSE since there isn't a valid SQL resource so + // we'll simply return an empty array. + if ($this->result_id === FALSE) + { + return array(); + } + + $this->num_rows = 0; + while ($row = $this->_fetch_object()) + { + $this->result_object[] = $row; + } + + return $this->result_object; + } + + // -------------------------------------------------------------------- + + /** + * Query result. "array" version. + * + * @return array + */ + public function result_array() + { + if (count($this->result_array) === $this->num_rows) + { + return $this->result_array; + } + + // Since the object and array are really similar, just case + // the result object to an array if need be + if (($c = count($this->result_object)) > 0) + { + for ($i = 0; $i < $c; $i++) + { + $this->result_array[$i] = (array) $this->result_object[$i]; + } + + return $this->result_array; + } + + // In the event that query caching is on the result_id variable + // will return FALSE since there isn't a valid SQL resource so + // we'll simply return an empty array. + if ($this->result_id === FALSE) + { + return array(); + } + + $this->num_rows = 0; + while ($row = $this->_fetch_assoc()) + { + $this->result_array[] = $row; + } + + return $this->result_array; + } + +} + +/* End of file interbase_result.php */ +/* Location: ./system/database/drivers/interbase/interbase_result.php */
\ No newline at end of file diff --git a/system/database/drivers/interbase/interbase_utility.php b/system/database/drivers/interbase/interbase_utility.php new file mode 100644 index 000000000..164211836 --- /dev/null +++ b/system/database/drivers/interbase/interbase_utility.php @@ -0,0 +1,62 @@ +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +/** + * CodeIgniter + * + * An open source application development framework for PHP 5.2.4 or newer + * + * NOTICE OF LICENSE + * + * Licensed under the Open Software License version 3.0 + * + * This source file is subject to the Open Software License (OSL 3.0) that is + * bundled with this package in the files license.txt / license.rst. It is + * also available through the world wide web at this URL: + * http://opensource.org/licenses/OSL-3.0 + * 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 + * licensing@ellislab.com so we can send you a copy immediately. + * + * @package CodeIgniter + * @author EllisLab Dev Team + * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) + * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * @link http://codeigniter.com + * @since Version 3.0 + * @filesource + */ + +/** + * Interbase/Firebird Utility Class + * + * @category Database + * @author EllisLab Dev Team + * @link http://codeigniter.com/user_guide/database/ + */ +class CI_DB_interbase_utility extends CI_DB_utility { + + protected $_list_databases = FALSE; + + /** + * Interbase/Firebird Export + * + * @param string $filename + * @return mixed + */ + protected function _backup($filename) + { + if ($service = ibase_service_attach($this->db->hostname, $this->db->username, $this->db->password)) + { + $res = ibase_backup($service, $this->db->database, $filename.'.fbk'); + + // Close the service connection + ibase_service_detach($service); + return $res; + } + + return FALSE; + } + +} + +/* End of file interbase_utility.php */ +/* Location: ./system/database/drivers/interbase/interbase_utility.php */
\ No newline at end of file diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php index 2a1098932..47dc55844 100644 --- a/system/database/drivers/mssql/mssql_driver.php +++ b/system/database/drivers/mssql/mssql_driver.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,13 +25,11 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * MS SQL Database Adapter Class * * Note: _DB is an extender class that the app controller - * creates dynamically based on whether the active record + * creates dynamically based on whether the query builder * class is being used or not. * * @package CodeIgniter @@ -42,133 +40,133 @@ */ class CI_DB_mssql_driver extends CI_DB { - var $dbdriver = 'mssql'; + public $dbdriver = 'mssql'; // The character used for escaping - var $_escape_char = ''; + protected $_escape_char = '"'; // clause and character used for LIKE escape sequences - var $_like_escape_str = " ESCAPE '%s' "; - var $_like_escape_chr = '!'; + protected $_like_escape_str = " ESCAPE '%s' "; + protected $_like_escape_chr = '!'; /** * The syntax to count rows is slightly different across different * database engines, so this string appears in each driver and is - * used for the count_all() and count_all_results() functions. + * used for the count_all() and count_all_results() methods. */ - var $_count_string = "SELECT COUNT(*) AS "; - var $_random_keyword = ' ASC'; // not currently supported + protected $_count_string = 'SELECT COUNT(*) AS '; + protected $_random_keyword = ' NEWID()'; - /** - * Non-persistent database connection + // MSSQL-specific properties + protected $_quoted_identifier = TRUE; + + /* + * Constructor * - * @access private called by the base class - * @return resource + * Appends the port number to the hostname, if needed. + * + * @param array + * @return void */ - function db_connect() + public function __construct($params) { - if ($this->port != '') + parent::__construct($params); + + if ( ! empty($this->port)) { - $this->hostname .= ','.$this->port; + $this->hostname .= (DIRECTORY_SEPARATOR === '\\' ? ',' : ':').$this->port; } - - return @mssql_connect($this->hostname, $this->username, $this->password); } // -------------------------------------------------------------------- /** - * Persistent database connection + * Non-persistent database connection * - * @access private called by the base class * @return resource */ - function db_pconnect() + public function db_connect() { - if ($this->port != '') - { - $this->hostname .= ','.$this->port; - } - - return @mssql_pconnect($this->hostname, $this->username, $this->password); + return $this->_mssql_connect(); } // -------------------------------------------------------------------- /** - * Reconnect - * - * Keep / reestablish the db connection if no queries have been - * sent for a length of time exceeding the server's idle timeout + * Persistent database connection * - * @access public - * @return void + * @return resource */ - function reconnect() + public function db_pconnect() { - // not implemented in MSSQL + return $this->_mssql_connect(TRUE); } // -------------------------------------------------------------------- - /** - * Select the database + /* + * MSSQL Connect * - * @access private called by the base class + * @param bool * @return resource */ - function db_select() + protected function _mssql_connect($persistent = FALSE) { - // Note: The brackets are required in the event that the DB name - // contains reserved characters - return @mssql_select_db('['.$this->database.']', $this->conn_id); - } + $conn_id = ($persistent) + ? @mssql_pconnect($this->hostname, $this->username, $this->password) + : @mssql_connect($this->hostname, $this->username, $this->password); - // -------------------------------------------------------------------- + if ( ! $conn_id) + { + return FALSE; + } - /** - * Set client character set - * - * @access public - * @param string - * @param string - * @return resource - */ - function db_set_charset($charset, $collation) - { - // @todo - add support if needed - return TRUE; + // Determine how identifiers are escaped + $query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi'); + $query = $query->row_array(); + $this->_quoted_identifier = empty($query) ? FALSE : (bool) $query->qi; + $this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']'); + + return $conn_id; } // -------------------------------------------------------------------- /** - * Execute the query + * Select the database * - * @access private called by the base class - * @param string an SQL query - * @return resource + * @param string database name + * @return bool */ - function _execute($sql) + public function db_select($database = '') { - $sql = $this->_prep_query($sql); - return @mssql_query($sql, $this->conn_id); + if ($database === '') + { + $database = $this->database; + } + + // Note: The brackets are required in the event that the DB name + // contains reserved characters + if (@mssql_select_db($this->escape_identifiers($database), $this->conn_id)) + { + $this->database = $database; + return TRUE; + } + + return FALSE; } // -------------------------------------------------------------------- /** - * Prep the query - * - * If needed, each database adapter can prep the query string + * Execute the query * - * @access private called by execute() * @param string an SQL query - * @return string + * @return mixed resource if rows are returned, bool otherwise */ - function _prep_query($sql) + protected function _execute($sql) { - return $sql; + return @mssql_query($sql, $this->conn_id); } // -------------------------------------------------------------------- @@ -176,18 +174,12 @@ class CI_DB_mssql_driver extends CI_DB { /** * Begin Transaction * - * @access public * @return bool */ - function trans_begin($test_mode = FALSE) + public function trans_begin($test_mode = FALSE) { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } @@ -195,10 +187,9 @@ class CI_DB_mssql_driver extends CI_DB { // Reset the transaction failure flag. // If the $test_mode flag is set to TRUE transactions will be rolled back // even if the queries produce a successful result. - $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE; + $this->_trans_failure = ($test_mode === TRUE); - $this->simple_query('BEGIN TRAN'); - return TRUE; + return $this->simple_query('BEGIN TRAN'); } // -------------------------------------------------------------------- @@ -206,24 +197,17 @@ class CI_DB_mssql_driver extends CI_DB { /** * Commit Transaction * - * @access public * @return bool */ - function trans_commit() + public function trans_commit() { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } - $this->simple_query('COMMIT TRAN'); - return TRUE; + return $this->simple_query('COMMIT TRAN'); } // -------------------------------------------------------------------- @@ -231,24 +215,17 @@ class CI_DB_mssql_driver extends CI_DB { /** * Rollback Transaction * - * @access public * @return bool */ - function trans_rollback() + public function trans_rollback() { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } - $this->simple_query('ROLLBACK TRAN'); - return TRUE; + return $this->simple_query('ROLLBACK TRAN'); } // -------------------------------------------------------------------- @@ -256,12 +233,11 @@ class CI_DB_mssql_driver extends CI_DB { /** * Escape String * - * @access public * @param string * @param bool whether or not the string will be used in a LIKE condition * @return string */ - function escape_str($str, $like = FALSE) + public function escape_str($str, $like = FALSE) { if (is_array($str)) { @@ -279,7 +255,7 @@ class CI_DB_mssql_driver extends CI_DB { // escape LIKE condition wildcards if ($like === TRUE) { - $str = str_replace( + return str_replace( array($this->_like_escape_chr, '%', '_'), array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'), $str @@ -294,10 +270,9 @@ class CI_DB_mssql_driver extends CI_DB { /** * Affected Rows * - * @access public - * @return integer + * @return int */ - function affected_rows() + public function affected_rows() { return @mssql_rows_affected($this->conn_id); } @@ -305,35 +280,35 @@ class CI_DB_mssql_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Insert ID - * - * Returns the last id created in the Identity column. - * - * @access public - * @return integer - */ - function insert_id() + * Insert ID + * + * Returns the last id created in the Identity column. + * + * @return string + */ + public function insert_id() { - $ver = self::_parse_major_version($this->version()); - $sql = ($ver >= 8 ? "SELECT SCOPE_IDENTITY() AS last_id" : "SELECT @@IDENTITY AS last_id"); - $query = $this->query($sql); - $row = $query->row(); - return $row->last_id; + $query = (self::_parse_major_version($this->version()) > 7) + ? 'SELECT SCOPE_IDENTITY() AS last_id' + : 'SELECT @@IDENTITY AS last_id'; + + $query = $this->query($query); + $query = $query->row(); + return $query->last_id; } // -------------------------------------------------------------------- /** - * Parse major version - * - * Grabs the major version number from the - * database server version string passed in. - * - * @access private - * @param string $version - * @return int16 major version number - */ - function _parse_major_version($version) + * Parse major version + * + * Grabs the major version number from the + * database server version string passed in. + * + * @param string $version + * @return int major version number + */ + protected function _parse_major_version($version) { preg_match('/([0-9]+)\.([0-9]+)\.([0-9]+)/', $version, $ver_info); return $ver_info[1]; // return the major version b/c that's all we're interested in. @@ -342,45 +317,13 @@ class CI_DB_mssql_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Version number query string - * - * @access public - * @return string - */ - function _version() - { - return "SELECT @@VERSION AS ver"; - } - - // -------------------------------------------------------------------- - - /** - * "Count All" query - * - * Generates a platform-specific query string that counts all records in - * the specified database + * Version number query string * - * @access public - * @param string * @return string */ - function count_all($table = '') + protected function _version() { - if ($table == '') - { - return 0; - } - - $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE)); - - if ($query->num_rows() == 0) - { - return 0; - } - - $row = $query->row(); - $this->_reset_select(); - return (int) $row->numrows; + return 'SELECT @@VERSION AS ver'; } // -------------------------------------------------------------------- @@ -390,16 +333,15 @@ class CI_DB_mssql_driver extends CI_DB { * * Generates a platform-specific query string so that the table names can be fetched * - * @access private - * @param boolean + * @param bool * @return string */ - function _list_tables($prefix_limit = FALSE) + protected function _list_tables($prefix_limit = FALSE) { $sql = "SELECT name FROM sysobjects WHERE type = 'U' ORDER BY name"; // for future compatibility - if ($prefix_limit !== FALSE AND $this->dbprefix != '') + if ($prefix_limit !== FALSE AND $this->dbprefix !== '') { //$sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); return FALSE; // not currently supported @@ -415,11 +357,10 @@ class CI_DB_mssql_driver extends CI_DB { * * Generates a platform-specific query string so that the column names can be fetched * - * @access private * @param string the table name * @return string */ - function _list_columns($table = '') + protected function _list_columns($table = '') { return "SELECT * FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '".$table."'"; } @@ -431,82 +372,29 @@ class CI_DB_mssql_driver extends CI_DB { * * Generates a platform-specific query so that the column data can be retrieved * - * @access public * @param string the table name - * @return object - */ - function _field_data($table) - { - return "SELECT TOP 1 * FROM ".$table; - } - - // -------------------------------------------------------------------- - - /** - * The error message string - * - * @access private * @return string */ - function _error_message() - { - return mssql_get_last_message(); - } - - // -------------------------------------------------------------------- - - /** - * The error message number - * - * @access private - * @return integer - */ - function _error_number() + protected function _field_data($table) { - // Are error numbers supported? - return ''; + return 'SELECT TOP 1 * FROM '.$table; } // -------------------------------------------------------------------- /** - * Escape the SQL Identifiers + * Error * - * This function escapes column and table names + * Returns an array containing code and message of the last + * database error that has occured. * - * @access private - * @param string - * @return string + * @return array */ - function _escape_identifiers($item) + public function error() { - if ($this->_escape_char == '') - { - return $item; - } - - foreach ($this->_reserved_identifiers as $id) - { - if (strpos($item, '.'.$id) !== FALSE) - { - $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item); - - // remove duplicates if the user already included the escape - return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); - } - } - - if (strpos($item, '.') !== FALSE) - { - $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char; - } - else - { - $str = $this->_escape_char.$item.$this->_escape_char; - } - - // remove duplicates if the user already included the escape - return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + $query = $this->query('SELECT @@ERROR AS code'); + $query = $query->row(); + return array('code' => $query->code, 'message' => mssql_get_last_message()); } // -------------------------------------------------------------------- @@ -517,36 +405,12 @@ class CI_DB_mssql_driver extends CI_DB { * This function implicitly groups FROM tables so there is no confusion * about operator precedence in harmony with SQL standards * - * @access public - * @param type - * @return type - */ - function _from_tables($tables) - { - if ( ! is_array($tables)) - { - $tables = array($tables); - } - - return implode(', ', $tables); - } - - // -------------------------------------------------------------------- - - /** - * Insert statement - * - * Generates a platform-specific insert string from the supplied data - * - * @access public - * @param string the table name - * @param array the insert keys - * @param array the insert values + * @param array * @return string */ - function _insert($table, $keys, $values) + protected function _from_tables($tables) { - return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")"; + return is_array($tables) ? implode(', ', $tables) : $tables; } // -------------------------------------------------------------------- @@ -556,51 +420,47 @@ class CI_DB_mssql_driver extends CI_DB { * * Generates a platform-specific update string from the supplied data * - * @access public * @param string the table name * @param array the update data * @param array the where clause - * @param array the orderby clause - * @param array the limit clause + * @param array the orderby clause (ignored) + * @param array the limit clause (ignored) + * @param array the like clause * @return string */ - function _update($table, $values, $where, $orderby = array(), $limit = FALSE) + protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array()) { - foreach ($values as $key => $val) + foreach($values as $key => $val) { - $valstr[] = $key." = ".$val; + $valstr[] = $key.' = '.$val; } - $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; - - $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):''; - - $sql = "UPDATE ".$table." SET ".implode(', ', $valstr); + $where = empty($where) ? '' : ' WHERE '.implode(' ', $where); - $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : ''; - - $sql .= $orderby.$limit; + if ( ! empty($like)) + { + $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like); + } - return $sql; + return 'UPDATE '.$table.' SET '.implode(', ', $valstr).' WHERE '.$where; } - // -------------------------------------------------------------------- /** * Truncate statement * * Generates a platform-specific truncate string from the supplied data - * If the database does not support the truncate() command - * This function maps to "DELETE FROM table" * - * @access public + * If the database does not support the truncate() command, + * then this method maps to 'DELETE FROM table' + * * @param string the table name * @return string */ - function _truncate($table) + protected function _truncate($table) { - return "TRUNCATE ".$table; + return 'TRUNCATE TABLE '.$table; } // -------------------------------------------------------------------- @@ -610,31 +470,24 @@ class CI_DB_mssql_driver extends CI_DB { * * Generates a platform-specific delete string from the supplied data * - * @access public * @param string the table name * @param array the where clause + * @param array the like clause * @param string the limit clause * @return string */ - function _delete($table, $where = array(), $like = array(), $limit = FALSE) + protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) { - $conditions = ''; - - if (count($where) > 0 OR count($like) > 0) - { - $conditions = "\nWHERE "; - $conditions .= implode("\n", $this->ar_where); + $conditions = array(); - if (count($where) > 0 && count($like) > 0) - { - $conditions .= " AND "; - } - $conditions .= implode("\n", $like); - } + empty($where) OR $conditions[] = implode(' ', $where); + empty($like) OR $conditions[] = implode(' ', $like); - $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : ''; - return "DELETE FROM ".$table.$conditions.$limit; + return ($limit) + ? 'WITH ci_delete AS (SELECT TOP '.$limit.' * FROM '.$table.$conditions.') DELETE FROM ci_delete' + : 'DELETE FROM '.$table.$conditions; } // -------------------------------------------------------------------- @@ -644,17 +497,37 @@ class CI_DB_mssql_driver extends CI_DB { * * Generates a platform-specific LIMIT clause * - * @access public * @param string the sql query string - * @param integer the number of rows to limit the query to - * @param integer the offset value + * @param int the number of rows to limit the query to + * @param int the offset value * @return string */ - function _limit($sql, $limit, $offset) + protected function _limit($sql, $limit, $offset) { - $i = $limit + $offset; + // As of SQL Server 2012 (11.0.*) OFFSET is supported + if (version_compare($this->version(), '11', '>=')) + { + return $sql.' OFFSET '.(int) $offset.' ROWS FETCH NEXT '.(int) $limit.' ROWS ONLY'; + } + + $limit = $offset + $limit; + + // As of SQL Server 2005 (9.0.*) ROW_NUMBER() is supported, + // however an ORDER BY clause is required for it to work + if (version_compare($this->version(), '9', '>=') && $offset && ! empty($this->qb_orderby)) + { + $orderby = 'ORDER BY '.implode(', ', $this->qb_orderby); + + // We have to strip the ORDER BY clause + $sql = trim(substr($sql, 0, strrpos($sql, 'ORDER BY '.$orderby))); - return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$i.' ', $sql); + return 'SELECT '.(count($this->qb_select) === 0 ? '*' : implode(', ', $this->qb_select))." FROM (\n" + .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.$orderby.') AS '.$this->escape_identifiers('CI_rownum').', ', $sql) + ."\n) ".$this->escape_identifiers('CI_subquery') + ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.((int) $offset + 1).' AND '.$limit; + } + + return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql); } // -------------------------------------------------------------------- @@ -662,18 +535,14 @@ class CI_DB_mssql_driver extends CI_DB { /** * Close DB Connection * - * @access public - * @param resource * @return void */ - function _close($conn_id) + protected function _close() { - @mssql_close($conn_id); + @mssql_close($this->conn_id); } } - - /* End of file mssql_driver.php */ /* Location: ./system/database/drivers/mssql/mssql_driver.php */
\ No newline at end of file diff --git a/system/database/drivers/mssql/mssql_forge.php b/system/database/drivers/mssql/mssql_forge.php index dd8aa3448..3a3528f7b 100644 --- a/system/database/drivers/mssql/mssql_forge.php +++ b/system/database/drivers/mssql/mssql_forge.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,8 +25,6 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * MS SQL Forge Class * @@ -36,112 +34,61 @@ */ class CI_DB_mssql_forge extends CI_DB_forge { - /** - * Create database - * - * @access private - * @param string the database name - * @return bool - */ - function _create_database($name) - { - return "CREATE DATABASE ".$name; - } - - // -------------------------------------------------------------------- - - /** - * Drop database - * - * @access private - * @param string the database name - * @return bool - */ - function _drop_database($name) - { - return "DROP DATABASE ".$name; - } - - // -------------------------------------------------------------------- - - /** - * Drop Table - * - * @access private - * @return bool - */ - function _drop_table($table) - { - return "DROP TABLE ".$this->db->_escape_identifiers($table); - } - - // -------------------------------------------------------------------- + protected $_drop_table = 'DROP TABLE %s'; /** * Create Table * - * @access private * @param string the table name * @param array the fields * @param mixed primary key(s) * @param mixed key(s) - * @param boolean should 'IF NOT EXISTS' be added to the SQL - * @return bool + * @param bool should 'IF NOT EXISTS' be added to the SQL + * @return string */ - function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) + protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) { - $sql = 'CREATE TABLE '; + $sql = ($if_not_exists === TRUE) + ? "IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'".$table."') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\n" + : ''; - if ($if_not_exists === TRUE) - { - $sql .= 'IF NOT EXISTS '; - } + $sql .= 'CREATE TABLE '.$this->db->escape_identifiers($table).' ('; - $sql .= $this->db->_escape_identifiers($table)." ("; $current_field_count = 0; - - foreach ($fields as $field=>$attributes) + foreach ($fields as $field => $attributes) { // Numeric field names aren't allowed in databases, so if the key is // numeric, we know it was assigned by PHP and the developer manually // entered the field information, so we'll simply add it to the list if (is_numeric($field)) { - $sql .= "\n\t$attributes"; + $sql .= "\n\t".$attributes; } else { $attributes = array_change_key_case($attributes, CASE_UPPER); - $sql .= "\n\t".$this->db->_protect_identifiers($field); + $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE']; - $sql .= ' '.$attributes['TYPE']; - - if (array_key_exists('CONSTRAINT', $attributes)) + if (stripos($attributes['TYPE'], 'INT') === FALSE && ! empty($attributes['CONSTRAINT'])) { $sql .= '('.$attributes['CONSTRAINT'].')'; } - if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE) + if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE) { $sql .= ' UNSIGNED'; } - if (array_key_exists('DEFAULT', $attributes)) + if (isset($attributes['DEFAULT'])) { - $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\''; + $sql .= " DEFAULT '".$attributes['DEFAULT']."'"; } - if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE) - { - $sql .= ' NULL'; - } - else - { - $sql .= ' NOT NULL'; - } + $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE) + ? ' NULL' : ' NOT NULL'; - if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE) + if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE) { $sql .= ' AUTO_INCREMENT'; } @@ -156,30 +103,22 @@ class CI_DB_mssql_forge extends CI_DB_forge { if (count($primary_keys) > 0) { - $primary_keys = $this->db->_protect_identifiers($primary_keys); - $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")"; + $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->db->escape_identifiers($primary_keys)).')'; } if (is_array($keys) && count($keys) > 0) { foreach ($keys as $key) { - if (is_array($key)) - { - $key = $this->db->_protect_identifiers($key); - } - else - { - $key = array($this->db->_protect_identifiers($key)); - } + $key = is_array($key) + ? $this->db->escape_identifiers($key) + : array($this->db->escape_identifiers($key)); - $sql .= ",\n\tFOREIGN KEY (" . implode(', ', $key) . ")"; + $sql .= ",\n\tFOREIGN KEY (".implode(', ', $key).')'; } } - $sql .= "\n)"; - - return $sql; + return $sql."\n)"; } // -------------------------------------------------------------------- @@ -190,68 +129,29 @@ class CI_DB_mssql_forge extends CI_DB_forge { * Generates a platform-specific query so that a table can be altered * Called by add_column(), drop_column(), and column_alter(), * - * @access private * @param string the ALTER type (ADD, DROP, CHANGE) * @param string the column name * @param string the table name * @param string the column definition * @param string the default value - * @param boolean should 'NOT NULL' be added + * @param bool should 'NOT NULL' be added * @param string the field after which we should add the new field - * @return object + * @return string */ - function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') + protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') { - $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name); + $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name); // DROP has everything it needs now. - if ($alter_type == 'DROP') + if ($alter_type === 'DROP') { return $sql; } - $sql .= " $column_definition"; - - if ($default_value != '') - { - $sql .= " DEFAULT \"$default_value\""; - } - - if ($null === NULL) - { - $sql .= ' NULL'; - } - else - { - $sql .= ' NOT NULL'; - } - - if ($after_field != '') - { - $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field); - } - - return $sql; - - } - - // -------------------------------------------------------------------- - - /** - * Rename a table - * - * Generates a platform-specific query so that a table can be renamed - * - * @access private - * @param string the old table name - * @param string the new table name - * @return string - */ - function _rename_table($table_name, $new_table_name) - { - // I think this syntax will work, but can find little documentation on renaming tables in MSSQL - $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name); - return $sql; + return $sql.' '.$column_definition + .($default_value != '' ? ' DEFAULT "'.$default_value.'"' : '') + .($null === NULL ? ' NULL' : ' NOT NULL') + .($after_field != '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : ''); } } diff --git a/system/database/drivers/mssql/mssql_result.php b/system/database/drivers/mssql/mssql_result.php index bba2e6243..5929306af 100644 --- a/system/database/drivers/mssql/mssql_result.php +++ b/system/database/drivers/mssql/mssql_result.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,8 +25,6 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * MS SQL Result Class * @@ -41,10 +39,9 @@ class CI_DB_mssql_result extends CI_DB_result { /** * Number of rows in the result set * - * @access public - * @return integer + * @return int */ - function num_rows() + public function num_rows() { return @mssql_num_rows($this->result_id); } @@ -54,10 +51,9 @@ class CI_DB_mssql_result extends CI_DB_result { /** * Number of fields in the result set * - * @access public - * @return integer + * @return int */ - function num_fields() + public function num_fields() { return @mssql_num_fields($this->result_id); } @@ -69,10 +65,9 @@ class CI_DB_mssql_result extends CI_DB_result { * * Generates an array of column names * - * @access public * @return array */ - function list_fields() + public function list_fields() { $field_names = array(); while ($field = mssql_fetch_field($this->result_id)) @@ -90,20 +85,19 @@ class CI_DB_mssql_result extends CI_DB_result { * * Generates an array of objects containing field meta-data * - * @access public * @return array */ - function field_data() + public function field_data() { $retval = array(); while ($field = mssql_fetch_field($this->result_id)) { - $F = new stdClass(); - $F->name = $field->name; - $F->type = $field->type; + $F = new stdClass(); + $F->name = $field->name; + $F->type = $field->type; $F->max_length = $field->max_length; $F->primary_key = 0; - $F->default = ''; + $F->default = ''; $retval[] = $F; } @@ -116,9 +110,9 @@ class CI_DB_mssql_result extends CI_DB_result { /** * Free the result * - * @return null + * @return void */ - function free_result() + public function free_result() { if (is_resource($this->result_id)) { @@ -132,14 +126,13 @@ class CI_DB_mssql_result extends CI_DB_result { /** * Data Seek * - * Moves the internal pointer to the desired offset. We call + * Moves the internal pointer to the desired offset. We call * this internally before fetching results to make sure the * result set starts at zero * - * @access private - * @return array + * @return bool */ - function _data_seek($n = 0) + protected function _data_seek($n = 0) { return mssql_data_seek($this->result_id, $n); } @@ -151,10 +144,9 @@ class CI_DB_mssql_result extends CI_DB_result { * * Returns the result set as an array * - * @access private * @return array */ - function _fetch_assoc() + protected function _fetch_assoc() { return mssql_fetch_assoc($this->result_id); } @@ -166,16 +158,14 @@ class CI_DB_mssql_result extends CI_DB_result { * * Returns the result set as an object * - * @access private * @return object */ - function _fetch_object() + protected function _fetch_object() { return mssql_fetch_object($this->result_id); } } - /* End of file mssql_result.php */ /* Location: ./system/database/drivers/mssql/mssql_result.php */
\ No newline at end of file diff --git a/system/database/drivers/mssql/mssql_utility.php b/system/database/drivers/mssql/mssql_utility.php index be6ed5bb0..69fcec5f6 100644 --- a/system/database/drivers/mssql/mssql_utility.php +++ b/system/database/drivers/mssql/mssql_utility.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,8 +25,6 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * MS SQL Utility Class * @@ -36,59 +34,16 @@ */ class CI_DB_mssql_utility extends CI_DB_utility { - /** - * List databases - * - * @access private - * @return bool - */ - function _list_databases() - { - return "EXEC sp_helpdb"; // Can also be: EXEC sp_databases - } - - // -------------------------------------------------------------------- - - /** - * Optimize table query - * - * Generates a platform-specific query so that a table can be optimized - * - * @access private - * @param string the table name - * @return object - */ - function _optimize_table($table) - { - return FALSE; // Is this supported in MS SQL? - } - - // -------------------------------------------------------------------- - - /** - * Repair table query - * - * Generates a platform-specific query so that a table can be repaired - * - * @access private - * @param string the table name - * @return object - */ - function _repair_table($table) - { - return FALSE; // Is this supported in MS SQL? - } - - // -------------------------------------------------------------------- + protected $_list_databases = 'EXEC sp_helpdb'; // Can also be: EXEC sp_databases + protected $_optimize_table = 'ALTER INDEX all ON %s REORGANIZE'; /** * MSSQL Export * - * @access private * @param array Preferences - * @return mixed + * @return bool */ - function _backup($params = array()) + protected function _backup($params = array()) { // Currently unsupported return $this->db->display_error('db_unsuported_feature'); diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php index 067710ff0..8938d22b5 100644 --- a/system/database/drivers/mysql/mysql_driver.php +++ b/system/database/drivers/mysql/mysql_driver.php @@ -2,7 +2,7 @@ /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE * @@ -29,7 +29,7 @@ * MySQL Database Adapter Class * * Note: _DB is an extender class that the app controller - * creates dynamically based on whether the active record + * creates dynamically based on whether the query builder * class is being used or not. * * @package CodeIgniter @@ -47,7 +47,7 @@ class CI_DB_mysql_driver extends CI_DB { // clause and character used for LIKE escape sequences - not used in MySQL protected $_like_escape_str = ''; - protected $_like_escape_chr = ''; + protected $_like_escape_chr = '\\'; /** * The syntax to count rows is slightly different across different @@ -68,7 +68,7 @@ class CI_DB_mysql_driver extends CI_DB { { parent::__construct($params); - if ($this->port != '') + if ( ! empty($this->port)) { $this->hostname .= ':'.$this->port; } @@ -119,11 +119,23 @@ class CI_DB_mysql_driver extends CI_DB { /** * Select the database * + * @param string database name * @return bool */ - public function db_select() + public function db_select($database = '') { - return @mysql_select_db($this->database, $this->conn_id); + if ($database === '') + { + $database = $this->database; + } + + if (@mysql_select_db($database, $this->conn_id)) + { + $this->database = $database; + return TRUE; + } + + return FALSE; } // -------------------------------------------------------------------- @@ -132,26 +144,25 @@ class CI_DB_mysql_driver extends CI_DB { * Set client character set * * @param string - * @param string * @return bool */ - public function db_set_charset($charset, $collation) + protected function _db_set_charset($charset) { - return function_exists('mysql_set_charset') - ? @mysql_set_charset($charset, $this->conn_id) - : @mysql_query("SET NAMES '".$this->escape_str($charset)."' COLLATE '".$this->escape_str($collation)."'", $this->conn_id); + return @mysql_set_charset($charset, $this->conn_id); } // -------------------------------------------------------------------- /** - * Version number query string + * Database version number * * @return string */ - protected function _version() + public function version() { - return 'SELECT version() AS ver'; + return isset($this->data_cache['version']) + ? $this->data_cache['version'] + : $this->data_cache['version'] = @mysql_get_server_info($this->conn_id); } // -------------------------------------------------------------------- @@ -275,23 +286,14 @@ class CI_DB_mysql_driver extends CI_DB { return $str; } - if (function_exists('mysql_real_escape_string') && is_resource($this->conn_id)) - { - $str = mysql_real_escape_string($str, $this->conn_id); - } - elseif (function_exists('mysql_escape_string')) - { - $str = mysql_escape_string($str); - } - else - { - $str = addslashes($str); - } + $str = is_resource($this->conn_id) ? mysql_real_escape_string($str, $this->conn_id) : addslashes($str); // escape LIKE condition wildcards if ($like === TRUE) { - return str_replace(array('%', '_'), array('\\%', '\\_'), $str); + return str_replace(array($this->_like_escape_chr, '%', '_'), + array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'), + $str); } return $str; @@ -324,35 +326,6 @@ class CI_DB_mysql_driver extends CI_DB { // -------------------------------------------------------------------- /** - * "Count All" query - * - * Generates a platform-specific query string that counts all records in - * the specified database - * - * @param string - * @return string - */ - public function count_all($table = '') - { - if ($table == '') - { - return 0; - } - - $query = $this->query($this->_count_string.$this->protect_identifiers('numrows').' FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE)); - if ($query->num_rows() == 0) - { - return 0; - } - - $query = $query->row(); - $this->_reset_select(); - return (int) $query->numrows; - } - - // -------------------------------------------------------------------- - - /** * List table query * * Generates a platform-specific query string so that the table names can be fetched @@ -364,7 +337,7 @@ class CI_DB_mysql_driver extends CI_DB { { $sql = 'SHOW TABLES FROM '.$this->_escape_char.$this->database.$this->_escape_char; - if ($prefix_limit !== FALSE && $this->dbprefix != '') + if ($prefix_limit !== FALSE && $this->dbprefix !== '') { return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'"; } @@ -390,189 +363,55 @@ class CI_DB_mysql_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Field data query - * - * Generates a platform-specific query so that the column data can be retrieved + * Returns an object with field data * * @param string the table name - * @return string + * @return object */ - public function _field_data($table) + public function field_data($table = '') { - return 'DESCRIBE '.$table; - } - - // -------------------------------------------------------------------- - - /** - * The error message string - * - * @return string - */ - protected function _error_message() - { - return mysql_error($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * The error message number - * - * @return int - */ - protected function _error_number() - { - return mysql_errno($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * Escape the SQL Identifiers - * - * This function escapes column and table names - * - * @param string - * @return string - */ - public function _escape_identifiers($item) - { - if ($this->_escape_char == '') + if ($table === '') { - return $item; + return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE; } - foreach ($this->_reserved_identifiers as $id) - { - if (strpos($item, '.'.$id) !== FALSE) - { - $item = str_replace('.', $this->_escape_char.'.', $item); - - // remove duplicates if the user already included the escape - return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $this->_escape_char.$item); - } - } + $query = $this->query('DESCRIBE '.$this->protect_identifiers($table, TRUE, NULL, FALSE)); + $query = $query->result_object(); - if (strpos($item, '.') !== FALSE) + $retval = array(); + for ($i = 0, $c = count($query); $i < $c; $i++) { - $item = str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item); + preg_match('/([a-z]+)(\(\d+\))?/', $query[$i]->Type, $matches); + + $retval[$i] = new stdClass(); + $retval[$i]->name = $query[$i]->Field; + $retval[$i]->type = empty($matches[1]) ? NULL : $matches[1]; + $retval[$i]->default = $query[$i]->Default; + $retval[$i]->max_length = empty($matches[2]) ? NULL : preg_replace('/[^\d]/', '', $matches[2]); + $retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI'); } - // remove duplicates if the user already included the escape - return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $this->_escape_char.$item.$this->_escape_char); + return $retval; } // -------------------------------------------------------------------- /** - * From Tables + * Error * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards + * Returns an array containing code and message of the last + * database error that has occured. * - * @param string table name - * @return string + * @return array */ - protected function _from_tables($tables) + public function error() { - if ( ! is_array($tables)) - { - $tables = array($tables); - } - - return '('.implode(', ', $tables).')'; + return array('code' => mysql_errno($this->conn_id), 'message' => mysql_error($this->conn_id)); } // -------------------------------------------------------------------- /** - * Insert statement - * - * Generates a platform-specific insert string from the supplied data - * - * @param string the table name - * @param array the insert keys - * @param array the insert values - * @return string - */ - protected function _insert($table, $keys, $values) - { - return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')'; - } - - // -------------------------------------------------------------------- - - - /** - * Replace statement - * - * Generates a platform-specific replace string from the supplied data - * - * @param string the table name - * @param array the insert keys - * @param array the insert values - * @return string - */ - protected function _replace($table, $keys, $values) - { - return 'REPLACE INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')'; - } - - // -------------------------------------------------------------------- - - /** - * Insert_batch statement - * - * Generates a platform-specific insert string from the supplied data - * - * @param string the table name - * @param array the insert keys - * @param array the insert values - * @return string - */ - protected function _insert_batch($table, $keys, $values) - { - return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES '.implode(', ', $values); - } - - // -------------------------------------------------------------------- - - - /** - * Update statement - * - * Generates a platform-specific update string from the supplied data - * - * @param string the table name - * @param array the update data - * @param array the where clause - * @param array the orderby clause - * @param array the limit clause - * @return string - */ - protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array()) - { - foreach ($values as $key => $val) - { - $valstr[] = $key.' = '.$val; - } - - $where = ($where != '' && count($where) > 0) ? ' WHERE '.implode(' ', $where) : ''; - if (count($like) > 0) - { - $where .= ($where == '' ? ' WHERE ' : ' AND ').implode(' ', $like); - } - - return 'UPDATE '.$table.' SET '.implode(', ', $valstr).$where - .(count($orderby) > 0 ? ' ORDER BY '.implode(', ', $orderby) : '') - .( ! $limit ? '' : ' LIMIT '.$limit); - } - - // -------------------------------------------------------------------- - - - /** * Update_Batch statement * * Generates a platform-specific batch update string from the supplied data @@ -591,7 +430,7 @@ class CI_DB_mysql_driver extends CI_DB { foreach (array_keys($val) as $field) { - if ($field != $index) + if ($field !== $index) { $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field]; } @@ -607,60 +446,13 @@ class CI_DB_mysql_driver extends CI_DB { } return 'UPDATE '.$table.' SET '.substr($cases, 0, -2) - .' WHERE '.(($where != '' && count($where) > 0) ? implode(' ', $where).' AND ' : '') + .' WHERE '.(($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '') .$index.' IN('.implode(',', $ids).')'; } // -------------------------------------------------------------------- /** - * Truncate statement - * - * Generates a platform-specific truncate string from the supplied data - * If the database does not support the truncate() command - * This function maps to "DELETE FROM table" - * - * @param string the table name - * @return string - */ - protected function _truncate($table) - { - return 'TRUNCATE '.$table; - } - - // -------------------------------------------------------------------- - - /** - * Delete statement - * - * Generates a platform-specific delete string from the supplied data - * - * @param string the table name - * @param array the where clause - * @param string the limit clause - * @return string - */ - protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) - { - $conditions = ''; - - if (count($where) > 0 OR count($like) > 0) - { - $conditions = "\nWHERE ".implode("\n", $this->ar_where); - - if (count($where) > 0 && count($like) > 0) - { - $conditions .= ' AND '; - } - $conditions .= implode("\n", $like); - } - - return 'DELETE FROM '.$table.$conditions.( ! $limit ? '' : ' LIMIT '.$limit); - } - - // -------------------------------------------------------------------- - - /** * Limit string * * Generates a platform-specific LIMIT clause @@ -680,15 +472,14 @@ class CI_DB_mysql_driver extends CI_DB { /** * Close DB Connection * - * @param resource * @return void */ - protected function _close($conn_id) + protected function _close() { - @mysql_close($conn_id); + @mysql_close($this->conn_id); } } /* End of file mysql_driver.php */ -/* Location: ./system/database/drivers/mysql/mysql_driver.php */ +/* Location: ./system/database/drivers/mysql/mysql_driver.php */
\ No newline at end of file diff --git a/system/database/drivers/mysql/mysql_forge.php b/system/database/drivers/mysql/mysql_forge.php index d3107134e..d22454d84 100644 --- a/system/database/drivers/mysql/mysql_forge.php +++ b/system/database/drivers/mysql/mysql_forge.php @@ -2,7 +2,7 @@ /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE * @@ -34,31 +34,7 @@ */ class CI_DB_mysql_forge extends CI_DB_forge { - /** - * Create database - * - * @param string the database name - * @return string - */ - public function _create_database($name) - { - return 'CREATE DATABASE '.$name; - } - - // -------------------------------------------------------------------- - - /** - * Drop database - * - * @param string the database name - * @return string - */ - public function _drop_database($name) - { - return 'DROP DATABASE '.$name; - } - - // -------------------------------------------------------------------- + protected $_create_database = 'CREATE DATABASE %s CHARACTER SET %s COLLATE %s'; /** * Process Fields @@ -66,7 +42,7 @@ class CI_DB_mysql_forge extends CI_DB_forge { * @param mixed the fields * @return string */ - private function _process_fields($fields) + protected function _process_fields($fields) { $current_field_count = 0; $sql = ''; @@ -84,8 +60,9 @@ class CI_DB_mysql_forge extends CI_DB_forge { { $attributes = array_change_key_case($attributes, CASE_UPPER); - $sql .= "\n\t".$this->db->protect_identifiers($field) - .( ! empty($attributes['NAME']) ? ' '.$this->db->protect_identifiers($attributes['NAME']).' ' : ''); + $sql .= "\n\t".$this->db->escape_identifiers($field); + + empty($attributes['NAME']) OR ' '.$this->db->escape_identifiers($attributes['NAME']).' '; if ( ! empty($attributes['TYPE'])) { @@ -110,10 +87,23 @@ class CI_DB_mysql_forge extends CI_DB_forge { } } - $sql .= (( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE) ? ' UNSIGNED' : '') - .(isset($attributes['DEFAULT']) ? " DEFAULT '".$attributes['DEFAULT']."'" : '') - .(( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE) ? ' NULL' : ' NOT NULL') - .(( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE) ? ' AUTO_INCREMENT' : ''); + if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE) + { + $sql .= ' UNSIGNED'; + } + + if (isset($attributes['DEFAULT'])) + { + $sql .= " DEFAULT '".$attributes['DEFAULT']."'"; + } + + $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE) + ? ' NULL' : ' NOT NULL'; + + if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE) + { + $sql .= ' AUTO_INCREMENT'; + } } // don't add a comma on the end of the last field @@ -138,7 +128,7 @@ class CI_DB_mysql_forge extends CI_DB_forge { * @param bool should 'IF NOT EXISTS' be added to the SQL * @return bool */ - public function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) + protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) { $sql = 'CREATE TABLE '; @@ -147,12 +137,12 @@ class CI_DB_mysql_forge extends CI_DB_forge { $sql .= 'IF NOT EXISTS '; } - $sql .= $this->db->_escape_identifiers($table).' ('.$this->_process_fields($fields); + $sql .= $this->db->escape_identifiers($table).' ('.$this->_process_fields($fields); if (count($primary_keys) > 0) { - $key_name = $this->db->_protect_identifiers(implode('_', $primary_keys)); - $sql .= ",\n\tPRIMARY KEY ".$key_name.' ('.implode(', ', $this->db->protect_identifiers($primary_keys)).')'; + $key_name = $this->db->escape_identifiers(implode('_', $primary_keys)); + $sql .= ",\n\tPRIMARY KEY ".$key_name.' ('.implode(', ', $this->db->escape_identifiers($primary_keys)).')'; } if (is_array($keys) && count($keys) > 0) @@ -161,12 +151,12 @@ class CI_DB_mysql_forge extends CI_DB_forge { { if (is_array($key)) { - $key_name = $this->db->_protect_identifiers(implode('_', $key)); - $key = $this->db->_protect_identifiers($key); + $key_name = $this->db->escape_identifiers(implode('_', $key)); + $key = $this->db->escape_identifiers($key); } else { - $key_name = $this->db->_protect_identifiers($key); + $key_name = $this->db->escape_identifiers($key); $key = array($key_name); } @@ -180,19 +170,6 @@ class CI_DB_mysql_forge extends CI_DB_forge { // -------------------------------------------------------------------- /** - * Drop Table - * - * @param string table name - * @return string - */ - public function _drop_table($table) - { - return 'DROP TABLE IF EXISTS '.$this->db->_escape_identifiers($table); - } - - // -------------------------------------------------------------------- - - /** * Alter table query * * Generates a platform-specific query so that a table can be altered @@ -204,37 +181,21 @@ class CI_DB_mysql_forge extends CI_DB_forge { * @param string the field after which we should add the new field * @return string */ - public function _alter_table($alter_type, $table, $fields, $after_field = '') + protected function _alter_table($alter_type, $table, $fields, $after_field = '') { - $sql = 'ALTER TABLE '.$this->db->protect_identifiers($table).' '.$alter_type.' '; + $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '; // DROP has everything it needs now. if ($alter_type === 'DROP') { - return $sql.$this->db->protect_identifiers($fields); + return $sql.$this->db->escape_identifiers($fields); } return $sql.$this->_process_fields($fields) - .($after_field != '' ? ' AFTER '.$this->db->protect_identifiers($after_field) : ''); - } - - // -------------------------------------------------------------------- - - /** - * Rename a table - * - * Generates a platform-specific query so that a table can be renamed - * - * @param string the old table name - * @param string the new table name - * @return string - */ - public function _rename_table($table_name, $new_table_name) - { - return 'ALTER TABLE '.$this->db->protect_identifiers($table_name).' RENAME TO '.$this->db->protect_identifiers($new_table_name); + .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : ''); } } /* End of file mysql_forge.php */ -/* Location: ./system/database/drivers/mysql/mysql_forge.php */ +/* Location: ./system/database/drivers/mysql/mysql_forge.php */
\ No newline at end of file diff --git a/system/database/drivers/mysql/mysql_result.php b/system/database/drivers/mysql/mysql_result.php index 8f04a936d..14d6d072a 100644 --- a/system/database/drivers/mysql/mysql_result.php +++ b/system/database/drivers/mysql/mysql_result.php @@ -2,7 +2,7 @@ /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE * @@ -90,18 +90,14 @@ class CI_DB_mysql_result extends CI_DB_result { public function field_data() { $retval = array(); - while ($field = mysql_fetch_object($this->result_id)) + for ($i = 0, $c = $this->num_fields(); $i < $c; $i++) { - preg_match('/([a-zA-Z]+)(\(\d+\))?/', $field->Type, $matches); - - $F = new stdClass(); - $F->name = $field->Field; - $F->type = ( ! empty($matches[1])) ? $matches[1] : NULL; - $F->default = $field->Default; - $F->max_length = ( ! empty($matches[2])) ? preg_replace('/[^\d]/', '', $matches[2]) : NULL; - $F->primary_key = (int) ($field->Key === 'PRI'); - - $retval[] = $F; + $retval[$i] = new stdClass(); + $retval[$i]->name = mysql_field_name($this->result_id, $i); + $retval[$i]->type = mysql_field_type($this->result_id, $i); + $retval[$i]->max_length = mysql_field_len($this->result_id, $i); + $retval[$i]->primary_key = (strpos(mysql_field_flags($this->result_id, $i), 'primary_key') === FALSE) ? 0 : 1; + $retval[$i]->default = ''; } return $retval; @@ -132,7 +128,7 @@ class CI_DB_mysql_result extends CI_DB_result { * this internally before fetching results to make sure the * result set starts at zero * - * @return array + * @return bool */ protected function _data_seek($n = 0) { @@ -170,4 +166,4 @@ class CI_DB_mysql_result extends CI_DB_result { } /* End of file mysql_result.php */ -/* Location: ./system/database/drivers/mysql/mysql_result.php */ +/* Location: ./system/database/drivers/mysql/mysql_result.php */
\ No newline at end of file diff --git a/system/database/drivers/mysql/mysql_utility.php b/system/database/drivers/mysql/mysql_utility.php index 0e7c18e16..f0bbc665e 100644 --- a/system/database/drivers/mysql/mysql_utility.php +++ b/system/database/drivers/mysql/mysql_utility.php @@ -2,7 +2,7 @@ /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE * @@ -34,54 +34,17 @@ */ class CI_DB_mysql_utility extends CI_DB_utility { - /** - * List databases - * - * @return string - */ - public function _list_databases() - { - return 'SHOW DATABASES'; - } - - // -------------------------------------------------------------------- - - /** - * Optimize table query - * - * Generates a platform-specific query so that a table can be optimized - * - * @param string the table name - * @return string - */ - public function _optimize_table($table) - { - return 'OPTIMIZE TABLE '.$this->db->_escape_identifiers($table); - } - - // -------------------------------------------------------------------- + protected $_list_databases = 'SHOW DATABASES'; + protected $_optimize_table = 'OPTIMIZE TABLE %s'; + protected $_repair_table = 'REPAIR TABLE %s'; /** - * Repair table query - * - * Generates a platform-specific query so that a table can be repaired - * - * @param string the table name - * @return string - */ - public function _repair_table($table) - { - return 'REPAIR TABLE '.$this->db->_escape_identifiers($table); - } - - // -------------------------------------------------------------------- - /** * MySQL Export * * @param array Preferences * @return mixed */ - public function _backup($params = array()) + protected function _backup($params = array()) { if (count($params) === 0) { @@ -102,7 +65,7 @@ class CI_DB_mysql_utility extends CI_DB_utility { } // Get the table schema - $query = $this->db->query('SHOW CREATE TABLE `'.$this->db->database.'`.`'.$table.'`'); + $query = $this->db->query('SHOW CREATE TABLE '.$this->db->escape_identifiers($this->db->database.'.'.$table)); // No result means the table name was invalid if ($query === FALSE) @@ -113,9 +76,9 @@ class CI_DB_mysql_utility extends CI_DB_utility { // Write out the table schema $output .= '#'.$newline.'# TABLE STRUCTURE FOR: '.$table.$newline.'#'.$newline.$newline; - if ($add_drop == TRUE) + if ($add_drop === TRUE) { - $output .= 'DROP TABLE IF EXISTS '.$table.';'.$newline.$newline; + $output .= 'DROP TABLE IF EXISTS '.$this->db->protect_identifiers($table).';'.$newline.$newline; } $i = 0; @@ -129,15 +92,15 @@ class CI_DB_mysql_utility extends CI_DB_utility { } // If inserts are not needed we're done... - if ($add_insert == FALSE) + if ($add_insert === FALSE) { continue; } // Grab all the data from the current table - $query = $this->db->query('SELECT * FROM '.$table); + $query = $this->db->query('SELECT * FROM '.$this->db->protect_identifiers($table)); - if ($query->num_rows() == 0) + if ($query->num_rows() === 0) { continue; } @@ -157,7 +120,7 @@ class CI_DB_mysql_utility extends CI_DB_utility { TRUE); // Create a string of field names - $field_str .= '`'.$field->name.'`, '; + $field_str .= $this->db->escape_identifiers($field->name).', '; $i++; } @@ -180,7 +143,7 @@ class CI_DB_mysql_utility extends CI_DB_utility { else { // Escape the data if it's not an integer - $val_str .= ($is_int[$i] == FALSE) ? $this->db->escape($v) : $v; + $val_str .= ($is_int[$i] === FALSE) ? $this->db->escape($v) : $v; } // Append a comma @@ -192,15 +155,16 @@ class CI_DB_mysql_utility extends CI_DB_utility { $val_str = preg_replace('/, $/' , '', $val_str); // Build the INSERT string - $output .= 'INSERT INTO '.$table.' ('.$field_str.') VALUES ('.$val_str.');'.$newline; + $output .= 'INSERT INTO '.$this->db->protect_identifiers($table).' ('.$field_str.') VALUES ('.$val_str.');'.$newline; } - return $output.$newline.$newline; + $output .= $newline.$newline; } return $output; } + } /* End of file mysql_utility.php */ -/* Location: ./system/database/drivers/mysql/mysql_utility.php */ +/* Location: ./system/database/drivers/mysql/mysql_utility.php */
\ No newline at end of file diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php index a79b2a4ad..d3fb77a22 100644 --- a/system/database/drivers/mysqli/mysqli_driver.php +++ b/system/database/drivers/mysqli/mysqli_driver.php @@ -2,7 +2,7 @@ /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE * @@ -29,7 +29,7 @@ * MySQLi Database Adapter Class * * Note: _DB is an extender class that the app controller - * creates dynamically based on whether the active record + * creates dynamically based on whether the query builder * class is being used or not. * * @package CodeIgniter @@ -47,7 +47,7 @@ class CI_DB_mysqli_driver extends CI_DB { // clause and character used for LIKE escape sequences - not used in MySQL protected $_like_escape_str = ''; - protected $_like_escape_chr = ''; + protected $_like_escape_chr = '\\'; /** * The syntax to count rows is slightly different across different @@ -71,9 +71,9 @@ class CI_DB_mysqli_driver extends CI_DB { */ public function db_connect() { - return ($this->port != '') - ? @mysqli_connect($this->hostname, $this->username, $this->password, $this->database, $this->port) - : @mysqli_connect($this->hostname, $this->username, $this->password, $this->database); + return empty($this->port) + ? @new mysqli($this->hostname, $this->username, $this->password, $this->database) + : @new mysqli($this->hostname, $this->username, $this->password, $this->database, $this->port); } // -------------------------------------------------------------------- @@ -91,9 +91,9 @@ class CI_DB_mysqli_driver extends CI_DB { return $this->db_connect(); } - return ($this->port != '') - ? @mysqli_connect('p:'.$this->hostname, $this->username, $this->password, $this->database, $this->port) - : @mysqli_connect('p:'.$this->hostname, $this->username, $this->password, $this->database); + return empty($this->port) + ? @new mysqli('p:'.$this->hostname, $this->username, $this->password, $this->database) + : @new mysqli('p:'.$this->hostname, $this->username, $this->password, $this->database, $this->port); } // -------------------------------------------------------------------- @@ -108,7 +108,7 @@ class CI_DB_mysqli_driver extends CI_DB { */ public function reconnect() { - if (mysqli_ping($this->conn_id) === FALSE) + if ($this->conn_id !== FALSE && $this->conn_id->ping() === FALSE) { $this->conn_id = FALSE; } @@ -119,11 +119,23 @@ class CI_DB_mysqli_driver extends CI_DB { /** * Select the database * + * @param string database name * @return bool */ - public function db_select() + public function db_select($database = '') { - return @mysqli_select_db($this->conn_id, $this->database); + if ($database === '') + { + $database = $this->database; + } + + if (@$this->conn_id->select_db($database)) + { + $this->database = $database; + return TRUE; + } + + return FALSE; } // -------------------------------------------------------------------- @@ -132,26 +144,25 @@ class CI_DB_mysqli_driver extends CI_DB { * Set client character set * * @param string - * @param string * @return bool */ - protected function _db_set_charset($charset, $collation) + protected function _db_set_charset($charset) { - return function_exists('mysqli_set_charset') - ? @mysqli_set_charset($this->conn_id, $charset) - : @mysqli_query($this->conn_id, "SET NAMES '".$this->escape_str($charset)."' COLLATE '".$this->escape_str($collation)."'"); + return @$this->conn_id->set_charset($charset); } // -------------------------------------------------------------------- /** - * Version number query string + * Database version number * * @return string */ - protected function _version() + public function version() { - return @mysqli_get_server_info($this->conn_id); + return isset($this->data_cache['version']) + ? $this->data_cache['version'] + : $this->data_cache['version'] = $this->conn_id->server_info; } // -------------------------------------------------------------------- @@ -164,7 +175,7 @@ class CI_DB_mysqli_driver extends CI_DB { */ protected function _execute($sql) { - return @mysqli_query($this->conn_id, $this->_prep_query($sql)); + return @$this->conn_id->query($this->_prep_query($sql)); } // -------------------------------------------------------------------- @@ -275,23 +286,14 @@ class CI_DB_mysqli_driver extends CI_DB { return $str; } - if (function_exists('mysqli_real_escape_string') && is_object($this->conn_id)) - { - $str = mysqli_real_escape_string($this->conn_id, $str); - } - elseif (function_exists('mysql_escape_string')) - { - $str = mysql_escape_string($str); - } - else - { - $str = addslashes($str); - } + $str = is_object($this->conn_id) ? $this->conn_id->real_escape_string($str) : addslashes($str); // escape LIKE condition wildcards if ($like === TRUE) { - return str_replace(array('%', '_'), array('\\%', '\\_'), $str); + return str_replace(array($this->_like_escape_chr, '%', '_'), + array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'), + $str); } return $str; @@ -306,7 +308,7 @@ class CI_DB_mysqli_driver extends CI_DB { */ public function affected_rows() { - return @mysqli_affected_rows($this->conn_id); + return $this->conn_id->affected_rows; } // -------------------------------------------------------------------- @@ -318,36 +320,7 @@ class CI_DB_mysqli_driver extends CI_DB { */ public function insert_id() { - return @mysqli_insert_id($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * "Count All" query - * - * Generates a platform-specific query string that counts all records in - * the specified database - * - * @param string - * @return string - */ - public function count_all($table = '') - { - if ($table == '') - { - return 0; - } - - $query = $this->query($this->_count_string.$this->_protect_identifiers('numrows').' FROM '.$this->_protect_identifiers($table, TRUE, NULL, FALSE)); - if ($query->num_rows() == 0) - { - return 0; - } - - $query = $query->row(); - $this->_reset_select(); - return (int) $query->numrows; + return $this->conn_id->insert_id; } // -------------------------------------------------------------------- @@ -357,7 +330,6 @@ class CI_DB_mysqli_driver extends CI_DB { * * Generates a platform-specific query string so that the table names can be fetched * - * @access private * @param bool * @return string */ @@ -365,7 +337,7 @@ class CI_DB_mysqli_driver extends CI_DB { { $sql = 'SHOW TABLES FROM '.$this->_escape_char.$this->database.$this->_escape_char; - if ($prefix_limit !== FALSE && $this->dbprefix != '') + if ($prefix_limit !== FALSE && $this->dbprefix !== '') { return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'"; } @@ -385,183 +357,56 @@ class CI_DB_mysqli_driver extends CI_DB { */ protected function _list_columns($table = '') { - return 'SHOW COLUMNS FROM '.$this->_protect_identifiers($table, TRUE, NULL, FALSE); + return 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE); } // -------------------------------------------------------------------- /** - * Field data query - * - * Generates a platform-specific query so that the column data can be retrieved + * Returns an object with field data * * @param string the table name - * @return string - */ - protected function _field_data($table) - { - return 'DESCRIBE '.$table; - } - - // -------------------------------------------------------------------- - - /** - * The error message string - * - * @return string - */ - protected function _error_message() - { - return mysqli_error($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * The error message number - * - * @return int - */ - protected function _error_number() - { - return mysqli_errno($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * Escape the SQL Identifiers - * - * This function escapes column and table names - * - * @param string - * @return string + * @return object */ - public function _escape_identifiers($item) + public function field_data($table = '') { - if ($this->_escape_char == '') + if ($table === '') { - return $item; + return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE; } - foreach ($this->_reserved_identifiers as $id) - { - if (strpos($item, '.'.$id) !== FALSE) - { - $item = str_replace('.', $this->_escape_char.'.', $item); - - // remove duplicates if the user already included the escape - return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $this->_escape_char.$item); - } - } + $query = $this->query('DESCRIBE '.$this->protect_identifiers($table, TRUE, NULL, FALSE)); + $query = $query->result_object(); - if (strpos($item, '.') !== FALSE) + $retval = array(); + for ($i = 0, $c = count($query); $i < $c; $i++) { - $item = str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item); + preg_match('/([a-z]+)(\(\d+\))?/', $query[$i]->Type, $matches); + + $retval[$i] = new stdClass(); + $retval[$i]->name = $query[$i]->Field; + $retval[$i]->type = empty($matches[1]) ? NULL : $matches[1]; + $retval[$i]->default = $query[$i]->Default; + $retval[$i]->max_length = empty($matches[2]) ? NULL : preg_replace('/[^\d]/', '', $matches[2]); + $retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI'); } - // remove duplicates if the user already included the escape - return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $this->_escape_char.$item.$this->_escape_char); + return $retval; } // -------------------------------------------------------------------- /** - * From Tables + * Error * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards + * Returns an array containing code and message of the last + * database error that has occured. * - * @param string - * @return string + * @return array */ - protected function _from_tables($tables) + public function error() { - if ( ! is_array($tables)) - { - $tables = array($tables); - } - - return '('.implode(', ', $tables).')'; - } - - // -------------------------------------------------------------------- - - /** - * Insert statement - * - * Generates a platform-specific insert string from the supplied data - * - * @param string the table name - * @param array the insert keys - * @param array the insert values - * @return string - */ - protected function _insert($table, $keys, $values) - { - return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')'; - } - - // -------------------------------------------------------------------- - - /** - * Insert_batch statement - * - * Generates a platform-specific insert string from the supplied data - * - * @param string the table name - * @param array the insert keys - * @param array the insert values - * @return string - */ - protected function _insert_batch($table, $keys, $values) - { - return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES '.implode(', ', $values); - } - - // -------------------------------------------------------------------- - - - /** - * Replace statement - * - * Generates a platform-specific replace string from the supplied data - * - * @param string the table name - * @param array the insert keys - * @param array the insert values - * @return string - */ - protected function _replace($table, $keys, $values) - { - return 'REPLACE INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')'; - } - - // -------------------------------------------------------------------- - - /** - * Update statement - * - * Generates a platform-specific update string from the supplied data - * - * @param string the table name - * @param array the update data - * @param array the where clause - * @param array the orderby clause - * @param array the limit clause - * @return string - */ - protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE) - { - foreach ($values as $key => $val) - { - $valstr[] = $key.' = '.$val; - } - - return 'UPDATE '.$table.' SET '.implode(', ', $valstr) - .(($where != '' && count($where) > 0) ? ' WHERE '.implode(' ', $where) : '') - .(count($orderby) > 0 ? ' ORDER BY '.implode(', ', $orderby) : '') - .( ! $limit ? '' : ' LIMIT '.$limit); + return array('code' => $this->conn_id->errno, 'message' => $this->conn_id->error); } // -------------------------------------------------------------------- @@ -585,7 +430,7 @@ class CI_DB_mysqli_driver extends CI_DB { foreach (array_keys($val) as $field) { - if ($field != $index) + if ($field !== $index) { $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field]; } @@ -600,62 +445,16 @@ class CI_DB_mysqli_driver extends CI_DB { .'ELSE '.$k.' END, '; } - $where = ($where != '' && count($where) > 0) ? implode(' ', $where).' AND ' : ''; + $where = ($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : ''; return 'UPDATE '.$table.' SET '.substr($cases, 0, -2) - .' WHERE '.(($where != '' && count($where) > 0) ? implode(' ', $where).' AND ' : '') + .' WHERE '.(($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '') .$index.' IN('.implode(',', $ids).')'; } // -------------------------------------------------------------------- /** - * Truncate statement - * - * Generates a platform-specific truncate string from the supplied data - * If the database does not support the truncate() command - * This function maps to "DELETE FROM table" - * - * @param string the table name - * @return string - */ - protected function _truncate($table) - { - return 'TRUNCATE '.$table; - } - - // -------------------------------------------------------------------- - - /** - * Delete statement - * - * Generates a platform-specific delete string from the supplied data - * - * @param string the table name - * @param array the where clause - * @param string the limit clause - * @return string - */ - protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) - { - $conditions = ''; - if (count($where) > 0 OR count($like) > 0) - { - $conditions = "\nWHERE ".implode("\n", $this->ar_where); - - if (count($where) > 0 && count($like) > 0) - { - $conditions .= ' AND '; - } - $conditions .= implode("\n", $like); - } - - return 'DELETE FROM '.$table.$conditions.( ! $limit ? '' : ' LIMIT '.$limit); - } - - // -------------------------------------------------------------------- - - /** * Limit string * * Generates a platform-specific LIMIT clause @@ -676,15 +475,14 @@ class CI_DB_mysqli_driver extends CI_DB { /** * Close DB Connection * - * @param object * @return void */ - protected function _close($conn_id) + protected function _close() { - @mysqli_close($conn_id); + $this->conn_id->close(); } } /* End of file mysqli_driver.php */ -/* Location: ./system/database/drivers/mysqli/mysqli_driver.php */ +/* Location: ./system/database/drivers/mysqli/mysqli_driver.php */
\ No newline at end of file diff --git a/system/database/drivers/mysqli/mysqli_forge.php b/system/database/drivers/mysqli/mysqli_forge.php index 7de036127..b74c775b2 100644 --- a/system/database/drivers/mysqli/mysqli_forge.php +++ b/system/database/drivers/mysqli/mysqli_forge.php @@ -2,7 +2,7 @@ /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE * @@ -34,31 +34,7 @@ */ class CI_DB_mysqli_forge extends CI_DB_forge { - /** - * Create database - * - * @param string the database name - * @return string - */ - public function _create_database($name) - { - return 'CREATE DATABASE '.$name; - } - - // -------------------------------------------------------------------- - - /** - * Drop database - * - * @param string the database name - * @return string - */ - public function _drop_database($name) - { - return 'DROP DATABASE '.$name; - } - - // -------------------------------------------------------------------- + protected $_create_database = 'CREATE DATABASE %s CHARACTER SET %s COLLATE %s'; /** * Process Fields @@ -66,7 +42,7 @@ class CI_DB_mysqli_forge extends CI_DB_forge { * @param mixed the fields * @return string */ - public function _process_fields($fields) + protected function _process_fields($fields) { $current_field_count = 0; $sql = ''; @@ -84,14 +60,50 @@ class CI_DB_mysqli_forge extends CI_DB_forge { { $attributes = array_change_key_case($attributes, CASE_UPPER); - $sql .= "\n\t".$this->db->protect_identifiers($field) - .( ! empty($attributes['NAME']) ? ' '.$this->db->protect_identifiers($attributes['NAME']).' ' : '') - .( ! empty($attributes['TYPE']) ? ' '.$attributes['TYPE'] : '') - .( ! empty($attributes['CONSTRAINT']) ? '('.$attributes['CONSTRAINT'].')' : '') - .(( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE) ? ' UNSIGNED' : '') - .(isset($attributes['DEFAULT']) ? " DEFAULT '".$attributes['DEFAULT']."'" : '') - .(( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE) ? ' NULL' : ' NOT NULL') - .(( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE) ? ' AUTO_INCREMENT' : ''); + $sql .= "\n\t".$this->db->escape_identifiers($field); + + empty($attributes['NAME']) OR $sql .= ' '.$this->db->escape_identifiers($attributes['NAME']).' '; + + if ( ! empty($attributes['TYPE'])) + { + $sql .= ' '.$attributes['TYPE']; + + if ( ! empty($attributes['CONSTRAINT'])) + { + switch (strtolower($attributes['TYPE'])) + { + case 'decimal': + case 'float': + case 'numeric': + $sql .= '('.implode(',', $attributes['CONSTRAINT']).')'; + break; + case 'enum': + case 'set': + $sql .= '("'.implode('","', $attributes['CONSTRAINT']).'")'; + break; + default: + $sql .= '('.$attributes['CONSTRAINT'].')'; + } + } + } + + if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE) + { + $sql .= ' UNSIGNED'; + } + + if (isset($attributes['DEFAULT'])) + { + $sql .= " DEFAULT '".$attributes['DEFAULT']."'"; + } + + $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE) + ? ' NULL' : ' NOT NULL'; + + if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE) + { + $sql .= ' AUTO_INCREMENT'; + } } // don't add a comma on the end of the last field @@ -116,7 +128,7 @@ class CI_DB_mysqli_forge extends CI_DB_forge { * @param bool should 'IF NOT EXISTS' be added to the SQL * @return bool */ - public function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) + protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) { $sql = 'CREATE TABLE '; @@ -125,12 +137,12 @@ class CI_DB_mysqli_forge extends CI_DB_forge { $sql .= 'IF NOT EXISTS '; } - $sql .= $this->db->_escape_identifiers($table).' ('.$this->_process_fields($fields); + $sql .= $this->db->escape_identifiers($table).' ('.$this->_process_fields($fields); if (count($primary_keys) > 0) { - $key_name = $this->db->protect_identifiers(implode('_', $primary_keys)); - $sql .= ",\n\tPRIMARY KEY ".$key_name.' ('.implode(', ', $this->db->protect_identifiers($primary_keys)).')'; + $key_name = $this->db->escape_identifiers(implode('_', $primary_keys)); + $sql .= ",\n\tPRIMARY KEY ".$key_name.' ('.implode(', ', $this->db->escape_identifiers($primary_keys)).')'; } if (is_array($keys) && count($keys) > 0) @@ -139,12 +151,12 @@ class CI_DB_mysqli_forge extends CI_DB_forge { { if (is_array($key)) { - $key_name = $this->db->protect_identifiers(implode('_', $key)); - $key = $this->db->protect_identifiers($key); + $key_name = $this->db->escape_identifiers(implode('_', $key)); + $key = $this->db->escape_identifiers($key); } else { - $key_name = $this->db->protect_identifiers($key); + $key_name = $this->db->escape_identifiers($key); $key = array($key_name); } @@ -158,18 +170,6 @@ class CI_DB_mysqli_forge extends CI_DB_forge { // -------------------------------------------------------------------- /** - * Drop Table - * - * @return string - */ - public function _drop_table($table) - { - return 'DROP TABLE IF EXISTS '.$this->db->_escape_identifiers($table); - } - - // -------------------------------------------------------------------- - - /** * Alter table query * * Generates a platform-specific query so that a table can be altered @@ -181,37 +181,21 @@ class CI_DB_mysqli_forge extends CI_DB_forge { * @param string the field after which we should add the new field * @return string */ - public function _alter_table($alter_type, $table, $fields, $after_field = '') + protected function _alter_table($alter_type, $table, $fields, $after_field = '') { - $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table).' '.$alter_type.' '; + $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '; // DROP has everything it needs now. if ($alter_type === 'DROP') { - return $sql.$this->db->protect_identifiers($fields); + return $sql.$this->db->escape_identifiers($fields); } return $sql.$this->_process_fields($fields) - .($after_field != '' ? ' AFTER '.$this->db->protect_identifiers($after_field) : ''); - } - - // -------------------------------------------------------------------- - - /** - * Rename a table - * - * Generates a platform-specific query so that a table can be renamed - * - * @param string the old table name - * @param string the new table name - * @return string - */ - public function _rename_table($table_name, $new_table_name) - { - return 'ALTER TABLE '.$this->db->protect_identifiers($table_name).' RENAME TO '.$this->db->protect_identifiers($new_table_name); + .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : ''); } } /* End of file mysqli_forge.php */ -/* Location: ./system/database/drivers/mysqli/mysqli_forge.php */ +/* Location: ./system/database/drivers/mysqli/mysqli_forge.php */
\ No newline at end of file diff --git a/system/database/drivers/mysqli/mysqli_result.php b/system/database/drivers/mysqli/mysqli_result.php index 0a50cccac..9b4d494d4 100644 --- a/system/database/drivers/mysqli/mysqli_result.php +++ b/system/database/drivers/mysqli/mysqli_result.php @@ -2,7 +2,7 @@ /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE * @@ -43,7 +43,7 @@ class CI_DB_mysqli_result extends CI_DB_result { */ public function num_rows() { - return @mysqli_num_rows($this->result_id); + return $this->result_id->num_rows; } // -------------------------------------------------------------------- @@ -55,7 +55,7 @@ class CI_DB_mysqli_result extends CI_DB_result { */ public function num_fields() { - return @mysqli_num_fields($this->result_id); + return $this->result_id->field_count; } // -------------------------------------------------------------------- @@ -70,7 +70,7 @@ class CI_DB_mysqli_result extends CI_DB_result { public function list_fields() { $field_names = array(); - while ($field = mysqli_fetch_field($this->result_id)) + while ($field = $this->result_id->fetch_field()) { $field_names[] = $field->name; } @@ -90,18 +90,15 @@ class CI_DB_mysqli_result extends CI_DB_result { public function field_data() { $retval = array(); - while ($field = mysqli_fetch_object($this->result_id)) + $field_data = $this->result_id->fetch_fields(); + for ($i = 0, $c = count($field_data); $i < $c; $i++) { - preg_match('/([a-zA-Z]+)(\(\d+\))?/', $field->Type, $matches); - - $F = new stdClass(); - $F->name = $field->Field; - $F->type = ( ! empty($matches[1])) ? $matches[1] : NULL; - $F->default = $field->Default; - $F->max_length = ( ! empty($matches[2])) ? preg_replace('/[^\d]/', '', $matches[2]) : NULL; - $F->primary_key = (int) ($field->Key === 'PRI'); - - $retval[] = $F; + $retval[$i] = new stdClass(); + $retval[$i]->name = $field_data[$i]->name; + $retval[$i]->type = $field_data[$i]->type; + $retval[$i]->max_length = $field_data[$i]->max_length; + $retval[$i]->primary_key = (int) ($field_data[$i]->flags & 2); + $retval[$i]->default = ''; } return $retval; @@ -118,7 +115,7 @@ class CI_DB_mysqli_result extends CI_DB_result { { if (is_object($this->result_id)) { - mysqli_free_result($this->result_id); + $this->result_id->free(); $this->result_id = FALSE; } } @@ -128,15 +125,15 @@ class CI_DB_mysqli_result extends CI_DB_result { /** * Data Seek * - * Moves the internal pointer to the desired offset. We call + * Moves the internal pointer to the desired offset. We call * this internally before fetching results to make sure the * result set starts at zero * - * @return array + * @return bool */ protected function _data_seek($n = 0) { - return mysqli_data_seek($this->result_id, $n); + return $this->result_id->data_seek($n); } // -------------------------------------------------------------------- @@ -150,7 +147,7 @@ class CI_DB_mysqli_result extends CI_DB_result { */ protected function _fetch_assoc() { - return mysqli_fetch_assoc($this->result_id); + return $this->result_id->fetch_assoc(); } // -------------------------------------------------------------------- @@ -164,10 +161,10 @@ class CI_DB_mysqli_result extends CI_DB_result { */ protected function _fetch_object() { - return mysqli_fetch_object($this->result_id); + return $this->result_id->fetch_object(); } } /* End of file mysqli_result.php */ -/* Location: ./system/database/drivers/mysqli/mysqli_result.php */ +/* Location: ./system/database/drivers/mysqli/mysqli_result.php */
\ No newline at end of file diff --git a/system/database/drivers/mysqli/mysqli_utility.php b/system/database/drivers/mysqli/mysqli_utility.php index 3fdc5c723..5d2bdbce0 100644 --- a/system/database/drivers/mysqli/mysqli_utility.php +++ b/system/database/drivers/mysqli/mysqli_utility.php @@ -2,7 +2,7 @@ /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE * @@ -34,60 +34,137 @@ */ class CI_DB_mysqli_utility extends CI_DB_utility { + protected $_list_databases = 'SHOW DATABASES'; + protected $_optimize_table = 'OPTIMIZE TABLE %s'; + protected $_repair_table = 'REPAIR TABLE %s'; + /** - * List databases + * MySQLi Export * - * @return string + * @param array Preferences + * @return mixed */ - public function _list_databases() + protected function _backup($params = array()) { - return 'SHOW DATABASES'; - } + if (count($params) === 0) + { + return FALSE; + } - // -------------------------------------------------------------------- + // Extract the prefs for simplicity + extract($params); - /** - * Optimize table query - * - * Generates a platform-specific query so that a table can be optimized - * - * @param string the table name - * @return string - */ - public function _optimize_table($table) - { - return 'OPTIMIZE TABLE '.$this->db->_escape_identifiers($table); - } + // Build the output + $output = ''; + foreach ( (array) $tables as $table) + { + // Is the table in the "ignore" list? + if (in_array($table, (array) $ignore, TRUE)) + { + continue; + } - // -------------------------------------------------------------------- + // Get the table schema + $query = $this->db->query('SHOW CREATE TABLE '.$this->db->escape_identifiers($this->db->database.'.'.$table)); - /** - * Repair table query - * - * Generates a platform-specific query so that a table can be repaired - * - * @param string the table name - * @return string - */ - public function _repair_table($table) - { - return 'REPAIR TABLE '.$this->db->_escape_identifiers($table); - } + // No result means the table name was invalid + if ($query === FALSE) + { + continue; + } - // -------------------------------------------------------------------- + // Write out the table schema + $output .= '#'.$newline.'# TABLE STRUCTURE FOR: '.$table.$newline.'#'.$newline.$newline; - /** - * MySQLi Export - * - * @param array Preferences - * @return mixed - */ - public function _backup($params = array()) - { - // Currently unsupported - return $this->db->display_error('db_unsuported_feature'); + if ($add_drop === TRUE) + { + $output .= 'DROP TABLE IF EXISTS '.$this->db->protect_identifiers($table).';'.$newline.$newline; + } + + $i = 0; + $result = $query->result_array(); + foreach ($result[0] as $val) + { + if ($i++ % 2) + { + $output .= $val.';'.$newline.$newline; + } + } + + // If inserts are not needed we're done... + if ($add_insert === FALSE) + { + continue; + } + + // Grab all the data from the current table + $query = $this->db->query('SELECT * FROM '.$this->db->protect_identifiers($table)); + + if ($query->num_rows() === 0) + { + continue; + } + + // Fetch the field names and determine if the field is an + // integer type. We use this info to decide whether to + // surround the data with quotes or not + + $i = 0; + $field_str = ''; + $is_int = array(); + while ($field = $query->result_id->fetch_field()) + { + // Most versions of MySQL store timestamp as a string + $is_int[$i] = in_array(strtolower($field->type), + array('tinyint', 'smallint', 'mediumint', 'int', 'bigint'), //, 'timestamp'), + TRUE); + + // Create a string of field names + $field_str .= $this->db->escape_identifiers($field->name).', '; + $i++; + } + + // Trim off the end comma + $field_str = preg_replace('/, $/' , '', $field_str); + + // Build the insert string + foreach ($query->result_array() as $row) + { + $val_str = ''; + + $i = 0; + foreach ($row as $v) + { + // Is the value NULL? + if ($v === NULL) + { + $val_str .= 'NULL'; + } + else + { + // Escape the data if it's not an integer + $val_str .= ($is_int[$i] === FALSE) ? $this->db->escape($v) : $v; + } + + // Append a comma + $val_str .= ', '; + $i++; + } + + // Remove the comma at the end of the string + $val_str = preg_replace('/, $/' , '', $val_str); + + // Build the INSERT string + $output .= 'INSERT INTO '.$this->db->protect_identifiers($table).' ('.$field_str.') VALUES ('.$val_str.');'.$newline; + } + + $output .= $newline.$newline; + } + + return $output; } + } /* End of file mysqli_utility.php */ -/* Location: ./system/database/drivers/mysqli/mysqli_utility.php */ +/* Location: ./system/database/drivers/mysqli/mysqli_utility.php */
\ No newline at end of file diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php index c6621901b..e78091614 100644 --- a/system/database/drivers/oci8/oci8_driver.php +++ b/system/database/drivers/oci8/oci8_driver.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,13 +25,11 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * oci8 Database Adapter Class * * Note: _DB is an extender class that the app controller - * creates dynamically based on whether the active record + * creates dynamically based on whether the query builder * class is being used or not. * * @package CodeIgniter @@ -48,121 +46,154 @@ * permit access to oracle databases * * @author Kelly McArdle - * */ - class CI_DB_oci8_driver extends CI_DB { - var $dbdriver = 'oci8'; + public $dbdriver = 'oci8'; // The character used for excaping - var $_escape_char = '"'; + protected $_escape_char = '"'; // clause and character used for LIKE escape sequences - var $_like_escape_str = " escape '%s' "; - var $_like_escape_chr = '!'; + protected $_like_escape_str = " ESCAPE '%s' "; + protected $_like_escape_chr = '!'; /** * The syntax to count rows is slightly different across different * database engines, so this string appears in each driver and is * used for the count_all() and count_all_results() functions. */ - var $_count_string = "SELECT COUNT(1) AS "; - var $_random_keyword = ' ASC'; // not currently supported + protected $_count_string = 'SELECT COUNT(1) AS '; + protected $_random_keyword = ' ASC'; // not currently supported // Set "auto commit" by default - var $_commit = OCI_COMMIT_ON_SUCCESS; + public $commit_mode = OCI_COMMIT_ON_SUCCESS; // need to track statement id and cursor id - var $stmt_id; - var $curs_id; + public $stmt_id; + public $curs_id; // if we use a limit, we will add a field that will // throw off num_fields later - var $limit_used; + public $limit_used; - /** - * Non-persistent database connection - * - * @access private called by the base class - * @return resource - */ - public function db_connect() + public function __construct($params) { - return @oci_connect($this->username, $this->password, $this->hostname, $this->char_set); - } + parent::__construct($params); - // -------------------------------------------------------------------- + $valid_dsns = array( + 'tns' => '/^\(DESCRIPTION=(\(.+\)){2,}\)$/', // TNS + // Easy Connect string (Oracle 10g+) + 'ec' => '/^(\/\/)?[a-z0-9.:_-]+(:[1-9][0-9]{0,4})?(\/[a-z0-9$_]+)?(:[^\/])?(\/[a-z0-9$_]+)?$/i', + 'in' => '/^[a-z0-9$_]+$/i' // Instance name (defined in tnsnames.ora) + ); - /** - * Persistent database connection - * - * @access private called by the base class - * @return resource - */ - public function db_pconnect() - { - return @oci_pconnect($this->username, $this->password, $this->hostname, $this->char_set); - } + /* Space characters don't have any effect when actually + * connecting, but can be a hassle while validating the DSN. + */ + $this->dsn = str_replace(array("\n", "\r", "\t", ' '), '', $this->dsn); - // -------------------------------------------------------------------- + if ($this->dsn !== '') + { + foreach ($valid_dsns as $regexp) + { + if (preg_match($regexp, $this->dsn)) + { + return; + } + } + } - /** - * Reconnect - * - * Keep / reestablish the db connection if no queries have been - * sent for a length of time exceeding the server's idle timeout - * - * @access public - * @return void - */ - public function reconnect() - { - // not implemented in oracle - return; - } + // Legacy support for TNS in the hostname configuration field + $this->hostname = str_replace(array("\n", "\r", "\t", ' '), '', $this->hostname); + if (preg_match($valid_dsns['tns'], $this->hostname)) + { + $this->dsn = $this->hostname; + return; + } + elseif ($this->hostname !== '' && strpos($this->hostname, '/') === FALSE && strpos($this->hostname, ':') === FALSE + && (( ! empty($this->port) && ctype_digit($this->port)) OR $this->database !== '')) + { + /* If the hostname field isn't empty, doesn't contain + * ':' and/or '/' and if port and/or database aren't + * empty, then the hostname field is most likely indeed + * just a hostname. Therefore we'll try and build an + * Easy Connect string from these 3 settings, assuming + * that the database field is a service name. + */ + $this->dsn = $this->hostname + .(( ! empty($this->port) && ctype_digit($this->port)) ? ':'.$this->port : '') + .($this->database !== '' ? '/'.ltrim($this->database, '/') : ''); + + if (preg_match($valid_dsns['ec'], $this->dsn)) + { + return; + } + } - // -------------------------------------------------------------------- + /* At this point, we can only try and validate the hostname and + * database fields separately as DSNs. + */ + if (preg_match($valid_dsns['ec'], $this->hostname) OR preg_match($valid_dsns['in'], $this->hostname)) + { + $this->dsn = $this->hostname; + return; + } + + $this->database = str_replace(array("\n", "\r", "\t", ' '), '', $this->database); + foreach ($valid_dsns as $regexp) + { + if (preg_match($regexp, $this->database)) + { + return; + } + } + + /* Well - OK, an empty string should work as well. + * PHP will try to use environment variables to + * determine which Oracle instance to connect to. + */ + $this->dsn = ''; + } /** - * Select the database + * Non-persistent database connection * - * @access private called by the base class - * @return resource + * @return resource */ - public function db_select() + public function db_connect() { - // Not in Oracle - schemas are actually usernames - return TRUE; + return ( ! empty($this->char_set)) + ? @oci_connect($this->username, $this->password, $this->dsn, $this->char_set) + : @oci_connect($this->username, $this->password, $this->dsn); } // -------------------------------------------------------------------- /** - * Set client character set + * Persistent database connection * - * @access public - * @param string - * @param string * @return resource */ - public function db_set_charset($charset, $collation) + public function db_pconnect() { - // this is done upon connect - return TRUE; + return ( ! empty($this->char_set)) + ? @oci_pconnect($this->username, $this->password, $this->dsn, $this->char_set) + : @oci_pconnect($this->username, $this->password, $this->dsn); } // -------------------------------------------------------------------- /** - * Version number query string + * Database version number * - * @access protected - * @return string + * @return string */ - protected function _version() + public function version() { - return oci_server_version($this->conn_id); + return isset($this->data_cache['version']) + ? $this->data_cache['version'] + : $this->data_cache['version'] = oci_server_version($this->conn_id); } // -------------------------------------------------------------------- @@ -170,63 +201,44 @@ class CI_DB_oci8_driver extends CI_DB { /** * Execute the query * - * @access protected called by the base class - * @param string an SQL query - * @return resource + * @param string an SQL query + * @return resource */ protected function _execute($sql) { - // oracle must parse the query before it is run. All of the actions with - // the query are based on the statement id returned by ociparse + /* Oracle must parse the query before it is run. All of the actions with + * the query are based on the statement id returned by oci_parse(). + */ $this->stmt_id = FALSE; $this->_set_stmt_id($sql); oci_set_prefetch($this->stmt_id, 1000); - return @oci_execute($this->stmt_id, $this->_commit); + return @oci_execute($this->stmt_id, $this->commit_mode); } /** * Generate a statement ID * - * @access private - * @param string an SQL query - * @return none + * @param string an SQL query + * @return void */ - private function _set_stmt_id($sql) + protected function _set_stmt_id($sql) { if ( ! is_resource($this->stmt_id)) { - $this->stmt_id = oci_parse($this->conn_id, $this->_prep_query($sql)); + $this->stmt_id = oci_parse($this->conn_id, $sql); } } // -------------------------------------------------------------------- /** - * Prep the query - * - * If needed, each database adapter can prep the query string - * - * @access private called by execute() - * @param string an SQL query - * @return string - */ - private function _prep_query($sql) - { - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * getCursor. Returns a cursor from the datbase + * Get cursor. Returns a cursor from the database * - * @access public - * @return cursor id + * @return cursor id */ public function get_cursor() { - $this->curs_id = oci_new_cursor($this->conn_id); - return $this->curs_id; + return $this->curs_id = oci_new_cursor($this->conn_id); } // -------------------------------------------------------------------- @@ -234,24 +246,23 @@ class CI_DB_oci8_driver extends CI_DB { /** * Stored Procedure. Executes a stored procedure * - * @access public - * @param package package stored procedure is in - * @param procedure stored procedure to execute - * @param params array of parameters - * @return array + * @param string package name in which the stored procedure is in + * @param string stored procedure name to execute + * @param array parameters + * @return mixed * * params array keys * * KEY OPTIONAL NOTES - * name no the name of the parameter should be in :<param_name> format - * value no the value of the parameter. If this is an OUT or IN OUT parameter, - * this should be a reference to a variable - * type yes the type of the parameter - * length yes the max size of the parameter + * name no the name of the parameter should be in :<param_name> format + * value no the value of the parameter. If this is an OUT or IN OUT parameter, + * this should be a reference to a variable + * type yes the type of the parameter + * length yes the max size of the parameter */ public function stored_procedure($package, $procedure, $params) { - if ($package == '' OR $procedure == '' OR ! is_array($params)) + if ($package === '' OR $procedure === '' OR ! is_array($params)) { if ($this->db_debug) { @@ -262,24 +273,24 @@ class CI_DB_oci8_driver extends CI_DB { } // build the query string - $sql = "begin $package.$procedure("; + $sql = 'BEGIN '.$package.'.'.$procedure.'('; $have_cursor = FALSE; foreach ($params as $param) { - $sql .= $param['name'] . ","; + $sql .= $param['name'].','; - if (array_key_exists('type', $param) && ($param['type'] === OCI_B_CURSOR)) + if (isset($param['type']) && $param['type'] === OCI_B_CURSOR) { $have_cursor = TRUE; } } - $sql = trim($sql, ",") . "); end;"; + $sql = trim($sql, ',') . '); END;'; $this->stmt_id = FALSE; $this->_set_stmt_id($sql); $this->_bind_params($params); - $this->query($sql, FALSE, $have_cursor); + return $this->query($sql, FALSE, $have_cursor); } // -------------------------------------------------------------------- @@ -287,10 +298,9 @@ class CI_DB_oci8_driver extends CI_DB { /** * Bind parameters * - * @access private - * @return none + * @return void */ - private function _bind_params($params) + protected function _bind_params($params) { if ( ! is_array($params) OR ! is_resource($this->stmt_id)) { @@ -316,7 +326,6 @@ class CI_DB_oci8_driver extends CI_DB { /** * Begin Transaction * - * @access public * @return bool */ public function trans_begin($test_mode = FALSE) @@ -337,7 +346,7 @@ class CI_DB_oci8_driver extends CI_DB { // even if the queries produce a successful result. $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE; - $this->_commit = OCI_DEFAULT; + $this->commit_mode = (is_php('5.3.2')) ? OCI_NO_AUTO_COMMIT : OCI_DEFAULT; return TRUE; } @@ -346,7 +355,6 @@ class CI_DB_oci8_driver extends CI_DB { /** * Commit Transaction * - * @access public * @return bool */ public function trans_commit() @@ -362,9 +370,8 @@ class CI_DB_oci8_driver extends CI_DB { return TRUE; } - $ret = oci_commit($this->conn_id); - $this->_commit = OCI_COMMIT_ON_SUCCESS; - return $ret; + $this->commit_mode = OCI_COMMIT_ON_SUCCESS; + return oci_commit($this->conn_id); } // -------------------------------------------------------------------- @@ -372,25 +379,18 @@ class CI_DB_oci8_driver extends CI_DB { /** * Rollback Transaction * - * @access public * @return bool */ public function trans_rollback() { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } - $ret = oci_rollback($this->conn_id); - $this->_commit = OCI_COMMIT_ON_SUCCESS; - return $ret; + $this->commit_mode = OCI_COMMIT_ON_SUCCESS; + return oci_rollback($this->conn_id); } // -------------------------------------------------------------------- @@ -398,10 +398,9 @@ class CI_DB_oci8_driver extends CI_DB { /** * Escape String * - * @access public - * @param string + * @param string * @param bool whether or not the string will be used in a LIKE condition - * @return string + * @return string */ public function escape_str($str, $like = FALSE) { @@ -415,15 +414,14 @@ class CI_DB_oci8_driver extends CI_DB { return $str; } - $str = remove_invisible_characters($str); - $str = str_replace("'", "''", $str); + $str = str_replace("'", "''", remove_invisible_characters($str)); // escape LIKE condition wildcards if ($like === TRUE) { - $str = str_replace( array('%', '_', $this->_like_escape_chr), - array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr), - $str); + return str_replace(array($this->_like_escape_chr, '%', '_'), + array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'), + $str); } return $str; @@ -434,8 +432,7 @@ class CI_DB_oci8_driver extends CI_DB { /** * Affected Rows * - * @access public - * @return integer + * @return int */ public function affected_rows() { @@ -447,8 +444,7 @@ class CI_DB_oci8_driver extends CI_DB { /** * Insert ID * - * @access public - * @return integer + * @return int */ public function insert_id() { @@ -459,52 +455,20 @@ class CI_DB_oci8_driver extends CI_DB { // -------------------------------------------------------------------- /** - * "Count All" query - * - * Generates a platform-specific query string that counts all records in - * the specified database - * - * @access public - * @param string - * @return string - */ - public function count_all($table = '') - { - if ($table == '') - { - return 0; - } - - $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE)); - - if ($query == FALSE) - { - return 0; - } - - $row = $query->row(); - $this->_reset_select(); - return (int) $row->numrows; - } - - // -------------------------------------------------------------------- - - /** * Show table query * * Generates a platform-specific query string so that the table names can be fetched * - * @access protected - * @param boolean + * @param bool * @return string */ protected function _list_tables($prefix_limit = FALSE) { - $sql = "SELECT TABLE_NAME FROM ALL_TABLES"; + $sql = 'SELECT TABLE_NAME FROM ALL_TABLES'; - if ($prefix_limit !== FALSE AND $this->dbprefix != '') + if ($prefix_limit !== FALSE && $this->dbprefix !== '') { - $sql .= " WHERE TABLE_NAME LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); + return $sql." WHERE TABLE_NAME LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); } return $sql; @@ -517,13 +481,12 @@ class CI_DB_oci8_driver extends CI_DB { * * Generates a platform-specific query string so that the column names can be fetched * - * @access protected - * @param string the table name - * @return string + * @param string the table name + * @return string */ protected function _list_columns($table = '') { - return "SELECT COLUMN_NAME FROM all_tab_columns WHERE table_name = '$table'"; + return 'SELECT COLUMN_NAME FROM all_tab_columns WHERE table_name = \''.$table.'\''; } // -------------------------------------------------------------------- @@ -533,85 +496,43 @@ class CI_DB_oci8_driver extends CI_DB { * * Generates a platform-specific query so that the column data can be retrieved * - * @access public - * @param string the table name - * @return object + * @param string the table name + * @return string */ protected function _field_data($table) { - return "SELECT * FROM ".$table." where rownum = 1"; - } - - // -------------------------------------------------------------------- - - /** - * The error message string - * - * @access protected - * @return string - */ - protected function _error_message() - { - // If the error was during connection, no conn_id should be passed - $error = is_resource($this->conn_id) ? oci_error($this->conn_id) : oci_error(); - return $error['message']; - } - - // -------------------------------------------------------------------- - - /** - * The error message number - * - * @access protected - * @return integer - */ - protected function _error_number() - { - // Same as _error_message() - $error = is_resource($this->conn_id) ? oci_error($this->conn_id) : oci_error(); - return $error['code']; + return 'SELECT * FROM '.$table.' WHERE rownum = 1'; } // -------------------------------------------------------------------- /** - * Escape the SQL Identifiers + * Error * - * This function escapes column and table names + * Returns an array containing code and message of the last + * database error that has occured. * - * @access protected - * @param string - * @return string + * @return array */ - protected function _escape_identifiers($item) + public function error() { - if ($this->_escape_char == '') - { - return $item; - } - - foreach ($this->_reserved_identifiers as $id) + /* oci_error() returns an array that already contains the + * 'code' and 'message' keys, so we can just return it. + */ + if (is_resource($this->curs_id)) { - if (strpos($item, '.'.$id) !== FALSE) - { - $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item); - - // remove duplicates if the user already included the escape - return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); - } + return oci_error($this->curs_id); } - - if (strpos($item, '.') !== FALSE) + elseif (is_resource($this->stmt_id)) { - $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char; + return oci_error($this->stmt_id); } - else + elseif (is_resource($this->conn_id)) { - $str = $this->_escape_char.$item.$this->_escape_char; + return oci_error($this->conn_id); } - // remove duplicates if the user already included the escape - return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + return oci_error(); } // -------------------------------------------------------------------- @@ -622,36 +543,12 @@ class CI_DB_oci8_driver extends CI_DB { * This function implicitly groups FROM tables so there is no confusion * about operator precedence in harmony with SQL standards * - * @access protected - * @param type - * @return type + * @param array + * @return string */ protected function _from_tables($tables) { - if ( ! is_array($tables)) - { - $tables = array($tables); - } - - return implode(', ', $tables); - } - - // -------------------------------------------------------------------- - - /** - * Insert statement - * - * Generates a platform-specific insert string from the supplied data - * - * @access public - * @param string the table name - * @param array the insert keys - * @param array the insert values - * @return string - */ - protected function _insert($table, $keys, $values) - { - return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")"; + return is_array($tables) ? implode(', ', $tables) : $tables; } // -------------------------------------------------------------------- @@ -661,10 +558,10 @@ class CI_DB_oci8_driver extends CI_DB { * * Generates a platform-specific insert string from the supplied data * - * @param string the table name - * @param array the insert keys - * @param array the insert values - * @return string + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string */ protected function _insert_batch($table, $keys, $values) { @@ -673,47 +570,10 @@ class CI_DB_oci8_driver extends CI_DB { for ($i = 0, $c = count($values); $i < $c; $i++) { - $sql .= ' INTO ' . $table . ' (' . $keys . ') VALUES ' . $values[$i] . "\n"; + $sql .= ' INTO '.$table.' ('.$keys.') VALUES '.$values[$i]."\n"; } - $sql .= 'SELECT * FROM dual'; - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Update statement - * - * Generates a platform-specific update string from the supplied data - * - * @access protected - * @param string the table name - * @param array the update data - * @param array the where clause - * @param array the orderby clause - * @param array the limit clause - * @return string - */ - protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE) - { - foreach ($values as $key => $val) - { - $valstr[] = $key." = ".$val; - } - - $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; - - $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):''; - - $sql = "UPDATE ".$table." SET ".implode(', ', $valstr); - - $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : ''; - - $sql .= $orderby.$limit; - - return $sql; + return $sql.'SELECT * FROM dual'; } // -------------------------------------------------------------------- @@ -722,16 +582,16 @@ class CI_DB_oci8_driver extends CI_DB { * Truncate statement * * Generates a platform-specific truncate string from the supplied data - * If the database does not support the truncate() command - * This function maps to "DELETE FROM table" * - * @access protected + * If the database does not support the truncate() command, + * then this method maps to 'DELETE FROM table' + * * @param string the table name * @return string */ protected function _truncate($table) { - return "TRUNCATE TABLE ".$table; + return 'TRUNCATE TABLE '.$table; } // -------------------------------------------------------------------- @@ -741,31 +601,21 @@ class CI_DB_oci8_driver extends CI_DB { * * Generates a platform-specific delete string from the supplied data * - * @access protected * @param string the table name * @param array the where clause + * @param array the like clause * @param string the limit clause * @return string */ protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) { - $conditions = ''; - - if (count($where) > 0 OR count($like) > 0) - { - $conditions = "\nWHERE "; - $conditions .= implode("\n", $this->ar_where); - - if (count($where) > 0 && count($like) > 0) - { - $conditions .= " AND "; - } - $conditions .= implode("\n", $like); - } + $conditions = array(); - $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + empty($where) OR $conditions[] = implode(' ', $where); + empty($like) OR $conditions[] = implode(' ', $like); + empty($limit) OR $conditions[] = 'rownum <= '.$limit; - return "DELETE FROM ".$table.$conditions.$limit; + return 'DELETE FROM '.$table.(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : ''); } // -------------------------------------------------------------------- @@ -775,26 +625,16 @@ class CI_DB_oci8_driver extends CI_DB { * * Generates a platform-specific LIMIT clause * - * @access protected - * @param string the sql query string - * @param integer the number of rows to limit the query to - * @param integer the offset value - * @return string + * @param string the sql query string + * @param int the number of rows to limit the query to + * @param int the offset value + * @return string */ protected function _limit($sql, $limit, $offset) { - $limit = $offset + $limit; - $newsql = "SELECT * FROM (select inner_query.*, rownum rnum FROM ($sql) inner_query WHERE rownum < $limit)"; - - if ($offset != 0) - { - $newsql .= " WHERE rnum >= $offset"; - } - - // remember that we used limits $this->limit_used = TRUE; - - return $newsql; + return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($offset + $limit).')' + .($offset !== 0 ? ' WHERE rnum >= '.$offset : ''); } // -------------------------------------------------------------------- @@ -802,19 +642,14 @@ class CI_DB_oci8_driver extends CI_DB { /** * Close DB Connection * - * @access protected - * @param resource - * @return void + * @return void */ - protected function _close($conn_id) + protected function _close() { - @oci_close($conn_id); + @oci_close($this->conn_id); } - } - - /* End of file oci8_driver.php */ -/* Location: ./system/database/drivers/oci8/oci8_driver.php */ +/* Location: ./system/database/drivers/oci8/oci8_driver.php */
\ No newline at end of file diff --git a/system/database/drivers/oci8/oci8_forge.php b/system/database/drivers/oci8/oci8_forge.php index b4a24cdca..92e8c02ed 100644 --- a/system/database/drivers/oci8/oci8_forge.php +++ b/system/database/drivers/oci8/oci8_forge.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,8 +25,6 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * Oracle Forge Class * @@ -36,46 +34,21 @@ */ class CI_DB_oci8_forge extends CI_DB_forge { - /** - * Create database - * - * @access public - * @param string the database name - * @return bool - */ - function _create_database($name) - { - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Drop database - * - * @access private - * @param string the database name - * @return bool - */ - function _drop_database($name) - { - return FALSE; - } - - // -------------------------------------------------------------------- + protected $_create_database = FALSE; + protected $_drop_database = FALSE; + protected $_drop_table = 'DROP TABLE %s'; /** * Create Table * - * @access private * @param string the table name * @param array the fields * @param mixed primary key(s) * @param mixed key(s) - * @param boolean should 'IF NOT EXISTS' be added to the SQL - * @return bool + * @param bool should 'IF NOT EXISTS' be added to the SQL + * @return string */ - function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) + protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) { $sql = 'CREATE TABLE '; @@ -84,54 +57,38 @@ class CI_DB_oci8_forge extends CI_DB_forge { $sql .= 'IF NOT EXISTS '; } - $sql .= $this->db->_escape_identifiers($table)." ("; + $sql .= $this->db->escape_identifiers($table).' ('; $current_field_count = 0; - foreach ($fields as $field=>$attributes) + foreach ($fields as $field => $attributes) { // Numeric field names aren't allowed in databases, so if the key is // numeric, we know it was assigned by PHP and the developer manually // entered the field information, so we'll simply add it to the list if (is_numeric($field)) { - $sql .= "\n\t$attributes"; + $sql .= "\n\t".$attributes; } else { $attributes = array_change_key_case($attributes, CASE_UPPER); - $sql .= "\n\t".$this->db->_protect_identifiers($field); - - $sql .= ' '.$attributes['TYPE']; - - if (array_key_exists('CONSTRAINT', $attributes)) - { - $sql .= '('.$attributes['CONSTRAINT'].')'; - } + $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE']; - if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE) + if (isset($attributes['UNSINGED']) && $attributes['UNSIGNED'] === TRUE) { $sql .= ' UNSIGNED'; } - if (array_key_exists('DEFAULT', $attributes)) + if (isset($attributes['DEFAULT'])) { - $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\''; + $sql .= " DEFAULT '".$attributes['DEFAULT']."'"; } - if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE) - { - $sql .= ' NULL'; - } - else - { - $sql .= ' NOT NULL'; - } + $sql .= (isset($attributes['NULL']) && $attributes['NULL'] === TRUE) + ? '' : ' NOT NULL'; - if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE) - { - $sql .= ' AUTO_INCREMENT'; - } + empty($attributes['CONSTRAINT']) OR ' CONSTRAINT '.$attributes['CONSTRAINT']; } // don't add a comma on the end of the last field @@ -143,43 +100,22 @@ class CI_DB_oci8_forge extends CI_DB_forge { if (count($primary_keys) > 0) { - $primary_keys = $this->db->_protect_identifiers($primary_keys); - $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")"; + $sql .= ",\n\tCONSTRAINT ".$table.' PRIMARY KEY ('.implode(', ', $this->db->escape_identifiers($primary_keys)).')'; } if (is_array($keys) && count($keys) > 0) { foreach ($keys as $key) { - if (is_array($key)) - { - $key = $this->db->_protect_identifiers($key); - } - else - { - $key = array($this->db->_protect_identifiers($key)); - } + $key = is_array($key) + ? $this->db->escape_identifiers($key) + : array($this->db->escape_identifiers($key)); - $sql .= ",\n\tUNIQUE COLUMNS (" . implode(', ', $key) . ")"; + $sql .= ",\n\tUNIQUE COLUMNS (".implode(', ', $key).')'; } } - $sql .= "\n)"; - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Drop Table - * - * @access private - * @return bool - */ - function _drop_table($table) - { - return FALSE; + return $sql."\n)"; } // -------------------------------------------------------------------- @@ -190,70 +126,32 @@ class CI_DB_oci8_forge extends CI_DB_forge { * Generates a platform-specific query so that a table can be altered * Called by add_column(), drop_column(), and column_alter(), * - * @access private * @param string the ALTER type (ADD, DROP, CHANGE) * @param string the column name * @param string the table name * @param string the column definition * @param string the default value - * @param boolean should 'NOT NULL' be added + * @param bool should 'NOT NULL' be added * @param string the field after which we should add the new field - * @return object + * @return string */ - function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') + protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') { - $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name); + $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name); // DROP has everything it needs now. - if ($alter_type == 'DROP') + if ($alter_type === 'DROP') { return $sql; } - $sql .= " $column_definition"; - - if ($default_value != '') - { - $sql .= " DEFAULT \"$default_value\""; - } + return $sql.' '.$column_definition + .($default_value !== '' ? ' DEFAULT "'.$default_value.'"' : '') + .($null === NULL ? ' NULL' : ' NOT NULL') + .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : ''); - if ($null === NULL) - { - $sql .= ' NULL'; - } - else - { - $sql .= ' NOT NULL'; - } - - if ($after_field != '') - { - $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field); - } - - return $sql; - - } - - // -------------------------------------------------------------------- - - /** - * Rename a table - * - * Generates a platform-specific query so that a table can be renamed - * - * @access private - * @param string the old table name - * @param string the new table name - * @return string - */ - function _rename_table($table_name, $new_table_name) - { - $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name); - return $sql; } - } /* End of file oci8_forge.php */ diff --git a/system/database/drivers/oci8/oci8_result.php b/system/database/drivers/oci8/oci8_result.php index 0f69fa9ef..6fb6c81f1 100644 --- a/system/database/drivers/oci8/oci8_result.php +++ b/system/database/drivers/oci8/oci8_result.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,8 +25,6 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * oci8 Result Class * @@ -38,31 +36,48 @@ */ class CI_DB_oci8_result extends CI_DB_result { - var $stmt_id; - var $curs_id; - var $limit_used; + public $stmt_id; + public $curs_id; + public $limit_used; + public $commit_mode; + + /* Overwriting the parent here, so we have a way to know if it's + * already called or not: + */ + public $num_rows; + + public function __construct(&$driver_object) + { + parent::__construct($driver_object); + $this->stmt_id = $driver_object->stmt_id; + $this->curs_id = $driver_object->curs_id; + $this->limit_used = $driver_object->limit_used; + $this->commit_mode =& $driver_object->commit_mode; + $driver_object->stmt_id = FALSE; + } /** * Number of rows in the result set. * - * Oracle doesn't have a graceful way to retun the number of rows + * Oracle doesn't have a graceful way to return the number of rows * so we have to use what amounts to a hack. * - * - * @access public - * @return integer + * @return int */ public function num_rows() { - if ($this->num_rows === 0 && count($this->result_array()) > 0) + if ( ! is_int($this->num_rows)) { - $this->num_rows = count($this->result_array()); - @oci_execute($this->stmt_id, OCI_DEFAULT); - - if ($this->curs_id) + if (count($this->result_array) > 0) + { + return $this->num_rows = count($this->result_array); + } + elseif (count($this->result_object) > 0) { - @oci_execute($this->curs_id, OCI_DEFAULT); + return $this->num_rows = count($this->result_object); } + + return $this->num_rows = count($this->result_array()); } return $this->num_rows; @@ -73,20 +88,14 @@ class CI_DB_oci8_result extends CI_DB_result { /** * Number of fields in the result set * - * @access public - * @return integer + * @return int */ public function num_fields() { $count = @oci_num_fields($this->stmt_id); // if we used a limit we subtract it - if ($this->limit_used) - { - $count = $count - 1; - } - - return $count; + return ($this->limit_used) ? $count - 1 : $count; } // -------------------------------------------------------------------- @@ -96,7 +105,6 @@ class CI_DB_oci8_result extends CI_DB_result { * * Generates an array of column names * - * @access public * @return array */ public function list_fields() @@ -116,18 +124,17 @@ class CI_DB_oci8_result extends CI_DB_result { * * Generates an array of objects containing field meta-data * - * @access public - * @return array + * @return array */ public function field_data() { $retval = array(); for ($c = 1, $fieldCount = $this->num_fields(); $c <= $fieldCount; $c++) { - $F = new stdClass(); - $F->name = oci_field_name($this->stmt_id, $c); - $F->type = oci_field_type($this->stmt_id, $c); - $F->max_length = oci_field_size($this->stmt_id, $c); + $F = new stdClass(); + $F->name = oci_field_name($this->stmt_id, $c); + $F->type = oci_field_type($this->stmt_id, $c); + $F->max_length = oci_field_size($this->stmt_id, $c); $retval[] = $F; } @@ -140,7 +147,7 @@ class CI_DB_oci8_result extends CI_DB_result { /** * Free the result * - * @return null + * @return void */ public function free_result() { @@ -149,6 +156,17 @@ class CI_DB_oci8_result extends CI_DB_result { oci_free_statement($this->result_id); $this->result_id = FALSE; } + + if (is_resource($this->stmt_id)) + { + oci_free_statement($this->stmt_id); + } + + if (is_resource($this->curs_id)) + { + oci_cancel($this->curs_id); + $this->curs_id = NULL; + } } // -------------------------------------------------------------------- @@ -158,8 +176,7 @@ class CI_DB_oci8_result extends CI_DB_result { * * Returns the result set as an array * - * @access protected - * @return array + * @return array */ protected function _fetch_assoc() { @@ -174,22 +191,20 @@ class CI_DB_oci8_result extends CI_DB_result { * * Returns the result set as an object * - * @access protected - * @return object + * @return object */ protected function _fetch_object() { $id = ($this->curs_id) ? $this->curs_id : $this->stmt_id; - return @oci_fetch_object($id); + return oci_fetch_object($id); } // -------------------------------------------------------------------- /** - * Query result. "array" version. + * Query result. Array version. * - * @access public - * @return array + * @return array */ public function result_array() { @@ -197,14 +212,429 @@ class CI_DB_oci8_result extends CI_DB_result { { return $this->result_array; } + elseif (count($this->result_object) > 0) + { + for ($i = 0, $c = count($this->result_object); $i < $c; $i++) + { + $this->result_array[$i] = (array) $this->result_object[$i]; + } + + return $this->result_array; + } + elseif (is_array($this->row_data)) + { + if (count($this->row_data) === 0) + { + return $this->result_array; + } + else + { + $row_index = count($this->row_data); + } + } + else + { + $row_index = 0; + $this->row_data = array(); + } $row = NULL; while ($row = $this->_fetch_assoc()) { - $this->result_array[] = $row; + $this->row_data[$row_index++] = $row; } - return $this->result_array; + return $this->result_array = $this->row_data; + } + + // -------------------------------------------------------------------- + + /** + * Query result. "object" version. + * + * @return array + */ + public function result_object() + { + if (count($this->result_object) > 0) + { + return $this->result_object; + } + elseif (count($this->result_array) > 0) + { + for ($i = 0, $c = count($this->result_array); $i < $c; $i++) + { + $this->result_object[] = (object) $this->result_array[$i]; + } + + return $this->result_object; + } + elseif (is_array($this->row_data)) + { + if (count($this->row_data) === 0) + { + return $this->result_object; + } + else + { + $row_index = count($this->row_data); + for ($i = 0; $i < $row_index; $i++) + { + $this->result_object[$i] = (object) $this->row_data[$i]; + } + } + } + else + { + $row_index = 0; + $this->row_data = array(); + } + + $row = NULL; + while ($row = $this->_fetch_object()) + { + $this->row_data[$row_index] = (array) $row; + $this->result_object[$row_index++] = $row; + } + + return $this->result_object; + } + + // -------------------------------------------------------------------- + + /** + * Query result. Custom object version. + * + * @param string class name used to instantiate rows to + * @return array + */ + public function custom_result_object($class_name) + { + if (isset($this->custom_result_object[$class_name])) + { + return $this->custom_result_object[$class_name]; + } + + if ( ! class_exists($class_name) OR $this->result_id === FALSE OR $this->num_rows() === 0) + { + return array(); + } + + /* Even if we didn't have result_array or result_object + * set prior to custom_result_object() being called, + * num_rows() has already done so. + * Pass by reference, as we don't know how + * large it might be and we don't want 1000 row + * sets being copied. + */ + if (count($this->result_array) > 0) + { + $data = &$this->result_array; + } + elseif (count($this->result_object) > 0) + { + $data = &$this->result_object; + } + + $this->custom_result_object[$class_name] = array(); + for ($i = 0, $c = count($data); $i < $c; $i++) + { + $this->custom_result_object[$class_name][$i] = new $class_name(); + foreach ($data[$i] as $key => $value) + { + $this->custom_result_object[$class_name][$i]->$key = $value; + } + } + + return $this->custom_result_object[$class_name]; + } + + // -------------------------------------------------------------------- + + /* Single row result. + * + * Acts as a wrapper for row_object(), row_array() + * and custom_row_object(). Also used by first_row(), next_row() + * and previous_row(). + * + * @param int row index + * @param string ('object', 'array' or a custom class name) + * @return mixed whatever was passed to the second parameter + */ + public function row($n = 0, $type = 'object') + { + if ($type === 'object') + { + return $this->row_object($n); + } + elseif ($type === 'array') + { + return $this->row_array($n); + } + + return $this->custom_row_object($n, $type); + } + + // -------------------------------------------------------------------- + + /* Single row result. Array version. + * + * @param int row index + * @return array + */ + public function row_array($n = 0) + { + // Make sure $n is not a string + if ( ! is_int($n)) + { + $n = (int) $n; + } + + /* If row_data is initialized, it means that we've already tried + * (at least) to fetch some data, so ... check if we already have + * this row. + */ + if (is_array($this->row_data)) + { + /* If we already have row_data[$n] - return it. + * + * If we enter the elseif, there's a number of reasons to + * return an empty array: + * + * - count($this->row_data) === 0 means there are no results + * - num_rows being set, result_array and/or result_object + * having count() > 0 means that we've already fetched all + * data and $n is greater than our highest row index available + * - $n < $this->current_row means that if such row existed, + * we would've already returned it, therefore $n is an + * invalid index + */ + if (isset($this->row_data[$n])) // We already have this row + { + $this->current_row = $n; + return $this->row_data[$n]; + } + elseif (count($this->row_data) === 0 OR is_int($this->num_rows) + OR count($this->result_array) > 0 OR count($this->result_object) > 0 + OR $n < $this->current_row) + { + // No such row exists + return NULL; + } + + // Get the next row index that would actually need to be fetched + $current_row = ($this->current_row < count($this->row_data)) ? count($this->row_data) : $this->current_row + 1; + } + else + { + $current_row = $this->current_row = 0; + $this->row_data = array(); + } + + /* Fetch more data, if available + * + * NOTE: Operator precedence is important here, if you change + * 'AND' with '&&' - it WILL BREAK the results, as + * $row will be assigned the scalar value of both + * expressions! + */ + while ($row = $this->_fetch_assoc() AND $current_row <= $n) + { + $this->row_data[$current_row++] = $row; + } + + // This would mean that there's no (more) data to fetch + if ( ! is_array($this->row_data) OR ! isset($this->row_data[$n])) + { + // Cache what we already have + if (is_array($this->row_data)) + { + $this->num_rows = count($this->row_data); + /* Usually, row_data could have less elements than result_array, + * but at this point - they should be exactly the same. + */ + $this->result_array = $this->row_data; + } + else + { + $this->num_rows = 0; + } + + return NULL; + } + + $this->current_row = $n; + return $this->row_data[$n]; + } + + // -------------------------------------------------------------------- + + /* Single row result. Object version. + * + * @param int row index + * @return mixed object if row found; empty array if not + */ + public function row_object($n = 0) + { + // Make sure $n is not a string + if ( ! is_int($n)) + { + $n = (int) $n; + } + /* Logic here is exactly the same as in row_array, + * except we have to cast row_data[$n] to an object. + * + * If we already have result_object though - we can + * directly return from it. + */ + if (isset($this->result_object[$n])) + { + $this->current_row = $n; + // Set this, if not already done. + if ( ! is_int($this->num_rows)) + { + $this->num_rows = count($this->result_object); + } + + return $this->result_object[$n]; + } + + $row = $this->row_array($n); + // Cast only if the row exists + if (count($row) > 0) + { + $this->current_row = $n; + return (object) $row; + } + + return NULL; + } + + // -------------------------------------------------------------------- + + /* Single row result. Custom object version. + * + * @param int row index + * @param string custom class name + * @return mixed custom object if row found; empty array otherwise + */ + public function custom_row_object($n = 0, $class_name) + { + // Make sure $n is not a string + if ( ! is_int($n)) + { + $n = (int) $n; + } + + if (array_key_exists($class_name, $this->custom_result_object)) + { + /* We already have a the whole result set with this class_name, + * return the specified row if it exists, and an empty array if + * it doesn't. + */ + if (isset($this->custom_result_object[$class_name][$n])) + { + $this->current_row = $n; + return $this->custom_result_object[$class_name][$n]; + } + else + { + return NULL; + } + } + elseif ( ! class_exists($class_name)) // No such class exists + { + return NULL; + } + + $row = $this->row_array($n); + // A non-array would mean that the row doesn't exist + if ( ! is_array($row)) + { + return NULL; + } + + // Convert to the desired class and return + $row_object = new $class_name(); + foreach ($row as $key => $value) + { + $row_object->$key = $value; + } + + $this->current_row = $n; + return $row_object; + } + + // -------------------------------------------------------------------- + + /* First row result. + * + * @param string ('object', 'array' or a custom class name) + * @return mixed whatever was passed to the second parameter + */ + public function first_row($type = 'object') + { + return $this->row(0, $type); + } + + // -------------------------------------------------------------------- + + /* Last row result. + * + * @param string ('object', 'array' or a custom class name) + * @return mixed whatever was passed to the second parameter + */ + public function last_row($type = 'object') + { + $result = &$this->result($type); + if ( ! isset($this->num_rows)) + { + $this->num_rows = count($result); + } + $this->current_row = $this->num_rows - 1; + return $result[$this->current_row]; + } + + // -------------------------------------------------------------------- + + /* Next row result. + * + * @param string ('object', 'array' or a custom class name) + * @return mixed whatever was passed to the second parameter + */ + public function next_row($type = 'object') + { + if (is_array($this->row_data)) + { + $count = count($this->row_data); + if ($this->current_row > $count OR ($this->current_row === 0 && $count === 0)) + { + $n = $count; + } + else + { + $n = $this->current_row + 1; + } + } + else + { + $n = 0; + } + + return $this->row($n, $type); + } + + // -------------------------------------------------------------------- + + /* Previous row result. + * + * @param string ('object', 'array' or a custom class name) + * @return mixed whatever was passed to the second parameter + */ + public function previous_row($type = 'object') + { + $n = ($this->current_row !== 0) ? $this->current_row - 1 : 0; + return $this->row($n, $type); } // -------------------------------------------------------------------- @@ -212,20 +642,59 @@ class CI_DB_oci8_result extends CI_DB_result { /** * Data Seek * - * Moves the internal pointer to the desired offset. We call + * Moves the internal pointer to the desired offset. We call * this internally before fetching results to make sure the - * result set starts at zero + * result set starts at zero. * - * @access protected - * @return array + * Oracle's PHP extension doesn't have an easy way of doing this + * and the only workaround is to (re)execute the statement or cursor + * in order to go to the first (zero) index of the result set. + * Then, we would need to "dummy" fetch ($n - 1) rows to get to the + * right one. + * + * This is as ridiculous as it sounds and it's the reason why every + * other method that is fetching data tries to use an already "cached" + * result set. Keeping this just in case it becomes needed at + * some point in the future, but it will only work for resetting the + * pointer to zero. + * + * @return bool */ - protected function _data_seek($n = 0) + protected function _data_seek() { - return FALSE; // Not needed + /* The PHP manual says that if OCI_NO_AUTO_COMMIT mode + * is used, and oci_rollback() and/or oci_commit() are + * not subsequently called - this will cause an unnecessary + * rollback to be triggered at the end of the script execution. + * + * Therefore we'll try to avoid using that mode flag + * if we're not currently in the middle of a transaction. + */ + if ($this->commit_mode !== OCI_COMMIT_ON_SUCCESS) + { + $result = @oci_execute($this->stmt_id, $this->commit_mode); + } + else + { + $result = @oci_execute($this->stmt_id); + } + + if ($result && $this->curs_id) + { + if ($this->commit_mode !== OCI_COMMIT_ON_SUCCESS) + { + return @oci_execute($this->curs_id, $this->commit_mode); + } + else + { + return @oci_execute($this->curs_id); + } + } + + return $result; } } - /* End of file oci8_result.php */ -/* Location: ./system/database/drivers/oci8/oci8_result.php */ +/* Location: ./system/database/drivers/oci8/oci8_result.php */
\ No newline at end of file diff --git a/system/database/drivers/oci8/oci8_utility.php b/system/database/drivers/oci8/oci8_utility.php index d60f98bc4..0183eda26 100644 --- a/system/database/drivers/oci8/oci8_utility.php +++ b/system/database/drivers/oci8/oci8_utility.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,8 +25,6 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * Oracle Utility Class * @@ -36,63 +34,20 @@ */ class CI_DB_oci8_utility extends CI_DB_utility { - /** - * List databases - * - * @access private - * @return bool - */ - function _list_databases() - { - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Optimize table query - * - * Generates a platform-specific query so that a table can be optimized - * - * @access private - * @param string the table name - * @return object - */ - function _optimize_table($table) - { - return FALSE; // Is this supported in Oracle? - } - - // -------------------------------------------------------------------- - - /** - * Repair table query - * - * Generates a platform-specific query so that a table can be repaired - * - * @access private - * @param string the table name - * @return object - */ - function _repair_table($table) - { - return FALSE; // Is this supported in Oracle? - } - - // -------------------------------------------------------------------- + protected $_list_databases = 'SELECT username FROM dba_users'; // Schemas are actual usernames /** * Oracle Export * - * @access private * @param array Preferences * @return mixed */ - function _backup($params = array()) + protected function _backup($params = array()) { // Currently unsupported return $this->db->display_error('db_unsuported_feature'); } + } /* End of file oci8_utility.php */ diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php index 6ba39f0cd..222c311c0 100644 --- a/system/database/drivers/odbc/odbc_driver.php +++ b/system/database/drivers/odbc/odbc_driver.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,13 +25,11 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * ODBC Database Adapter Class * * Note: _DB is an extender class that the app controller - * creates dynamically based on whether the active record + * creates dynamically based on whether the query builder * class is being used or not. * * @package CodeIgniter @@ -42,40 +40,44 @@ */ class CI_DB_odbc_driver extends CI_DB { - var $dbdriver = 'odbc'; + public $dbdriver = 'odbc'; // the character used to excape - not necessary for ODBC - var $_escape_char = ''; + protected $_escape_char = ''; // clause and character used for LIKE escape sequences - var $_like_escape_str = " {escape '%s'} "; - var $_like_escape_chr = '!'; + protected $_like_escape_str = " {escape '%s'} "; + protected $_like_escape_chr = '!'; /** * The syntax to count rows is slightly different across different * database engines, so this string appears in each driver and is * used for the count_all() and count_all_results() functions. */ - var $_count_string = "SELECT COUNT(*) AS "; - var $_random_keyword; + protected $_count_string = 'SELECT COUNT(*) AS '; + protected $_random_keyword; - - function __construct($params) + public function __construct($params) { parent::__construct($params); $this->_random_keyword = ' RND('.time().')'; // database specific random keyword + + // Legacy support for DSN in the hostname field + if (empty($this->dsn)) + { + $this->dsn = $this->hostname; + } } /** * Non-persistent database connection * - * @access private called by the base class * @return resource */ - function db_connect() + public function db_connect() { - return @odbc_connect($this->hostname, $this->username, $this->password); + return @odbc_connect($this->dsn, $this->username, $this->password); } // -------------------------------------------------------------------- @@ -83,71 +85,11 @@ class CI_DB_odbc_driver extends CI_DB { /** * Persistent database connection * - * @access private called by the base class * @return resource */ - function db_pconnect() + public function db_pconnect() { - return @odbc_pconnect($this->hostname, $this->username, $this->password); - } - - // -------------------------------------------------------------------- - - /** - * Reconnect - * - * Keep / reestablish the db connection if no queries have been - * sent for a length of time exceeding the server's idle timeout - * - * @access public - * @return void - */ - function reconnect() - { - // not implemented in odbc - } - - // -------------------------------------------------------------------- - - /** - * Select the database - * - * @access private called by the base class - * @return resource - */ - function db_select() - { - // Not needed for ODBC - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Set client character set - * - * @access public - * @param string - * @param string - * @return resource - */ - function db_set_charset($charset, $collation) - { - // @todo - add support if needed - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Version number query string - * - * @access public - * @return string - */ - function _version() - { - return "SELECT version() AS ver"; + return @odbc_pconnect($this->dsn, $this->username, $this->password); } // -------------------------------------------------------------------- @@ -155,49 +97,25 @@ class CI_DB_odbc_driver extends CI_DB { /** * Execute the query * - * @access private called by the base class * @param string an SQL query * @return resource */ - function _execute($sql) + protected function _execute($sql) { - $sql = $this->_prep_query($sql); return @odbc_exec($this->conn_id, $sql); } // -------------------------------------------------------------------- /** - * Prep the query - * - * If needed, each database adapter can prep the query string - * - * @access private called by execute() - * @param string an SQL query - * @return string - */ - function _prep_query($sql) - { - return $sql; - } - - // -------------------------------------------------------------------- - - /** * Begin Transaction * - * @access public * @return bool */ - function trans_begin($test_mode = FALSE) + public function trans_begin($test_mode = FALSE) { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } @@ -205,7 +123,7 @@ class CI_DB_odbc_driver extends CI_DB { // Reset the transaction failure flag. // If the $test_mode flag is set to TRUE transactions will be rolled back // even if the queries produce a successful result. - $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE; + $this->_trans_failure = ($test_mode === TRUE); return odbc_autocommit($this->conn_id, FALSE); } @@ -215,18 +133,12 @@ class CI_DB_odbc_driver extends CI_DB { /** * Commit Transaction * - * @access public * @return bool */ - function trans_commit() + public function trans_commit() { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } @@ -241,18 +153,12 @@ class CI_DB_odbc_driver extends CI_DB { /** * Rollback Transaction * - * @access public * @return bool */ - function trans_rollback() + public function trans_rollback() { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } @@ -267,12 +173,11 @@ class CI_DB_odbc_driver extends CI_DB { /** * Escape String * - * @access public * @param string * @param bool whether or not the string will be used in a LIKE condition * @return string */ - function escape_str($str, $like = FALSE) + public function escape_str($str, $like = FALSE) { if (is_array($str)) { @@ -284,15 +189,14 @@ class CI_DB_odbc_driver extends CI_DB { return $str; } - // ODBC doesn't require escaping $str = remove_invisible_characters($str); // escape LIKE condition wildcards if ($like === TRUE) { - $str = str_replace( array('%', '_', $this->_like_escape_chr), - array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr), - $str); + return str_replace(array($this->_like_escape_chr, '%', '_'), + array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'), + $str); } return $str; @@ -303,10 +207,9 @@ class CI_DB_odbc_driver extends CI_DB { /** * Affected Rows * - * @access public - * @return integer + * @return int */ - function affected_rows() + public function affected_rows() { return @odbc_num_rows($this->conn_id); } @@ -316,43 +219,11 @@ class CI_DB_odbc_driver extends CI_DB { /** * Insert ID * - * @access public - * @return integer - */ - function insert_id() - { - return @odbc_insert_id($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * "Count All" query - * - * Generates a platform-specific query string that counts all records in - * the specified database - * - * @access public - * @param string - * @return string + * @return bool */ - function count_all($table = '') + public function insert_id() { - if ($table == '') - { - return 0; - } - - $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE)); - - if ($query->num_rows() == 0) - { - return 0; - } - - $row = $query->row(); - $this->_reset_select(); - return (int) $row->numrows; + return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE; } // -------------------------------------------------------------------- @@ -362,15 +233,14 @@ class CI_DB_odbc_driver extends CI_DB { * * Generates a platform-specific query string so that the table names can be fetched * - * @access private - * @param boolean + * @param bool * @return string */ - function _list_tables($prefix_limit = FALSE) + protected function _list_tables($prefix_limit = FALSE) { - $sql = "SHOW TABLES FROM `".$this->database."`"; + $sql = 'SHOW TABLES FROM '.$this->database; - if ($prefix_limit !== FALSE AND $this->dbprefix != '') + if ($prefix_limit !== FALSE && $this->dbprefix !== '') { //$sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); return FALSE; // not currently supported @@ -386,13 +256,12 @@ class CI_DB_odbc_driver extends CI_DB { * * Generates a platform-specific query string so that the column names can be fetched * - * @access public * @param string the table name * @return string */ - function _list_columns($table = '') + protected function _list_columns($table = '') { - return "SHOW COLUMNS FROM ".$table; + return 'SHOW COLUMNS FROM '.$table; } // -------------------------------------------------------------------- @@ -402,81 +271,27 @@ class CI_DB_odbc_driver extends CI_DB { * * Generates a platform-specific query so that the column data can be retrieved * - * @access public * @param string the table name - * @return object - */ - function _field_data($table) - { - return "SELECT TOP 1 FROM ".$table; - } - - // -------------------------------------------------------------------- - - /** - * The error message string - * - * @access private * @return string */ - function _error_message() - { - return odbc_errormsg($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * The error message number - * - * @access private - * @return integer - */ - function _error_number() + protected function _field_data($table) { - return odbc_error($this->conn_id); + return 'SELECT TOP 1 FROM '.$table; } // -------------------------------------------------------------------- /** - * Escape the SQL Identifiers + * Error * - * This function escapes column and table names + * Returns an array containing code and message of the last + * database error that has occured. * - * @access private - * @param string - * @return string + * @return array */ - function _escape_identifiers($item) + public function error() { - if ($this->_escape_char == '') - { - return $item; - } - - foreach ($this->_reserved_identifiers as $id) - { - if (strpos($item, '.'.$id) !== FALSE) - { - $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item); - - // remove duplicates if the user already included the escape - return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); - } - } - - if (strpos($item, '.') !== FALSE) - { - $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char; - } - else - { - $str = $this->_escape_char.$item.$this->_escape_char; - } - - // remove duplicates if the user already included the escape - return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + return array('code' => odbc_error($this->conn_id), 'message' => odbc_errormsg($this->conn_id)); } // -------------------------------------------------------------------- @@ -487,124 +302,30 @@ class CI_DB_odbc_driver extends CI_DB { * This function implicitly groups FROM tables so there is no confusion * about operator precedence in harmony with SQL standards * - * @access public - * @param type - * @return type - */ - function _from_tables($tables) - { - if ( ! is_array($tables)) - { - $tables = array($tables); - } - - return '('.implode(', ', $tables).')'; - } - - // -------------------------------------------------------------------- - - /** - * Insert statement - * - * Generates a platform-specific insert string from the supplied data - * - * @access public - * @param string the table name - * @param array the insert keys - * @param array the insert values - * @return string - */ - function _insert($table, $keys, $values) - { - return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")"; - } - - // -------------------------------------------------------------------- - - /** - * Update statement - * - * Generates a platform-specific update string from the supplied data - * - * @access public - * @param string the table name - * @param array the update data - * @param array the where clause - * @param array the orderby clause - * @param array the limit clause + * @param array * @return string */ - function _update($table, $values, $where, $orderby = array(), $limit = FALSE) + protected function _from_tables($tables) { - foreach ($values as $key => $val) - { - $valstr[] = $key." = ".$val; - } - - $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; - - $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):''; - - $sql = "UPDATE ".$table." SET ".implode(', ', $valstr); - - $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : ''; - - $sql .= $orderby.$limit; - - return $sql; + return is_array($tables) ? implode(', ', $tables) : $tables; } - // -------------------------------------------------------------------- /** * Truncate statement * * Generates a platform-specific truncate string from the supplied data - * If the database does not support the truncate() command - * This function maps to "DELETE FROM table" * - * @access public - * @param string the table name - * @return string - */ - function _truncate($table) - { - return $this->_delete($table); - } - - // -------------------------------------------------------------------- - - /** - * Delete statement + * If the database does not support the truncate() command, + * then this method maps to 'DELETE FROM table' * - * Generates a platform-specific delete string from the supplied data - * - * @access public * @param string the table name - * @param array the where clause - * @param string the limit clause * @return string */ - function _delete($table, $where = array(), $like = array(), $limit = FALSE) + protected function _truncate($table) { - $conditions = ''; - - if (count($where) > 0 OR count($like) > 0) - { - $conditions = "\nWHERE "; - $conditions .= implode("\n", $this->ar_where); - - if (count($where) > 0 && count($like) > 0) - { - $conditions .= " AND "; - } - $conditions .= implode("\n", $like); - } - - $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; - - return "DELETE FROM ".$table.$conditions.$limit; + return 'DELETE FROM '.$table; } // -------------------------------------------------------------------- @@ -614,16 +335,14 @@ class CI_DB_odbc_driver extends CI_DB { * * Generates a platform-specific LIMIT clause * - * @access public * @param string the sql query string - * @param integer the number of rows to limit the query to - * @param integer the offset value + * @param int the number of rows to limit the query to + * @param int the offset value * @return string */ - function _limit($sql, $limit, $offset) + protected function _limit($sql, $limit, $offset) { - // Does ODBC doesn't use the LIMIT clause? - return $sql; + return $sql.($offset == 0 ? '' : $offset.', ').$limit; } // -------------------------------------------------------------------- @@ -631,19 +350,14 @@ class CI_DB_odbc_driver extends CI_DB { /** * Close DB Connection * - * @access public - * @param resource * @return void */ - function _close($conn_id) + protected function _close() { - @odbc_close($conn_id); + @odbc_close($this->conn_id); } - } - - /* End of file odbc_driver.php */ /* Location: ./system/database/drivers/odbc/odbc_driver.php */
\ No newline at end of file diff --git a/system/database/drivers/odbc/odbc_forge.php b/system/database/drivers/odbc/odbc_forge.php index e0ec687c8..b074c5884 100644 --- a/system/database/drivers/odbc/odbc_forge.php +++ b/system/database/drivers/odbc/odbc_forge.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,8 +25,6 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * ODBC Forge Class * @@ -36,58 +34,20 @@ */ class CI_DB_odbc_forge extends CI_DB_forge { - /** - * Create database - * - * @access private - * @param string the database name - * @return bool - */ - function _create_database() - { - // ODBC has no "create database" command since it's - // designed to connect to an existing database - if ($this->db->db_debug) - { - return $this->db->display_error('db_unsuported_feature'); - } - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Drop database - * - * @access private - * @param string the database name - * @return bool - */ - function _drop_database($name) - { - // ODBC has no "drop database" command since it's - // designed to connect to an existing database - if ($this->db->db_debug) - { - return $this->db->display_error('db_unsuported_feature'); - } - return FALSE; - } - - // -------------------------------------------------------------------- + protected $_drop_database = 'DROP DATABASE %s'; + protected $_drop_table = 'DROP TABLE %s'; /** * Create Table * - * @access private * @param string the table name * @param array the fields * @param mixed primary key(s) * @param mixed key(s) - * @param boolean should 'IF NOT EXISTS' be added to the SQL + * @param bool should 'IF NOT EXISTS' be added to the SQL * @return bool */ - function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) + protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) { $sql = 'CREATE TABLE '; @@ -96,51 +56,40 @@ class CI_DB_odbc_forge extends CI_DB_forge { $sql .= 'IF NOT EXISTS '; } - $sql .= $this->db->_escape_identifiers($table)." ("; + $sql .= $this->db->escape_identifiers($table).' ('; $current_field_count = 0; - foreach ($fields as $field=>$attributes) + foreach ($fields as $field => $attributes) { // Numeric field names aren't allowed in databases, so if the key is // numeric, we know it was assigned by PHP and the developer manually // entered the field information, so we'll simply add it to the list if (is_numeric($field)) { - $sql .= "\n\t$attributes"; + $sql .= "\n\t".$attributes; } else { $attributes = array_change_key_case($attributes, CASE_UPPER); - $sql .= "\n\t".$this->db->_protect_identifiers($field); + $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE']; - $sql .= ' '.$attributes['TYPE']; + empty($attributes['CONSTRAINT']) OR $sql .= '('.$attributes['CONSTRAINT'].')'; - if (array_key_exists('CONSTRAINT', $attributes)) - { - $sql .= '('.$attributes['CONSTRAINT'].')'; - } - - if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE) + if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE) { $sql .= ' UNSIGNED'; } - if (array_key_exists('DEFAULT', $attributes)) + if (isset($attributes['DEFAULT'])) { - $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\''; + $sql .= " DEFAULT '".$attributes['DEFAULT']."'"; } - if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE) - { - $sql .= ' NULL'; - } - else - { - $sql .= ' NOT NULL'; - } + $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE) + ? ' NULL' : ' NOT NULL'; - if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE) + if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE) { $sql .= ' AUTO_INCREMENT'; } @@ -155,48 +104,22 @@ class CI_DB_odbc_forge extends CI_DB_forge { if (count($primary_keys) > 0) { - $primary_keys = $this->db->_protect_identifiers($primary_keys); - $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")"; + $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->escape_identifiers($primary_keys)).')'; } if (is_array($keys) && count($keys) > 0) { foreach ($keys as $key) { - if (is_array($key)) - { - $key = $this->db->_protect_identifiers($key); - } - else - { - $key = array($this->db->_protect_identifiers($key)); - } + $key = is_array($key) + ? $this->db->escape_identifiers($key) + : array($this->db->escape_identifiers($key)); - $sql .= ",\n\tFOREIGN KEY (" . implode(', ', $key) . ")"; + $sql .= ",\n\tFOREIGN KEY (".implode(', ', $key).')'; } } - $sql .= "\n)"; - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Drop Table - * - * @access private - * @return bool - */ - function _drop_table($table) - { - // Not a supported ODBC feature - if ($this->db->db_debug) - { - return $this->db->display_error('db_unsuported_feature'); - } - return FALSE; + return $sql."\n)"; } // -------------------------------------------------------------------- @@ -207,71 +130,31 @@ class CI_DB_odbc_forge extends CI_DB_forge { * Generates a platform-specific query so that a table can be altered * Called by add_column(), drop_column(), and column_alter(), * - * @access private * @param string the ALTER type (ADD, DROP, CHANGE) * @param string the column name * @param string the table name * @param string the column definition * @param string the default value - * @param boolean should 'NOT NULL' be added + * @param bool should 'NOT NULL' be added * @param string the field after which we should add the new field - * @return object + * @return string */ - function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') + protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') { - $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name); + $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name); // DROP has everything it needs now. - if ($alter_type == 'DROP') + if ($alter_type === 'DROP') { return $sql; } - $sql .= " $column_definition"; - - if ($default_value != '') - { - $sql .= " DEFAULT \"$default_value\""; - } - - if ($null === NULL) - { - $sql .= ' NULL'; - } - else - { - $sql .= ' NOT NULL'; - } - - if ($after_field != '') - { - $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field); - } - - return $sql; - - } - - - // -------------------------------------------------------------------- - - /** - * Rename a table - * - * Generates a platform-specific query so that a table can be renamed - * - * @access private - * @param string the old table name - * @param string the new table name - * @return string - */ - function _rename_table($table_name, $new_table_name) - { - $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name); - return $sql; + return $sql.' '.$column_definition + .($default_value != '' ? ' DEFAULT "'.$default_value.'"' : '') + .($null === NULL ? ' NULL' : ' NOT NULL') + .($after_field != '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : ''); } - } /* End of file odbc_forge.php */ diff --git a/system/database/drivers/odbc/odbc_result.php b/system/database/drivers/odbc/odbc_result.php index ba660856e..227fe4fac 100644 --- a/system/database/drivers/odbc/odbc_result.php +++ b/system/database/drivers/odbc/odbc_result.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,8 +25,6 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * ODBC Result Class * @@ -38,26 +36,35 @@ */ class CI_DB_odbc_result extends CI_DB_result { + public $num_rows; + /** * Number of rows in the result set * - * @access public - * @return integer + * @return int */ - function num_rows() + public function num_rows() { - return @odbc_num_rows($this->result_id); - } + if (is_int($this->num_rows)) + { + return $this->num_rows; + } - // -------------------------------------------------------------------- + // Work-around for ODBC subdrivers that don't support num_rows() + if (($this->num_rows = @odbc_num_rows($this->result_id)) === -1) + { + $this->num_rows = count($this->result_array()); + } + + return $this->num_rows; + } /** * Number of fields in the result set * - * @access public - * @return integer + * @return int */ - function num_fields() + public function num_fields() { return @odbc_num_fields($this->result_id); } @@ -69,15 +76,19 @@ class CI_DB_odbc_result extends CI_DB_result { * * Generates an array of column names * - * @access public * @return array */ - function list_fields() + public function list_fields() { $field_names = array(); - for ($i = 0; $i < $this->num_fields(); $i++) + $num_fields = $this->num_fields(); + + if ($num_fields > 0) { - $field_names[] = odbc_field_name($this->result_id, $i); + for ($i = 1; $i <= $num_fields; $i++) + { + $field_names[] = odbc_field_name($this->result_id, $i); + } } return $field_names; @@ -90,22 +101,19 @@ class CI_DB_odbc_result extends CI_DB_result { * * Generates an array of objects containing field meta-data * - * @access public * @return array */ - function field_data() + public function field_data() { $retval = array(); - for ($i = 0; $i < $this->num_fields(); $i++) + for ($i = 0, $odbc_index = 1, $c = $this->num_fields(); $i < $c; $i++, $odbc_index++) { - $F = new stdClass(); - $F->name = odbc_field_name($this->result_id, $i); - $F->type = odbc_field_type($this->result_id, $i); - $F->max_length = odbc_field_len($this->result_id, $i); - $F->primary_key = 0; - $F->default = ''; - - $retval[] = $F; + $retval[$i] = new stdClass(); + $retval[$i]->name = odbc_field_name($this->result_id, $odbc_index); + $retval[$i]->type = odbc_field_type($this->result_id, $odbc_index); + $retval[$i]->max_length = odbc_field_len($this->result_id, $odbc_index); + $retval[$i]->primary_key = 0; + $retval[$i]->default = ''; } return $retval; @@ -116,9 +124,9 @@ class CI_DB_odbc_result extends CI_DB_result { /** * Free the result * - * @return null + * @return void */ - function free_result() + public function free_result() { if (is_resource($this->result_id)) { @@ -130,40 +138,33 @@ class CI_DB_odbc_result extends CI_DB_result { // -------------------------------------------------------------------- /** - * Data Seek + * Result - associative array * - * Moves the internal pointer to the desired offset. We call - * this internally before fetching results to make sure the - * result set starts at zero + * Returns the result set as an array * - * @access private * @return array */ - function _data_seek($n = 0) + protected function _fetch_assoc() { - return FALSE; + return function_exists('odbc_fetch_array') + ? odbc_fetch_array($this->result_id) + : $this->_odbc_fetch_array($this->result_id); } // -------------------------------------------------------------------- /** - * Result - associative array + * Result - object * - * Returns the result set as an array + * Returns the result set as an object * - * @access private - * @return array + * @return object */ - function _fetch_assoc() + protected function _fetch_object() { - if (function_exists('odbc_fetch_object')) - { - return odbc_fetch_array($this->result_id); - } - else - { - return $this->_odbc_fetch_array($this->result_id); - } + return function_exists('odbc_fetch_object') + ? odbc_fetch_object($this->result_id) + : $this->_odbc_fetch_object($this->result_id); } // -------------------------------------------------------------------- @@ -171,70 +172,128 @@ class CI_DB_odbc_result extends CI_DB_result { /** * Result - object * - * Returns the result set as an object + * subsititutes the odbc_fetch_object function when + * not available (odbc_fetch_object requires unixODBC) * - * @access private * @return object */ - function _fetch_object() + protected function _odbc_fetch_object(& $odbc_result) { - if (function_exists('odbc_fetch_object')) + $rs = array(); + if ( ! odbc_fetch_into($odbc_result, $rs)) { - return odbc_fetch_object($this->result_id); + return FALSE; } - else + + $rs_obj = new stdClass(); + foreach ($rs as $k => $v) { - return $this->_odbc_fetch_object($this->result_id); + $field_name = odbc_field_name($odbc_result, $k+1); + $rs_obj->$field_name = $v; } + + return $rs_obj; } + // -------------------------------------------------------------------- /** - * Result - object + * Result - array * - * subsititutes the odbc_fetch_object function when - * not available (odbc_fetch_object requires unixODBC) + * subsititutes the odbc_fetch_array function when + * not available (odbc_fetch_array requires unixODBC) * - * @access private - * @return object + * @return array */ - function _odbc_fetch_object(& $odbc_result) { + protected function _odbc_fetch_array(& $odbc_result) + { $rs = array(); - $rs_obj = FALSE; - if (odbc_fetch_into($odbc_result, $rs)) { - foreach ($rs as $k=>$v) { - $field_name= odbc_field_name($odbc_result, $k+1); - $rs_obj->$field_name = $v; - } + if ( ! odbc_fetch_into($odbc_result, $rs)) + { + return FALSE; } - return $rs_obj; + + $rs_assoc = array(); + foreach ($rs as $k => $v) + { + $field_name = odbc_field_name($odbc_result, $k+1); + $rs_assoc[$field_name] = $v; + } + + return $rs_assoc; } + // -------------------------------------------------------------------- /** - * Result - array + * Query result. Array version. * - * subsititutes the odbc_fetch_array function when - * not available (odbc_fetch_array requires unixODBC) + * @return array + */ + public function result_array() + { + if (count($this->result_array) > 0) + { + return $this->result_array; + } + elseif (($c = count($this->result_object)) > 0) + { + for ($i = 0; $i < $c; $i++) + { + $this->result_array[$i] = (array) $this->result_object[$i]; + } + } + elseif ($this->result_id === FALSE) + { + return array(); + } + else + { + while ($row = $this->_fetch_assoc()) + { + $this->result_array[] = $row; + } + } + + return $this->result_array; + } + + // -------------------------------------------------------------------- + + /** + * Query result. Object version. * - * @access private * @return array */ - function _odbc_fetch_array(& $odbc_result) { - $rs = array(); - $rs_assoc = FALSE; - if (odbc_fetch_into($odbc_result, $rs)) { - $rs_assoc=array(); - foreach ($rs as $k=>$v) { - $field_name= odbc_field_name($odbc_result, $k+1); - $rs_assoc[$field_name] = $v; + public function result_object() + { + if (count($this->result_object) > 0) + { + return $this->result_object; + } + elseif (($c = count($this->result_array)) > 0) + { + for ($i = 0; $i < $c; $i++) + { + $this->result_object[$i] = (object) $this->result_array[$i]; } } - return $rs_assoc; + elseif ($this->result_id === FALSE) + { + return array(); + } + else + { + while ($row = $this->_fetch_object()) + { + $this->result_object[] = $row; + } + } + + return $this->result_object; } } - /* End of file odbc_result.php */ /* Location: ./system/database/drivers/odbc/odbc_result.php */
\ No newline at end of file diff --git a/system/database/drivers/odbc/odbc_utility.php b/system/database/drivers/odbc/odbc_utility.php index bae3fe853..224d48d2b 100644 --- a/system/database/drivers/odbc/odbc_utility.php +++ b/system/database/drivers/odbc/odbc_utility.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,8 +25,6 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * ODBC Utility Class * @@ -36,74 +34,15 @@ */ class CI_DB_odbc_utility extends CI_DB_utility { - /** - * List databases - * - * @access private - * @return bool - */ - function _list_databases() - { - // Not sure if ODBC lets you list all databases... - if ($this->db->db_debug) - { - return $this->db->display_error('db_unsuported_feature'); - } - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Optimize table query - * - * Generates a platform-specific query so that a table can be optimized - * - * @access private - * @param string the table name - * @return object - */ - function _optimize_table($table) - { - // Not a supported ODBC feature - if ($this->db->db_debug) - { - return $this->db->display_error('db_unsuported_feature'); - } - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Repair table query - * - * Generates a platform-specific query so that a table can be repaired - * - * @access private - * @param string the table name - * @return object - */ - function _repair_table($table) - { - // Not a supported ODBC feature - if ($this->db->db_debug) - { - return $this->db->display_error('db_unsuported_feature'); - } - return FALSE; - } - - // -------------------------------------------------------------------- + protected $_list_databases = FALSE; /** * ODBC Export * - * @access private * @param array Preferences * @return mixed */ - function _backup($params = array()) + protected function _backup($params = array()) { // Currently unsupported return $this->db->display_error('db_unsuported_feature'); diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php index 4f4f44ba7..e25013a52 100644 --- a/system/database/drivers/pdo/pdo_driver.php +++ b/system/database/drivers/pdo/pdo_driver.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,13 +25,11 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * PDO Database Adapter Class * * Note: _DB is an extender class that the app controller - * creates dynamically based on whether the active record + * creates dynamically based on whether the query builder * class is being used or not. * * @package CodeIgniter @@ -42,196 +40,238 @@ */ class CI_DB_pdo_driver extends CI_DB { - var $dbdriver = 'pdo'; + public $dbdriver = 'pdo'; // the character used to excape - not necessary for PDO - var $_escape_char = ''; - var $_like_escape_str; - var $_like_escape_chr; - + protected $_escape_char = ''; + + // clause and character used for LIKE escape sequences + protected $_like_escape_str = " ESCAPE '%s' "; + protected $_like_escape_chr = '!'; /** * The syntax to count rows is slightly different across different * database engines, so this string appears in each driver and is * used for the count_all() and count_all_results() functions. */ - var $_count_string = "SELECT COUNT(*) AS "; - var $_random_keyword; - - var $options = array(); + protected $_count_string = 'SELECT COUNT(*) AS '; + protected $_random_keyword; - function __construct($params) + // need to track the pdo driver and options + public $pdodriver; + public $options = array(); + + public function __construct($params) { parent::__construct($params); - + + if (preg_match('/([^;]+):/', $this->dsn, $match) && count($match) === 2) + { + // If there is a minimum valid dsn string pattern found, we're done + // This is for general PDO users, who tend to have a full DSN string. + $this->pdodriver = end($match); + } + else + { + // Try to build a complete DSN string from params + $this->_connect_string($params); + } + // clause and character used for LIKE escape sequences - if (strpos($this->hostname, 'mysql') !== FALSE) + // this one depends on the driver being used + if ($this->pdodriver === 'mysql') { + $this->_escape_char = '`'; $this->_like_escape_str = ''; - $this->_like_escape_chr = ''; - - //Prior to this version, the charset can't be set in the dsn - if(is_php('5.3.6')) - { - $this->hostname .= ";charset={$this->char_set}"; - } - - //Set the charset with the connection options - $this->options['PDO::MYSQL_ATTR_INIT_COMMAND'] = "SET NAMES {$this->char_set}"; + $this->_like_escape_chr = '\\'; } - else if (strpos($this->hostname, 'odbc') !== FALSE) + elseif ($this->pdodriver === 'odbc') { $this->_like_escape_str = " {escape '%s'} "; - $this->_like_escape_chr = '!'; } - else + elseif ( ! in_array($this->pdodriver, array('sqlsrv', 'mssql', 'dblib', 'sybase'))) { - $this->_like_escape_str = " ESCAPE '%s' "; - $this->_like_escape_chr = '!'; + $this->_escape_char = '"'; } - - if (strpos($this->hostname, 'sqlite') === FALSE) - { - $this->hostname .= ";dbname=".$this->database; - } - - $this->trans_enabled = FALSE; + $this->trans_enabled = FALSE; $this->_random_keyword = ' RND('.time().')'; // database specific random keyword } /** - * Non-persistent database connection + * Connection String * - * @access private called by the base class - * @return resource + * @param array + * @return void */ - function db_connect() + protected function _connect_string($params) { - $this->options['PDO::ATTR_ERRMODE'] = PDO::ERRMODE_SILENT; - - return new PDO($this->hostname, $this->username, $this->password, $this->options); - } + if (strpos($this->hostname, ':')) + { + // hostname generally would have this prototype + // $db['hostname'] = 'pdodriver:host(/Server(/DSN))=hostname(/DSN);'; + // We need to get the prefix (pdodriver used by PDO). + $dsnarray = explode(':', $this->hostname); + $this->pdodriver = $dsnarray[0]; - // -------------------------------------------------------------------- + // End dsn with a semicolon for extra backward compability + // if database property was not empty. + if ( ! empty($this->database)) + { + $this->dsn .= rtrim($this->hostname, ';').';'; + } + } + else + { + // Invalid DSN, display an error + if ( ! array_key_exists('pdodriver', $params)) + { + show_error('Invalid DB Connection String for PDO'); + } - /** - * Persistent database connection - * - * @access private called by the base class - * @return resource - */ - function db_pconnect() - { - $this->options['PDO::ATTR_ERRMODE'] = PDO::ERRMODE_SILENT; - $this->options['PDO::ATTR_PERSISTENT'] = TRUE; - - return new PDO($this->hostname, $this->username, $this->password, $this->options); - } + // Assuming that the following DSN string format is used: + // $dsn = 'pdo://username:password@hostname:port/database?pdodriver=pgsql'; + $this->dsn = $this->pdodriver.':'; - // -------------------------------------------------------------------- + // Add hostname to the DSN for databases that need it + if ( ! empty($this->hostname) + && strpos($this->hostname, ':') === FALSE + && in_array($this->pdodriver, array('informix', 'mysql', 'pgsql', 'sybase', 'mssql', 'dblib', 'cubrid'))) + { + $this->dsn .= 'host='.$this->hostname.';'; + } - /** - * Reconnect - * - * Keep / reestablish the db connection if no queries have been - * sent for a length of time exceeding the server's idle timeout - * - * @access public - * @return void - */ - function reconnect() - { - if ($this->db->db_debug) - { - return $this->db->display_error('db_unsuported_feature'); + // Add a port to the DSN for databases that can use it + if ( ! empty($this->port) && in_array($this->pdodriver, array('informix', 'mysql', 'pgsql', 'ibm', 'cubrid'))) + { + $this->dsn .= 'port='.$this->port.';'; + } } - return FALSE; + + // Add the database name to the DSN, if needed + if (stripos($this->dsn, 'dbname') === FALSE + && in_array($this->pdodriver, array('4D', 'pgsql', 'mysql', 'firebird', 'sybase', 'mssql', 'dblib', 'cubrid'))) + { + $this->dsn .= 'dbname='.$this->database.';'; + } + elseif (stripos($this->dsn, 'database') === FALSE && in_array($this->pdodriver, array('ibm', 'sqlsrv'))) + { + if (stripos($this->dsn, 'dsn') === FALSE) + { + $this->dsn .= 'database='.$this->database.';'; + } + } + elseif ($this->pdodriver === 'sqlite' && $this->dsn === 'sqlite:') + { + if ($this->database !== ':memory') + { + if ( ! file_exists($this->database)) + { + show_error('Invalid DB Connection string for PDO SQLite'); + } + + $this->dsn .= (strpos($this->database, DIRECTORY_SEPARATOR) !== 0) ? DIRECTORY_SEPARATOR : ''; + } + + $this->dsn .= $this->database; + } + + // Add charset to the DSN, if needed + if ( ! empty($this->char_set) && in_array($this->pdodriver, array('4D', 'mysql', 'sybase', 'mssql', 'dblib', 'oci'))) + { + $this->dsn .= 'charset='.$this->char_set.';'; + } } // -------------------------------------------------------------------- /** - * Select the database + * Non-persistent database connection * - * @access private called by the base class - * @return resource + * @return object */ - function db_select() + public function db_connect() { - // Not needed for PDO - return TRUE; + return $this->_pdo_connect(); } // -------------------------------------------------------------------- /** - * Set client character set + * Persistent database connection * - * @access public - * @param string - * @param string - * @return resource + * @return object */ - function db_set_charset($charset, $collation) + public function db_pconnect() { - // @todo - add support if needed - return TRUE; + return $this->_pdo_connect(TRUE); } // -------------------------------------------------------------------- /** - * Version number query string + * PDO connection * - * @access public - * @return string + * @param bool + * @return object */ - function _version() + protected function _pdo_connect($persistent = FALSE) { - return $this->conn_id->getAttribute(PDO::ATTR_CLIENT_VERSION); + $this->options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_SILENT; + $persistent === FALSE OR $this->options[PDO::ATTR_PERSISTENT] = TRUE; + + /* Prior to PHP 5.3.6, even if the charset was supplied in the DSN + * on connect - it was ignored. This is a work-around for the issue. + * + * Reference: http://www.php.net/manual/en/ref.pdo-mysql.connection.php + */ + if ($this->pdodriver === 'mysql' && ! is_php('5.3.6') && ! empty($this->char_set)) + { + $this->options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES '.$this->char_set + .( ! empty($this->db_collat) ? " COLLATE '".$this->dbcollat."'" : ''); + } + + // Connecting... + try + { + return new PDO($this->dsn, $this->username, $this->password, $this->options); + } + catch (PDOException $e) + { + if ($this->db_debug && empty($this->failover)) + { + $this->display_error($e->getMessage(), '', TRUE); + } + + return FALSE; + } } // -------------------------------------------------------------------- /** - * Execute the query + * Database version number * - * @access private called by the base class - * @param string an SQL query - * @return object + * @return string */ - function _execute($sql) + public function version() { - $sql = $this->_prep_query($sql); - $result_id = $this->conn_id->query($sql); - - if (is_object($result_id)) - { - $this->affect_rows = $result_id->rowCount(); - } - else - { - $this->affect_rows = 0; - } - - return $result_id; + return isset($this->data_cache['version']) + ? $this->data_cache['version'] + : $this->data_cache['version'] = $this->conn_id->getAttribute(PDO::ATTR_SERVER_VERSION); } // -------------------------------------------------------------------- /** - * Prep the query - * - * If needed, each database adapter can prep the query string + * Execute the query * - * @access private called by execute() * @param string an SQL query - * @return string + * @return mixed */ - function _prep_query($sql) + protected function _execute($sql) { - return $sql; + return $this->conn_id->query($sql); } // -------------------------------------------------------------------- @@ -239,18 +279,12 @@ class CI_DB_pdo_driver extends CI_DB { /** * Begin Transaction * - * @access public * @return bool */ - function trans_begin($test_mode = FALSE) + public function trans_begin($test_mode = FALSE) { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } @@ -258,7 +292,7 @@ class CI_DB_pdo_driver extends CI_DB { // Reset the transaction failure flag. // If the $test_mode flag is set to TRUE transactions will be rolled back // even if the queries produce a successful result. - $this->_trans_failure = (bool) ($test_mode === TRUE); + $this->_trans_failure = ($test_mode === TRUE); return $this->conn_id->beginTransaction(); } @@ -268,24 +302,17 @@ class CI_DB_pdo_driver extends CI_DB { /** * Commit Transaction * - * @access public * @return bool */ - function trans_commit() + public function trans_commit() { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } - $ret = $this->conn->commit(); - return $ret; + return $this->conn_id->commit(); } // -------------------------------------------------------------------- @@ -293,24 +320,17 @@ class CI_DB_pdo_driver extends CI_DB { /** * Rollback Transaction * - * @access public * @return bool */ - function trans_rollback() + public function trans_rollback() { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } - $ret = $this->conn_id->rollBack(); - return $ret; + return $this->conn_id->rollBack(); } // -------------------------------------------------------------------- @@ -318,12 +338,11 @@ class CI_DB_pdo_driver extends CI_DB { /** * Escape String * - * @access public * @param string * @param bool whether or not the string will be used in a LIKE condition * @return string */ - function escape_str($str, $like = FALSE) + public function escape_str($str, $like = FALSE) { if (is_array($str)) { @@ -334,22 +353,22 @@ class CI_DB_pdo_driver extends CI_DB { return $str; } - - //Escape the string + + // Escape the string $str = $this->conn_id->quote($str); - - //If there are duplicated quotes, trim them away + + // If there are duplicated quotes, trim them away if (strpos($str, "'") === 0) { $str = substr($str, 1, -1); } - + // escape LIKE condition wildcards if ($like === TRUE) { - $str = str_replace( array('%', '_', $this->_like_escape_chr), - array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr), - $str); + return str_replace(array($this->_like_escape_chr, '%', '_'), + array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'), + $str); } return $str; @@ -360,74 +379,31 @@ class CI_DB_pdo_driver extends CI_DB { /** * Affected Rows * - * @access public - * @return integer + * @return int */ - function affected_rows() + public function affected_rows() { - return $this->affect_rows; + return is_object($this->result_id) ? $this->result_id->rowCount() : 0; } // -------------------------------------------------------------------- /** * Insert ID - * - * @access public - * @return integer - */ - function insert_id($name=NULL) - { - //Convenience method for postgres insertid - if (strpos($this->hostname, 'pgsql') !== FALSE) - { - $v = $this->_version(); - - $table = func_num_args() > 0 ? func_get_arg(0) : NULL; - - if ($table == NULL && $v >= '8.1') - { - $sql='SELECT LASTVAL() as ins_id'; - } - $query = $this->query($sql); - $row = $query->row(); - return $row->ins_id; - } - else - { - return $this->conn_id->lastInsertId($name); - } - } - - // -------------------------------------------------------------------- - - /** - * "Count All" query * - * Generates a platform-specific query string that counts all records in - * the specified database - * - * @access public * @param string - * @return string + * @return int */ - function count_all($table = '') + public function insert_id($name = NULL) { - if ($table == '') + if ($this->pdodriver === 'pgsql' && $name === NULL && $this->version() >= '8.1') { - return 0; + $query = $this->query('SELECT LASTVAL() AS ins_id'); + $query = $query->row(); + return $query->ins_id; } - $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE)); - - if ($query->num_rows() == 0) - { - return 0; - } - - $row = $query->row(); - $this->_reset_select(); - return (int) $row->numrows; + return $this->conn_id->lastInsertId($name); } // -------------------------------------------------------------------- @@ -437,18 +413,29 @@ class CI_DB_pdo_driver extends CI_DB { * * Generates a platform-specific query string so that the table names can be fetched * - * @access private - * @param boolean + * @param bool * @return string */ - function _list_tables($prefix_limit = FALSE) + protected function _list_tables($prefix_limit = FALSE) { - $sql = "SHOW TABLES FROM `".$this->database."`"; + if ($this->pdodriver === 'pgsql') + { + // Analog function to show all tables in postgre + $sql = "SELECT * FROM information_schema.tables WHERE table_schema = 'public'"; + } + elseif ($this->pdodriver === 'sqlite') + { + // Analog function to show all tables in sqlite + $sql = "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'"; + } + else + { + $sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database); + } - if ($prefix_limit !== FALSE AND $this->dbprefix != '') + if ($prefix_limit !== FALSE AND $this->dbprefix !== '') { - //$sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); - return FALSE; // not currently supported + return FALSE; } return $sql; @@ -461,13 +448,12 @@ class CI_DB_pdo_driver extends CI_DB { * * Generates a platform-specific query string so that the column names can be fetched * - * @access public * @param string the table name * @return string */ - function _list_columns($table = '') + protected function _list_columns($table = '') { - return "SHOW COLUMNS FROM ".$table; + return 'SHOW COLUMNS FROM '.$this->escape_identifiers($table); } // -------------------------------------------------------------------- @@ -477,178 +463,59 @@ class CI_DB_pdo_driver extends CI_DB { * * Generates a platform-specific query so that the column data can be retrieved * - * @access public * @param string the table name - * @return object - */ - function _field_data($table) - { - return "SELECT TOP 1 FROM ".$table; - } - - // -------------------------------------------------------------------- - - /** - * The error message string - * - * @access private * @return string */ - function _error_message() + protected function _field_data($table) { - $error_array = $this->conn_id->errorInfo(); - return $error_array[2]; - } - - // -------------------------------------------------------------------- - - /** - * The error message number - * - * @access private - * @return integer - */ - function _error_number() - { - return $this->conn_id->errorCode(); - } - - // -------------------------------------------------------------------- - - /** - * Escape the SQL Identifiers - * - * This function escapes column and table names - * - * @access private - * @param string - * @return string - */ - function _escape_identifiers($item) - { - if ($this->_escape_char == '') + if ($this->pdodriver === 'mysql' or $this->pdodriver === 'pgsql') { - return $item; + // Analog function for mysql and postgre + return 'SELECT * FROM '.$this->escape_identifiers($table).' LIMIT 1'; } - - foreach ($this->_reserved_identifiers as $id) + elseif ($this->pdodriver === 'oci') { - if (strpos($item, '.'.$id) !== FALSE) - { - $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item); - - // remove duplicates if the user already included the escape - return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); - } + // Analog function for oci + return 'SELECT * FROM '.$this->escape_identifiers($table).' WHERE ROWNUM <= 1'; } - - if (strpos($item, '.') !== FALSE) + elseif ($this->pdodriver === 'sqlite') { - $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char; - - } - else - { - $str = $this->_escape_char.$item.$this->_escape_char; + // Analog function for sqlite + return 'PRAGMA table_info('.$this->escape_identifiers($table).')'; } - // remove duplicates if the user already included the escape - return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + return 'SELECT TOP 1 FROM '.$this->escape_identifiers($table); } // -------------------------------------------------------------------- /** - * From Tables + * Error * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards + * Returns an array containing code and message of the last + * database error that has occured. * - * @access public - * @param type - * @return type + * @return array */ - function _from_tables($tables) + public function error() { - if ( ! is_array($tables)) + $error = array('code' => '00000', 'message' => ''); + $pdo_error = $this->conn_id->errorInfo(); + + if (empty($pdo_error[0])) { - $tables = array($tables); + return $error; } - return (count($tables) == 1) ? $tables[0] : '('.implode(', ', $tables).')'; - } - - // -------------------------------------------------------------------- - - /** - * Insert statement - * - * Generates a platform-specific insert string from the supplied data - * - * @access public - * @param string the table name - * @param array the insert keys - * @param array the insert values - * @return string - */ - function _insert($table, $keys, $values) - { - return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")"; - } - - // -------------------------------------------------------------------- - - /** - * Insert_batch statement - * - * Generates a platform-specific insert string from the supplied data - * - * @access public - * @param string the table name - * @param array the insert keys - * @param array the insert values - * @return string - */ - function _insert_batch($table, $keys, $values) - { - return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES ".implode(', ', $values); - } - - // -------------------------------------------------------------------- - - /** - * Update statement - * - * Generates a platform-specific update string from the supplied data - * - * @access public - * @param string the table name - * @param array the update data - * @param array the where clause - * @param array the orderby clause - * @param array the limit clause - * @return string - */ - function _update($table, $values, $where, $orderby = array(), $limit = FALSE) - { - foreach ($values as $key => $val) + $error['code'] = isset($pdo_error[1]) ? $pdo_error[0].'/'.$pdo_error[1] : $pdo_error[0]; + if (isset($pdo_error[2])) { - $valstr[] = $key." = ".$val; + $error['message'] = $pdo_error[2]; } - $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; - - $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):''; - - $sql = "UPDATE ".$table." SET ".implode(', ', $valstr); - - $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : ''; - - $sql .= $orderby.$limit; - - return $sql; + return $error; } - + // -------------------------------------------------------------------- /** @@ -656,16 +523,15 @@ class CI_DB_pdo_driver extends CI_DB { * * Generates a platform-specific batch update string from the supplied data * - * @access public * @param string the table name * @param array the update data * @param array the where clause * @return string */ - function _update_batch($table, $values, $index, $where = NULL) + protected function _update_batch($table, $values, $index, $where = NULL) { - $ids = array(); - $where = ($where != '' AND count($where) >=1) ? implode(" ", $where).' AND ' : ''; + $ids = array(); + $where = ($where !== '' && count($where) >=1) ? implode(" ", $where).' AND ' : ''; foreach ($values as $key => $val) { @@ -673,19 +539,20 @@ class CI_DB_pdo_driver extends CI_DB { foreach (array_keys($val) as $field) { - if ($field != $index) + if ($field !== $index) { $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field]; } } } - $sql = "UPDATE ".$table." SET "; + $sql = 'UPDATE '.$table.' SET '; $cases = ''; foreach ($final as $k => $v) { $cases .= $k.' = CASE '."\n"; + foreach ($v as $row) { $cases .= $row."\n"; @@ -695,63 +562,27 @@ class CI_DB_pdo_driver extends CI_DB { } $sql .= substr($cases, 0, -2); - $sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')'; return $sql; } - // -------------------------------------------------------------------- /** * Truncate statement * * Generates a platform-specific truncate string from the supplied data - * If the database does not support the truncate() command - * This function maps to "DELETE FROM table" - * - * @access public - * @param string the table name - * @return string - */ - function _truncate($table) - { - return $this->_delete($table); - } - - // -------------------------------------------------------------------- - - /** - * Delete statement * - * Generates a platform-specific delete string from the supplied data + * If the database does not support the truncate() command, + * then this method maps to 'DELETE FROM table' * - * @access public * @param string the table name - * @param array the where clause - * @param string the limit clause * @return string */ - function _delete($table, $where = array(), $like = array(), $limit = FALSE) + protected function _truncate($table) { - $conditions = ''; - - if (count($where) > 0 OR count($like) > 0) - { - $conditions = "\nWHERE "; - $conditions .= implode("\n", $this->ar_where); - - if (count($where) > 0 && count($like) > 0) - { - $conditions .= " AND "; - } - $conditions .= implode("\n", $like); - } - - $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; - - return "DELETE FROM ".$table.$conditions.$limit; + return 'DELETE FROM '.$table; } // -------------------------------------------------------------------- @@ -761,58 +592,29 @@ class CI_DB_pdo_driver extends CI_DB { * * Generates a platform-specific LIMIT clause * - * @access public * @param string the sql query string - * @param integer the number of rows to limit the query to - * @param integer the offset value + * @param int the number of rows to limit the query to + * @param int the offset value * @return string */ - function _limit($sql, $limit, $offset) + protected function _limit($sql, $limit, $offset) { - if (strpos($this->hostname, 'cubrid') !== FALSE || strpos($this->hostname, 'sqlite') !== FALSE) + if ($this->pdodriver === 'cubrid' OR $this->pdodriver === 'sqlite') { - if ($offset == 0) - { - $offset = ''; - } - else - { - $offset .= ", "; - } + $offset = ($offset == 0) ? '' : $offset.', '; - return $sql."LIMIT ".$offset.$limit; + return $sql.'LIMIT '.$offset.$limit; } else { - $sql .= "LIMIT ".$limit; + $sql .= 'LIMIT '.$limit; + $sql .= ($offset > 0) ? ' OFFSET '.$offset : ''; - if ($offset > 0) - { - $sql .= " OFFSET ".$offset; - } - return $sql; } } - // -------------------------------------------------------------------- - - /** - * Close DB Connection - * - * @access public - * @param resource - * @return void - */ - function _close($conn_id) - { - $this->conn_id = null; - } - - } - - /* End of file pdo_driver.php */ /* Location: ./system/database/drivers/pdo/pdo_driver.php */
\ No newline at end of file diff --git a/system/database/drivers/pdo/pdo_forge.php b/system/database/drivers/pdo/pdo_forge.php index 076415928..02ceb74fe 100644 --- a/system/database/drivers/pdo/pdo_forge.php +++ b/system/database/drivers/pdo/pdo_forge.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,8 +25,6 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * PDO Forge Class * @@ -36,58 +34,20 @@ */ class CI_DB_pdo_forge extends CI_DB_forge { - /** - * Create database - * - * @access private - * @param string the database name - * @return bool - */ - function _create_database() - { - // PDO has no "create database" command since it's - // designed to connect to an existing database - if ($this->db->db_debug) - { - return $this->db->display_error('db_unsuported_feature'); - } - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Drop database - * - * @access private - * @param string the database name - * @return bool - */ - function _drop_database($name) - { - // PDO has no "drop database" command since it's - // designed to connect to an existing database - if ($this->db->db_debug) - { - return $this->db->display_error('db_unsuported_feature'); - } - return FALSE; - } - - // -------------------------------------------------------------------- + protected $_drop_database = 'DROP DATABASE %s'; + protected $_drop_table = 'DROP TABLE %s'; /** * Create Table * - * @access private * @param string the table name * @param array the fields * @param mixed primary key(s) * @param mixed key(s) - * @param boolean should 'IF NOT EXISTS' be added to the SQL + * @param bool should 'IF NOT EXISTS' be added to the SQL * @return bool */ - function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) + protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) { $sql = 'CREATE TABLE '; @@ -96,51 +56,48 @@ class CI_DB_pdo_forge extends CI_DB_forge { $sql .= 'IF NOT EXISTS '; } - $sql .= $this->db->_escape_identifiers($table)." ("; + $sql .= $this->db->escape_identifiers($table).' ('; $current_field_count = 0; - foreach ($fields as $field=>$attributes) + foreach ($fields as $field => $attributes) { // Numeric field names aren't allowed in databases, so if the key is // numeric, we know it was assigned by PHP and the developer manually // entered the field information, so we'll simply add it to the list if (is_numeric($field)) { - $sql .= "\n\t$attributes"; + $sql .= "\n\t".$attributes; } else { $attributes = array_change_key_case($attributes, CASE_UPPER); + $numeric = array('SERIAL', 'INTEGER'); - $sql .= "\n\t".$this->db->_protect_identifiers($field); - - $sql .= ' '.$attributes['TYPE']; + $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE']; - if (array_key_exists('CONSTRAINT', $attributes)) + if ( ! empty($attributes['CONSTRAINT'])) { - $sql .= '('.$attributes['CONSTRAINT'].')'; + // Exception for Postgre numeric which not too happy with constraint within those type + if ( ! ($this->db->pdodriver === 'pgsql' && in_array($attributes['TYPE'], $numeric))) + { + $sql .= '('.$attributes['CONSTRAINT'].')'; + } } - if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE) + if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE) { $sql .= ' UNSIGNED'; } - if (array_key_exists('DEFAULT', $attributes)) + if (isset($attributes['DEFAULT'])) { - $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\''; + $sql .= " DEFAULT '".$attributes['DEFAULT']."'"; } - if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE) - { - $sql .= ' NULL'; - } - else - { - $sql .= ' NOT NULL'; - } + $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE) + ? ' NULL' : ' NOT NULL'; - if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE) + if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE) { $sql .= ' AUTO_INCREMENT'; } @@ -155,48 +112,22 @@ class CI_DB_pdo_forge extends CI_DB_forge { if (count($primary_keys) > 0) { - $primary_keys = $this->db->_protect_identifiers($primary_keys); - $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")"; + $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->db->escape_identifiers($primary_keys)).')'; } if (is_array($keys) && count($keys) > 0) { foreach ($keys as $key) { - if (is_array($key)) - { - $key = $this->db->_protect_identifiers($key); - } - else - { - $key = array($this->db->_protect_identifiers($key)); - } + $key = is_array($key) + ? $this->db->escape_identifiers($key) + : array($this->db->escape_identifiers($key)); - $sql .= ",\n\tFOREIGN KEY (" . implode(', ', $key) . ")"; + $sql .= ",\n\tFOREIGN KEY (".implode(', ', $key).')'; } } - $sql .= "\n)"; - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Drop Table - * - * @access private - * @return bool - */ - function _drop_table($table) - { - // Not a supported PDO feature - if ($this->db->db_debug) - { - return $this->db->display_error('db_unsuported_feature'); - } - return FALSE; + return $sql."\n)"; } // -------------------------------------------------------------------- @@ -207,71 +138,31 @@ class CI_DB_pdo_forge extends CI_DB_forge { * Generates a platform-specific query so that a table can be altered * Called by add_column(), drop_column(), and column_alter(), * - * @access private * @param string the ALTER type (ADD, DROP, CHANGE) * @param string the column name * @param string the table name * @param string the column definition * @param string the default value - * @param boolean should 'NOT NULL' be added + * @param bool should 'NOT NULL' be added * @param string the field after which we should add the new field - * @return object + * @return string */ - function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') + protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') { - $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name); + $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name); // DROP has everything it needs now. - if ($alter_type == 'DROP') + if ($alter_type === 'DROP') { return $sql; } - $sql .= " $column_definition"; - - if ($default_value != '') - { - $sql .= " DEFAULT \"$default_value\""; - } - - if ($null === NULL) - { - $sql .= ' NULL'; - } - else - { - $sql .= ' NOT NULL'; - } - - if ($after_field != '') - { - $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field); - } - - return $sql; - + return $sql .' '.$column_definition + .($default_value !== '' ? " DEFAULT '".$default_value."'" : '') + .($null === NULL ? ' NULL' : ' NOT NULL') + .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : ''); } - - // -------------------------------------------------------------------- - - /** - * Rename a table - * - * Generates a platform-specific query so that a table can be renamed - * - * @access private - * @param string the old table name - * @param string the new table name - * @return string - */ - function _rename_table($table_name, $new_table_name) - { - $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name); - return $sql; - } - - } /* End of file pdo_forge.php */ diff --git a/system/database/drivers/pdo/pdo_result.php b/system/database/drivers/pdo/pdo_result.php index 6b523b001..0b8937cc5 100644 --- a/system/database/drivers/pdo/pdo_result.php +++ b/system/database/drivers/pdo/pdo_result.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,8 +25,6 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * PDO Result Class * @@ -39,14 +37,68 @@ class CI_DB_pdo_result extends CI_DB_result { /** + * @var bool Hold the flag whether a result handler already fetched before + */ + protected $is_fetched = FALSE; + + /** + * @var mixed Hold the fetched assoc array of a result handler + */ + protected $result_assoc; + + /** * Number of rows in the result set * - * @access public - * @return integer + * @return int */ - function num_rows() + public function num_rows() { - return $this->result_id->rowCount(); + if (empty($this->result_id) OR ! is_object($this->result_id)) + { + // invalid result handler + return 0; + } + elseif (($num_rows = $this->result_id->rowCount()) && $num_rows > 0) + { + // If rowCount return something, we're done. + return $num_rows; + } + + // Fetch the result, instead perform another extra query + return ($this->is_fetched && is_array($this->result_assoc)) ? count($this->result_assoc) : count($this->result_assoc()); + } + + /** + * Fetch the result handler + * + * @return mixed + */ + public function result_assoc() + { + // If the result already fetched before, use that one + if (count($this->result_array) > 0 OR $this->is_fetched) + { + return $this->result_array(); + } + + // Define the output + $output = array('assoc', 'object'); + + // Initial value + $this->result_assoc = array() and $this->result_object = array(); + + // Fetch the result + while ($row = $this->_fetch_assoc()) + { + $this->result_assoc[] = $row; + $this->result_object[] = (object) $row; + } + + // Save this as buffer and marked the fetch flag + $this->result_array = $this->result_assoc; + $this->is_fetched = TRUE; + + return $this->result_assoc; } // -------------------------------------------------------------------- @@ -54,10 +106,9 @@ class CI_DB_pdo_result extends CI_DB_result { /** * Number of fields in the result set * - * @access public - * @return integer + * @return int */ - function num_fields() + public function num_fields() { return $this->result_id->columnCount(); } @@ -69,15 +120,15 @@ class CI_DB_pdo_result extends CI_DB_result { * * Generates an array of column names * - * @access public - * @return array + * @return bool */ - function list_fields() + public function list_fields() { if ($this->db->db_debug) { return $this->db->display_error('db_unsuported_feature'); } + return FALSE; } @@ -88,20 +139,58 @@ class CI_DB_pdo_result extends CI_DB_result { * * Generates an array of objects containing field meta-data * - * @access public * @return array */ - function field_data() + public function field_data() { $data = array(); - + try { - for($i = 0; $i < $this->num_fields(); $i++) + if (strpos($this->result_id->queryString, 'PRAGMA') !== FALSE) + { + foreach ($this->result_array() as $field) + { + preg_match('/([a-zA-Z]+)(\(\d+\))?/', $field['type'], $matches); + + $F = new stdClass(); + $F->name = $field['name']; + $F->type = ( ! empty($matches[1])) ? $matches[1] : NULL; + $F->default = NULL; + $F->max_length = ( ! empty($matches[2])) ? preg_replace('/[^\d]/', '', $matches[2]) : NULL; + $F->primary_key = (int) $field['pk']; + $F->pdo_type = NULL; + + $data[] = $F; + } + } + else { - $data[] = $this->result_id->getColumnMeta($i); + for($i = 0, $max = $this->num_fields(); $i < $max; $i++) + { + $field = $this->result_id->getColumnMeta($i); + + $F = new stdClass(); + $F->name = $field['name']; + $F->type = $field['native_type']; + $F->default = NULL; + $F->pdo_type = $field['pdo_type']; + + if ($field['precision'] < 0) + { + $F->max_length = NULL; + $F->primary_key = 0; + } + else + { + $F->max_length = ($field['len'] > 255) ? 0 : $field['len']; + $F->primary_key = (int) ( ! empty($field['flags']) && in_array('primary_key', $field['flags'])); + } + + $data[] = $F; + } } - + return $data; } catch (Exception $e) @@ -110,6 +199,7 @@ class CI_DB_pdo_result extends CI_DB_result { { return $this->db->display_error('db_unsuported_feature'); } + return FALSE; } } @@ -119,9 +209,9 @@ class CI_DB_pdo_result extends CI_DB_result { /** * Free the result * - * @return null + * @return void */ - function free_result() + public function free_result() { if (is_object($this->result_id)) { @@ -132,31 +222,13 @@ class CI_DB_pdo_result extends CI_DB_result { // -------------------------------------------------------------------- /** - * Data Seek - * - * Moves the internal pointer to the desired offset. We call - * this internally before fetching results to make sure the - * result set starts at zero - * - * @access private - * @return array - */ - function _data_seek($n = 0) - { - return FALSE; - } - - // -------------------------------------------------------------------- - - /** * Result - associative array * * Returns the result set as an array * - * @access private * @return array */ - function _fetch_assoc() + protected function _fetch_assoc() { return $this->result_id->fetch(PDO::FETCH_ASSOC); } @@ -168,16 +240,14 @@ class CI_DB_pdo_result extends CI_DB_result { * * Returns the result set as an object * - * @access private * @return object */ - function _fetch_object() - { - return $this->result_id->fetchObject(); + protected function _fetch_object() + { + return $this->result_id->fetch(PDO::FETCH_OBJ); } } - /* End of file pdo_result.php */ /* Location: ./system/database/drivers/pdo/pdo_result.php */
\ No newline at end of file diff --git a/system/database/drivers/pdo/pdo_utility.php b/system/database/drivers/pdo/pdo_utility.php index 971ec8803..930842118 100644 --- a/system/database/drivers/pdo/pdo_utility.php +++ b/system/database/drivers/pdo/pdo_utility.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,8 +25,6 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * PDO Utility Class * @@ -36,74 +34,15 @@ */ class CI_DB_pdo_utility extends CI_DB_utility { - /** - * List databases - * - * @access private - * @return bool - */ - function _list_databases() - { - // Not sure if PDO lets you list all databases... - if ($this->db->db_debug) - { - return $this->db->display_error('db_unsuported_feature'); - } - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Optimize table query - * - * Generates a platform-specific query so that a table can be optimized - * - * @access private - * @param string the table name - * @return object - */ - function _optimize_table($table) - { - // Not a supported PDO feature - if ($this->db->db_debug) - { - return $this->db->display_error('db_unsuported_feature'); - } - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Repair table query - * - * Generates a platform-specific query so that a table can be repaired - * - * @access private - * @param string the table name - * @return object - */ - function _repair_table($table) - { - // Not a supported PDO feature - if ($this->db->db_debug) - { - return $this->db->display_error('db_unsuported_feature'); - } - return FALSE; - } - - // -------------------------------------------------------------------- + protected $_list_databases = FALSE; /** * PDO Export * - * @access private * @param array Preferences * @return mixed */ - function _backup($params = array()) + protected function _backup($params = array()) { // Currently unsupported return $this->db->display_error('db_unsuported_feature'); diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php index 42329bded..ad9ac9000 100644 --- a/system/database/drivers/postgre/postgre_driver.php +++ b/system/database/drivers/postgre/postgre_driver.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,13 +25,11 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * Postgre Database Adapter Class * * Note: _DB is an extender class that the app controller - * creates dynamically based on whether the active record + * creates dynamically based on whether the query builder * class is being used or not. * * @package CodeIgniter @@ -42,47 +40,81 @@ */ class CI_DB_postgre_driver extends CI_DB { - var $dbdriver = 'postgre'; + public $dbdriver = 'postgre'; - var $_escape_char = '"'; + protected $_escape_char = '"'; // clause and character used for LIKE escape sequences - var $_like_escape_str = " ESCAPE '%s' "; - var $_like_escape_chr = '!'; + protected $_like_escape_str = " ESCAPE '%s' "; + protected $_like_escape_chr = '!'; /** * The syntax to count rows is slightly different across different * database engines, so this string appears in each driver and is * used for the count_all() and count_all_results() functions. */ - var $_count_string = "SELECT COUNT(*) AS "; - var $_random_keyword = ' RANDOM()'; // database specific random keyword + protected $_count_string = 'SELECT COUNT(*) AS '; + protected $_random_keyword = ' RANDOM()'; // database specific random keyword /** - * Connection String + * Constructor * - * @access private - * @return string + * Creates a DSN string to be used for db_connect() and db_pconnect() + * + * @return void */ - function _connect_string() + public function __construct($params) { - $components = array( - 'hostname' => 'host', - 'port' => 'port', - 'database' => 'dbname', - 'username' => 'user', - 'password' => 'password' - ); - - $connect_string = ""; - foreach ($components as $key => $val) + parent::__construct($params); + + if ( ! empty($this->dsn)) { - if (isset($this->$key) && $this->$key != '') + return; + } + + $this->dsn === '' OR $this->dsn = ''; + + if (strpos($this->hostname, '/') !== FALSE) + { + // If UNIX sockets are used, we shouldn't set a port + $this->port = ''; + } + + $this->hostname === '' OR $this->dsn = 'host='.$this->hostname.' '; + + if ( ! empty($this->port) && ctype_digit($this->port)) + { + $this->dsn .= 'port='.$this->port.' '; + } + + if ($this->username !== '') + { + $this->dsn .= 'user='.$this->username.' '; + + /* An empty password is valid! + * + * $db['password'] = NULL must be done in order to ignore it. + */ + $this->password === NULL OR $this->dsn .= "password='".$this->password."' "; + } + + $this->database === '' OR $this->dsn .= 'dbname='.$this->database.' '; + + /* We don't have these options as elements in our standard configuration + * array, but they might be set by parse_url() if the configuration was + * provided via string. Example: + * + * postgre://username:password@localhost:5432/database?connect_timeout=5&sslmode=1 + */ + foreach (array('connect_timeout', 'options', 'sslmode', 'service') as $key) + { + if (isset($this->$key) && is_string($this->key) && $this->key !== '') { - $connect_string .= " $val=".$this->$key; + $this->dsn .= $key."='".$this->key."' "; } } - return trim($connect_string); + + $this->dsn = rtrim($this->dsn); } // -------------------------------------------------------------------- @@ -90,12 +122,11 @@ class CI_DB_postgre_driver extends CI_DB { /** * Non-persistent database connection * - * @access private called by the base class * @return resource */ - function db_connect() + public function db_connect() { - return @pg_connect($this->_connect_string()); + return @pg_connect($this->dsn); } // -------------------------------------------------------------------- @@ -103,12 +134,11 @@ class CI_DB_postgre_driver extends CI_DB { /** * Persistent database connection * - * @access private called by the base class * @return resource */ - function db_pconnect() + public function db_pconnect() { - return @pg_pconnect($this->_connect_string()); + return @pg_pconnect($this->dsn); } // -------------------------------------------------------------------- @@ -119,10 +149,9 @@ class CI_DB_postgre_driver extends CI_DB { * Keep / reestablish the db connection if no queries have been * sent for a length of time exceeding the server's idle timeout * - * @access public * @return void */ - function reconnect() + public function reconnect() { if (pg_ping($this->conn_id) === FALSE) { @@ -133,44 +162,43 @@ class CI_DB_postgre_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Select the database - * - * @access private called by the base class - * @return resource - */ - function db_select() - { - // Not needed for Postgre so we'll return TRUE - return TRUE; - } - - // -------------------------------------------------------------------- - - /** * Set client character set * - * @access public - * @param string * @param string - * @return resource + * @return bool */ - function db_set_charset($charset, $collation) + protected function _db_set_charset($charset) { - // @todo - add support if needed - return TRUE; + return (pg_set_client_encoding($this->conn_id, $charset) === 0); } // -------------------------------------------------------------------- /** - * Version number query string + * Database version number * - * @access public * @return string */ - function _version() + public function version() { - return "SELECT version() AS ver"; + if (isset($this->data_cache['version'])) + { + return $this->data_cache['version']; + } + + if (($pg_version = pg_version($this->conn_id)) === FALSE) + { + return FALSE; + } + + /* If PHP was compiled with PostgreSQL lib versions earlier + * than 7.4, pg_version() won't return the server version + * and so we'll have to fall back to running a query in + * order to get it. + */ + return isset($pg_version['server']) + ? $this->data_cache['version'] = $pg_version['server'] + : parent::version(); } // -------------------------------------------------------------------- @@ -178,49 +206,26 @@ class CI_DB_postgre_driver extends CI_DB { /** * Execute the query * - * @access private called by the base class * @param string an SQL query * @return resource */ - function _execute($sql) + protected function _execute($sql) { - $sql = $this->_prep_query($sql); return @pg_query($this->conn_id, $sql); } // -------------------------------------------------------------------- /** - * Prep the query - * - * If needed, each database adapter can prep the query string - * - * @access private called by execute() - * @param string an SQL query - * @return string - */ - function _prep_query($sql) - { - return $sql; - } - - // -------------------------------------------------------------------- - - /** * Begin Transaction * - * @access public + * @param bool * @return bool */ - function trans_begin($test_mode = FALSE) + public function trans_begin($test_mode = FALSE) { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } @@ -228,9 +233,9 @@ class CI_DB_postgre_driver extends CI_DB { // Reset the transaction failure flag. // If the $test_mode flag is set to TRUE transactions will be rolled back // even if the queries produce a successful result. - $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE; + $this->_trans_failure = ($test_mode === TRUE); - return @pg_exec($this->conn_id, "begin"); + return (bool) @pg_query($this->conn_id, 'BEGIN'); } // -------------------------------------------------------------------- @@ -238,23 +243,17 @@ class CI_DB_postgre_driver extends CI_DB { /** * Commit Transaction * - * @access public * @return bool */ - function trans_commit() + public function trans_commit() { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } - return @pg_exec($this->conn_id, "commit"); + return (bool) @pg_query($this->conn_id, 'COMMIT'); } // -------------------------------------------------------------------- @@ -262,23 +261,17 @@ class CI_DB_postgre_driver extends CI_DB { /** * Rollback Transaction * - * @access public * @return bool */ - function trans_rollback() + public function trans_rollback() { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } - return @pg_exec($this->conn_id, "rollback"); + return (bool) @pg_query($this->conn_id, 'ROLLBACK'); } // -------------------------------------------------------------------- @@ -286,12 +279,11 @@ class CI_DB_postgre_driver extends CI_DB { /** * Escape String * - * @access public * @param string * @param bool whether or not the string will be used in a LIKE condition * @return string */ - function escape_str($str, $like = FALSE) + public function escape_str($str, $like = FALSE) { if (is_array($str)) { @@ -308,9 +300,9 @@ class CI_DB_postgre_driver extends CI_DB { // escape LIKE condition wildcards if ($like === TRUE) { - $str = str_replace( array('%', '_', $this->_like_escape_chr), - array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr), - $str); + return str_replace(array($this->_like_escape_chr, '%', '_'), + array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'), + $str); } return $str; @@ -319,86 +311,80 @@ class CI_DB_postgre_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Affected Rows + * "Smart" Escape String + * + * Escapes data based on type + * Sets boolean and null types * - * @access public - * @return integer + * @param string + * @return mixed */ - function affected_rows() + public function escape($str) { - return @pg_affected_rows($this->result_id); + if (is_bool($str)) + { + return ($str) ? 'TRUE' : 'FALSE'; + } + + return parent::escape($str); } // -------------------------------------------------------------------- /** - * Insert ID + * Affected Rows * - * @access public - * @return integer + * @return int */ - function insert_id() + public function affected_rows() { - $v = $this->_version(); - $v = $v['server']; - - $table = func_num_args() > 0 ? func_get_arg(0) : NULL; - $column = func_num_args() > 1 ? func_get_arg(1) : NULL; - - if ($table == NULL && $v >= '8.1') - { - $sql='SELECT LASTVAL() as ins_id'; - } - elseif ($table != NULL && $column != NULL && $v >= '8.0') - { - $sql = sprintf("SELECT pg_get_serial_sequence('%s','%s') as seq", $table, $column); - $query = $this->query($sql); - $row = $query->row(); - $sql = sprintf("SELECT CURRVAL('%s') as ins_id", $row->seq); - } - elseif ($table != NULL) - { - // seq_name passed in table parameter - $sql = sprintf("SELECT CURRVAL('%s') as ins_id", $table); - } - else - { - return pg_last_oid($this->result_id); - } - $query = $this->query($sql); - $row = $query->row(); - return $row->ins_id; + return @pg_affected_rows($this->result_id); } // -------------------------------------------------------------------- /** - * "Count All" query - * - * Generates a platform-specific query string that counts all records in - * the specified database + * Insert ID * - * @access public - * @param string * @return string */ - function count_all($table = '') + public function insert_id() { - if ($table == '') + $v = pg_version($this->conn_id); + $v = isset($v['server']) ? $v['server'] : 0; // 'server' key is only available since PosgreSQL 7.4 + + $table = (func_num_args() > 0) ? func_get_arg(0) : NULL; + $column = (func_num_args() > 1) ? func_get_arg(1) : NULL; + + if ($table === NULL && $v >= '8.1') { - return 0; + $sql = 'SELECT LASTVAL() AS ins_id'; } + elseif ($table !== NULL) + { + if ($column !== NULL && $v >= '8.0') + { + $sql = 'SELECT pg_get_serial_sequence(\''.$table."', '".$column."') AS seq"; + $query = $this->query($sql); + $query = $query->row(); + $seq = $query->seq; + } + else + { + // seq_name passed in table parameter + $seq = $table; + } - $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE)); - - if ($query->num_rows() == 0) + $sql = 'SELECT CURRVAL(\''.$seq."') AS ins_id"; + } + else { - return 0; + return pg_last_oid($this->result_id); } - $row = $query->row(); - $this->_reset_select(); - return (int) $row->numrows; + $query = $this->query($sql); + $query = $query->row(); + return (int) $query->ins_id; } // -------------------------------------------------------------------- @@ -408,17 +394,16 @@ class CI_DB_postgre_driver extends CI_DB { * * Generates a platform-specific query string so that the table names can be fetched * - * @access private - * @param boolean + * @param bool * @return string */ - function _list_tables($prefix_limit = FALSE) + protected function _list_tables($prefix_limit = FALSE) { $sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'"; - if ($prefix_limit !== FALSE AND $this->dbprefix != '') + if ($prefix_limit !== FALSE && $this->dbprefix !== '') { - $sql .= " AND table_name LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); + return $sql." AND table_name LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); } return $sql; @@ -431,13 +416,12 @@ class CI_DB_postgre_driver extends CI_DB { * * Generates a platform-specific query string so that the column names can be fetched * - * @access public * @param string the table name * @return string */ - function _list_columns($table = '') + protected function _list_columns($table = '') { - return "SELECT column_name FROM information_schema.columns WHERE table_name ='".$table."'"; + return "SELECT column_name FROM information_schema.columns WHERE table_name = '".$table."'"; } // -------------------------------------------------------------------- @@ -447,250 +431,227 @@ class CI_DB_postgre_driver extends CI_DB { * * Generates a platform-specific query so that the column data can be retrieved * - * @access public * @param string the table name - * @return object + * @return string */ - function _field_data($table) + protected function _field_data($table) { - return "SELECT * FROM ".$table." LIMIT 1"; + return 'SELECT * FROM '.$table.' LIMIT 1'; } // -------------------------------------------------------------------- /** - * The error message string + * Error * - * @access private - * @return string + * Returns an array containing code and message of the last + * database error that has occured. + * + * @return array */ - function _error_message() + public function error() { - return pg_last_error($this->conn_id); + return array('code' => '', 'message' => pg_last_error($this->conn_id)); } // -------------------------------------------------------------------- /** - * The error message number + * From Tables * - * @access private - * @return integer + * This function implicitly groups FROM tables so there is no confusion + * about operator precedence in harmony with SQL standards + * + * @param array + * @return string */ - function _error_number() + protected function _from_tables($tables) { - return ''; + return is_array($tables) ? implode(', ', $tables) : $tables; } // -------------------------------------------------------------------- /** - * Escape the SQL Identifiers + * Update statement * - * This function escapes column and table names + * Generates a platform-specific update string from the supplied data * - * @access private - * @param string + * @param string the table name + * @param array the update data + * @param array the where clause + * @param array the orderby clause (ignored) + * @param array the limit clause (ignored) + * @param array the like clause * @return string */ - function _escape_identifiers($item) + protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array()) { - if ($this->_escape_char == '') + foreach ($values as $key => $val) { - return $item; + $valstr[] = $key.' = '.$val; } - foreach ($this->_reserved_identifiers as $id) - { - if (strpos($item, '.'.$id) !== FALSE) - { - $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item); - - // remove duplicates if the user already included the escape - return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); - } - } + $where = empty($where) ? '' : ' WHERE '.implode(' ', $where); - if (strpos($item, '.') !== FALSE) - { - $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char; - } - else + if ( ! empty($like)) { - $str = $this->_escape_char.$item.$this->_escape_char; + $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like); } - // remove duplicates if the user already included the escape - return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + return 'UPDATE '.$table.' SET '.implode(', ', $valstr).$where; } // -------------------------------------------------------------------- /** - * From Tables + * Update_Batch statement * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards + * Generates a platform-specific batch update string from the supplied data * - * @access public - * @param type - * @return type - */ - function _from_tables($tables) - { - if ( ! is_array($tables)) - { - $tables = array($tables); - } - - return implode(', ', $tables); - } - - // -------------------------------------------------------------------- - - /** - * Insert statement - * - * Generates a platform-specific insert string from the supplied data - * - * @access public * @param string the table name - * @param array the insert keys - * @param array the insert values + * @param array the update data + * @param array the where clause * @return string */ - function _insert($table, $keys, $values) + protected function _update_batch($table, $values, $index, $where = NULL) { - return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")"; - } + $ids = array(); + foreach ($values as $key => $val) + { + $ids[] = $val[$index]; - // -------------------------------------------------------------------- + foreach (array_keys($val) as $field) + { + if ($field !== $index) + { + $final[$field][] = 'WHEN '.$val[$index].' THEN '.$val[$field]; + } + } + } - /** - * Insert_batch statement - * - * Generates a platform-specific insert string from the supplied data - * - * @access public - * @param string the table name - * @param array the insert keys - * @param array the insert values - * @return string - */ - function _insert_batch($table, $keys, $values) - { - return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES ".implode(', ', $values); + $cases = ''; + foreach ($final as $k => $v) + { + $cases .= $k.' = (CASE '.$k."\n" + .implode("\n", $v)."\n" + .'ELSE '.$k.' END), '; + } + + return 'UPDATE '.$table.' SET '.substr($cases, 0, -2) + .' WHERE '.(($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '') + .$index.' IN('.implode(',', $ids).')'; } // -------------------------------------------------------------------- /** - * Update statement + * Delete statement * - * Generates a platform-specific update string from the supplied data + * Generates a platform-specific delete string from the supplied data * - * @access public * @param string the table name - * @param array the update data * @param array the where clause - * @param array the orderby clause - * @param array the limit clause + * @param array the like clause + * @param string the limit clause (ignored) * @return string */ - function _update($table, $values, $where, $orderby = array(), $limit = FALSE) + protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) { - foreach ($values as $key => $val) - { - $valstr[] = $key." = ".$val; - } - - $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; - - $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):''; - - $sql = "UPDATE ".$table." SET ".implode(', ', $valstr); + $conditions = array(); - $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : ''; + empty($where) OR $conditions[] = implode(' ', $where); + empty($like) OR $conditions[] = implode(' ', $like); - $sql .= $orderby.$limit; - - return $sql; + return 'DELETE FROM '.$table.(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : ''); } // -------------------------------------------------------------------- /** - * Truncate statement + * Limit string * - * Generates a platform-specific truncate string from the supplied data - * If the database does not support the truncate() command - * This function maps to "DELETE FROM table" + * Generates a platform-specific LIMIT clause * - * @access public - * @param string the table name + * @param string the sql query string + * @param int the number of rows to limit the query to + * @param int the offset value * @return string */ - function _truncate($table) + protected function _limit($sql, $limit, $offset) { - return "TRUNCATE ".$table; + return $sql.' LIMIT '.$limit.($offset == 0 ? '' : ' OFFSET '.$offset); } // -------------------------------------------------------------------- /** - * Delete statement + * Where * - * Generates a platform-specific delete string from the supplied data + * Called by where() or or_where() + * + * @param mixed + * @param mixed + * @param string + * @return object * - * @access public - * @param string the table name - * @param array the where clause - * @param string the limit clause - * @return string */ - function _delete($table, $where = array(), $like = array(), $limit = FALSE) + protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL) { - $conditions = ''; + $type = $this->_group_get_type($type); - if (count($where) > 0 OR count($like) > 0) + if ( ! is_array($key)) { - $conditions = "\nWHERE "; - $conditions .= implode("\n", $this->ar_where); + $key = array($key => $value); + } - if (count($where) > 0 && count($like) > 0) - { - $conditions .= " AND "; - } - $conditions .= implode("\n", $like); + // If the escape value was not set will will base it on the global setting + if ( ! is_bool($escape)) + { + $escape = $this->_protect_identifiers; } - $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + foreach ($key as $k => $v) + { + $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) ? '' : $type; - return "DELETE FROM ".$table.$conditions.$limit; - } + $k = $this->_has_operator($k) + ? $this->protect_identifiers(substr($k, 0, strpos(rtrim($k), ' ')), FALSE, $escape).strchr(rtrim($k), ' ') + : $this->protect_identifiers($k, FALSE, $escape); - // -------------------------------------------------------------------- - /** - * Limit string - * - * Generates a platform-specific LIMIT clause - * - * @access public - * @param string the sql query string - * @param integer the number of rows to limit the query to - * @param integer the offset value - * @return string - */ - function _limit($sql, $limit, $offset) - { - $sql .= "LIMIT ".$limit; + if (is_null($v) && ! $this->_has_operator($k)) + { + // value appears not to have been set, assign the test to IS NULL + $k .= ' IS NULL'; + } + + if ( ! is_null($v)) + { + if ($escape === TRUE) + { + $v = ' '.$this->escape($v); + } + elseif (is_bool($v)) + { + $v = ($v ? ' TRUE' : ' FALSE'); + } + + if ( ! $this->_has_operator($k)) + { + $k .= ' = '; + } + } + + $this->qb_where[] = $prefix.$k.$v; + if ($this->qb_caching === TRUE) + { + $this->qb_cache_where[] = $prefix.$k.$v; + $this->qb_cache_exists[] = 'where'; + } - if ($offset > 0) - { - $sql .= " OFFSET ".$offset; } - return $sql; + return $this; } // -------------------------------------------------------------------- @@ -698,18 +659,14 @@ class CI_DB_postgre_driver extends CI_DB { /** * Close DB Connection * - * @access public - * @param resource * @return void */ - function _close($conn_id) + protected function _close() { - @pg_close($conn_id); + @pg_close($this->conn_id); } - } - /* End of file postgre_driver.php */ /* Location: ./system/database/drivers/postgre/postgre_driver.php */
\ No newline at end of file diff --git a/system/database/drivers/postgre/postgre_forge.php b/system/database/drivers/postgre/postgre_forge.php index 756fd347a..c434e9510 100644 --- a/system/database/drivers/postgre/postgre_forge.php +++ b/system/database/drivers/postgre/postgre_forge.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,8 +25,6 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * Postgre Forge Class * @@ -36,61 +34,34 @@ */ class CI_DB_postgre_forge extends CI_DB_forge { - /** - * Create database - * - * @access private - * @param string the database name - * @return bool - */ - function _create_database($name) - { - return "CREATE DATABASE ".$name; - } - - // -------------------------------------------------------------------- - - /** - * Drop database - * - * @access private - * @param string the database name - * @return bool - */ - function _drop_database($name) - { - return "DROP DATABASE ".$name; - } + protected $_drop_table = 'DROP TABLE IF EXISTS %s CASCADE'; - // -------------------------------------------------------------------- - /** * Process Fields * * @param mixed the fields * @return string */ - function _process_fields($fields, $primary_keys=array()) + protected function _process_fields($fields, $primary_keys = array()) { $sql = ''; $current_field_count = 0; - foreach ($fields as $field=>$attributes) + foreach ($fields as $field => $attributes) { // Numeric field names aren't allowed in databases, so if the key is // numeric, we know it was assigned by PHP and the developer manually // entered the field information, so we'll simply add it to the list if (is_numeric($field)) { - $sql .= "\n\t$attributes"; + $sql .= "\n\t".$attributes; } else { - $attributes = array_change_key_case($attributes, CASE_UPPER); + $sql .= "\n\t".$this->db->escape_identifiers($field); - $sql .= "\n\t".$this->db->_protect_identifiers($field); - - $is_unsigned = (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE); + $attributes = array_change_key_case($attributes, CASE_UPPER); + $is_unsigned = ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE); // Convert datatypes to be PostgreSQL-compatible switch (strtoupper($attributes['TYPE'])) @@ -122,41 +93,30 @@ class CI_DB_postgre_forge extends CI_DB_forge { case 'BLOB': $attributes['TYPE'] = 'BYTEA'; break; + default: + break; } // If this is an auto-incrementing primary key, use the serial data type instead - if (in_array($field, $primary_keys) && array_key_exists('AUTO_INCREMENT', $attributes) - && $attributes['AUTO_INCREMENT'] === TRUE) - { - $sql .= ' SERIAL'; - } - else - { - $sql .= ' '.$attributes['TYPE']; - } + $sql .= (in_array($field, $primary_keys) && ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE) + ? ' SERIAL' : ' '.$attributes['TYPE']; // Modified to prevent constraints with integer data types - if (array_key_exists('CONSTRAINT', $attributes) && strpos($attributes['TYPE'], 'INT') === false) + if ( ! empty($attributes['CONSTRAINT']) && strpos($attributes['TYPE'], 'INT') === FALSE) { $sql .= '('.$attributes['CONSTRAINT'].')'; } - if (array_key_exists('DEFAULT', $attributes)) + if (isset($attributes['DEFAULT'])) { - $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\''; + $sql .= " DEFAULT '".$attributes['DEFAULT']."'"; } - if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE) - { - $sql .= ' NULL'; - } - else - { - $sql .= ' NOT NULL'; - } + $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE) + ? ' NULL' : ' NOT NULL'; - // Added new attribute to create unqite fields. Also works with MySQL - if (array_key_exists('UNIQUE', $attributes) && $attributes['UNIQUE'] === TRUE) + // Added new attribute to create unique fields. Also works with MySQL + if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE) { $sql .= ' UNIQUE'; } @@ -168,7 +128,7 @@ class CI_DB_postgre_forge extends CI_DB_forge { $sql .= ','; } } - + return $sql; } @@ -177,39 +137,28 @@ class CI_DB_postgre_forge extends CI_DB_forge { /** * Create Table * - * @access private * @param string the table name * @param array the fields * @param mixed primary key(s) * @param mixed key(s) - * @param boolean should 'IF NOT EXISTS' be added to the SQL + * @param bool should 'IF NOT EXISTS' be added to the SQL * @return bool */ - function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) + protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) { $sql = 'CREATE TABLE '; - if ($if_not_exists === TRUE) + // PostgreSQL doesn't support IF NOT EXISTS syntax so we check if table exists manually + if ($if_not_exists === TRUE && $this->db->table_exists($table)) { - // PostgreSQL doesn't support IF NOT EXISTS syntax so we check if table exists manually - if ($this->db->table_exists($table)) - { - return TRUE; - } + return TRUE; } - $sql .= $this->db->_escape_identifiers($table)." ("; - $sql .= $this->_process_fields($fields, $primary_keys); + $sql .= $this->db->escape_identifiers($table).' ('.$this->_process_fields($fields, $primary_keys); if (count($primary_keys) > 0) { - // Something seems to break when passing an array to _protect_identifiers() - foreach ($primary_keys as $index => $key) - { - $primary_keys[$index] = $this->db->_protect_identifiers($key); - } - - $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")"; + $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->db->escape_identifiers($primary_keys)).')'; } $sql .= "\n);"; @@ -218,18 +167,14 @@ class CI_DB_postgre_forge extends CI_DB_forge { { foreach ($keys as $key) { - if (is_array($key)) - { - $key = $this->db->_protect_identifiers($key); - } - else - { - $key = array($this->db->_protect_identifiers($key)); - } + $key = is_array($key) + ? $this->db->escape_identifiers($key) + : array($this->db->escape_identifiers($key)); foreach ($key as $field) { - $sql .= "CREATE INDEX " . $table . "_" . str_replace(array('"', "'"), '', $field) . "_index ON $table ($field); "; + $sql .= "\nCREATE INDEX ".$this->db->escape_identifiers($table.'_'.str_replace(array('"', "'"), '', $field).'_index') + .' ON '.$this->db->escape_identifiers($table).' ('.$this->db->escape_identifiers($field).');'; } } } @@ -240,68 +185,34 @@ class CI_DB_postgre_forge extends CI_DB_forge { // -------------------------------------------------------------------- /** - * Drop Table - */ - function _drop_table($table) - { - return "DROP TABLE IF EXISTS ".$this->db->_escape_identifiers($table)." CASCADE"; - } - - // -------------------------------------------------------------------- - - /** * Alter table query * * Generates a platform-specific query so that a table can be altered * Called by add_column(), drop_column(), and column_alter(), * - * @access private * @param string the ALTER type (ADD, DROP, CHANGE) * @param string the column name * @param string the table name * @param string the column definition * @param string the default value - * @param boolean should 'NOT NULL' be added + * @param bool should 'NOT NULL' be added * @param string the field after which we should add the new field - * @return object + * @return string */ - function _alter_table($alter_type, $table, $fields, $after_field = '') + protected function _alter_table($alter_type, $table, $fields, $after_field = '') { - $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type "; + $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '; // DROP has everything it needs now. - if ($alter_type == 'DROP') - { - return $sql.$this->db->_protect_identifiers($fields); - } - - $sql .= $this->_process_fields($fields); - - if ($after_field != '') + if ($alter_type === 'DROP') { - $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field); + return $sql.$this->db->escape_identifiers($fields); } - return $sql; + return $sql.$this->_process_fields($fields) + .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : ''); } - // -------------------------------------------------------------------- - - /** - * Rename a table - * - * Generates a platform-specific query so that a table can be renamed - * - * @access private - * @param string the old table name - * @param string the new table name - * @return string - */ - function _rename_table($table_name, $new_table_name) - { - $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name); - return $sql; - } } /* End of file postgre_forge.php */ diff --git a/system/database/drivers/postgre/postgre_result.php b/system/database/drivers/postgre/postgre_result.php index 9161bf955..f913bc9eb 100644 --- a/system/database/drivers/postgre/postgre_result.php +++ b/system/database/drivers/postgre/postgre_result.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,8 +25,6 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * Postgres Result Class * @@ -41,10 +39,9 @@ class CI_DB_postgre_result extends CI_DB_result { /** * Number of rows in the result set * - * @access public - * @return integer + * @return int */ - function num_rows() + public function num_rows() { return @pg_num_rows($this->result_id); } @@ -54,10 +51,9 @@ class CI_DB_postgre_result extends CI_DB_result { /** * Number of fields in the result set * - * @access public - * @return integer + * @return int */ - function num_fields() + public function num_fields() { return @pg_num_fields($this->result_id); } @@ -69,13 +65,12 @@ class CI_DB_postgre_result extends CI_DB_result { * * Generates an array of column names * - * @access public * @return array */ - function list_fields() + public function list_fields() { $field_names = array(); - for ($i = 0; $i < $this->num_fields(); $i++) + for ($i = 0, $c = $this->num_fields(); $i < $c; $i++) { $field_names[] = pg_field_name($this->result_id, $i); } @@ -90,22 +85,19 @@ class CI_DB_postgre_result extends CI_DB_result { * * Generates an array of objects containing field meta-data * - * @access public * @return array */ - function field_data() + public function field_data() { $retval = array(); - for ($i = 0; $i < $this->num_fields(); $i++) + for ($i = 0, $c = $this->num_fields(); $i < $c; $i++) { - $F = new stdClass(); - $F->name = pg_field_name($this->result_id, $i); - $F->type = pg_field_type($this->result_id, $i); - $F->max_length = pg_field_size($this->result_id, $i); - $F->primary_key = 0; - $F->default = ''; - - $retval[] = $F; + $retval[$i] = new stdClass(); + $retval[$i]->name = pg_field_name($this->result_id, $i); + $retval[$i]->type = pg_field_type($this->result_id, $i); + $retval[$i]->max_length = pg_field_size($this->result_id, $i); + $retval[$i]->primary_key = 0; + $retval[$i]->default = ''; } return $retval; @@ -116,9 +108,9 @@ class CI_DB_postgre_result extends CI_DB_result { /** * Free the result * - * @return null + * @return void */ - function free_result() + public function free_result() { if (is_resource($this->result_id)) { @@ -132,14 +124,13 @@ class CI_DB_postgre_result extends CI_DB_result { /** * Data Seek * - * Moves the internal pointer to the desired offset. We call + * Moves the internal pointer to the desired offset. We call * this internally before fetching results to make sure the * result set starts at zero * - * @access private - * @return array + * @return bool */ - function _data_seek($n = 0) + protected function _data_seek($n = 0) { return pg_result_seek($this->result_id, $n); } @@ -151,10 +142,9 @@ class CI_DB_postgre_result extends CI_DB_result { * * Returns the result set as an array * - * @access private * @return array */ - function _fetch_assoc() + protected function _fetch_assoc() { return pg_fetch_assoc($this->result_id); } @@ -166,16 +156,14 @@ class CI_DB_postgre_result extends CI_DB_result { * * Returns the result set as an object * - * @access private * @return object */ - function _fetch_object() + protected function _fetch_object() { return pg_fetch_object($this->result_id); } } - /* End of file postgre_result.php */ /* Location: ./system/database/drivers/postgre/postgre_result.php */
\ No newline at end of file diff --git a/system/database/drivers/postgre/postgre_utility.php b/system/database/drivers/postgre/postgre_utility.php index dffd8c549..c95e6df0c 100644 --- a/system/database/drivers/postgre/postgre_utility.php +++ b/system/database/drivers/postgre/postgre_utility.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,8 +25,6 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * Postgre Utility Class * @@ -36,65 +34,21 @@ */ class CI_DB_postgre_utility extends CI_DB_utility { - /** - * List databases - * - * @access private - * @return bool - */ - function _list_databases() - { - return "SELECT datname FROM pg_database"; - } - - // -------------------------------------------------------------------- - - /** - * Optimize table query - * - * Is table optimization supported in Postgre? - * - * @access private - * @param string the table name - * @return object - */ - function _optimize_table($table) - { - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Repair table query - * - * Are table repairs supported in Postgre? - * - * @access private - * @param string the table name - * @return object - */ - function _repair_table($table) - { - return FALSE; - } - - // -------------------------------------------------------------------- + protected $_list_databases = 'SELECT datname FROM pg_database'; + protected $_optimize_table = 'REINDEX TABLE %s'; /** * Postgre Export * - * @access private * @param array Preferences * @return mixed */ - function _backup($params = array()) + protected function _backup($params = array()) { // Currently unsupported return $this->db->display_error('db_unsuported_feature'); } } - /* End of file postgre_utility.php */ /* Location: ./system/database/drivers/postgre/postgre_utility.php */
\ No newline at end of file diff --git a/system/database/drivers/sqlite/sqlite_driver.php b/system/database/drivers/sqlite/sqlite_driver.php index 28c3caecd..3305f6030 100644 --- a/system/database/drivers/sqlite/sqlite_driver.php +++ b/system/database/drivers/sqlite/sqlite_driver.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,15 +25,11 @@ * @filesource */ -// ------------------------------------------------------------------------ - - - /** * SQLite Database Adapter Class * * Note: _DB is an extender class that the app controller - * creates dynamically based on whether the active record + * creates dynamically based on whether the query builder * class is being used or not. * * @package CodeIgniter @@ -44,30 +40,29 @@ */ class CI_DB_sqlite_driver extends CI_DB { - var $dbdriver = 'sqlite'; + public $dbdriver = 'sqlite'; // The character used to escape with - not needed for SQLite - var $_escape_char = ''; + protected $_escape_char = '"'; // clause and character used for LIKE escape sequences - var $_like_escape_str = " ESCAPE '%s' "; - var $_like_escape_chr = '!'; + protected $_like_escape_str = " ESCAPE '%s' "; + protected $_like_escape_chr = '!'; /** * The syntax to count rows is slightly different across different * database engines, so this string appears in each driver and is * used for the count_all() and count_all_results() functions. */ - var $_count_string = "SELECT COUNT(*) AS "; - var $_random_keyword = ' Random()'; // database specific random keyword + protected $_count_string = 'SELECT COUNT(*) AS '; + protected $_random_keyword = ' Random()'; // database specific random keyword /** * Non-persistent database connection * - * @access private called by the base class * @return resource */ - function db_connect() + public function db_connect() { if ( ! $conn_id = @sqlite_open($this->database, FILE_WRITE_MODE, $error)) { @@ -89,10 +84,9 @@ class CI_DB_sqlite_driver extends CI_DB { /** * Persistent database connection * - * @access private called by the base class * @return resource */ - function db_pconnect() + public function db_pconnect() { if ( ! $conn_id = @sqlite_popen($this->database, FILE_WRITE_MODE, $error)) { @@ -112,59 +106,15 @@ class CI_DB_sqlite_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Reconnect - * - * Keep / reestablish the db connection if no queries have been - * sent for a length of time exceeding the server's idle timeout - * - * @access public - * @return void - */ - function reconnect() - { - // not implemented in SQLite - } - - // -------------------------------------------------------------------- - - /** - * Select the database + * Database version number * - * @access private called by the base class - * @return resource - */ - function db_select() - { - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Set client character set - * - * @access public - * @param string - * @param string - * @return resource - */ - function db_set_charset($charset, $collation) - { - // @todo - add support if needed - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Version number query string - * - * @access public * @return string */ - function _version() + public function version() { - return sqlite_libversion(); + return isset($this->data_cache['version']) + ? $this->data_cache['version'] + : $this->data_cache['version'] = sqlite_libversion(); } // -------------------------------------------------------------------- @@ -172,30 +122,14 @@ class CI_DB_sqlite_driver extends CI_DB { /** * Execute the query * - * @access private called by the base class * @param string an SQL query * @return resource */ - function _execute($sql) - { - $sql = $this->_prep_query($sql); - return @sqlite_query($this->conn_id, $sql); - } - - // -------------------------------------------------------------------- - - /** - * Prep the query - * - * If needed, each database adapter can prep the query string - * - * @access private called by execute() - * @param string an SQL query - * @return string - */ - function _prep_query($sql) + protected function _execute($sql) { - return $sql; + return $this->is_write_type($sql) + ? @sqlite_exec($this->conn_id, $sql) + : @sqlite_query($this->conn_id, $sql); } // -------------------------------------------------------------------- @@ -203,18 +137,12 @@ class CI_DB_sqlite_driver extends CI_DB { /** * Begin Transaction * - * @access public * @return bool */ - function trans_begin($test_mode = FALSE) + public function trans_begin($test_mode = FALSE) { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } @@ -222,7 +150,7 @@ class CI_DB_sqlite_driver extends CI_DB { // Reset the transaction failure flag. // If the $test_mode flag is set to TRUE transactions will be rolled back // even if the queries produce a successful result. - $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE; + $this->_trans_failure = ($test_mode === TRUE); $this->simple_query('BEGIN TRANSACTION'); return TRUE; @@ -233,18 +161,12 @@ class CI_DB_sqlite_driver extends CI_DB { /** * Commit Transaction * - * @access public * @return bool */ - function trans_commit() + public function trans_commit() { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } @@ -258,18 +180,12 @@ class CI_DB_sqlite_driver extends CI_DB { /** * Rollback Transaction * - * @access public * @return bool */ - function trans_rollback() + public function trans_rollback() { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } @@ -283,12 +199,11 @@ class CI_DB_sqlite_driver extends CI_DB { /** * Escape String * - * @access public * @param string * @param bool whether or not the string will be used in a LIKE condition * @return string */ - function escape_str($str, $like = FALSE) + public function escape_str($str, $like = FALSE) { if (is_array($str)) { @@ -305,9 +220,9 @@ class CI_DB_sqlite_driver extends CI_DB { // escape LIKE condition wildcards if ($like === TRUE) { - $str = str_replace( array('%', '_', $this->_like_escape_chr), - array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr), - $str); + return str_replace(array($this->_like_escape_chr, '%', '_'), + array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'), + $str); } return $str; @@ -318,10 +233,9 @@ class CI_DB_sqlite_driver extends CI_DB { /** * Affected Rows * - * @access public - * @return integer + * @return int */ - function affected_rows() + public function affected_rows() { return sqlite_changes($this->conn_id); } @@ -331,10 +245,9 @@ class CI_DB_sqlite_driver extends CI_DB { /** * Insert ID * - * @access public - * @return integer + * @return int */ - function insert_id() + public function insert_id() { return @sqlite_last_insert_rowid($this->conn_id); } @@ -342,53 +255,22 @@ class CI_DB_sqlite_driver extends CI_DB { // -------------------------------------------------------------------- /** - * "Count All" query - * - * Generates a platform-specific query string that counts all records in - * the specified database - * - * @access public - * @param string - * @return string - */ - function count_all($table = '') - { - if ($table == '') - { - return 0; - } - - $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE)); - - if ($query->num_rows() == 0) - { - return 0; - } - - $row = $query->row(); - $this->_reset_select(); - return (int) $row->numrows; - } - - // -------------------------------------------------------------------- - - /** * List table query * * Generates a platform-specific query string so that the table names can be fetched * - * @access private - * @param boolean + * @param bool * @return string */ - function _list_tables($prefix_limit = FALSE) + protected function _list_tables($prefix_limit = FALSE) { - $sql = "SELECT name from sqlite_master WHERE type='table'"; + $sql = "SELECT name FROM sqlite_master WHERE type='table'"; - if ($prefix_limit !== FALSE AND $this->dbprefix != '') + if ($prefix_limit !== FALSE && $this->dbprefix != '') { - $sql .= " AND 'name' LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); + return $sql." AND 'name' LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); } + return $sql; } @@ -399,11 +281,10 @@ class CI_DB_sqlite_driver extends CI_DB { * * Generates a platform-specific query string so that the column names can be fetched * - * @access public * @param string the table name - * @return string + * @return bool */ - function _list_columns($table = '') + protected function _list_columns($table = '') { // Not supported return FALSE; @@ -416,209 +297,64 @@ class CI_DB_sqlite_driver extends CI_DB { * * Generates a platform-specific query so that the column data can be retrieved * - * @access public * @param string the table name - * @return object - */ - function _field_data($table) - { - return "SELECT * FROM ".$table." LIMIT 1"; - } - - // -------------------------------------------------------------------- - - /** - * The error message string - * - * @access private * @return string */ - function _error_message() - { - return sqlite_error_string(sqlite_last_error($this->conn_id)); - } - - // -------------------------------------------------------------------- - - /** - * The error message number - * - * @access private - * @return integer - */ - function _error_number() + protected function _field_data($table) { - return sqlite_last_error($this->conn_id); + return 'SELECT * FROM '.$this->escape_identifiers($table).' LIMIT 1'; } // -------------------------------------------------------------------- /** - * Escape the SQL Identifiers + * Error * - * This function escapes column and table names + * Returns an array containing code and message of the last + * database error that has occured. * - * @access private - * @param string - * @return string + * @return array */ - function _escape_identifiers($item) + public function error() { - if ($this->_escape_char == '') - { - return $item; - } - - foreach ($this->_reserved_identifiers as $id) - { - if (strpos($item, '.'.$id) !== FALSE) - { - $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item); - - // remove duplicates if the user already included the escape - return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); - } - } - - if (strpos($item, '.') !== FALSE) - { - $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char; - } - else - { - $str = $this->_escape_char.$item.$this->_escape_char; - } - - // remove duplicates if the user already included the escape - return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + $error = array('code' => sqlite_last_error($this->conn_id)); + $error['message'] = sqlite_error_string($error['code']); + return $error; } // -------------------------------------------------------------------- /** - * From Tables + * Replace statement * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards + * Generates a platform-specific replace string from the supplied data * - * @access public - * @param type - * @return type - */ - function _from_tables($tables) - { - if ( ! is_array($tables)) - { - $tables = array($tables); - } - - return '('.implode(', ', $tables).')'; - } - - // -------------------------------------------------------------------- - - /** - * Insert statement - * - * Generates a platform-specific insert string from the supplied data - * - * @access public * @param string the table name * @param array the insert keys * @param array the insert values * @return string */ - function _insert($table, $keys, $values) - { - return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")"; - } - - // -------------------------------------------------------------------- - - /** - * Update statement - * - * Generates a platform-specific update string from the supplied data - * - * @access public - * @param string the table name - * @param array the update data - * @param array the where clause - * @param array the orderby clause - * @param array the limit clause - * @return string - */ - function _update($table, $values, $where, $orderby = array(), $limit = FALSE) + protected function _replace($table, $keys, $values) { - foreach ($values as $key => $val) - { - $valstr[] = $key." = ".$val; - } - - $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; - - $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):''; - - $sql = "UPDATE ".$table." SET ".implode(', ', $valstr); - - $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : ''; - - $sql .= $orderby.$limit; - - return $sql; + return 'INSERT OR '.parent::_replace($table, $keys, $values); } - // -------------------------------------------------------------------- /** * Truncate statement * * Generates a platform-specific truncate string from the supplied data - * If the database does not support the truncate() command - * This function maps to "DELETE FROM table" * - * @access public - * @param string the table name - * @return string - */ - function _truncate($table) - { - return $this->_delete($table); - } - - // -------------------------------------------------------------------- - - /** - * Delete statement - * - * Generates a platform-specific delete string from the supplied data + * If the database does not support the truncate() command, + * then this function maps to 'DELETE FROM table' * - * @access public * @param string the table name - * @param array the where clause - * @param string the limit clause * @return string */ - function _delete($table, $where = array(), $like = array(), $limit = FALSE) + protected function _truncate($table) { - $conditions = ''; - - if (count($where) > 0 OR count($like) > 0) - { - $conditions = "\nWHERE "; - $conditions .= implode("\n", $this->ar_where); - - if (count($where) > 0 && count($like) > 0) - { - $conditions .= " AND "; - } - $conditions .= implode("\n", $like); - } - - $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; - - return "DELETE FROM ".$table.$conditions.$limit; + return 'DELETE FROM '.$table; } // -------------------------------------------------------------------- @@ -628,24 +364,14 @@ class CI_DB_sqlite_driver extends CI_DB { * * Generates a platform-specific LIMIT clause * - * @access public * @param string the sql query string - * @param integer the number of rows to limit the query to - * @param integer the offset value + * @param int the number of rows to limit the query to + * @param int the offset value * @return string */ - function _limit($sql, $limit, $offset) + protected function _limit($sql, $limit, $offset) { - if ($offset == 0) - { - $offset = ''; - } - else - { - $offset .= ", "; - } - - return $sql."LIMIT ".$offset.$limit; + return $sql.'LIMIT '.($offset == 0 ? '' : $offset.', ').$limit; } // -------------------------------------------------------------------- @@ -653,18 +379,14 @@ class CI_DB_sqlite_driver extends CI_DB { /** * Close DB Connection * - * @access public - * @param resource * @return void */ - function _close($conn_id) + protected function _close() { - @sqlite_close($conn_id); + @sqlite_close($this->conn_id); } - } - /* End of file sqlite_driver.php */ /* Location: ./system/database/drivers/sqlite/sqlite_driver.php */
\ No newline at end of file diff --git a/system/database/drivers/sqlite/sqlite_forge.php b/system/database/drivers/sqlite/sqlite_forge.php index 2b723be0b..e02e327f3 100644 --- a/system/database/drivers/sqlite/sqlite_forge.php +++ b/system/database/drivers/sqlite/sqlite_forge.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,8 +25,6 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * SQLite Forge Class * @@ -39,11 +37,10 @@ class CI_DB_sqlite_forge extends CI_DB_forge { /** * Create database * - * @access public * @param string the database name * @return bool */ - function _create_database() + public function create_database($db_name = '') { // In SQLite, a database is created when you connect to the database. // We'll return TRUE so that an error isn't generated @@ -55,90 +52,84 @@ class CI_DB_sqlite_forge extends CI_DB_forge { /** * Drop database * - * @access private - * @param string the database name + * @param string the database name (ignored) * @return bool */ - function _drop_database($name) + public function drop_database($db_name = '') { if ( ! @file_exists($this->db->database) OR ! @unlink($this->db->database)) { - if ($this->db->db_debug) + return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE; + } + elseif ( ! empty($this->db->data_cache['db_names'])) + { + $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE); + if ($key !== FALSE) { - return $this->db->display_error('db_unable_to_drop'); + unset($this->db->data_cache['db_names'][$key]); } - return FALSE; } + return TRUE; } + // -------------------------------------------------------------------- /** * Create Table * - * @access private * @param string the table name * @param array the fields * @param mixed primary key(s) * @param mixed key(s) - * @param boolean should 'IF NOT EXISTS' be added to the SQL + * @param bool should 'IF NOT EXISTS' be added to the SQL * @return bool */ - function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) + protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) { $sql = 'CREATE TABLE '; // IF NOT EXISTS added to SQLite in 3.3.0 - if ($if_not_exists === TRUE && version_compare($this->db->_version(), '3.3.0', '>=') === TRUE) + if ($if_not_exists === TRUE && version_compare($this->db->version(), '3.3.0', '>=') === TRUE) { $sql .= 'IF NOT EXISTS '; } - $sql .= $this->db->_escape_identifiers($table)."("; + $sql .= $this->db->escape_identifiers($table).' ('; $current_field_count = 0; - foreach ($fields as $field=>$attributes) + foreach ($fields as $field => $attributes) { // Numeric field names aren't allowed in databases, so if the key is // numeric, we know it was assigned by PHP and the developer manually // entered the field information, so we'll simply add it to the list if (is_numeric($field)) { - $sql .= "\n\t$attributes"; + $sql .= "\n\t".$attributes; } else { $attributes = array_change_key_case($attributes, CASE_UPPER); - $sql .= "\n\t".$this->db->_protect_identifiers($field); - - $sql .= ' '.$attributes['TYPE']; + $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE']; - if (array_key_exists('CONSTRAINT', $attributes)) - { - $sql .= '('.$attributes['CONSTRAINT'].')'; - } + empty($attributes['CONSTRAINT']) OR $sql .= '('.$attributes['CONSTRAINT'].')'; - if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE) + if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE) { $sql .= ' UNSIGNED'; } - if (array_key_exists('DEFAULT', $attributes)) + if (isset($attributes['DEFAULT'])) { - $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\''; + $sql .= " DEFAULT '".$attributes['DEFAULT']."'"; } - if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE) - { - $sql .= ' NULL'; - } - else - { - $sql .= ' NOT NULL'; - } - if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE) + $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE) + ? ' NULL' : ' NOT NULL'; + + if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE) { $sql .= ' AUTO_INCREMENT'; } @@ -153,49 +144,22 @@ class CI_DB_sqlite_forge extends CI_DB_forge { if (count($primary_keys) > 0) { - $primary_keys = $this->db->_protect_identifiers($primary_keys); - $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")"; + $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->db->escape_identifiers($primary_keys)).')'; } if (is_array($keys) && count($keys) > 0) { foreach ($keys as $key) { - if (is_array($key)) - { - $key = $this->db->_protect_identifiers($key); - } - else - { - $key = array($this->db->_protect_identifiers($key)); - } + $key = is_array($key) + ? $this->db->escape_identifiers($key) + : array($this->db->escape_identifiers($key)); - $sql .= ",\n\tUNIQUE (" . implode(', ', $key) . ")"; + $sql .= ",\n\tUNIQUE (".implode(', ', $key).')'; } } - $sql .= "\n)"; - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Drop Table - * - * Unsupported feature in SQLite - * - * @access private - * @return bool - */ - function _drop_table($table) - { - if ($this->db->db_debug) - { - return $this->db->display_error('db_unsuported_feature'); - } - return array(); + return $sql."\n)"; } // -------------------------------------------------------------------- @@ -206,71 +170,34 @@ class CI_DB_sqlite_forge extends CI_DB_forge { * Generates a platform-specific query so that a table can be altered * Called by add_column(), drop_column(), and column_alter(), * - * @access private * @param string the ALTER type (ADD, DROP, CHANGE) * @param string the column name * @param string the table name * @param string the column definition * @param string the default value - * @param boolean should 'NOT NULL' be added + * @param bool should 'NOT NULL' be added * @param string the field after which we should add the new field - * @return object + * @return string */ - function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') + protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') { - $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name); - - // DROP has everything it needs now. - if ($alter_type == 'DROP') + /* SQLite only supports adding new columns and it does + * NOT support the AFTER statement. Each new column will + * be added as the last one in the table. + */ + if ($alter_type !== 'ADD COLUMN') { - // SQLite does not support dropping columns - // http://www.sqlite.org/omitted.html - // http://www.sqlite.org/faq.html#q11 + // Not supported return FALSE; } - $sql .= " $column_definition"; - - if ($default_value != '') - { - $sql .= " DEFAULT \"$default_value\""; - } - - if ($null === NULL) - { - $sql .= ' NULL'; - } - else - { - $sql .= ' NOT NULL'; - } - - if ($after_field != '') - { - $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field); - } - - return $sql; - + return 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name) + .' '.$column_definition + .($default_value != '' ? " DEFAULT '".$default_value."'" : '') + // If NOT NULL is specified, the field must have a DEFAULT value other than NULL + .(($null !== NULL && $default_value !== 'NULL') ? ' NOT NULL' : ' NULL'); } - // -------------------------------------------------------------------- - - /** - * Rename a table - * - * Generates a platform-specific query so that a table can be renamed - * - * @access private - * @param string the old table name - * @param string the new table name - * @return string - */ - function _rename_table($table_name, $new_table_name) - { - $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name); - return $sql; - } } /* End of file sqlite_forge.php */ diff --git a/system/database/drivers/sqlite/sqlite_result.php b/system/database/drivers/sqlite/sqlite_result.php index 74c0dc549..741dc9d8d 100644 --- a/system/database/drivers/sqlite/sqlite_result.php +++ b/system/database/drivers/sqlite/sqlite_result.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,8 +25,6 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * SQLite Result Class * @@ -41,10 +39,9 @@ class CI_DB_sqlite_result extends CI_DB_result { /** * Number of rows in the result set * - * @access public - * @return integer + * @return int */ - function num_rows() + public function num_rows() { return @sqlite_num_rows($this->result_id); } @@ -54,10 +51,9 @@ class CI_DB_sqlite_result extends CI_DB_result { /** * Number of fields in the result set * - * @access public - * @return integer + * @return int */ - function num_fields() + public function num_fields() { return @sqlite_num_fields($this->result_id); } @@ -69,15 +65,14 @@ class CI_DB_sqlite_result extends CI_DB_result { * * Generates an array of column names * - * @access public * @return array */ - function list_fields() + public function list_fields() { $field_names = array(); - for ($i = 0; $i < $this->num_fields(); $i++) + for ($i = 0, $c = $this->num_fields(); $i < $c; $i++) { - $field_names[] = sqlite_field_name($this->result_id, $i); + $field_names[$i] = sqlite_field_name($this->result_id, $i); } return $field_names; @@ -90,22 +85,19 @@ class CI_DB_sqlite_result extends CI_DB_result { * * Generates an array of objects containing field meta-data * - * @access public * @return array */ - function field_data() + public function field_data() { $retval = array(); - for ($i = 0; $i < $this->num_fields(); $i++) + for ($i = 0, $c = $this->num_fields(); $i < $c; $i++) { - $F = new stdClass(); - $F->name = sqlite_field_name($this->result_id, $i); - $F->type = 'varchar'; - $F->max_length = 0; - $F->primary_key = 0; - $F->default = ''; - - $retval[] = $F; + $retval[$i] = new stdClass(); + $retval[$i]->name = sqlite_field_name($this->result_id, $i); + $retval[$i]->type = 'varchar'; + $retval[$i]->max_length = 0; + $retval[$i]->primary_key = 0; + $retval[$i]->default = ''; } return $retval; @@ -114,28 +106,15 @@ class CI_DB_sqlite_result extends CI_DB_result { // -------------------------------------------------------------------- /** - * Free the result - * - * @return null - */ - function free_result() - { - // Not implemented in SQLite - } - - // -------------------------------------------------------------------- - - /** * Data Seek * - * Moves the internal pointer to the desired offset. We call + * Moves the internal pointer to the desired offset. We call * this internally before fetching results to make sure the * result set starts at zero * - * @access private - * @return array + * @return bool */ - function _data_seek($n = 0) + protected function _data_seek($n = 0) { return sqlite_seek($this->result_id, $n); } @@ -147,10 +126,9 @@ class CI_DB_sqlite_result extends CI_DB_result { * * Returns the result set as an array * - * @access private * @return array */ - function _fetch_assoc() + protected function _fetch_assoc() { return sqlite_fetch_array($this->result_id); } @@ -162,30 +140,20 @@ class CI_DB_sqlite_result extends CI_DB_result { * * Returns the result set as an object * - * @access private * @return object */ - function _fetch_object() + protected function _fetch_object() { if (function_exists('sqlite_fetch_object')) { return sqlite_fetch_object($this->result_id); } - else - { - $arr = sqlite_fetch_array($this->result_id, SQLITE_ASSOC); - if (is_array($arr)) - { - $obj = (object) $arr; - return $obj; - } else { - return NULL; - } - } + + $arr = sqlite_fetch_array($this->result_id, SQLITE_ASSOC); + return is_array($arr) ? (object) $arr : FALSE; } } - /* End of file sqlite_result.php */ /* Location: ./system/database/drivers/sqlite/sqlite_result.php */
\ No newline at end of file diff --git a/system/database/drivers/sqlite/sqlite_utility.php b/system/database/drivers/sqlite/sqlite_utility.php index f00687e38..1bcb42d9f 100644 --- a/system/database/drivers/sqlite/sqlite_utility.php +++ b/system/database/drivers/sqlite/sqlite_utility.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -25,8 +25,6 @@ * @filesource */ -// ------------------------------------------------------------------------ - /** * SQLite Utility Class * @@ -36,72 +34,20 @@ */ class CI_DB_sqlite_utility extends CI_DB_utility { - /** - * List databases - * - * I don't believe you can do a database listing with SQLite - * since each database is its own file. I suppose we could - * try reading a directory looking for SQLite files, but - * that doesn't seem like a terribly good idea - * - * @access private - * @return bool - */ - function _list_databases() - { - if ($this->db_debug) - { - return $this->db->display_error('db_unsuported_feature'); - } - return array(); - } - - // -------------------------------------------------------------------- - - /** - * Optimize table query - * - * Is optimization even supported in SQLite? - * - * @access private - * @param string the table name - * @return object - */ - function _optimize_table($table) - { - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Repair table query - * - * Are table repairs even supported in SQLite? - * - * @access private - * @param string the table name - * @return object - */ - function _repair_table($table) - { - return FALSE; - } - - // -------------------------------------------------------------------- + protected $_list_databases = FALSE; /** * SQLite Export * - * @access private * @param array Preferences * @return mixed */ - function _backup($params = array()) + protected function _backup($params = array()) { // Currently unsupported return $this->db->display_error('db_unsuported_feature'); } + } /* End of file sqlite_utility.php */ diff --git a/system/database/drivers/sqlite3/index.html b/system/database/drivers/sqlite3/index.html new file mode 100644 index 000000000..c942a79ce --- /dev/null +++ b/system/database/drivers/sqlite3/index.html @@ -0,0 +1,10 @@ +<html> +<head> + <title>403 Forbidden</title> +</head> +<body> + +<p>Directory access is forbidden.</p> + +</body> +</html>
\ No newline at end of file diff --git a/system/database/drivers/sqlite3/sqlite3_driver.php b/system/database/drivers/sqlite3/sqlite3_driver.php new file mode 100644 index 000000000..bed61891b --- /dev/null +++ b/system/database/drivers/sqlite3/sqlite3_driver.php @@ -0,0 +1,385 @@ +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +/** + * CodeIgniter + * + * An open source application development framework for PHP 5.2.4 or newer + * + * NOTICE OF LICENSE + * + * Licensed under the Open Software License version 3.0 + * + * This source file is subject to the Open Software License (OSL 3.0) that is + * bundled with this package in the files license.txt / license.rst. It is + * also available through the world wide web at this URL: + * http://opensource.org/licenses/OSL-3.0 + * 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 + * licensing@ellislab.com so we can send you a copy immediately. + * + * @package CodeIgniter + * @author EllisLab Dev Team + * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) + * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * @link http://codeigniter.com + * @since Version 1.0 + * @filesource + */ + +/** + * SQLite3 Database Adapter Class + * + * Note: _DB is an extender class that the app controller + * creates dynamically based on whether the query builder + * class is being used or not. + * + * @package CodeIgniter + * @subpackage Drivers + * @category Database + * @author Andrey Andreev + * @link http://codeigniter.com/user_guide/database/ + * @since Version 3.0 + */ +class CI_DB_sqlite3_driver extends CI_DB { + + public $dbdriver = 'sqlite3'; + + // The character used for escaping + protected $_escape_char = '"'; + + // clause and character used for LIKE escape sequences + protected $_like_escape_str = ' ESCAPE \'%s\' '; + protected $_like_escape_chr = '!'; + + /** + * The syntax to count rows is slightly different across different + * database engines, so this string appears in each driver and is + * used for the count_all() and count_all_results() functions. + */ + protected $_count_string = 'SELECT COUNT(*) AS '; + protected $_random_keyword = ' RANDOM()'; + + /** + * Non-persistent database connection + * + * @return object type SQLite3 + */ + public function db_connect() + { + try + { + return ( ! $this->password) + ? new SQLite3($this->database) + : new SQLite3($this->database, SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE, $this->password); + } + catch (Exception $e) + { + return FALSE; + } + } + + // -------------------------------------------------------------------- + + /** + * Persistent database connection + * + * @return object type SQLite3 + */ + public function db_pconnect() + { + log_message('debug', 'SQLite3 doesn\'t support persistent connections'); + return $this->db_connect(); + } + + // -------------------------------------------------------------------- + + /** + * Database version number + * + * @return string + */ + public function version() + { + if (isset($this->data_cache['version'])) + { + return $this->data_cache['version']; + } + + $version = SQLite3::version(); + return $this->data_cache['version'] = $version['versionString']; + } + + // -------------------------------------------------------------------- + + /** + * Execute the query + * + * @param string an SQL query + * @return mixed SQLite3Result object or bool + */ + protected function _execute($sql) + { + // TODO: Implement use of SQLite3::querySingle(), if needed + + return $this->is_write_type($sql) + ? $this->conn_id->exec($sql) + : $this->conn_id->query($sql); + } + + // -------------------------------------------------------------------- + + /** + * Begin Transaction + * + * @return bool + */ + public function trans_begin($test_mode = FALSE) + { + // When transactions are nested we only begin/commit/rollback the outermost ones + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) + { + return TRUE; + } + + // Reset the transaction failure flag. + // If the $test_mode flag is set to TRUE transactions will be rolled back + // even if the queries produce a successful result. + $this->_trans_failure = ($test_mode === TRUE); + + return $this->conn_id->exec('BEGIN TRANSACTION'); + } + + // -------------------------------------------------------------------- + + /** + * Commit Transaction + * + * @return bool + */ + public function trans_commit() + { + // When transactions are nested we only begin/commit/rollback the outermost ones + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) + { + return TRUE; + } + + return $this->conn_id->exec('END TRANSACTION'); + } + + // -------------------------------------------------------------------- + + /** + * Rollback Transaction + * + * @return bool + */ + public function trans_rollback() + { + // When transactions are nested we only begin/commit/rollback the outermost ones + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) + { + return TRUE; + } + + return $this->conn_id->exec('ROLLBACK'); + } + + // -------------------------------------------------------------------- + + /** + * Escape String + * + * @param string + * @param bool whether or not the string will be used in a LIKE condition + * @return string + */ + public function escape_str($str, $like = FALSE) + { + if (is_array($str)) + { + foreach ($str as $key => $val) + { + $str[$key] = $this->escape_str($val, $like); + } + + return $str; + } + + $str = $this->conn_id->escapeString(remove_invisible_characters($str)); + + // escape LIKE condition wildcards + if ($like === TRUE) + { + return str_replace(array($this->_like_escape_chr, '%', '_'), + array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'), + $str); + } + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Affected Rows + * + * @return int + */ + public function affected_rows() + { + return $this->conn_id->changes(); + } + + // -------------------------------------------------------------------- + + /** + * Insert ID + * + * @return int + */ + public function insert_id() + { + return $this->conn_id->lastInsertRowID(); + } + + // -------------------------------------------------------------------- + + /** + * Show table query + * + * Generates a platform-specific query string so that the table names can be fetched + * + * @param bool + * @return string + */ + protected function _list_tables($prefix_limit = FALSE) + { + return 'SELECT "NAME" FROM "SQLITE_MASTER" WHERE "TYPE" = \'table\'' + .(($prefix_limit !== FALSE && $this->dbprefix != '') + ? ' AND "NAME" LIKE \''.$this->escape_like_str($this->dbprefix).'%\' '.sprintf($this->_like_escape_str, $this->_like_escape_chr) + : ''); + } + + // -------------------------------------------------------------------- + + /** + * Show column query + * + * Generates a platform-specific query string so that the column names can be fetched + * + * @param string the table name + * @return string + */ + protected function _list_columns($table = '') + { + // Not supported + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Field data query + * + * Generates a platform-specific query so that the column data can be retrieved + * + * @param string the table name + * @return string + */ + protected function _field_data($table) + { + return 'SELECT * FROM '.$table.' LIMIT 0,1'; + } + + // -------------------------------------------------------------------- + + /** + * The error message string + * + * @return string + */ + protected function _error_message() + { + return $this->conn_id->lastErrorMsg(); + } + + // -------------------------------------------------------------------- + + /** + * The error message number + * + * @return int + */ + protected function _error_number() + { + return $this->conn_id->lastErrorCode(); + } + + // -------------------------------------------------------------------- + + /** + * Replace statement + * + * Generates a platform-specific replace string from the supplied data + * + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + protected function _replace($table, $keys, $values) + { + return 'INSERT OR '.parent::_replace($table, $keys, $values); + } + + // -------------------------------------------------------------------- + + /** + * Truncate statement + * + * Generates a platform-specific truncate string from the supplied data + * + * If the database does not support the truncate() command, then, + * then this method maps to 'DELETE FROM table' + * + * @param string the table name + * @return string + */ + protected function _truncate($table) + { + return 'DELETE FROM '.$table; + } + + // -------------------------------------------------------------------- + + /** + * Limit string + * + * Generates a platform-specific LIMIT clause + * + * @param string the sql query string + * @param int the number of rows to limit the query to + * @param int the offset value + * @return string + */ + protected function _limit($sql, $limit, $offset) + { + return $sql.' LIMIT '.($offset ? $offset.',' : '').$limit; + } + + // -------------------------------------------------------------------- + + /** + * Close DB Connection + * + * @return void + */ + protected function _close() + { + $this->conn_id->close(); + } + +} + +/* End of file sqlite3_driver.php */ +/* Location: ./system/database/drivers/sqlite3/sqlite3_driver.php */
\ No newline at end of file diff --git a/system/database/drivers/sqlite3/sqlite3_forge.php b/system/database/drivers/sqlite3/sqlite3_forge.php new file mode 100644 index 000000000..6a76ba929 --- /dev/null +++ b/system/database/drivers/sqlite3/sqlite3_forge.php @@ -0,0 +1,211 @@ +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +/** + * CodeIgniter + * + * An open source application development framework for PHP 5.1.6 or newer + * + * NOTICE OF LICENSE + * + * Licensed under the Open Software License version 3.0 + * + * This source file is subject to the Open Software License (OSL 3.0) that is + * bundled with this package in the files license.txt / license.rst. It is + * also available through the world wide web at this URL: + * http://opensource.org/licenses/OSL-3.0 + * 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 + * licensing@ellislab.com so we can send you a copy immediately. + * + * @package CodeIgniter + * @author EllisLab Dev Team + * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) + * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * @link http://codeigniter.com + * @since Version 1.0 + * @filesource + */ + +/** + * SQLite3 Forge Class + * + * @category Database + * @author Andrey Andreev + * @link http://codeigniter.com/user_guide/database/ + */ +class CI_DB_sqlite3_forge extends CI_DB_forge { + + /** + * Create database + * + * @param string the database name + * @return bool + */ + public function create_database($db_name = '') + { + // In SQLite, a database is created when you connect to the database. + // We'll return TRUE so that an error isn't generated + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Drop database + * + * @param string the database name (ignored) + * @return bool + */ + public function drop_database($db_name = '') + { + // In SQLite, a database is dropped when we delete a file + if (@file_exists($this->db->database)) + { + // We need to close the pseudo-connection first + $this->db->close(); + if ( ! @unlink($this->db->database)) + { + return $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE; + } + elseif ( ! empty($this->db->data_cache['db_names'])) + { + $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE); + if ($key !== FALSE) + { + unset($this->db->data_cache['db_names'][$key]); + } + } + + return TRUE; + } + + return $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Create Table + * + * @param string the table name + * @param array the fields + * @param mixed primary key(s) + * @param mixed key(s) + * @param bool should 'IF NOT EXISTS' be added to the SQL + * @return bool + */ + protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) + { + $sql = 'CREATE TABLE '; + + // IF NOT EXISTS added to SQLite in 3.3.0 + if ($if_not_exists === TRUE && version_compare($this->db->version(), '3.3.0', '>=') === TRUE) + { + $sql .= 'IF NOT EXISTS '; + } + + $sql .= $this->db->escape_identifiers($table).' ('; + $current_field_count = 0; + + foreach ($fields as $field => $attributes) + { + // Numeric field names aren't allowed in databases, so if the key is + // numeric, we know it was assigned by PHP and the developer manually + // entered the field information, so we'll simply add it to the list + if (is_numeric($field)) + { + $sql .= "\n\t".$attributes; + } + else + { + $attributes = array_change_key_case($attributes, CASE_UPPER); + + $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE']; + + empty($attributes['CONSTRAINT']) OR $sql .= '('.$attributes['CONSTRAINT'].')'; + + if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE) + { + $sql .= ' UNSIGNED'; + } + + if (isset($attributes['DEFAULT'])) + { + $sql .= " DEFAULT '".$attributes['DEFAULT']."'"; + } + + $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE) + ? ' NULL' : ' NOT NULL'; + + if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE) + { + $sql .= ' AUTO_INCREMENT'; + } + } + + // don't add a comma on the end of the last field + if (++$current_field_count < count($fields)) + { + $sql .= ','; + } + } + + if (count($primary_keys) > 0) + { + $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->db->escape_identifiers($primary_keys)).')'; + } + + if (is_array($keys) && count($keys) > 0) + { + foreach ($keys as $key) + { + $key = is_array($key) + ? $this->db->escape_identifiers($key) + : array($this->db->escape_identifiers($key)); + + $sql .= ",\n\tUNIQUE (".implode(', ', $key).')'; + } + } + + return $sql."\n)"; + } + + // -------------------------------------------------------------------- + + /** + * Alter table query + * + * Generates a platform-specific query so that a table can be altered + * Called by add_column(), drop_column(), and column_alter(), + * + * @param string the ALTER type (ADD, DROP, CHANGE) + * @param string the column name + * @param string the table name + * @param string the column definition + * @param string the default value + * @param bool should 'NOT NULL' be added + * @param string the field after which we should add the new field + * @return string + */ + protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') + { + /* SQLite only supports adding new columns and it does + * NOT support the AFTER statement. Each new column will + * be added as the last one in the table. + */ + if ($alter_type !== 'ADD COLUMN') + { + // Not supported + return FALSE; + } + + return 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name) + .' '.$column_definition + .($default_value !== '' ? ' DEFAULT '.$default_value : '') + // If NOT NULL is specified, the field must have a DEFAULT value other than NULL + .(($null !== NULL && $default_value !== 'NULL') ? ' NOT NULL' : ' NULL'); + } + +} + +/* End of file sqlite3_forge.php */ +/* Location: ./system/database/drivers/sqlite3/sqlite3_forge.php */
\ No newline at end of file diff --git a/system/database/drivers/sqlite3/sqlite3_result.php b/system/database/drivers/sqlite3/sqlite3_result.php new file mode 100644 index 000000000..946b36557 --- /dev/null +++ b/system/database/drivers/sqlite3/sqlite3_result.php @@ -0,0 +1,615 @@ +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +/** + * CodeIgniter + * + * An open source application development framework for PHP 5.1.6 or newer + * + * NOTICE OF LICENSE + * + * Licensed under the Open Software License version 3.0 + * + * This source file is subject to the Open Software License (OSL 3.0) that is + * bundled with this package in the files license.txt / license.rst. It is + * also available through the world wide web at this URL: + * http://opensource.org/licenses/OSL-3.0 + * 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 + * licensing@ellislab.com so we can send you a copy immediately. + * + * @package CodeIgniter + * @author EllisLab Dev Team + * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) + * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * @link http://codeigniter.com + * @since Version 1.0 + * @filesource + */ + +/** + * SQLite Result Class + * + * This class extends the parent result class: CI_DB_result + * + * @category Database + * @author Andrey Andreev + * @link http://codeigniter.com/user_guide/database/ + */ +class CI_DB_sqlite3_result extends CI_DB_result { + + // Overwriting the parent here, so we have a way to know if it's already set + public $num_rows; + + // num_fields() might be called multiple times, so we'll use this one to cache it's result + protected $_num_fields; + + /** + * Number of rows in the result set + * + * @return int + */ + public function num_rows() + { + /* The SQLite3 driver doesn't have a graceful way to do this, + * so we'll have to do it on our own. + */ + return is_int($this->num_rows) + ? $this->num_rows + : $this->num_rows = count($this->result_array()); + } + + // -------------------------------------------------------------------- + + /** + * Number of fields in the result set + * + * @return int + */ + public function num_fields() + { + return ( ! is_int($this->_num_fields)) + ? $this->_num_fields = $this->result_id->numColumns() + : $this->_num_fields; + } + + // -------------------------------------------------------------------- + + /** + * Fetch Field Names + * + * Generates an array of column names + * + * @return array + */ + public function list_fields() + { + $field_names = array(); + for ($i = 0, $c = $this->num_fields(); $i < $c; $i++) + { + $field_names[] = $this->result_id->columnName($i); + } + + return $field_names; + } + + // -------------------------------------------------------------------- + + /** + * Field data + * + * Generates an array of objects containing field meta-data + * + * @return array + */ + public function field_data() + { + $retval = array(); + for ($i = 0, $c = $this->num_fields(); $i < $this->num_fields(); $i++) + { + $retval[$i] = new stdClass(); + $retval[$i]->name = $this->result_id->columnName($i); + $retval[$i]->type = 'varchar'; + $retval[$i]->max_length = 0; + $retval[$i]->primary_key = 0; + $retval[$i]->default = ''; + } + + return $retval; + } + + // -------------------------------------------------------------------- + + /** + * Free the result + * + * @return void + */ + public function free_result() + { + if (is_object($this->result_id)) + { + $this->result_id->finalize(); + $this->result_id = NULL; + } + } + + // -------------------------------------------------------------------- + + /** + * Result - associative array + * + * Returns the result set as an array + * + * @return array + */ + protected function _fetch_assoc() + { + return $this->result_id->fetchArray(SQLITE3_ASSOC); + } + + // -------------------------------------------------------------------- + + /** + * Result - object + * + * Returns the result set as an object + * + * @return object + */ + protected function _fetch_object() + { + // No native support for fetching as an object + $row = $this->_fetch_assoc(); + return ($row !== FALSE) ? (object) $row : FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Query result. "array" version. + * + * return array + */ + public function result_array() + { + if (count($this->result_array) > 0) + { + return $this->result_array; + } + elseif (is_array($this->row_data)) + { + if (count($this->row_data) === 0) + { + return $this->result_array; + } + else + { + $row_index = count($this->row_data); + } + } + else + { + $row_index = 0; + $this->row_data = array(); + } + + $row = NULL; + while ($row = $this->_fetch_assoc()) + { + $this->row_data[$row_index++] = $row; + } + + return $this->result_array = $this->row_data; + } + + // -------------------------------------------------------------------- + + /** + * Query result. "object" version. + * + * @return array + */ + public function result_object() + { + if (count($this->result_object) > 0) + { + return $this->result_object; + } + elseif (count($this->result_array) > 0) + { + for ($i = 0, $c = count($this->result_array); $i < $c; $i++) + { + $this->result_object[] = (object) $this->result_array[$i]; + } + + return $this->result_object; + } + elseif (is_array($this->row_data)) + { + if (count($this->row_data) === 0) + { + return $this->result_object; + } + else + { + $row_index = count($this->row_data); + for ($i = 0; $i < $row_index; $i++) + { + $this->result_object[$i] = (object) $this->row_data[$i]; + } + } + } + else + { + $row_index = 0; + $this->row_data = array(); + } + + $row = NULL; + while ($row = $this->_fetch_assoc()) + { + $this->row_data[$row_index] = $row; + $this->result_object[$row_index++] = (object) $row; + } + + $this->result_array = $this->row_data; + + /* As described for the num_rows() method - there's no easy + * way to get the number of rows selected. Our work-around + * solution (as in here as well) first checks if result_array + * exists and returns its count. It doesn't however check for + * custom_object_result, so - do it here. + */ + if ( ! is_int($this->num_rows)) + { + $this->num_rows = count($this->result_object); + } + + return $this->result_object; + } + + // -------------------------------------------------------------------- + + /** + * Query result. Custom object version. + * + * @param string class name used to instantiate rows to + * @return array + */ + public function custom_result_object($class_name) + { + if (array_key_exists($class_name, $this->custom_result_object)) + { + return $this->custom_result_object[$class_name]; + } + + if ( ! class_exists($class_name) OR ! is_object($this->result_id) OR $this->num_rows() === 0) + { + return array(); + } + + /* Even if result_array hasn't been set prior to custom_result_object being called, + * num_rows() has done it. + */ + $data = &$this->result_array; + + $result_object = array(); + for ($i = 0, $c = count($data); $i < $c; $i++) + { + $result_object[$i] = new $class_name(); + foreach ($data[$i] as $key => $value) + { + $result_object[$i]->$key = $value; + } + } + + /* As described for the num_rows() method - there's no easy + * way to get the number of rows selected. Our work-around + * solution (as in here as well) first checks if result_array + * exists and returns its count. It doesn't however check for + * custom_object_result, so - do it here. + */ + if ( ! is_int($this->num_rows)) + { + $this->num_rows = count($result_object); + } + + // Cache and return the array + return $this->custom_result_object[$class_name] = $result_object; + } + + // -------------------------------------------------------------------- + + /* Single row result. + * + * Acts as a wrapper for row_object(), row_array() + * and custom_row_object(). Also used by first_row(), next_row() + * and previous_row(). + * + * @param int row index + * @param string ('object', 'array' or a custom class name) + * @return mixed whatever was passed to the second parameter + */ + public function row($n = 0, $type = 'object') + { + if ($type === 'object') + { + return $this->row_object($n); + } + elseif ($type === 'array') + { + return $this->row_array($n); + } + + return $this->custom_row_object($n, $type); + } + + // -------------------------------------------------------------------- + + /* Single row result. Array version. + * + * @param int row index + * @return array + */ + public function row_array($n = 0) + { + // Make sure $n is not a string + if ( ! is_int($n)) + { + $n = (int) $n; + } + + /* If row_data is initialized, it means that we've already tried + * (at least) to fetch some data, so ... check if we already have + * this row. + */ + if (is_array($this->row_data)) + { + /* If we already have row_data[$n] - return it. + * + * If we enter the elseif, there's a number of reasons to + * return an empty array: + * + * - count($this->row_data) === 0 means there are no results + * - num_rows being set or result_array having count() > 0 means + * that we've already fetched all data and $n is greater than + * our highest row index available + * - $n < $this->current_row means that if such row existed, + * we would've already returned it, therefore $n is an + * invalid index + */ + if (isset($this->row_data[$n])) // We already have this row + { + $this->current_row = $n; + return $this->row_data[$n]; + } + elseif (count($this->row_data) === 0 OR is_int($this->num_rows) + OR count($this->result_array) > 0 OR $n < $this->current_row) + { + // No such row exists + return NULL; + } + + // Get the next row index that would actually need to be fetched + $current_row = ($this->current_row < count($this->row_data)) ? count($this->row_data) : $this->current_row + 1; + } + else + { + $current_row = $this->current_row = 0; + $this->row_data = array(); + } + + /* Fetch more data, if available + * + * NOTE: Operator precedence is important here, if you change + * 'AND' with '&&' - it WILL BREAK the results, as + * $row will be assigned the scalar value of both + * expressions! + */ + while ($row = $this->_fetch_assoc() AND $current_row <= $n) + { + $this->row_data[$current_row++] = $row; + } + + // This would mean that there's no (more) data to fetch + if ( ! is_array($this->row_data) OR ! isset($this->row_data[$n])) + { + // Cache what we already have + if (is_array($this->row_data)) + { + $this->num_rows = count($this->row_data); + /* Usually, row_data could have less elements than result_array, + * but at this point - they should be exactly the same. + */ + $this->result_array = $this->row_data; + } + else + { + $this->num_rows = 0; + } + + return NULL; + } + + $this->current_row = $n; + return $this->row_data[$n]; + } + + // -------------------------------------------------------------------- + + /* Single row result. Object version. + * + * @param int row index + * @return mixed object if row found; empty array if not + */ + public function row_object($n = 0) + { + // Make sure $n is not a string + if ( ! is_int($n)) + { + $n = (int) $n; + } + + /* Logic here is exactly the same as in row_array, + * except we have to cast row_data[$n] to an object. + * + * If we already have result_object though - we can + * directly return from it. + */ + if (isset($this->result_object[$n])) + { + $this->current_row = $n; + return $this->result_object[$n]; + } + + $row = $this->row_array($n); + // Cast only if the row exists + if (count($row) > 0) + { + $this->current_row = $n; + return (object) $row; + } + + return NULL; + } + + // -------------------------------------------------------------------- + + /* Single row result. Custom object version. + * + * @param int row index + * @param string custom class name + * @return mixed custom object if row found; empty array otherwise + */ + public function custom_row_object($n = 0, $class_name) + { + // Make sure $n is not a string + if ( ! is_int($n)) + { + $n = (int) $n; + } + + if (array_key_exists($class_name, $this->custom_result_object)) + { + /* We already have a the whole result set with this class_name, + * return the specified row if it exists, and an empty array if + * it doesn't. + */ + if (isset($this->custom_result_object[$class_name][$n])) + { + $this->current_row = $n; + return $this->custom_result_object[$class_name][$n]; + } + else + { + return NULL; + } + } + elseif ( ! class_exists($class_name)) // No such class exists + { + return NULL; + } + + $row = $this->row_array($n); + // A non-array would mean that the row doesn't exist + if ( ! is_array($row)) + { + return NULL; + } + + // Convert to the desired class and return + $row_object = new $class_name(); + foreach ($row as $key => $value) + { + $row_object->$key = $value; + } + + $this->current_row = $n; + return $row_object; + } + + // -------------------------------------------------------------------- + + /* First row result. + * + * @param string ('object', 'array' or a custom class name) + * @return mixed whatever was passed to the second parameter + */ + public function first_row($type = 'object') + { + return $this->row(0, $type); + } + + // -------------------------------------------------------------------- + + /* Last row result. + * + * @param string ('object', 'array' or a custom class name) + * @return mixed whatever was passed to the second parameter + */ + public function last_row($type = 'object') + { + $result = &$this->result($type); + if ( ! isset($this->num_rows)) + { + $this->num_rows = count($result); + } + $this->current_row = $this->num_rows - 1; + return $result[$this->current_row]; + } + + // -------------------------------------------------------------------- + + /* Next row result. + * + * @param string ('object', 'array' or a custom class name) + * @return mixed whatever was passed to the second parameter + */ + public function next_row($type = 'object') + { + if (is_array($this->row_data)) + { + $count = count($this->row_data); + $n = ($this->current_row > $count OR ($this->current_row === 0 && $count === 0)) ? $count : $this->current_row + 1; + } + else + { + $n = 0; + } + + return $this->row($n, $type); + } + + // -------------------------------------------------------------------- + + /* Previous row result. + * + * @param string ('object', 'array' or a custom class name) + * @return mixed whatever was passed to the second parameter + */ + public function previous_row($type = 'object') + { + $n = ($this->current_row !== 0) ? $this->current_row - 1 : 0; + return $this->row($n, $type); + } + + // -------------------------------------------------------------------- + + /** + * Data Seek + * + * Moves the internal pointer to the desired offset. We call + * this internally before fetching results to make sure the + * result set starts at zero + * + * @return array + */ + protected function _data_seek($n = 0) + { + // Only resetting to the start of the result set is supported + return $this->result_id->reset(); + } + +} + +/* End of file sqlite3_result.php */ +/* Location: ./system/database/drivers/sqlite3/sqlite3_result.php */
\ No newline at end of file diff --git a/system/database/drivers/sqlite3/sqlite3_utility.php b/system/database/drivers/sqlite3/sqlite3_utility.php new file mode 100644 index 000000000..965c838e5 --- /dev/null +++ b/system/database/drivers/sqlite3/sqlite3_utility.php @@ -0,0 +1,54 @@ +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +/** + * CodeIgniter + * + * An open source application development framework for PHP 5.1.6 or newer + * + * NOTICE OF LICENSE + * + * Licensed under the Open Software License version 3.0 + * + * This source file is subject to the Open Software License (OSL 3.0) that is + * bundled with this package in the files license.txt / license.rst. It is + * also available through the world wide web at this URL: + * http://opensource.org/licenses/OSL-3.0 + * 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 + * licensing@ellislab.com so we can send you a copy immediately. + * + * @package CodeIgniter + * @author EllisLab Dev Team + * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) + * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * @link http://codeigniter.com + * @since Version 1.0 + * @filesource + */ + +/** + * SQLite3 Utility Class + * + * @category Database + * @author Andrey Andreev + * @link http://codeigniter.com/user_guide/database/ + */ +class CI_DB_sqlite3_utility extends CI_DB_utility { + + protected $_list_databases = FALSE; + + /** + * SQLite Export + * + * @param array Preferences + * @return mixed + */ + protected function _backup($params = array()) + { + // Not supported + return $this->db->display_error('db_unsuported_feature'); + } + +} + +/* End of file sqlite3_utility.php */ +/* Location: ./system/database/drivers/sqlite3/sqlite3_utility.php */
\ No newline at end of file diff --git a/system/database/drivers/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php index 6fd52ef70..825c02452 100644 --- a/system/database/drivers/sqlsrv/sqlsrv_driver.php +++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -21,17 +21,15 @@ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com - * @since Version 1.0 + * @since Version 2.0.3 * @filesource */ -// ------------------------------------------------------------------------ - /** * SQLSRV Database Adapter Class * * Note: _DB is an extender class that the app controller - * creates dynamically based on whether the active record + * creates dynamically based on whether the query builder * class is being used or not. * * @package CodeIgniter @@ -42,50 +40,61 @@ */ class CI_DB_sqlsrv_driver extends CI_DB { - var $dbdriver = 'sqlsrv'; + public $dbdriver = 'sqlsrv'; // The character used for escaping - var $_escape_char = ''; + protected $_escape_char = '"'; // clause and character used for LIKE escape sequences - var $_like_escape_str = " ESCAPE '%s' "; - var $_like_escape_chr = '!'; + protected $_like_escape_str = " ESCAPE '%s' "; + protected $_like_escape_chr = '!'; /** * The syntax to count rows is slightly different across different * database engines, so this string appears in each driver and is * used for the count_all() and count_all_results() functions. */ - var $_count_string = "SELECT COUNT(*) AS "; - var $_random_keyword = ' ASC'; // not currently supported + protected $_count_string = 'SELECT COUNT(*) AS '; + protected $_random_keyword = ' NEWID()'; + + // SQLSRV-specific properties + protected $_quoted_identifier = TRUE; /** * Non-persistent database connection * - * @access private called by the base class * @return resource */ - function db_connect($pooling = false) + public function db_connect($pooling = FALSE) { // Check for a UTF-8 charset being passed as CI's default 'utf8'. $character_set = (0 === strcasecmp('utf8', $this->char_set)) ? 'UTF-8' : $this->char_set; $connection = array( - 'UID' => empty($this->username) ? '' : $this->username, - 'PWD' => empty($this->password) ? '' : $this->password, - 'Database' => $this->database, - 'ConnectionPooling' => $pooling ? 1 : 0, + 'UID' => empty($this->username) ? '' : $this->username, + 'PWD' => empty($this->password) ? '' : $this->password, + 'Database' => $this->database, + 'ConnectionPooling' => $pooling ? 1 : 0, 'CharacterSet' => $character_set, - 'ReturnDatesAsStrings' => 1 + 'ReturnDatesAsStrings' => 1 ); - - // If the username and password are both empty, assume this is a + + // If the username and password are both empty, assume this is a // 'Windows Authentication Mode' connection. - if(empty($connection['UID']) && empty($connection['PWD'])) { + if (empty($connection['UID']) && empty($connection['PWD'])) + { unset($connection['UID'], $connection['PWD']); } - return sqlsrv_connect($this->hostname, $connection); + $conn_id = sqlsrv_connect($this->hostname, $connection); + + // Determine how identifiers are escaped + $query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi'); + $query = $query->row_array(); + $this->_quoted_identifier = empty($query) ? FALSE : (bool) $query->qi; + $this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']'); + + return $conn_id; } // -------------------------------------------------------------------- @@ -93,10 +102,9 @@ class CI_DB_sqlsrv_driver extends CI_DB { /** * Persistent database connection * - * @access private called by the base class * @return resource */ - function db_pconnect() + public function db_pconnect() { return $this->db_connect(TRUE); } @@ -104,46 +112,25 @@ class CI_DB_sqlsrv_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Reconnect - * - * Keep / reestablish the db connection if no queries have been - * sent for a length of time exceeding the server's idle timeout - * - * @access public - * @return void - */ - function reconnect() - { - // not implemented in MSSQL - } - - // -------------------------------------------------------------------- - - /** * Select the database * - * @access private called by the base class - * @return resource + * @param string database name + * @return bool */ - function db_select() + public function db_select($database = '') { - return $this->_execute('USE ' . $this->database); - } + if ($database === '') + { + $database = $this->database; + } - // -------------------------------------------------------------------- + if ($this->_execute('USE '.$database)) + { + $this->database = $database; + return TRUE; + } - /** - * Set client character set - * - * @access public - * @param string - * @param string - * @return resource - */ - function db_set_charset($charset, $collation) - { - // @todo - add support if needed - return TRUE; + return FALSE; } // -------------------------------------------------------------------- @@ -151,33 +138,14 @@ class CI_DB_sqlsrv_driver extends CI_DB { /** * Execute the query * - * @access private called by the base class * @param string an SQL query * @return resource */ - function _execute($sql) + protected function _execute($sql) { - $sql = $this->_prep_query($sql); - return sqlsrv_query($this->conn_id, $sql, null, array( - 'Scrollable' => SQLSRV_CURSOR_STATIC, - 'SendStreamParamsAtExec' => true - )); - } - - // -------------------------------------------------------------------- - - /** - * Prep the query - * - * If needed, each database adapter can prep the query string - * - * @access private called by execute() - * @param string an SQL query - * @return string - */ - function _prep_query($sql) - { - return $sql; + return (is_write_type($sql) && stripos($sql, 'INSERT') === FALSE) + ? sqlsrv_query($this->conn_id, $sql) + : sqlsrv_query($this->conn_id, $sql, NULL, array('Scrollable' => SQLSRV_CURSOR_STATIC)); } // -------------------------------------------------------------------- @@ -185,18 +153,12 @@ class CI_DB_sqlsrv_driver extends CI_DB { /** * Begin Transaction * - * @access public * @return bool */ - function trans_begin($test_mode = FALSE) + public function trans_begin($test_mode = FALSE) { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } @@ -204,7 +166,7 @@ class CI_DB_sqlsrv_driver extends CI_DB { // Reset the transaction failure flag. // If the $test_mode flag is set to TRUE transactions will be rolled back // even if the queries produce a successful result. - $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE; + $this->_trans_failure = ($test_mode === TRUE); return sqlsrv_begin_transaction($this->conn_id); } @@ -214,18 +176,12 @@ class CI_DB_sqlsrv_driver extends CI_DB { /** * Commit Transaction * - * @access public * @return bool */ - function trans_commit() + public function trans_commit() { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } @@ -238,18 +194,12 @@ class CI_DB_sqlsrv_driver extends CI_DB { /** * Rollback Transaction * - * @access public * @return bool */ - function trans_rollback() + public function trans_rollback() { - if ( ! $this->trans_enabled) - { - return TRUE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - if ($this->_trans_depth > 0) + if ( ! $this->trans_enabled OR $this->_trans_depth > 0) { return TRUE; } @@ -262,12 +212,11 @@ class CI_DB_sqlsrv_driver extends CI_DB { /** * Escape String * - * @access public * @param string * @param bool whether or not the string will be used in a LIKE condition * @return string */ - function escape_str($str, $like = FALSE) + public function escape_str($str, $like = FALSE) { // Escape single quotes return str_replace("'", "''", $str); @@ -278,86 +227,49 @@ class CI_DB_sqlsrv_driver extends CI_DB { /** * Affected Rows * - * @access public - * @return integer + * @return int */ - function affected_rows() + public function affected_rows() { - return @sqlrv_rows_affected($this->conn_id); + return sqlrv_rows_affected($this->result_id); } // -------------------------------------------------------------------- /** - * Insert ID - * - * Returns the last id created in the Identity column. - * - * @access public - * @return integer - */ - function insert_id() - { - return $this->query('select @@IDENTITY as insert_id')->row('insert_id'); - } - - // -------------------------------------------------------------------- - - /** - * Parse major version - * - * Grabs the major version number from the - * database server version string passed in. - * - * @access private - * @param string $version - * @return int16 major version number - */ - function _parse_major_version($version) - { - preg_match('/([0-9]+)\.([0-9]+)\.([0-9]+)/', $version, $ver_info); - return $ver_info[1]; // return the major version b/c that's all we're interested in. - } - - // -------------------------------------------------------------------- - - /** - * Version number query string - * - * @access public - * @return string - */ - function _version() + * Insert ID + * + * Returns the last id created in the Identity column. + * + * @return string + */ + public function insert_id() { - $info = sqlsrv_server_info($this->conn_id); - return sprintf("select '%s' as ver", $info['SQLServerVersion']); + $query = $this->query('SELECT @@IDENTITY AS insert_id'); + $query = $query->row(); + return $query->insert_id; } // -------------------------------------------------------------------- /** - * "Count All" query + * Database version number * - * Generates a platform-specific query string that counts all records in - * the specified database - * - * @access public - * @param string * @return string */ - function count_all($table = '') + public function version() { - if ($table == '') - return '0'; - - $query = $this->query("SELECT COUNT(*) AS numrows FROM " . $this->dbprefix . $table); - - if ($query->num_rows() == 0) - return '0'; - - $row = $query->row(); - $this->_reset_select(); - return $row->numrows; + if (isset($this->data_cache['version'])) + { + return $this->data_cache['version']; + } + + if (($info = sqlsrv_server_info($this->conn_id)) === FALSE) + { + return FALSE; + } + + return $this->data_cache['version'] = $info['SQLServerVersion']; } // -------------------------------------------------------------------- @@ -367,11 +279,10 @@ class CI_DB_sqlsrv_driver extends CI_DB { * * Generates a platform-specific query string so that the table names can be fetched * - * @access private - * @param boolean + * @param bool * @return string */ - function _list_tables($prefix_limit = FALSE) + protected function _list_tables($prefix_limit = FALSE) { return "SELECT name FROM sysobjects WHERE type = 'U' ORDER BY name"; } @@ -383,13 +294,12 @@ class CI_DB_sqlsrv_driver extends CI_DB { * * Generates a platform-specific query string so that the column names can be fetched * - * @access private * @param string the table name * @return string */ - function _list_columns($table = '') + protected function _list_columns($table = '') { - return "SELECT * FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '".$this->_escape_table($table)."'"; + return "SELECT * FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '".$table."'"; } // -------------------------------------------------------------------- @@ -399,113 +309,66 @@ class CI_DB_sqlsrv_driver extends CI_DB { * * Generates a platform-specific query so that the column data can be retrieved * - * @access public * @param string the table name - * @return object - */ - function _field_data($table) - { - return "SELECT TOP 1 * FROM " . $this->_escape_table($table); - } - - // -------------------------------------------------------------------- - - /** - * The error message string - * - * @access private * @return string */ - function _error_message() + protected function _field_data($table) { - $error = array_shift(sqlsrv_errors()); - return !empty($error['message']) ? $error['message'] : null; + return 'SELECT TOP 1 * FROM '.$table; } // -------------------------------------------------------------------- /** - * The error message number + * Error * - * @access private - * @return integer - */ - function _error_number() - { - $error = array_shift(sqlsrv_errors()); - return isset($error['SQLSTATE']) ? $error['SQLSTATE'] : null; - } - - // -------------------------------------------------------------------- - - /** - * Escape Table Name - * - * This function adds backticks if the table name has a period - * in it. Some DBs will get cranky unless periods are escaped + * Returns an array containing code and message of the last + * database error that has occured. * - * @access private - * @param string the table name - * @return string + * @return array */ - function _escape_table($table) + public function error() { - return $table; - } + $error = array('code' => '00000', 'message' => ''); + $sqlsrv_errors = sqlsrv_errors(SQLSRV_ERR_ERRORS); + if ( ! is_array($sqlsrv_errors)) + { + return $error; + } - /** - * Escape the SQL Identifiers - * - * This function escapes column and table names - * - * @access private - * @param string - * @return string - */ - function _escape_identifiers($item) - { - return $item; - } - - // -------------------------------------------------------------------- + $sqlsrv_error = array_shift($sqlsrv_errors); + if (isset($sqlsrv_error['SQLSTATE'])) + { + $error['code'] = isset($sqlsrv_error['code']) ? $sqlsrv_error['SQLSTATE'].'/'.$sqlsrv_error['code'] : $sqlsrv_error['SQLSTATE']; + } + elseif (isset($sqlsrv_error['code'])) + { + $error['code'] = $sqlsrv_error['code']; + } - /** - * From Tables - * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards - * - * @access public - * @param type - * @return type - */ - function _from_tables($tables) - { - if ( ! is_array($tables)) + if (isset($sqlsrv_error['message'])) { - $tables = array($tables); + $error['message'] = $sqlsrv_error['message']; } - return implode(', ', $tables); + return $error; } // -------------------------------------------------------------------- /** - * Insert statement + * From Tables * - * Generates a platform-specific insert string from the supplied data + * This function implicitly groups FROM tables so there is no confusion + * about operator precedence in harmony with SQL standards * - * @access public - * @param string the table name - * @param array the insert keys - * @param array the insert values + * @param array * @return string */ - function _insert($table, $keys, $values) - { - return "INSERT INTO ".$this->_escape_table($table)." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")"; + protected function _from_tables($tables) + { + return is_array($tables) ? implode(', ', $tables) : $tables; } // -------------------------------------------------------------------- @@ -515,40 +378,47 @@ class CI_DB_sqlsrv_driver extends CI_DB { * * Generates a platform-specific update string from the supplied data * - * @access public * @param string the table name * @param array the update data * @param array the where clause - * @param array the orderby clause - * @param array the limit clause + * @param array the orderby clause (ignored) + * @param array the limit clause (ignored) + * @param array the like clause * @return string */ - function _update($table, $values, $where) + protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array()) { - foreach($values as $key => $val) + foreach ($values as $key => $val) { - $valstr[] = $key." = ".$val; + $valstr[] = $key.' = '.$val; } - - return "UPDATE ".$this->_escape_table($table)." SET ".implode(', ', $valstr)." WHERE ".implode(" ", $where); + + $where = empty($where) ? '' : ' WHERE '.implode(' ', $where); + + if ( ! empty($like)) + { + $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like); + } + + return 'UPDATE '.$table.' SET '.implode(', ', $valstr).$where; } - + // -------------------------------------------------------------------- /** * Truncate statement * * Generates a platform-specific truncate string from the supplied data - * If the database does not support the truncate() command - * This function maps to "DELETE FROM table" * - * @access public + * If the database does not support the truncate() command, + * then this method maps to 'DELETE FROM table' + * * @param string the table name * @return string */ - function _truncate($table) + protected function _truncate($table) { - return "TRUNCATE ".$table; + return 'TRUNCATE TABLE '.$table; } // -------------------------------------------------------------------- @@ -558,15 +428,24 @@ class CI_DB_sqlsrv_driver extends CI_DB { * * Generates a platform-specific delete string from the supplied data * - * @access public * @param string the table name * @param array the where clause + * @param array the like clause * @param string the limit clause * @return string */ - function _delete($table, $where) + protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) { - return "DELETE FROM ".$this->_escape_table($table)." WHERE ".implode(" ", $where); + $conditions = array(); + + empty($where) OR $conditions[] = implode(' ', $where); + empty($like) OR $conditions[] = implode(' ', $like); + + $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : ''; + + return ($limit) + ? 'WITH ci_delete AS (SELECT TOP '.$limit.' * FROM '.$table.$conditions.') DELETE FROM ci_delete' + : 'DELETE FROM '.$table.$conditions; } // -------------------------------------------------------------------- @@ -576,17 +455,36 @@ class CI_DB_sqlsrv_driver extends CI_DB { * * Generates a platform-specific LIMIT clause * - * @access public * @param string the sql query string - * @param integer the number of rows to limit the query to - * @param integer the offset value + * @param int the number of rows to limit the query to + * @param int the offset value * @return string */ - function _limit($sql, $limit, $offset) + protected function _limit($sql, $limit, $offset) { - $i = $limit + $offset; - - return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$i.' ', $sql); + // As of SQL Server 2012 (11.0.*) OFFSET is supported + if (version_compare($this->version(), '11', '>=')) + { + return $sql.' OFFSET '.(int) $offset.' ROWS FETCH NEXT '.(int) $limit.' ROWS ONLY'; + } + + $limit = $offset + $limit; + + // An ORDER BY clause is required for ROW_NUMBER() to work + if ($offset && ! empty($this->qb_orderby)) + { + $orderby = 'ORDER BY '.implode(', ', $this->qb_orderby); + + // We have to strip the ORDER BY clause + $sql = trim(substr($sql, 0, strrpos($sql, 'ORDER BY '.$orderby))); + + return 'SELECT '.(count($this->qb_select) === 0 ? '*' : implode(', ', $this->qb_select))." FROM (\n" + .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.$orderby.') AS '.$this->escape_identifiers('CI_rownum').', ', $sql) + ."\n) ".$this->escape_identifiers('CI_subquery') + ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.((int) $offset + 1).' AND '.$limit; + } + + return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql); } // -------------------------------------------------------------------- @@ -594,18 +492,14 @@ class CI_DB_sqlsrv_driver extends CI_DB { /** * Close DB Connection * - * @access public - * @param resource * @return void */ - function _close($conn_id) + protected function _close() { - @sqlsrv_close($conn_id); + @sqlsrv_close($this->conn_id); } } - - -/* End of file mssql_driver.php */ -/* Location: ./system/database/drivers/mssql/mssql_driver.php */
\ No newline at end of file +/* End of file sqlsrv_driver.php */ +/* Location: ./system/database/drivers/sqlsrv/sqlsrv_driver.php */
\ No newline at end of file diff --git a/system/database/drivers/sqlsrv/sqlsrv_forge.php b/system/database/drivers/sqlsrv/sqlsrv_forge.php index 2a7766927..ccdb36929 100644 --- a/system/database/drivers/sqlsrv/sqlsrv_forge.php +++ b/system/database/drivers/sqlsrv/sqlsrv_forge.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -21,12 +21,10 @@ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com - * @since Version 1.0 + * @since Version 2.0.3 * @filesource */ -// ------------------------------------------------------------------------ - /** * SQLSRV Forge Class * @@ -36,112 +34,61 @@ */ class CI_DB_sqlsrv_forge extends CI_DB_forge { - /** - * Create database - * - * @access private - * @param string the database name - * @return bool - */ - function _create_database($name) - { - return "CREATE DATABASE ".$name; - } - - // -------------------------------------------------------------------- - - /** - * Drop database - * - * @access private - * @param string the database name - * @return bool - */ - function _drop_database($name) - { - return "DROP DATABASE ".$name; - } - - // -------------------------------------------------------------------- - - /** - * Drop Table - * - * @access private - * @return bool - */ - function _drop_table($table) - { - return "DROP TABLE ".$this->db->_escape_identifiers($table); - } - - // -------------------------------------------------------------------- + protected $_drop_table = 'DROP TABLE %s'; /** * Create Table * - * @access private * @param string the table name * @param array the fields * @param mixed primary key(s) * @param mixed key(s) - * @param boolean should 'IF NOT EXISTS' be added to the SQL - * @return bool + * @param bool should 'IF NOT EXISTS' be added to the SQL + * @return string */ - function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) + protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) { - $sql = 'CREATE TABLE '; + $sql = ($if_not_exists === TRUE) + ? "IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'".$table."') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\n" + : ''; - if ($if_not_exists === TRUE) - { - $sql .= 'IF NOT EXISTS '; - } + $sql .= 'CREATE TABLE '.$this->db->escape_identifiers($table).' ('; - $sql .= $this->db->_escape_identifiers($table)." ("; $current_field_count = 0; - - foreach ($fields as $field=>$attributes) + foreach ($fields as $field => $attributes) { // Numeric field names aren't allowed in databases, so if the key is // numeric, we know it was assigned by PHP and the developer manually // entered the field information, so we'll simply add it to the list if (is_numeric($field)) { - $sql .= "\n\t$attributes"; + $sql .= "\n\t".$attributes; } else { $attributes = array_change_key_case($attributes, CASE_UPPER); - $sql .= "\n\t".$this->db->_protect_identifiers($field); + $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE']; - $sql .= ' '.$attributes['TYPE']; - - if (array_key_exists('CONSTRAINT', $attributes)) + if (stripos($attributes['TYPE'], 'INT') === FALSE && ! empty($attributes['CONSTRAINT'])) { $sql .= '('.$attributes['CONSTRAINT'].')'; } - if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE) + if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE) { $sql .= ' UNSIGNED'; } - if (array_key_exists('DEFAULT', $attributes)) + if (isset($attributes['DEFAULT'])) { - $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\''; + $sql .= " DEFAULT '".$attributes['DEFAULT']."'"; } - if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE) - { - $sql .= ' NULL'; - } - else - { - $sql .= ' NOT NULL'; - } + $sql .= ( ! empty($attributes['NULL']) && $attribues['NULL'] === TRUE) + ? ' NULL' : ' NOT NULL'; - if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE) + if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE) { $sql .= ' AUTO_INCREMENT'; } @@ -156,30 +103,22 @@ class CI_DB_sqlsrv_forge extends CI_DB_forge { if (count($primary_keys) > 0) { - $primary_keys = $this->db->_protect_identifiers($primary_keys); - $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")"; + $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->db->escape_identifiers($primary_keys)).')'; } if (is_array($keys) && count($keys) > 0) { foreach ($keys as $key) { - if (is_array($key)) - { - $key = $this->db->_protect_identifiers($key); - } - else - { - $key = array($this->db->_protect_identifiers($key)); - } + $key = is_array($key) + ? $this->db->escape_identifiers($key) + : array($this->escape_identifiers($key)); - $sql .= ",\n\tFOREIGN KEY (" . implode(', ', $key) . ")"; + $sql .= ",\n\tFOREIGN KEY (".implode(', ', $key).')'; } } - $sql .= "\n)"; - - return $sql; + return $sql."\n)"; } // -------------------------------------------------------------------- @@ -190,71 +129,32 @@ class CI_DB_sqlsrv_forge extends CI_DB_forge { * Generates a platform-specific query so that a table can be altered * Called by add_column(), drop_column(), and column_alter(), * - * @access private * @param string the ALTER type (ADD, DROP, CHANGE) * @param string the column name * @param string the table name * @param string the column definition * @param string the default value - * @param boolean should 'NOT NULL' be added + * @param bool should 'NOT NULL' be added * @param string the field after which we should add the new field - * @return object + * @return string */ - function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') + protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') { - $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name); + $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name); // DROP has everything it needs now. - if ($alter_type == 'DROP') + if ($alter_type === 'DROP') { return $sql; } - $sql .= " $column_definition"; - - if ($default_value != '') - { - $sql .= " DEFAULT \"$default_value\""; - } - - if ($null === NULL) - { - $sql .= ' NULL'; - } - else - { - $sql .= ' NOT NULL'; - } - - if ($after_field != '') - { - $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field); - } - - return $sql; - - } - - // -------------------------------------------------------------------- - - /** - * Rename a table - * - * Generates a platform-specific query so that a table can be renamed - * - * @access private - * @param string the old table name - * @param string the new table name - * @return string - */ - function _rename_table($table_name, $new_table_name) - { - // I think this syntax will work, but can find little documentation on renaming tables in MSSQL - $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name); - return $sql; + return $sql.' '.$column_definition + .($default_value != '' ? ' DEFAULT "'.$default_value.'"' : '') + .($null === NULL ? ' NULL' : ' NOT NULL') + .($after_field != '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : ''); } } -/* End of file mssql_forge.php */ -/* Location: ./system/database/drivers/mssql/mssql_forge.php */
\ No newline at end of file +/* End of file sqlsrv_forge.php */ +/* Location: ./system/database/drivers/sqlsrv/sqlsrv_forge.php */
\ No newline at end of file diff --git a/system/database/drivers/sqlsrv/sqlsrv_result.php b/system/database/drivers/sqlsrv/sqlsrv_result.php index 1ee19c2d1..f9d5a0d29 100644 --- a/system/database/drivers/sqlsrv/sqlsrv_result.php +++ b/system/database/drivers/sqlsrv/sqlsrv_result.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -21,12 +21,10 @@ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com - * @since Version 1.0 + * @since Version 2.0.3 * @filesource */ -// ------------------------------------------------------------------------ - /** * SQLSRV Result Class * @@ -41,10 +39,9 @@ class CI_DB_sqlsrv_result extends CI_DB_result { /** * Number of rows in the result set * - * @access public - * @return integer + * @return int */ - function num_rows() + public function num_rows() { return @sqlsrv_num_rows($this->result_id); } @@ -54,10 +51,9 @@ class CI_DB_sqlsrv_result extends CI_DB_result { /** * Number of fields in the result set * - * @access public - * @return integer + * @return int */ - function num_fields() + public function num_fields() { return @sqlsrv_num_fields($this->result_id); } @@ -69,17 +65,16 @@ class CI_DB_sqlsrv_result extends CI_DB_result { * * Generates an array of column names * - * @access public * @return array */ - function list_fields() + public function list_fields() { $field_names = array(); - foreach(sqlsrv_field_metadata($this->result_id) as $offset => $field) + foreach (sqlsrv_field_metadata($this->result_id) as $offset => $field) { $field_names[] = $field['Name']; } - + return $field_names; } @@ -90,24 +85,23 @@ class CI_DB_sqlsrv_result extends CI_DB_result { * * Generates an array of objects containing field meta-data * - * @access public * @return array */ - function field_data() + public function field_data() { $retval = array(); - foreach(sqlsrv_field_metadata($this->result_id) as $offset => $field) + foreach (sqlsrv_field_metadata($this->result_id) as $offset => $field) { - $F = new stdClass(); - $F->name = $field['Name']; - $F->type = $field['Type']; + $F = new stdClass(); + $F->name = $field['Name']; + $F->type = $field['Type']; $F->max_length = $field['Size']; $F->primary_key = 0; - $F->default = ''; - + $F->default = ''; + $retval[] = $F; } - + return $retval; } @@ -116,9 +110,9 @@ class CI_DB_sqlsrv_result extends CI_DB_result { /** * Free the result * - * @return null + * @return void */ - function free_result() + public function free_result() { if (is_resource($this->result_id)) { @@ -130,31 +124,13 @@ class CI_DB_sqlsrv_result extends CI_DB_result { // -------------------------------------------------------------------- /** - * Data Seek - * - * Moves the internal pointer to the desired offset. We call - * this internally before fetching results to make sure the - * result set starts at zero - * - * @access private - * @return array - */ - function _data_seek($n = 0) - { - // Not implemented - } - - // -------------------------------------------------------------------- - - /** * Result - associative array * * Returns the result set as an array * - * @access private * @return array */ - function _fetch_assoc() + protected function _fetch_assoc() { return sqlsrv_fetch_array($this->result_id, SQLSRV_FETCH_ASSOC); } @@ -166,16 +142,14 @@ class CI_DB_sqlsrv_result extends CI_DB_result { * * Returns the result set as an object * - * @access private * @return object */ - function _fetch_object() + protected function _fetch_object() { return sqlsrv_fetch_object($this->result_id); } } - -/* End of file mssql_result.php */ -/* Location: ./system/database/drivers/mssql/mssql_result.php */
\ No newline at end of file +/* End of file sqlsrv_result.php */ +/* Location: ./system/database/drivers/sqlsrv/sqlsrv_result.php */
\ No newline at end of file diff --git a/system/database/drivers/sqlsrv/sqlsrv_utility.php b/system/database/drivers/sqlsrv/sqlsrv_utility.php index e96df96f9..d518cc15a 100644 --- a/system/database/drivers/sqlsrv/sqlsrv_utility.php +++ b/system/database/drivers/sqlsrv/sqlsrv_utility.php @@ -1,13 +1,13 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer * * NOTICE OF LICENSE - * + * * Licensed under the Open Software License version 3.0 - * + * * This source file is subject to the Open Software License (OSL 3.0) that is * bundled with this package in the files license.txt / license.rst. It is * also available through the world wide web at this URL: @@ -21,12 +21,10 @@ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com - * @since Version 1.0 + * @since Version 2.0.3 * @filesource */ -// ------------------------------------------------------------------------ - /** * SQLSRV Utility Class * @@ -36,59 +34,16 @@ */ class CI_DB_sqlsrv_utility extends CI_DB_utility { - /** - * List databases - * - * @access private - * @return bool - */ - function _list_databases() - { - return "EXEC sp_helpdb"; // Can also be: EXEC sp_databases - } - - // -------------------------------------------------------------------- + protected $_list_databases = 'EXEC sp_helpdb'; // Can also be: EXEC sp_databases + protected $_optimize_table = 'ALTER INDEX all ON %s REORGANIZE'; /** - * Optimize table query - * - * Generates a platform-specific query so that a table can be optimized + * SQLSRV Export * - * @access private - * @param string the table name - * @return object - */ - function _optimize_table($table) - { - return FALSE; // Is this supported in MS SQL? - } - - // -------------------------------------------------------------------- - - /** - * Repair table query - * - * Generates a platform-specific query so that a table can be repaired - * - * @access private - * @param string the table name - * @return object - */ - function _repair_table($table) - { - return FALSE; // Is this supported in MS SQL? - } - - // -------------------------------------------------------------------- - - /** - * MSSQL Export - * - * @access private * @param array Preferences - * @return mixed + * @return bool */ - function _backup($params = array()) + protected function _backup($params = array()) { // Currently unsupported return $this->db->display_error('db_unsuported_feature'); @@ -96,5 +51,5 @@ class CI_DB_sqlsrv_utility extends CI_DB_utility { } -/* End of file mssql_utility.php */ -/* Location: ./system/database/drivers/mssql/mssql_utility.php */
\ No newline at end of file +/* End of file sqlsrv_utility.php */ +/* Location: ./system/database/drivers/sqlsrv/sqlsrv_utility.php */
\ No newline at end of file |