summaryrefslogtreecommitdiffstats
path: root/system/database
diff options
context:
space:
mode:
Diffstat (limited to 'system/database')
-rw-r--r--[-rwxr-xr-x]system/database/DB.php47
-rw-r--r--system/database/DB_cache.php10
-rw-r--r--system/database/DB_driver.php293
-rw-r--r--system/database/DB_forge.php76
-rw-r--r--system/database/DB_query_builder.php386
-rw-r--r--system/database/DB_result.php171
-rw-r--r--system/database/DB_utility.php17
-rw-r--r--system/database/drivers/cubrid/cubrid_driver.php52
-rw-r--r--system/database/drivers/cubrid/cubrid_forge.php45
-rw-r--r--system/database/drivers/cubrid/cubrid_result.php10
-rw-r--r--system/database/drivers/cubrid/cubrid_utility.php6
-rw-r--r--system/database/drivers/ibase/ibase_driver.php (renamed from system/database/drivers/interbase/interbase_driver.php)43
-rw-r--r--system/database/drivers/ibase/ibase_forge.php (renamed from system/database/drivers/interbase/interbase_forge.php)96
-rw-r--r--system/database/drivers/ibase/ibase_result.php (renamed from system/database/drivers/interbase/interbase_result.php)135
-rw-r--r--system/database/drivers/ibase/ibase_utility.php (renamed from system/database/drivers/interbase/interbase_utility.php)6
-rw-r--r--system/database/drivers/ibase/index.html (renamed from system/database/drivers/interbase/index.html)0
-rw-r--r--system/database/drivers/mssql/mssql_driver.php169
-rw-r--r--system/database/drivers/mssql/mssql_forge.php57
-rw-r--r--system/database/drivers/mssql/mssql_result.php33
-rw-r--r--system/database/drivers/mssql/mssql_utility.php2
-rw-r--r--system/database/drivers/mysql/mysql_driver.php66
-rw-r--r--system/database/drivers/mysql/mysql_forge.php44
-rw-r--r--system/database/drivers/mysql/mysql_result.php29
-rw-r--r--system/database/drivers/mysql/mysql_utility.php12
-rw-r--r--system/database/drivers/mysqli/mysqli_driver.php69
-rw-r--r--system/database/drivers/mysqli/mysqli_forge.php45
-rw-r--r--system/database/drivers/mysqli/mysqli_result.php10
-rw-r--r--system/database/drivers/mysqli/mysqli_utility.php119
-rw-r--r--system/database/drivers/oci8/oci8_driver.php33
-rw-r--r--system/database/drivers/oci8/oci8_forge.php41
-rw-r--r--system/database/drivers/oci8/oci8_result.php481
-rw-r--r--system/database/drivers/odbc/odbc_driver.php65
-rw-r--r--system/database/drivers/odbc/odbc_forge.php81
-rw-r--r--system/database/drivers/odbc/odbc_result.php174
-rw-r--r--system/database/drivers/pdo/pdo_driver.php345
-rw-r--r--system/database/drivers/pdo/pdo_forge.php82
-rw-r--r--system/database/drivers/pdo/pdo_result.php72
-rw-r--r--system/database/drivers/pdo/subdrivers/index.html10
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_4d_driver.php223
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php189
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php265
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php262
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php262
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_informix_driver.php271
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php217
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_oci_driver.php230
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php268
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php341
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php167
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php299
-rw-r--r--system/database/drivers/postgre/postgre_driver.php60
-rw-r--r--system/database/drivers/postgre/postgre_forge.php56
-rw-r--r--system/database/drivers/postgre/postgre_result.php10
-rw-r--r--system/database/drivers/sqlite/sqlite_driver.php91
-rw-r--r--system/database/drivers/sqlite/sqlite_forge.php99
-rw-r--r--system/database/drivers/sqlite/sqlite_result.php16
-rw-r--r--system/database/drivers/sqlite3/sqlite3_driver.php48
-rw-r--r--system/database/drivers/sqlite3/sqlite3_forge.php54
-rw-r--r--system/database/drivers/sqlite3/sqlite3_result.php462
-rw-r--r--system/database/drivers/sqlsrv/sqlsrv_driver.php97
-rw-r--r--system/database/drivers/sqlsrv/sqlsrv_forge.php61
-rw-r--r--system/database/drivers/sqlsrv/sqlsrv_result.php18
-rw-r--r--system/database/drivers/sqlsrv/sqlsrv_utility.php4
63 files changed, 4660 insertions, 2842 deletions
diff --git a/system/database/DB.php b/system/database/DB.php
index 1fe44c0e5..d751325ce 100755..100644
--- a/system/database/DB.php
+++ b/system/database/DB.php
@@ -29,8 +29,8 @@
* Initialize the database
*
* @category Database
- * @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
* @param string
* @param bool Determines if query builder should be used or not
*/
@@ -47,13 +47,28 @@ function &DB($params = '', $query_builder_override = NULL)
}
include($file_path);
+ //make packages contain database config files
+ foreach(get_instance()->load->get_package_paths() as $path)
+ {
+ if ($path !== APPPATH)
+ {
+ if (file_exists ($file_path = $path.'config/'.ENVIRONMENT.'/database.php'))
+ {
+ include ($file_path);
+ }
+ elseif ( file_exists ($file_path = $path.'config/database.php'))
+ {
+ include ($file_path);
+ }
+ }
+ }
if ( ! isset($db) OR count($db) === 0)
{
show_error('No database connection settings were found in the database config file.');
}
- if ($params != '')
+ if ($params !== '')
{
$active_group = $params;
}
@@ -106,7 +121,7 @@ function &DB($params = '', $query_builder_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.');
}
@@ -128,7 +143,7 @@ function &DB($params = '', $query_builder_override = NULL)
require_once(BASEPATH.'database/DB_driver.php');
- if ( ! isset($query_builder) OR $query_builder == TRUE)
+ if ( ! isset($query_builder) OR $query_builder === TRUE)
{
require_once(BASEPATH.'database/DB_query_builder.php');
if ( ! class_exists('CI_DB'))
@@ -144,7 +159,10 @@ function &DB($params = '', $query_builder_override = NULL)
// 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');
+ if ( ! file_exists($driver_file))
+ {
+ show_error('Invalid DB driver');
+ }
require_once($driver_file);
@@ -152,12 +170,25 @@ function &DB($params = '', $query_builder_override = NULL)
$driver = 'CI_DB_'.$params['dbdriver'].'_driver';
$DB = new $driver($params);
- if ($DB->autoinit == TRUE)
+ // Check for a subdriver
+ if ( ! empty($DB->subdriver))
+ {
+ $driver_file = BASEPATH.'database/drivers/'.$DB->dbdriver.'/subdrivers/'.$DB->dbdriver.'_'.$DB->subdriver.'_driver.php';
+
+ if (file_exists($driver_file))
+ {
+ require_once($driver_file);
+ $driver = 'CI_DB_'.$DB->dbdriver.'_'.$DB->subdriver.'_driver';
+ $DB = new $driver($params);
+ }
+ }
+
+ 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"');
}
diff --git a/system/database/DB_cache.php b/system/database/DB_cache.php
index ff942856b..ba9110382 100644
--- a/system/database/DB_cache.php
+++ b/system/database/DB_cache.php
@@ -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);
}
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index bbb7b7a80..e9efc8914 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -45,7 +45,8 @@ abstract class CI_DB_driver {
public $password;
public $hostname;
public $database;
- public $dbdriver = 'mysql';
+ public $dbdriver = 'mysqli';
+ public $subdriver;
public $dbprefix = '';
public $char_set = 'utf8';
public $dbcollat = 'utf8_general_ci';
@@ -77,6 +78,19 @@ abstract class CI_DB_driver {
protected $_protect_identifiers = TRUE;
protected $_reserved_identifiers = array('*'); // Identifiers that should NOT be escaped
+ /**
+ * 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 ';
+
+ /**
+ * Constructor
+ *
+ * @param array
+ * @return void
+ */
public function __construct($params)
{
if (is_array($params))
@@ -113,7 +127,7 @@ abstract 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
if ( ! $this->conn_id)
@@ -131,7 +145,7 @@ abstract 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)
@@ -295,17 +309,21 @@ abstract class CI_DB_driver {
* @param array An array of binding data
* @return mixed
*/
- public function query($sql, $binds = FALSE, $return_object = TRUE)
+ public function query($sql, $binds = FALSE, $return_object = NULL)
{
- if ($sql == '')
+ if ($sql === '')
{
log_message('error', 'Invalid query: '.$sql);
return ($this->db_debug) ? $this->display_error('db_invalid_query') : FALSE;
}
+ elseif ( ! is_bool($return_object))
+ {
+ $return_object = ! $this->is_write_type($sql);
+ }
// Verify table prefix and replace if necessary
- if ($this->dbprefix != '' && $this->swap_pre != '' && $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);
}
@@ -319,7 +337,7 @@ abstract class CI_DB_driver {
// 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 && stripos($sql, 'SELECT') !== FALSE && $this->_cache_init())
+ if ($this->cache_on === TRUE && $return_object === TRUE && $this->_cache_init())
{
$this->load_rdriver();
if (FALSE !== ($cache = $this->CACHE->read($sql)))
@@ -328,8 +346,8 @@ abstract class CI_DB_driver {
}
}
- // Save the query for debugging
- if ($this->save_queries == TRUE)
+ // Save the query for debugging
+ if ($this->save_queries === TRUE)
{
$this->queries[] = $sql;
}
@@ -340,7 +358,7 @@ abstract class CI_DB_driver {
// 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;
}
@@ -352,7 +370,7 @@ abstract class CI_DB_driver {
$error = $this->error();
// Log errors
- log_message('error', 'Query error: '.$error['message']);
+ log_message('error', 'Query error: '.$error['message'].' - Invalid query: '.$sql);
if ($this->db_debug)
{
@@ -373,7 +391,7 @@ abstract class CI_DB_driver {
$time_end = microtime(TRUE);
$this->benchmark += $time_end - $time_start;
- if ($this->save_queries == TRUE)
+ if ($this->save_queries === TRUE)
{
$this->query_times[] = $time_end - $time_start;
}
@@ -381,13 +399,11 @@ abstract class CI_DB_driver {
// Increment the query counter
$this->query_count++;
- // Was the query a "write" type?
- // If so we'll simply return true
- if ($this->is_write_type($sql) === TRUE)
+ // Will we have a result object instantiated? If not - we'll simply return TRUE
+ if ($return_object !== TRUE)
{
- // If caching is enabled we'll auto-cleanup any
- // existing files related to this particular URI
- if ($this->cache_on == TRUE && $this->cache_autodel == TRUE && $this->_cache_init())
+ // If caching is enabled we'll auto-cleanup any existing files related to this particular URI
+ if ($this->cache_on === TRUE && $this->cache_autodel === TRUE && $this->_cache_init())
{
$this->CACHE->delete();
}
@@ -396,8 +412,6 @@ abstract class CI_DB_driver {
}
// Return TRUE if we don't need to create a result object
- // Currently only the Oracle driver uses this when stored
- // procedures are used
if ($return_object !== TRUE)
{
return TRUE;
@@ -409,7 +423,7 @@ abstract class CI_DB_driver {
// Is query caching enabled? If so, we'll serialize the
// result object and save it to a cache file.
- if ($this->cache_on == TRUE && $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
@@ -596,35 +610,53 @@ abstract class CI_DB_driver {
*/
public function compile_binds($sql, $binds)
{
- if (strpos($sql, $this->bind_marker) === FALSE)
+ if (empty($binds) OR empty($this->bind_marker) OR strpos($sql, $this->bind_marker) === FALSE)
{
return $sql;
}
-
- if ( ! is_array($binds))
+ elseif ( ! is_array($binds))
{
$binds = array($binds);
+ $bind_count = 1;
+ }
+ else
+ {
+ // Make sure we're using numeric keys
+ $binds = array_values($binds);
+ $bind_count = count($binds);
}
- // Get the sql segments around the bind markers
- $segments = explode($this->bind_marker, $sql);
+ // We'll need the marker length later
+ $ml = strlen($this->bind_marker);
- // 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))
+ // Make sure not to replace a chunk inside a string that happens to match the bind marker
+ if ($c = preg_match_all("/'[^']*'/i", $sql, $matches))
{
- $binds = array_slice($binds, 0, count($segments)-1);
+ $c = preg_match_all('/'.preg_quote($this->bind_marker).'/i',
+ str_replace($matches[0],
+ str_replace($this->bind_marker, str_repeat(' ', $ml), $matches[0]),
+ $sql, $c),
+ $matches, PREG_OFFSET_CAPTURE);
+
+ // Bind values' count must match the count of markers in the query
+ if ($bind_count !== $c)
+ {
+ return $sql;
+ }
+ }
+ elseif (($c = preg_match_all('/'.preg_quote($this->bind_marker).'/i', $sql, $matches, PREG_OFFSET_CAPTURE)) !== $bind_count)
+ {
+ return $sql;
}
- // Construct the binded query
- $result = $segments[0];
- $i = 0;
- foreach ($binds as $bind)
+ do
{
- $result .= $this->escape($bind).$segments[++$i];
+ $c--;
+ $sql = substr_replace($sql, $this->escape($binds[$c]), $matches[0][$c][1], $ml);
}
+ while ($c !== 0);
- return $result;
+ return $sql;
}
// --------------------------------------------------------------------
@@ -752,13 +784,13 @@ abstract class CI_DB_driver {
*/
public function count_all($table = '')
{
- if ($table == '')
+ if ($table === '')
{
return 0;
}
$query = $this->query($this->_count_string.$this->escape_identifiers('numrows').' FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE));
- if ($query->num_rows() == 0)
+ if ($query->num_rows() === 0)
{
return 0;
}
@@ -837,7 +869,7 @@ abstract class CI_DB_driver {
// --------------------------------------------------------------------
/**
- * Fetch MySQL Field Names
+ * Fetch Field Names
*
* @param string the table name
* @return array
@@ -850,7 +882,7 @@ abstract class CI_DB_driver {
return $this->data_cache['field_names'][$table];
}
- if ($table == '')
+ if ($table === '')
{
return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
}
@@ -918,7 +950,7 @@ abstract class CI_DB_driver {
*/
public function field_data($table = '')
{
- if ($table == '')
+ if ($table === '')
{
return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
}
@@ -934,34 +966,57 @@ abstract class CI_DB_driver {
*
* This function escapes column and table names
*
- * @param string
- * @return string
+ * @param mixed
+ * @return mixed
*/
public function escape_identifiers($item)
{
- if ($this->_escape_char == '')
+ if ($this->_escape_char === '' OR empty($item))
{
return $item;
}
-
- foreach ($this->_reserved_identifiers as $id)
+ elseif (is_array($item))
{
- if (strpos($item, '.'.$id) !== FALSE)
+ foreach ($item as $key => $value)
{
- $item = str_replace('.', $this->_escape_char.'.', $item);
+ $item[$key] = $this->escape_identifiers($value);
+ }
- // remove duplicates if the user already included the escape
- return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $this->_escape_char.$item);
+ return $item;
+ }
+ // Avoid breaking functions and literal values inside queries
+ elseif (ctype_digit($item) OR $item[0] === "'" OR strpos($item, '(') !== FALSE)
+ {
+ return $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]),
+ $this->_escape_char[0], $this->_escape_char[1]
+ );
+ }
+ else
+ {
+ $preg_ec[0] = $preg_ec[1] = preg_quote($this->_escape_char);
+ $preg_ec[2] = $preg_ec[3] = $this->_escape_char;
}
}
- if (strpos($item, '.') !== FALSE)
+ foreach ($this->_reserved_identifiers as $id)
{
- $item = str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item);
+ if (strpos($item, '.'.$id) !== FALSE)
+ {
+ return preg_replace('/'.$preg_ec[0].'?([^'.$preg_ec[1].'\.]+)'.$preg_ec[1].'?\./i', $preg_ec[2].'$1'.$preg_ec[3].'.', $item);
+ }
}
- // 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 preg_replace('/'.$preg_ec[0].'?([^'.$preg_ec[1].'\.]+)'.$preg_ec[1].'?(\.)?/i', $preg_ec[2].'$1'.$preg_ec[3].'$2', $item);
}
// --------------------------------------------------------------------
@@ -989,6 +1044,23 @@ abstract class 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).')';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Generate an update string
*
* @param string the table upon which the query will be performed
@@ -998,7 +1070,7 @@ abstract class CI_DB_driver {
*/
public function update_string($table, $data, $where)
{
- if ($where == '')
+ if ($where === '')
{
return FALSE;
}
@@ -1018,7 +1090,7 @@ abstract class CI_DB_driver {
$dest = array();
foreach ($where as $key => $val)
{
- $prefix = (count($dest) == 0) ? '' : ' AND ';
+ $prefix = (count($dest) === 0) ? '' : ' AND ';
$key = $this->protect_identifiers($key);
if ($val !== '')
@@ -1041,6 +1113,41 @@ abstract class 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 : '');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Tests whether the string has an SQL operator
*
* @param string
@@ -1048,7 +1155,21 @@ abstract class CI_DB_driver {
*/
protected function _has_operator($str)
{
- return (bool) preg_match('/(\s|<|>|!|=|IS NULL|IS NOT NULL)/i', trim($str));
+ return (bool) preg_match('/(\s|<|>|!|=|IS NULL|IS NOT NULL|BETWEEN)/i', trim($str));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns the SQL string operator
+ *
+ * @param string
+ * @return string
+ */
+ protected function _get_operator($str)
+ {
+ return preg_match('/(=|!|<|>| IS NULL| IS NOT NULL| BETWEEN)/i', $str, $match)
+ ? $match[1] : FALSE;
}
// --------------------------------------------------------------------
@@ -1062,7 +1183,7 @@ abstract class CI_DB_driver {
*/
public function call_function($function)
{
- $driver = ($this->dbdriver == 'postgre') ? 'pg_' : $this->dbdriver.'_';
+ $driver = ($this->dbdriver === 'postgre') ? 'pg_' : $this->dbdriver.'_';
if (FALSE === strpos($driver, $function))
{
@@ -1116,7 +1237,6 @@ abstract class CI_DB_driver {
return $this->cache_on = FALSE;
}
-
// --------------------------------------------------------------------
/**
@@ -1217,7 +1337,7 @@ abstract class CI_DB_driver {
$heading = $LANG->line('db_error_heading');
- if ($native == TRUE)
+ if ($native === TRUE)
{
$message = (array) $error;
}
@@ -1235,7 +1355,7 @@ abstract class CI_DB_driver {
if (isset($call['file']) && strpos($call['file'], BASEPATH.'database') === FALSE)
{
// Found it - use a relative path for safety
- $message[] = 'Filename: '.str_replace(array(BASEPATH, APPPATH), '', $call['file']);
+ $message[] = 'Filename: '.str_replace(array(APPPATH, BASEPATH), '', $call['file']);
$message[] = 'Line Number: '.$call['line'];
break;
}
@@ -1286,34 +1406,43 @@ abstract class CI_DB_driver {
$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);
// 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
- if (strpos($item, ' ') !== FALSE)
+ // Note: strripos() is used in order to support spaces in table names
+ if ($offset = strripos($item, ' AS '))
{
- $alias = strstr($item, ' ');
- $item = substr($item, 0, - strlen($alias));
+ $alias = ($protect_identifiers)
+ ? substr($item, $offset, 4).$this->escape_identifiers(substr($item, $offset + 4))
+ : substr($item, $offset);
+ $item = substr($item, 0, $offset);
}
- else
+ elseif ($offset = strrpos($item, ' '))
{
- $alias = '';
+ $alias = ($protect_identifiers)
+ ? ' '.$this->escape_identifiers(substr($item, $offset + 1))
+ : substr($item, $offset);
+ $item = substr($item, 0, $offset);
}
-
- // 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)
+ else
{
- return $item.$alias;
+ $alias = '';
}
// Break the string apart if it contains periods, then insert the table prefix
@@ -1345,7 +1474,7 @@ abstract class CI_DB_driver {
}
// Is there a table prefix defined in the config file? If not, no need to do anything
- if ($this->dbprefix != '')
+ if ($this->dbprefix !== '')
{
// We now add the table prefix based on some logic.
// Do we have 4 segments (hostname.database.table.column)?
@@ -1369,13 +1498,13 @@ abstract 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 != '' && strpos($parts[$i], $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]);
}
@@ -1398,15 +1527,15 @@ abstract class CI_DB_driver {
}
// Is there a table prefix? If not, no need to insert it
- if ($this->dbprefix != '')
+ if ($this->dbprefix !== '')
{
// Verify table prefix and replace if necessary
- if ($this->swap_pre != '' && strpos($item, $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);
}
// Do we prefix an item with no segments?
- elseif ($prefix_single == TRUE && strpos($item, $this->dbprefix) !== 0)
+ elseif ($prefix_single === TRUE && strpos($item, $this->dbprefix) !== 0)
{
$item = $this->dbprefix.$item;
}
diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php
index a519575f0..91f9d560c 100644
--- a/system/database/DB_forge.php
+++ b/system/database/DB_forge.php
@@ -72,6 +72,11 @@ abstract class CI_DB_forge {
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;
}
@@ -85,7 +90,7 @@ abstract class CI_DB_forge {
*/
public function drop_database($db_name)
{
- if ($db_name == '')
+ if ($db_name === '')
{
show_error('A table name is required for that operation.');
return FALSE;
@@ -99,6 +104,15 @@ abstract class CI_DB_forge {
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;
}
@@ -123,7 +137,7 @@ abstract class CI_DB_forge {
return;
}
- if ($key == '')
+ if ($key === '')
{
show_error('Key information is required for that operation.');
}
@@ -150,7 +164,7 @@ abstract class CI_DB_forge {
*/
public function add_field($field = '')
{
- if ($field == '')
+ if ($field === '')
{
show_error('Field information is required.');
}
@@ -197,7 +211,7 @@ abstract 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.');
}
@@ -209,7 +223,18 @@ abstract 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;
}
// --------------------------------------------------------------------
@@ -222,7 +247,7 @@ abstract class CI_DB_forge {
*/
public function drop_table($table_name)
{
- if ($table_name == '')
+ if ($table_name === '')
{
return ($this->db->db_debug) ? $this->db->display_error('db_table_name_required') : FALSE;
}
@@ -231,7 +256,19 @@ abstract class CI_DB_forge {
return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE;
}
- return $this->db->query(sprintf($this->_drop_table, $this->db->escape_identifiers($this->db->dbprefix.$table_name)));
+ $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;
}
// --------------------------------------------------------------------
@@ -245,7 +282,7 @@ abstract 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;
@@ -255,10 +292,21 @@ abstract class CI_DB_forge {
return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE;
}
- return $this->db->query(sprintf($this->_rename_table,
+ $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))
);
+
+ 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;
}
// --------------------------------------------------------------------
@@ -273,7 +321,7 @@ abstract 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.');
}
@@ -284,7 +332,7 @@ abstract 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.');
}
@@ -312,12 +360,12 @@ abstract 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.');
}
@@ -337,7 +385,7 @@ abstract 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.');
}
diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php
index cee4354e9..479b7f24a 100644
--- a/system/database/DB_query_builder.php
+++ b/system/database/DB_query_builder.php
@@ -53,7 +53,6 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
protected $qb_keys = array();
protected $qb_limit = FALSE;
protected $qb_offset = FALSE;
- protected $qb_order = FALSE;
protected $qb_orderby = array();
protected $qb_set = array();
protected $qb_wherein = array();
@@ -84,6 +83,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* Generates the SELECT portion of the query
*
* @param string
+ * @param mixed
* @return object
*/
public function select($select = '*', $escape = NULL)
@@ -93,11 +93,14 @@ abstract class CI_DB_query_builder 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->qb_select[] = $val;
$this->qb_no_escape[] = $escape;
@@ -194,7 +197,7 @@ abstract class CI_DB_query_builder 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');
}
@@ -206,7 +209,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
show_error('Invalid function type: '.$type);
}
- if ($alias == '')
+ if ($alias === '')
{
$alias = $this->_create_alias_from_table(trim($select));
}
@@ -321,15 +324,16 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* @param string
* @param string the join condition
* @param string the type of join
+ * @param string whether not to try to escape identifiers
* @return object
*/
- public function join($table, $cond, $type = '')
+ public function join($table, $cond, $type = '', $escape = NULL)
{
- 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 = '';
}
@@ -343,14 +347,51 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
// 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))
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
+
+ // Split multiple conditions
+ if ($escape === TRUE && preg_match_all('/\sAND\s|\sOR\s/i', $cond, $m, 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] - $s));
+
+ $newcond .= preg_match("/([\[\]\w\.'-]+)(\s*[^\"\[`'\w]+\s*)(.+)/i", $temp, $match)
+ ? $this->protect_identifiers($match[1]).$match[2].$this->protect_identifiers($match[3])
+ : $temp;
+
+ $newcond .= $m[0][$i][0];
+ }
+
+ $cond = ' ON '.$newcond;
+ }
+ // Split apart the condition and protect the identifiers
+ elseif ($escape === TRUE && preg_match("/([\[\]\w\.'-]+)(\s*[^\"\[`'\w]+\s*)(.+)/i", $cond, $match))
+ {
+ $cond = ' ON '.$this->protect_identifiers($match[1]).$match[2].$this->protect_identifiers($match[3]);
+ }
+ elseif ( ! $this->_has_operator($cond))
+ {
+ $cond = ' USING ('.($escape ? $this->escape_identifiers($cond) : $cond).')';
+ }
+ else
+ {
+ $cond = ' ON '.$cond;
+ }
+
+ // 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->qb_join[] = $join = $type.'JOIN '.$this->protect_identifiers($table, TRUE, NULL, FALSE).' ON '.$cond;
+ $this->qb_join[] = $join = $type.'JOIN '.$table.$cond;
if ($this->qb_caching === TRUE)
{
@@ -371,9 +412,10 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
*
* @param mixed
* @param mixed
+ * @param bool
* @return object
*/
- public function where($key, $value = NULL, $escape = TRUE)
+ public function where($key, $value = NULL, $escape = NULL)
{
return $this->_where($key, $value, 'AND ', $escape);
}
@@ -388,9 +430,10 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
*
* @param mixed
* @param mixed
+ * @param bool
* @return object
*/
- public function or_where($key, $value = NULL, $escape = TRUE)
+ public function or_where($key, $value = NULL, $escape = NULL)
{
return $this->_where($key, $value, 'OR ', $escape);
}
@@ -405,26 +448,31 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* @param mixed
* @param mixed
* @param string
+ * @param mixed
* @return object
*/
protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL)
{
- $type = $this->_group_get_type($type);
-
if ( ! is_array($key))
{
$key = array($key => $value);
}
// If the escape value was not set will will base it on the global setting
- if ( ! is_bool($escape))
- {
- $escape = $this->_protect_identifiers;
- }
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
foreach ($key as $k => $v)
{
- $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) ? '' : $type;
+ $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0)
+ ? $this->_group_get_type('')
+ : $this->_group_get_type($type);
+
+ if ($escape === TRUE)
+ {
+ $k = (($op = $this->_get_operator($k)) !== FALSE)
+ ? $this->escape_identifiers(trim(substr($k, 0, strpos($k, $op)))).' '.strstr($k, $op)
+ : $this->escape_identifiers(trim($k));
+ }
if (is_null($v) && ! $this->_has_operator($k))
{
@@ -436,7 +484,6 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
{
if ($escape === TRUE)
{
- $k = $this->protect_identifiers($k, FALSE, $escape);
$v = ' '.$this->escape($v);
}
@@ -445,10 +492,6 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$k .= ' = ';
}
}
- else
- {
- $k = $this->protect_identifiers($k, FALSE, $escape);
- }
$this->qb_where[] = $prefix.$k.$v;
if ($this->qb_caching === TRUE)
@@ -474,9 +517,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* @param array The values searched on
* @return object
*/
- public function where_in($key = NULL, $values = NULL)
+ public function where_in($key = NULL, $values = NULL, $escape = NULL)
{
- return $this->_where_in($key, $values);
+ return $this->_where_in($key, $values, FALSE, 'AND ', $escape);
}
// --------------------------------------------------------------------
@@ -491,9 +534,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* @param array The values searched on
* @return object
*/
- public function or_where_in($key = NULL, $values = NULL)
+ public function or_where_in($key = NULL, $values = NULL, $escape = NULL)
{
- return $this->_where_in($key, $values, FALSE, 'OR ');
+ return $this->_where_in($key, $values, FALSE, 'OR ', $escape);
}
// --------------------------------------------------------------------
@@ -508,9 +551,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* @param array The values searched on
* @return object
*/
- public function where_not_in($key = NULL, $values = NULL)
+ public function where_not_in($key = NULL, $values = NULL, $escape = NULL)
{
- return $this->_where_in($key, $values, TRUE);
+ return $this->_where_in($key, $values, TRUE, 'AND ', $escape);
}
// --------------------------------------------------------------------
@@ -525,9 +568,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* @param array The values searched on
* @return object
*/
- public function or_where_not_in($key = NULL, $values = NULL)
+ public function or_where_not_in($key = NULL, $values = NULL, $escape = NULL)
{
- return $this->_where_in($key, $values, TRUE, 'OR ');
+ return $this->_where_in($key, $values, TRUE, 'OR ', $escape);
}
// --------------------------------------------------------------------
@@ -543,20 +586,20 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* @param string
* @return object
*/
- protected function _where_in($key = NULL, $values = NULL, $not = FALSE, $type = 'AND ')
+ protected function _where_in($key = NULL, $values = NULL, $not = FALSE, $type = 'AND ', $escape = NULL)
{
if ($key === NULL OR $values === NULL)
{
- return;
+ return $this;
}
- $type = $this->_group_get_type($type);
-
if ( ! is_array($values))
{
$values = array($values);
}
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
+
$not = ($not) ? ' NOT' : '';
foreach ($values as $value)
@@ -564,8 +607,13 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$this->qb_wherein[] = $this->escape($value);
}
- $prefix = (count($this->qb_where) === 0) ? '' : $type;
- $this->qb_where[] = $where_in = $prefix.$this->protect_identifiers($key).$not.' IN ('.implode(', ', $this->qb_wherein).') ';
+ if ($escape === TRUE)
+ {
+ $key = $this->escape_identifiers(trim($key));
+ }
+
+ $prefix = (count($this->qb_where) === 0) ? $this->_group_get_type('') : $this->_group_get_type($type);
+ $this->qb_where[] = $where_in = $prefix.$key.$not.' IN ('.implode(', ', $this->qb_wherein).') ';
if ($this->qb_caching === TRUE)
{
@@ -660,8 +708,6 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
*/
protected function _like($field, $match = '', $type = 'AND ', $side = 'both', $not = '')
{
- $type = $this->_group_get_type($type);
-
if ( ! is_array($field))
{
$field = array($field => $match);
@@ -670,28 +716,28 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
foreach ($field as $k => $v)
{
$k = $this->protect_identifiers($k);
- $prefix = (count($this->qb_like) === 0) ? '' : $type;
+ $prefix = (count($this->qb_like) === 0) ? $this->_group_get_type('') : $this->_group_get_type($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);
}
@@ -829,7 +875,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
{
$val = trim($val);
- if ($val != '')
+ if ($val !== '')
{
$this->qb_groupby[] = $val = $this->protect_identifiers($val);
@@ -853,9 +899,10 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
*
* @param string
* @param string
+ * @param bool
* @return object
*/
- public function having($key, $value = '', $escape = TRUE)
+ public function having($key, $value = '', $escape = NULL)
{
return $this->_having($key, $value, 'AND ', $escape);
}
@@ -869,9 +916,10 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
*
* @param string
* @param string
+ * @param bool
* @return object
*/
- public function or_having($key, $value = '', $escape = TRUE)
+ public function or_having($key, $value = '', $escape = NULL)
{
return $this->_having($key, $value, 'OR ', $escape);
}
@@ -885,30 +933,33 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
*
* @param string
* @param string
+ * @param string
+ * @param bool
* @return object
*/
- protected function _having($key, $value = '', $type = 'AND ', $escape = TRUE)
+ protected function _having($key, $value = '', $type = 'AND ', $escape = NULL)
{
if ( ! is_array($key))
{
$key = array($key => $value);
}
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
+
foreach ($key as $k => $v)
{
$prefix = (count($this->qb_having) === 0) ? '' : $type;
- if ($escape === TRUE)
- {
- $k = $this->protect_identifiers($k);
- }
+ $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 ( ! $this->_has_operator($k))
{
$k .= ' = ';
}
- if ($v != '')
+ if ($v !== '')
{
$v = ' '.$this->escape($v);
}
@@ -934,20 +985,21 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* @param bool enable field name escaping
* @return object
*/
- public function order_by($orderby, $direction = '', $escape = TRUE)
+ public function order_by($orderby, $direction = '', $escape = NULL)
{
if (strtolower($direction) === 'random')
{
$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';
}
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
- if ((strpos($orderby, ',') !== FALSE) && $escape === TRUE)
+ if ($escape === TRUE && strpos($orderby, ',') !== FALSE)
{
$temp = array();
foreach (explode(',', $orderby) as $part)
@@ -955,7 +1007,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$part = trim($part);
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;
@@ -963,12 +1017,11 @@ abstract class CI_DB_query_builder 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->qb_orderby[] = $orderby_statement = $orderby.$direction;
@@ -993,12 +1046,8 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
*/
public function limit($value, $offset = NULL)
{
- $this->qb_limit = (int) $value;
-
- if ( ! is_null($offset))
- {
- $this->qb_offset = (int) $offset;
- }
+ is_null($value) OR $this->qb_limit = (int) $value;
+ empty($offset) OR $this->qb_offset = (int) $offset;
return $this;
}
@@ -1013,21 +1062,40 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
*/
public function offset($offset)
{
- $this->qb_offset = (int) $offset;
+ empty($offset) OR $this->qb_offset = (int) $offset;
return $this;
}
// --------------------------------------------------------------------
/**
- * The "set" function. Allows key/value pairs to be set for inserting or updating
+ * 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;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * The "set" function.
+ *
+ * Allows key/value pairs to be set for inserting or updating
*
* @param mixed
* @param string
* @param bool
* @return object
*/
- public function set($key, $value = '', $escape = TRUE)
+ public function set($key, $value = '', $escape = NULL)
{
$key = $this->_object_to_array($key);
@@ -1036,16 +1104,12 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$key = array($key => $value);
}
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
+
foreach ($key as $k => $v)
{
- if ($escape === FALSE)
- {
- $this->qb_set[$this->protect_identifiers($k)] = $v;
- }
- else
- {
- $this->qb_set[$this->protect_identifiers($k, FALSE, TRUE)] = $this->escape($v);
- }
+ $this->qb_set[$this->protect_identifiers($k, FALSE, $escape)] = ($escape)
+ ? $this->escape($v) : $v;
}
return $this;
@@ -1064,13 +1128,13 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
*/
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)
{
@@ -1093,15 +1157,15 @@ abstract class CI_DB_query_builder 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);
}
@@ -1124,7 +1188,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
*/
public function count_all_results($table = '')
{
- if ($table != '')
+ if ($table !== '')
{
$this->_track_aliases($table);
$this->from($table);
@@ -1154,9 +1218,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* @param string the offset clause
* @return object
*/
- public function get_where($table = '', $where = null, $limit = null, $offset = null)
+ public function get_where($table = '', $where = NULL, $limit = NULL, $offset = NULL)
{
- if ($table != '')
+ if ($table !== '')
{
$this->from($table);
}
@@ -1166,7 +1230,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$this->where($where);
}
- if ( ! is_null($limit))
+ if ( ! empty($limit))
{
$this->limit($limit, $offset);
}
@@ -1204,7 +1268,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
return FALSE;
}
- if ($table == '')
+ if ($table === '')
{
if ( ! isset($this->qb_from[0]))
{
@@ -1251,7 +1315,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* @param bool
* @return object
*/
- public function set_insert_batch($key, $value = '', $escape = TRUE)
+ public function set_insert_batch($key, $value = '', $escape = NULL)
{
$key = $this->_object_to_array_batch($key);
@@ -1260,6 +1324,8 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$key = array($key => $value);
}
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
+
$keys = array_keys($this->_object_to_array(current($key)));
sort($keys);
@@ -1275,11 +1341,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
ksort($row); // puts $row in the same order as our keys
- if ($escape === FALSE)
- {
- $this->qb_set[] = '('.implode(',', $row).')';
- }
- else
+ if ($escape !== FALSE)
{
$clean = array();
foreach ($row as $value)
@@ -1287,13 +1349,15 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$clean[] = $this->escape($value);
}
- $this->qb_set[] = '('.implode(',', $clean).')';
+ $row = $clean;
}
+
+ $this->qb_set[] = '('.implode(',', $row).')';
}
foreach ($keys as $k)
{
- $this->qb_keys[] = $this->protect_identifiers($k);
+ $this->qb_keys[] = $this->protect_identifiers($k, FALSE, $escape);
}
return $this;
@@ -1371,23 +1435,6 @@ abstract class CI_DB_query_builder 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
@@ -1404,7 +1451,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE;
}
- if ($table != '')
+ if ($table !== '')
{
$this->qb_from[0] = $table;
}
@@ -1439,7 +1486,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE;
}
- if ($table == '')
+ if ($table === '')
{
if ( ! isset($this->qb_from[0]))
{
@@ -1475,6 +1522,24 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
// --------------------------------------------------------------------
/**
+ * 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
@@ -1530,12 +1595,12 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
return FALSE;
}
- if ($where != NULL)
+ if ($where !== NULL)
{
$this->where($where);
}
- if ($limit != NULL)
+ if ( ! empty($limit))
{
$this->limit($limit);
}
@@ -1549,41 +1614,6 @@ abstract class CI_DB_query_builder 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
@@ -1595,12 +1625,12 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
*/
protected function _validate_update($table = '')
{
- if (count($this->qb_set) == 0)
+ if (count($this->qb_set) === 0)
{
return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE;
}
- if ($table != '')
+ if ($table !== '')
{
$this->qb_from[0] = $table;
}
@@ -1644,7 +1674,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE;
}
- if ($table == '')
+ if ($table === '')
{
if ( ! isset($this->qb_from[0]))
{
@@ -1674,7 +1704,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* @param bool
* @return object
*/
- public function set_update_batch($key, $index = '', $escape = TRUE)
+ public function set_update_batch($key, $index = '', $escape = NULL)
{
$key = $this->_object_to_array_batch($key);
@@ -1683,18 +1713,20 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
// @todo error
}
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
+
foreach ($key as $k => $v)
{
$index_set = FALSE;
$clean = array();
foreach ($v as $k2 => $v2)
{
- if ($k2 == $index)
+ if ($k2 === $index)
{
$index_set = TRUE;
}
- $clean[$this->protect_identifiers($k2)] = ($escape === FALSE) ? $v2 : $this->escape($v2);
+ $clean[$this->protect_identifiers($k2, FALSE, $escape)] = ($escape === FALSE) ? $v2 : $this->escape($v2);
}
if ($index_set === FALSE)
@@ -1720,7 +1752,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
*/
public function empty_table($table = '')
{
- if ($table == '')
+ if ($table === '')
{
if ( ! isset($this->qb_from[0]))
{
@@ -1753,7 +1785,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
*/
public function truncate($table = '')
{
- if ($table == '')
+ if ($table === '')
{
if ( ! isset($this->qb_from[0]))
{
@@ -1827,7 +1859,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
// Combine any cached components with the current statements
$this->_merge_cache();
- if ($table == '')
+ if ($table === '')
{
if ( ! isset($this->qb_from[0]))
{
@@ -1851,12 +1883,12 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$table = $this->protect_identifiers($table, TRUE, NULL, FALSE);
}
- if ($where != '')
+ if ($where !== '')
{
$this->where($where);
}
- if ($limit != NULL)
+ if ( ! empty($limit))
{
$this->limit($limit);
}
@@ -1897,7 +1929,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
return 'DELETE FROM '.$table
.(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : '')
- .($limit ? ' LIMIT '.$limit : '');
+ .($limit ? ' LIMIT '.(int) $limit : '');
}
// --------------------------------------------------------------------
@@ -1912,7 +1944,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
*/
public function dbprefix($table = '')
{
- if ($table == '')
+ if ($table === '')
{
$this->display_error('db_table_name_required');
}
@@ -1967,7 +1999,7 @@ abstract class CI_DB_query_builder 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, ' '));
@@ -2070,10 +2102,6 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
if (count($this->qb_orderby) > 0)
{
$sql .= "\nORDER BY ".implode(', ', $this->qb_orderby);
- if ($this->qb_order !== FALSE)
- {
- $sql .= ($this->qb_order == 'desc') ? ' DESC' : ' ASC';
- }
}
// Write the "LIMIT" portion of the query
@@ -2106,7 +2134,7 @@ abstract class CI_DB_query_builder 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;
}
@@ -2303,8 +2331,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
'qb_no_escape' => array(),
'qb_distinct' => FALSE,
'qb_limit' => FALSE,
- 'qb_offset' => FALSE,
- 'qb_order' => FALSE
+ 'qb_offset' => FALSE
)
);
}
@@ -2327,8 +2354,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
'qb_like' => array(),
'qb_orderby' => array(),
'qb_keys' => array(),
- 'qb_limit' => FALSE,
- 'qb_order' => FALSE
+ 'qb_limit' => FALSE
)
);
}
diff --git a/system/database/DB_result.php b/system/database/DB_result.php
index 334e08c72..d44df6c02 100644
--- a/system/database/DB_result.php
+++ b/system/database/DB_result.php
@@ -38,32 +38,74 @@
*/
class CI_DB_result {
- public $conn_id = NULL;
- public $result_id = NULL;
+ public $conn_id;
+ public $result_id;
public $result_array = array();
public $result_object = array();
public $custom_result_object = array();
public $current_row = 0;
- public $num_rows = 0;
- public $row_data = NULL;
+ public $num_rows;
+ public $row_data;
+ /**
+ * Constructor
+ *
+ * @param object
+ * @return void
+ */
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.
+ * Number of rows in the result set
*
- * @param string can be "object" or "array"
- * @return object
+ * @return int
+ */
+ public function num_rows()
+ {
+ if (is_int($this->num_rows))
+ {
+ return $this->num_rows;
+ }
+ elseif (count($this->result_array) > 0)
+ {
+ return $this->num_rows = count($this->result_array);
+ }
+ elseif (count($this->result_object) > 0)
+ {
+ return $this->num_rows = count($this->result_object);
+ }
+
+ return $this->num_rows = count($this->result_array());
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Query result. Acts as a wrapper function for the following functions.
+ *
+ * @param string 'object', 'array' or a custom class name
+ * @return array
*/
public function result($type = 'object')
{
- if ($type === 'array') return $this->result_array();
- elseif ($type === 'object') return $this->result_object();
- else return $this->custom_result_object($type);
+ if ($type === 'array')
+ {
+ return $this->result_array();
+ }
+ elseif ($type === 'object')
+ {
+ return $this->result_object();
+ }
+ else
+ {
+ return $this->custom_result_object($type);
+ }
}
// --------------------------------------------------------------------
@@ -76,33 +118,50 @@ class CI_DB_result {
*/
public function custom_result_object($class_name)
{
- if (array_key_exists($class_name, $this->custom_result_object))
+ if (isset($this->custom_result_object[$class_name]))
{
return $this->custom_result_object[$class_name];
}
-
- if ($this->result_id === FALSE OR $this->num_rows() == 0)
+ elseif ( ! $this->result_id OR $this->num_rows === 0)
{
return array();
}
- // add the data to the object
- $this->_data_seek(0);
- $result_object = array();
+ // Don't fetch the result set again if we already have it
+ $_data = NULL;
+ if (($c = count($this->result_array)) > 0)
+ {
+ $_data = 'result_array';
+ }
+ elseif (($c = count($this->result_object)) > 0)
+ {
+ $_data = 'result_object';
+ }
- while ($row = $this->_fetch_object())
+ if ($_data !== NULL)
{
- $object = new $class_name();
- foreach ($row as $key => $value)
+ for ($i = 0; $i < $c; $i++)
{
- $object->$key = $value;
+ $this->custom_result_object[$class_name][$i] = new $class_name();
+
+ foreach ($this->{$_data}[$i] as $key => $value)
+ {
+ $this->custom_result_object[$class_name][$i]->$key = $value;
+ }
}
- $result_object[] = $object;
+ return $this->custom_result_object[$class_name];
}
- // return the array
- return $this->custom_result_object[$class_name] = $result_object;
+ $this->_data_seek(0);
+ $this->custom_result_object[$class_name] = array();
+
+ while ($row = $this->_fetch_object($class_name))
+ {
+ $this->custom_result_object[$class_name][] = $row;
+ }
+
+ return $this->custom_result_object[$class_name];
}
// --------------------------------------------------------------------
@@ -119,14 +178,24 @@ class CI_DB_result {
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 OR $this->num_rows() == 0)
+ // In the event that query caching is on, the result_id variable
+ // will not be a valid resource so we'll simply return an empty
+ // array.
+ if ( ! $this->result_id OR $this->num_rows === 0)
{
return array();
}
+ 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;
+ }
+
$this->_data_seek(0);
while ($row = $this->_fetch_object())
{
@@ -139,7 +208,7 @@ class CI_DB_result {
// --------------------------------------------------------------------
/**
- * Query result. "array" version.
+ * Query result. "array" version.
*
* @return array
*/
@@ -150,14 +219,24 @@ class CI_DB_result {
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 OR $this->num_rows() == 0)
+ // In the event that query caching is on, the result_id variable
+ // will not be a valid resource so we'll simply return an empty
+ // array.
+ if ( ! $this->result_id OR $this->num_rows === 0)
{
return array();
}
+ 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;
+ }
+
$this->_data_seek(0);
while ($row = $this->_fetch_assoc())
{
@@ -224,7 +303,7 @@ class CI_DB_result {
return;
}
- if ($key != '' && ! is_null($value))
+ if ($key !== '' && ! is_null($value))
{
$this->row_data[$key] = $value;
}
@@ -239,18 +318,19 @@ class CI_DB_result {
*/
public function custom_row_object($n, $type)
{
- $result = $this->custom_result_object($type);
- if (count($result) === 0)
+ isset($this->custom_result_object[$type]) OR $this->custom_result_object($type);
+
+ if (count($this->custom_result_object[$type]) === 0)
{
return NULL;
}
- if ($n != $this->current_row && isset($result[$n]))
+ if ($n !== $this->current_row && isset($this->custom_result_object[$type][$n]))
{
$this->current_row = $n;
}
- return $result[$this->current_row];
+ return $this->custom_result_object[$type][$this->current_row];
}
// --------------------------------------------------------------------
@@ -268,7 +348,7 @@ class CI_DB_result {
return NULL;
}
- if ($n != $this->current_row && isset($result[$n]))
+ if ($n !== $this->current_row && isset($result[$n]))
{
$this->current_row = $n;
}
@@ -291,7 +371,7 @@ class CI_DB_result {
return NULL;
}
- if ($n != $this->current_row && isset($result[$n]))
+ if ($n !== $this->current_row && isset($result[$n]))
{
$this->current_row = $n;
}
@@ -375,11 +455,21 @@ class CI_DB_result {
/**
* Returns an unbuffered row and move pointer to next row
*
+ * @param string 'array', 'object' or a custom class name
* @return mixed either a result object or array
*/
public function unbuffered_row($type = 'object')
{
- return ($type !== 'array') ? $this->_fetch_object() : $this->_fetch_assoc();
+ if ($type === 'array')
+ {
+ return $this->_fetch_assoc();
+ }
+ elseif ($type === 'object')
+ {
+ return $this->_fetch_object();
+ }
+
+ return $this->_fetch_object($type);
}
// --------------------------------------------------------------------
@@ -393,7 +483,6 @@ class CI_DB_result {
* operational due to the unavailability of the database resource IDs with
* cached results.
*/
- public function num_rows() { return $this->num_rows; }
public function num_fields() { return 0; }
public function list_fields() { return array(); }
public function field_data() { return array(); }
diff --git a/system/database/DB_utility.php b/system/database/DB_utility.php
index cb97ff448..6a3b40779 100644
--- a/system/database/DB_utility.php
+++ b/system/database/DB_utility.php
@@ -35,7 +35,6 @@
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
@@ -60,29 +59,29 @@ abstract class CI_DB_utility extends CI_DB_forge {
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->data_cache['db_names'];
+ return $this->db->data_cache['db_names'];
}
elseif ($this->_list_databases === FALSE)
{
return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE;
}
- $this->data_cache['db_names'] = array();
+ $this->db->data_cache['db_names'] = array();
$query = $this->db->query($this->_list_databases);
if ($query === FALSE)
{
- return $this->data_cache['db_names'];
+ return $this->db->data_cache['db_names'];
}
for ($i = 0, $c = count($query); $i < $c; $i++)
{
- $this->data_cache['db_names'] = current($query[$i]);
+ $this->db->data_cache['db_names'] = current($query[$i]);
}
- return $this->data_cache['db_names'];
+ return $this->db->data_cache['db_names'];
}
// --------------------------------------------------------------------
@@ -343,7 +342,7 @@ abstract 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 @@ abstract 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);
}
diff --git a/system/database/drivers/cubrid/cubrid_driver.php b/system/database/drivers/cubrid/cubrid_driver.php
index 817dfdc98..a3d0287f5 100644
--- a/system/database/drivers/cubrid/cubrid_driver.php
+++ b/system/database/drivers/cubrid/cubrid_driver.php
@@ -49,12 +49,6 @@ class CI_DB_cubrid_driver extends CI_DB {
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.
- */
- protected $_count_string = 'SELECT COUNT(*) AS ';
protected $_random_keyword = ' RAND()'; // database specific random keyword
// CUBRID-specific properties
@@ -74,7 +68,7 @@ class CI_DB_cubrid_driver extends CI_DB {
else
{
// If no port is defined by the user, use the default value
- $this->port == '' OR $this->port = 33000;
+ empty($this->port) OR $this->port = 33000;
}
}
@@ -340,7 +334,7 @@ class CI_DB_cubrid_driver extends CI_DB {
{
$sql = 'SHOW TABLES';
- if ($prefix_limit !== FALSE && $this->dbprefix != '')
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
{
return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'";
}
@@ -396,27 +390,6 @@ class CI_DB_cubrid_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This 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)
- {
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return '('.implode(', ', $tables).')';
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update_Batch statement
*
* Generates a platform-specific batch update string from the supplied data
@@ -435,7 +408,7 @@ class CI_DB_cubrid_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];
}
@@ -451,30 +424,13 @@ class CI_DB_cubrid_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).')';
}
// --------------------------------------------------------------------
/**
- * 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 == 0 ? '' : $offset.', ').$limit;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Close DB Connection
*
* @return void
diff --git a/system/database/drivers/cubrid/cubrid_forge.php b/system/database/drivers/cubrid/cubrid_forge.php
index 4e66f81e3..d328aa241 100644
--- a/system/database/drivers/cubrid/cubrid_forge.php
+++ b/system/database/drivers/cubrid/cubrid_forge.php
@@ -60,8 +60,10 @@ class CI_DB_cubrid_forge extends CI_DB_forge {
else
{
$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 $sql .= ' '.$this->db->escape_identifiers($attributes['NAME']).' ';
if ( ! empty($attributes['TYPE']))
{
@@ -69,7 +71,7 @@ class CI_DB_cubrid_forge extends CI_DB_forge {
if ( ! empty($attributes['CONSTRAINT']))
{
- switch ($attributes['TYPE'])
+ switch (strtolower($attributes['TYPE']))
{
case 'decimal':
case 'float':
@@ -98,10 +100,23 @@ class CI_DB_cubrid_forge extends CI_DB_forge {
}
*/
- $sql .= (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' : '')
- .(( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE) ? ' UNIQUE' : '');
+ 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';
+ }
+
+ if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)
+ {
+ $sql .= ' UNIQUE';
+ }
}
// don't add a comma on the end of the last field
@@ -142,8 +157,8 @@ class CI_DB_cubrid_forge extends CI_DB_forge {
// If there is a PK defined
if (count($primary_keys) > 0)
{
- $key_name = $this->db->protect_identifiers('pk_'.$table.'_'.implode('_', $primary_keys));
- $sql .= ",\n\tCONSTRAINT ".$key_name.' PRIMARY KEY('.implode(', ', $this->db->protect_identifiers($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)
@@ -152,12 +167,12 @@ class CI_DB_cubrid_forge extends CI_DB_forge {
{
if (is_array($key))
{
- $key_name = $this->db->protect_identifiers('idx_'.$table.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('idx_'.$table.$key);
+ $key_name = $this->db->escape_identifiers('idx_'.$table.$key);
$key = array($key_name);
}
@@ -184,16 +199,16 @@ class CI_DB_cubrid_forge extends CI_DB_forge {
*/
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) : '');
+ .($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 3eb9f7e3d..4a06a2d39 100644
--- a/system/database/drivers/cubrid/cubrid_result.php
+++ b/system/database/drivers/cubrid/cubrid_result.php
@@ -33,6 +33,7 @@
* @category Database
* @author Esen Sagynov
* @link http://codeigniter.com/user_guide/database/
+ * @since 2.1
*/
class CI_DB_cubrid_result extends CI_DB_result {
@@ -43,7 +44,9 @@ class CI_DB_cubrid_result extends CI_DB_result {
*/
public function num_rows()
{
- return @cubrid_num_rows($this->result_id);
+ return is_int($this->num_rows)
+ ? $this->num_rows
+ : $this->num_rows = @cubrid_num_rows($this->result_id);
}
// --------------------------------------------------------------------
@@ -157,11 +160,12 @@ class CI_DB_cubrid_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string
* @return object
*/
- protected function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- return cubrid_fetch_object($this->result_id);
+ return cubrid_fetch_object($this->result_id, $class_name);
}
}
diff --git a/system/database/drivers/cubrid/cubrid_utility.php b/system/database/drivers/cubrid/cubrid_utility.php
index c8cee99b6..ea8feb4e2 100644
--- a/system/database/drivers/cubrid/cubrid_utility.php
+++ b/system/database/drivers/cubrid/cubrid_utility.php
@@ -41,12 +41,12 @@ class CI_DB_cubrid_utility extends CI_DB_utility {
*/
public function list_databases()
{
- if (isset($this->data_cache['db_names']))
+ if (isset($this->db->data_cache['db_names']))
{
- return $this->data_cache['db_names'];
+ return $this->db->data_cache['db_names'];
}
- return $this->data_cache['db_names'] = cubrid_list_dbs($this->db->conn_id);
+ return $this->db->data_cache['db_names'] = cubrid_list_dbs($this->db->conn_id);
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/interbase/interbase_driver.php b/system/database/drivers/ibase/ibase_driver.php
index 49d3cda87..c9027670d 100644
--- a/system/database/drivers/interbase/interbase_driver.php
+++ b/system/database/drivers/ibase/ibase_driver.php
@@ -38,9 +38,9 @@
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
*/
-class CI_DB_interbase_driver extends CI_DB {
+class CI_DB_ibase_driver extends CI_DB {
- public $dbdriver = 'interbase';
+ public $dbdriver = 'ibase';
// The character used to escape with
protected $_escape_char = '"';
@@ -49,13 +49,7 @@ class CI_DB_interbase_driver extends CI_DB {
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
+ protected $_random_keyword = ' Random()'; // database specific random keyword
// Keeps track of the resource for the current transaction
protected $trans;
@@ -235,7 +229,7 @@ class CI_DB_interbase_driver extends CI_DB {
* @param int $inc_by
* @return int
*/
- public function insert_id($generator_name, $inc_by=0)
+ 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);
@@ -255,9 +249,10 @@ class CI_DB_interbase_driver extends CI_DB {
{
$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 != '')
+ 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.' AND "RDB$RELATION_NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
}
return $sql;
@@ -275,7 +270,7 @@ class CI_DB_interbase_driver extends CI_DB {
*/
protected function _list_columns($table = '')
{
- return 'SELECT "RDB$FIELD_NAME" FROM "RDB$RELATION_FIELDS" WHERE "RDB$RELATION_NAME" = \''.$this->escape_str($table)."'";
+ return 'SELECT "RDB$FIELD_NAME" FROM "RDB$RELATION_FIELDS" WHERE "RDB$RELATION_NAME" = '.$this->escape($table);
}
// --------------------------------------------------------------------
@@ -290,10 +285,7 @@ class CI_DB_interbase_driver extends CI_DB {
*/
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;
+ return $this->_limit('SELECT * FROM '.$this->protect_identifiers($table), 1, NULL);
}
// --------------------------------------------------------------------
@@ -324,13 +316,7 @@ class CI_DB_interbase_driver extends CI_DB {
*/
protected function _from_tables($tables)
{
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- //Interbase/Firebird doesn't like grouped tables
- return implode(', ', $tables);
+ return is_array($tables) ? implode(', ', $tables) : $tables;
}
// --------------------------------------------------------------------
@@ -367,7 +353,6 @@ class CI_DB_interbase_driver extends CI_DB {
.(count($orderby) > 0 ? ' ORDER BY '.implode(', ', $orderby) : '');
}
-
// --------------------------------------------------------------------
/**
@@ -427,12 +412,12 @@ class CI_DB_interbase_driver extends CI_DB {
if (stripos($this->version(), 'firebird') !== FALSE)
{
$select = 'FIRST '. (int) $limit
- .($offset > 0 ? ' SKIP '. (int) $offset : '');
+ .($offset ? ' SKIP '. (int) $offset : '');
}
else
{
$select = 'ROWS '
- .($offset > 0 ? (int) $offset.' TO '.($limit + $offset) : (int) $limit);
+ .($offset ? (int) $offset.' TO '.($limit + $offset) : (int) $limit);
}
return preg_replace('`SELECT`i', 'SELECT '.$select, $sql);
@@ -452,5 +437,5 @@ class CI_DB_interbase_driver extends CI_DB {
}
-/* End of file interbase_driver.php */
-/* Location: ./system/database/drivers/interbase/interbase_driver.php */ \ No newline at end of file
+/* End of file ibase_driver.php */
+/* Location: ./system/database/drivers/ibase/ibase_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/interbase/interbase_forge.php b/system/database/drivers/ibase/ibase_forge.php
index c850656a8..da75eb9c3 100644
--- a/system/database/drivers/interbase/interbase_forge.php
+++ b/system/database/drivers/ibase/ibase_forge.php
@@ -32,7 +32,7 @@
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
*/
-class CI_DB_interbase_forge extends CI_DB_forge {
+class CI_DB_ibase_forge extends CI_DB_forge {
protected $_drop_table = 'DROP TABLE %s';
@@ -67,6 +67,14 @@ class CI_DB_interbase_forge extends CI_DB_forge {
{
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;
}
@@ -87,7 +95,7 @@ class CI_DB_interbase_forge extends CI_DB_forge {
{
$sql = 'CREATE TABLE ';
- $sql .= $this->db->protect_identifiers($table)."(";
+ $sql .= $this->db->escape_identifiers($table).'(';
$current_field_count = 0;
foreach ($fields as $field => $attributes)
@@ -97,41 +105,30 @@ class CI_DB_interbase_forge extends CI_DB_forge {
// 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';
}
@@ -146,30 +143,23 @@ class CI_DB_interbase_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) . ")";
+ $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)
{
- 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;
+ return $sql."\n)";
}
// --------------------------------------------------------------------
@@ -191,34 +181,14 @@ class CI_DB_interbase_forge extends CI_DB_forge {
*/
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 .= " {$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.'"' : '')
+ .($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
+/* End of file ibase_forge.php */
+/* Location: ./system/database/drivers/ibase/ibase_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/interbase/interbase_result.php b/system/database/drivers/ibase/ibase_result.php
index 5ddb6fa47..95e55710b 100644
--- a/system/database/drivers/interbase/interbase_result.php
+++ b/system/database/drivers/ibase/ibase_result.php
@@ -21,7 +21,7 @@
* @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
+ * @since Version 1.0
* @filesource
*/
@@ -33,30 +33,9 @@
* @category Database
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
+ * @since 3.0
*/
-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;
- }
-
- // --------------------------------------------------------------------
+class CI_DB_ibase_result extends CI_DB_result {
/**
* Number of fields in the result set
@@ -139,13 +118,7 @@ class CI_DB_interbase_result extends CI_DB_result {
*/
protected function _fetch_assoc()
{
- if (($row = @ibase_fetch_assoc($this->result_id, IBASE_FETCH_BLOBS)) !== FALSE)
- {
- //Increment row count
- $this->num_rows++;
- }
-
- return $row;
+ return @ibase_fetch_assoc($this->result_id, IBASE_FETCH_BLOBS);
}
// --------------------------------------------------------------------
@@ -155,106 +128,28 @@ class CI_DB_interbase_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string
* @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()
+ protected function _fetch_object($class_name = 'stdClass')
{
- 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;
- }
+ $row = @ibase_fetch_object($this->result_id, IBASE_FETCH_BLOBS);
- // 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)
+ if ($class_name === 'stdClass' OR ! $row)
{
- return array();
+ return $row;
}
- $this->num_rows = 0;
- while ($row = $this->_fetch_assoc())
+ $class_name = new $class_name();
+ foreach ($row as $key => $value)
{
- $this->result_array[] = $row;
+ $class_name->$key = $value;
}
- return $this->result_array;
+ return $class_name;
}
}
-/* End of file interbase_result.php */
-/* Location: ./system/database/drivers/interbase/interbase_result.php */ \ No newline at end of file
+/* End of file ibase_result.php */
+/* Location: ./system/database/drivers/ibase/ibase_result.php */ \ No newline at end of file
diff --git a/system/database/drivers/interbase/interbase_utility.php b/system/database/drivers/ibase/ibase_utility.php
index 164211836..d0e84a7b2 100644
--- a/system/database/drivers/interbase/interbase_utility.php
+++ b/system/database/drivers/ibase/ibase_utility.php
@@ -32,7 +32,7 @@
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
*/
-class CI_DB_interbase_utility extends CI_DB_utility {
+class CI_DB_ibase_utility extends CI_DB_utility {
protected $_list_databases = FALSE;
@@ -58,5 +58,5 @@ class CI_DB_interbase_utility extends CI_DB_utility {
}
-/* End of file interbase_utility.php */
-/* Location: ./system/database/drivers/interbase/interbase_utility.php */ \ No newline at end of file
+/* End of file ibase_utility.php */
+/* Location: ./system/database/drivers/ibase/ibase_utility.php */ \ No newline at end of file
diff --git a/system/database/drivers/interbase/index.html b/system/database/drivers/ibase/index.html
index c942a79ce..c942a79ce 100644
--- a/system/database/drivers/interbase/index.html
+++ b/system/database/drivers/ibase/index.html
diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php
index 342ff2647..1714704a8 100644
--- a/system/database/drivers/mssql/mssql_driver.php
+++ b/system/database/drivers/mssql/mssql_driver.php
@@ -43,33 +43,61 @@ class CI_DB_mssql_driver extends CI_DB {
public $dbdriver = 'mssql';
// The character used for escaping
- protected $_escape_char = '';
+ 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() methods.
- */
- protected $_count_string = 'SELECT COUNT(*) AS ';
protected $_random_keyword = ' NEWID()';
+ // MSSQL-specific properties
+ protected $_quoted_identifier = TRUE;
+
+ /*
+ * Constructor
+ *
+ * Appends the port number to the hostname, if needed.
+ *
+ * @param array
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if ( ! empty($this->port))
+ {
+ $this->hostname .= (DIRECTORY_SEPARATOR === '\\' ? ',' : ':').$this->port;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
/**
* Non-persistent database connection
*
+ * @param bool
* @return resource
*/
- public function db_connect()
+ public function db_connect($persistent = FALSE)
{
- if ($this->port != '')
+ $this->conn_id = ($persistent)
+ ? @mssql_pconnect($this->hostname, $this->username, $this->password)
+ : @mssql_connect($this->hostname, $this->username, $this->password);
+
+ if ( ! $this->conn_id)
{
- $this->hostname .= ','.$this->port;
+ return FALSE;
}
- return @mssql_connect($this->hostname, $this->username, $this->password);
+ // 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 $this->conn_id;
}
// --------------------------------------------------------------------
@@ -81,12 +109,7 @@ class CI_DB_mssql_driver extends CI_DB {
*/
public function db_pconnect()
{
- if ($this->port != '')
- {
- $this->hostname .= ','.$this->port;
- }
-
- return @mssql_pconnect($this->hostname, $this->username, $this->password);
+ return $this->db_connect(TRUE);
}
// --------------------------------------------------------------------
@@ -106,7 +129,7 @@ class CI_DB_mssql_driver extends CI_DB {
// Note: The brackets are required in the event that the DB name
// contains reserved characters
- if (@mssql_select_db('['.$database.']', $this->conn_id))
+ if (@mssql_select_db($this->escape_identifiers($database), $this->conn_id))
{
$this->database = $database;
return TRUE;
@@ -121,7 +144,7 @@ class CI_DB_mssql_driver extends CI_DB {
* Execute the query
*
* @param string an SQL query
- * @return resource
+ * @return mixed resource if rows are returned, bool otherwise
*/
protected function _execute($sql)
{
@@ -137,13 +160,8 @@ class CI_DB_mssql_driver extends CI_DB {
*/
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;
}
@@ -151,10 +169,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');
}
// --------------------------------------------------------------------
@@ -166,19 +183,13 @@ class CI_DB_mssql_driver extends CI_DB {
*/
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');
}
// --------------------------------------------------------------------
@@ -190,19 +201,13 @@ class CI_DB_mssql_driver extends CI_DB {
*/
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');
}
// --------------------------------------------------------------------
@@ -232,7 +237,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
@@ -265,28 +270,13 @@ class CI_DB_mssql_driver extends CI_DB {
*/
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 = version_compare($this->version(), '8', '>=')
+ ? 'SELECT SCOPE_IDENTITY() AS last_id'
+ : 'SELECT @@IDENTITY AS last_id';
- /**
- * 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.
+ $query = $this->query($query);
+ $query = $query->row();
+ return $query->last_id;
}
// --------------------------------------------------------------------
@@ -313,16 +303,17 @@ class CI_DB_mssql_driver extends CI_DB {
*/
protected function _list_tables($prefix_limit = FALSE)
{
- $sql = "SELECT name FROM sysobjects WHERE type = 'U' ORDER BY name";
+ $sql = 'SELECT '.$this->escape_identifiers('name')
+ .' FROM '.$this->escape_identifiers('sysobjects')
+ .' WHERE '.$this->escape_identifiers('type')." = 'U'";
- // 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
+ $sql .= ' AND '.$this->escape_identifiers('name')." LIKE '".$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
}
- return $sql;
+ return $sql.' ORDER BY '.$this->escape_identifiers('name');
}
// --------------------------------------------------------------------
@@ -352,7 +343,7 @@ class CI_DB_mssql_driver extends CI_DB {
*/
protected function _field_data($table)
{
- return "SELECT TOP 1 * FROM ".$table;
+ return 'SELECT TOP 1 * FROM '.$this->protect_identifiers($table);
}
// --------------------------------------------------------------------
@@ -385,12 +376,7 @@ class CI_DB_mssql_driver extends CI_DB {
*/
protected function _from_tables($tables)
{
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return implode(', ', $tables);
+ return is_array($tables) ? implode(', ', $tables) : $tables;
}
// --------------------------------------------------------------------
@@ -484,9 +470,30 @@ class CI_DB_mssql_driver extends CI_DB {
*/
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 '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 '.$i.' ', $sql);
+ return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql);
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/mssql/mssql_forge.php b/system/database/drivers/mssql/mssql_forge.php
index bbf2d9685..3a3528f7b 100644
--- a/system/database/drivers/mssql/mssql_forge.php
+++ b/system/database/drivers/mssql/mssql_forge.php
@@ -70,31 +70,25 @@ class CI_DB_mssql_forge extends CI_DB_forge {
$sql .= "\n\t".$this->db->escape_identifiers($field).' '.$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';
}
@@ -109,22 +103,16 @@ 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).')';
}
@@ -152,29 +140,18 @@ class CI_DB_mssql_forge extends CI_DB_forge {
*/
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."'";
- }
-
- $sql .= ($null === NULL) ? ' NULL' : ' NOT NULL';
-
- if ($after_field != '')
- {
- return $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) : '');
}
}
diff --git a/system/database/drivers/mssql/mssql_result.php b/system/database/drivers/mssql/mssql_result.php
index 4cc87f4cf..aeede3f4b 100644
--- a/system/database/drivers/mssql/mssql_result.php
+++ b/system/database/drivers/mssql/mssql_result.php
@@ -26,13 +26,14 @@
*/
/**
- * MS SQL Result Class
+ * MSSQL 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/
+ * @since 1.3
*/
class CI_DB_mssql_result extends CI_DB_result {
@@ -43,7 +44,9 @@ class CI_DB_mssql_result extends CI_DB_result {
*/
public function num_rows()
{
- return @mssql_num_rows($this->result_id);
+ return is_int($this->num_rows)
+ ? $this->num_rows
+ : $this->num_rows = @mssql_num_rows($this->result_id);
}
// --------------------------------------------------------------------
@@ -92,12 +95,12 @@ class CI_DB_mssql_result extends CI_DB_result {
$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;
}
@@ -158,11 +161,25 @@ class CI_DB_mssql_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string
* @return object
*/
- protected function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- return mssql_fetch_object($this->result_id);
+ $row = @mssql_fetch_object($this->result_id);
+
+ if ($class_name === 'stdClass' OR ! $row)
+ {
+ return $row;
+ }
+
+ $class_name = new $class_name();
+ foreach ($row as $key => $value)
+ {
+ $class_name->$key = $value;
+ }
+
+ return $class_name;
}
}
diff --git a/system/database/drivers/mssql/mssql_utility.php b/system/database/drivers/mssql/mssql_utility.php
index 6d47618ce..69fcec5f6 100644
--- a/system/database/drivers/mssql/mssql_utility.php
+++ b/system/database/drivers/mssql/mssql_utility.php
@@ -41,7 +41,7 @@ class CI_DB_mssql_utility extends CI_DB_utility {
* MSSQL Export
*
* @param array Preferences
- * @return mixed
+ * @return bool
*/
protected function _backup($params = array())
{
diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php
index 7a1a7b9a2..29db90408 100644
--- a/system/database/drivers/mysql/mysql_driver.php
+++ b/system/database/drivers/mysql/mysql_driver.php
@@ -49,12 +49,6 @@ class CI_DB_mysql_driver extends CI_DB {
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.
- */
- protected $_count_string = 'SELECT COUNT(*) AS ';
protected $_random_keyword = ' RAND()'; // database specific random keyword
/**
@@ -64,16 +58,24 @@ class CI_DB_mysql_driver extends CI_DB {
*/
public $delete_hack = TRUE;
+ /**
+ * Constructor
+ *
+ * @param array
+ * @return void
+ */
public function __construct($params)
{
parent::__construct($params);
- if ($this->port != '')
+ if ( ! empty($this->port))
{
$this->hostname .= ':'.$this->port;
}
}
+ // --------------------------------------------------------------------
+
/**
* Non-persistent database connection
*
@@ -335,9 +337,9 @@ class CI_DB_mysql_driver extends CI_DB {
*/
protected function _list_tables($prefix_limit = FALSE)
{
- $sql = 'SHOW TABLES FROM '.$this->_escape_char.$this->database.$this->_escape_char;
+ $sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database);
- if ($prefix_limit !== FALSE && $this->dbprefix != '')
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
{
return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'";
}
@@ -355,7 +357,7 @@ class CI_DB_mysql_driver extends CI_DB {
* @param string the table name
* @return string
*/
- public function _list_columns($table = '')
+ protected function _list_columns($table = '')
{
return 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE);
}
@@ -370,7 +372,7 @@ class CI_DB_mysql_driver extends CI_DB {
*/
public function field_data($table = '')
{
- if ($table == '')
+ if ($table === '')
{
return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
}
@@ -412,27 +414,6 @@ class CI_DB_mysql_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param string table name
- * @return string
- */
- protected function _from_tables($tables)
- {
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return '('.implode(', ', $tables).')';
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update_Batch statement
*
* Generates a platform-specific batch update string from the supplied data
@@ -451,7 +432,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];
}
@@ -467,30 +448,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).')';
}
// --------------------------------------------------------------------
/**
- * 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 == 0 ? '' : $offset.', ').$limit;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Close DB Connection
*
* @return void
diff --git a/system/database/drivers/mysql/mysql_forge.php b/system/database/drivers/mysql/mysql_forge.php
index 0e39affa7..2ac75bad2 100644
--- a/system/database/drivers/mysql/mysql_forge.php
+++ b/system/database/drivers/mysql/mysql_forge.php
@@ -60,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 $sql .= ' '.$this->db->escape_identifiers($attributes['NAME']).' ';
if ( ! empty($attributes['TYPE']))
{
@@ -86,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
@@ -123,12 +137,12 @@ class CI_DB_mysql_forge extends CI_DB_forge {
$sql .= 'IF NOT EXISTS ';
}
- $sql .= $this->db->protect_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)
@@ -137,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);
}
@@ -169,16 +183,16 @@ class CI_DB_mysql_forge extends CI_DB_forge {
*/
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) : '');
+ .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
}
}
diff --git a/system/database/drivers/mysql/mysql_result.php b/system/database/drivers/mysql/mysql_result.php
index 14d6d072a..7fbb65496 100644
--- a/system/database/drivers/mysql/mysql_result.php
+++ b/system/database/drivers/mysql/mysql_result.php
@@ -33,17 +33,35 @@
* @category Database
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
+ * @since 1.0
*/
class CI_DB_mysql_result extends CI_DB_result {
/**
+ * Constructor
+ *
+ * @param object
+ * @return void
+ */
+ public function __construct(&$driver_object)
+ {
+ parent::__construct($driver_object);
+
+ // Required, due to mysql_data_seek() causing nightmares
+ // with empty result sets
+ $this->num_rows = @mysql_num_rows($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Number of rows in the result set
*
* @return int
*/
public function num_rows()
{
- return @mysql_num_rows($this->result_id);
+ return $this->num_rows;
}
// --------------------------------------------------------------------
@@ -132,7 +150,9 @@ class CI_DB_mysql_result extends CI_DB_result {
*/
protected function _data_seek($n = 0)
{
- return mysql_data_seek($this->result_id, $n);
+ return $this->num_rows
+ ? @mysql_data_seek($this->result_id, $n)
+ : FALSE;
}
// --------------------------------------------------------------------
@@ -156,11 +176,12 @@ class CI_DB_mysql_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string
* @return object
*/
- protected function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- return mysql_fetch_object($this->result_id);
+ return mysql_fetch_object($this->result_id, $class_name);
}
}
diff --git a/system/database/drivers/mysql/mysql_utility.php b/system/database/drivers/mysql/mysql_utility.php
index 642323dbd..f0bbc665e 100644
--- a/system/database/drivers/mysql/mysql_utility.php
+++ b/system/database/drivers/mysql/mysql_utility.php
@@ -65,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->protect_identifiers($this->db->database).'.'.$this->db->protect_identifiers($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)
@@ -76,7 +76,7 @@ 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 '.$this->db->protect_identifiers($table).';'.$newline.$newline;
}
@@ -92,7 +92,7 @@ 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;
}
@@ -100,7 +100,7 @@ class CI_DB_mysql_utility extends CI_DB_utility {
// Grab all the data from the current table
$query = $this->db->query('SELECT * FROM '.$this->db->protect_identifiers($table));
- if ($query->num_rows() == 0)
+ if ($query->num_rows() === 0)
{
continue;
}
@@ -120,7 +120,7 @@ class CI_DB_mysql_utility extends CI_DB_utility {
TRUE);
// Create a string of field names
- $field_str .= $this->db->protect_identifiers($field->name).', ';
+ $field_str .= $this->db->escape_identifiers($field->name).', ';
$i++;
}
@@ -143,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
diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index dd544f686..be61aab20 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -49,12 +49,6 @@ class CI_DB_mysqli_driver extends CI_DB {
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.
- */
- protected $_count_string = 'SELECT COUNT(*) AS ';
protected $_random_keyword = ' RAND()'; // database specific random keyword
/**
@@ -71,9 +65,9 @@ class CI_DB_mysqli_driver extends CI_DB {
*/
public function db_connect()
{
- return ($this->port != '')
- ? @new mysqli($this->hostname, $this->username, $this->password, $this->database, $this->port)
- : @new mysqli($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 +85,9 @@ class CI_DB_mysqli_driver extends CI_DB {
return $this->db_connect();
}
- return ($this->port != '')
- ? @new mysqli('p:'.$this->hostname, $this->username, $this->password, $this->database, $this->port)
- : @new mysqli('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);
}
// --------------------------------------------------------------------
@@ -335,9 +329,9 @@ class CI_DB_mysqli_driver extends CI_DB {
*/
protected function _list_tables($prefix_limit = FALSE)
{
- $sql = 'SHOW TABLES FROM '.$this->_escape_char.$this->database.$this->_escape_char;
+ $sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database);
- if ($prefix_limit !== FALSE && $this->dbprefix != '')
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
{
return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'";
}
@@ -370,7 +364,7 @@ class CI_DB_mysqli_driver extends CI_DB {
*/
public function field_data($table = '')
{
- if ($table == '')
+ if ($table === '')
{
return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
}
@@ -412,27 +406,6 @@ class CI_DB_mysqli_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param string
- * @return string
- */
- protected function _from_tables($tables)
- {
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return '('.implode(', ', $tables).')';
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update_Batch statement
*
* Generates a platform-specific batch update string from the supplied data
@@ -451,7 +424,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];
}
@@ -466,34 +439,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).')';
}
// --------------------------------------------------------------------
/**
- * 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 '.$limit
- .($offset > 0 ? ' OFFSET '.$offset : '');
- }
-
- // --------------------------------------------------------------------
-
- /**
* Close DB Connection
*
* @return void
diff --git a/system/database/drivers/mysqli/mysqli_forge.php b/system/database/drivers/mysqli/mysqli_forge.php
index 503574dfc..b74c775b2 100644
--- a/system/database/drivers/mysqli/mysqli_forge.php
+++ b/system/database/drivers/mysqli/mysqli_forge.php
@@ -60,13 +60,13 @@ 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']).' ' : '')
- ;
+ $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'];
+ $sql .= ' '.$attributes['TYPE'];
if ( ! empty($attributes['CONSTRAINT']))
{
@@ -87,10 +87,23 @@ class CI_DB_mysqli_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
@@ -128,8 +141,8 @@ class CI_DB_mysqli_forge extends CI_DB_forge {
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)
@@ -138,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);
}
@@ -170,16 +183,16 @@ class CI_DB_mysqli_forge extends CI_DB_forge {
*/
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) : '');
+ .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
}
}
diff --git a/system/database/drivers/mysqli/mysqli_result.php b/system/database/drivers/mysqli/mysqli_result.php
index 9b4d494d4..c1ec4da76 100644
--- a/system/database/drivers/mysqli/mysqli_result.php
+++ b/system/database/drivers/mysqli/mysqli_result.php
@@ -33,6 +33,7 @@
* @category Database
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
+ * @since 1.3
*/
class CI_DB_mysqli_result extends CI_DB_result {
@@ -43,7 +44,9 @@ class CI_DB_mysqli_result extends CI_DB_result {
*/
public function num_rows()
{
- return $this->result_id->num_rows;
+ return is_int($this->num_rows)
+ ? $this->num_rows
+ : $this->num_rows = $this->result_id->num_rows;
}
// --------------------------------------------------------------------
@@ -157,11 +160,12 @@ class CI_DB_mysqli_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string
* @return object
*/
- protected function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- return $this->result_id->fetch_object();
+ return $this->result_id->fetch_object($class_name);
}
}
diff --git a/system/database/drivers/mysqli/mysqli_utility.php b/system/database/drivers/mysqli/mysqli_utility.php
index 27d4ef817..5d2bdbce0 100644
--- a/system/database/drivers/mysqli/mysqli_utility.php
+++ b/system/database/drivers/mysqli/mysqli_utility.php
@@ -46,9 +46,124 @@ class CI_DB_mysqli_utility extends CI_DB_utility {
*/
protected function _backup($params = array())
{
- // Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ if (count($params) === 0)
+ {
+ return FALSE;
+ }
+
+ // Extract the prefs for simplicity
+ extract($params);
+
+ // 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));
+
+ // 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;
+
+ 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 */
diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php
index b979c8a17..691247fee 100644
--- a/system/database/drivers/oci8/oci8_driver.php
+++ b/system/database/drivers/oci8/oci8_driver.php
@@ -66,6 +66,8 @@ class CI_DB_oci8_driver extends CI_DB {
protected $_count_string = 'SELECT COUNT(1) AS ';
protected $_random_keyword = ' ASC'; // not currently supported
+ protected $_reserved_identifiers = array('*', 'rownum');
+
// Set "auto commit" by default
public $commit_mode = OCI_COMMIT_ON_SUCCESS;
@@ -156,6 +158,8 @@ class CI_DB_oci8_driver extends CI_DB {
$this->dsn = '';
}
+ // --------------------------------------------------------------------
+
/**
* Non-persistent database connection
*
@@ -177,9 +181,9 @@ class CI_DB_oci8_driver extends CI_DB {
*/
public function db_pconnect()
{
- return ( ! empty($this->char_set))
- ? @oci_pconnect($this->username, $this->password, $this->dsn, $this->char_set)
- : @oci_pconnect($this->username, $this->password, $this->dsn);
+ return empty($this->char_set)
+ ? @oci_pconnect($this->username, $this->password, $this->dsn)
+ : @oci_pconnect($this->username, $this->password, $this->dsn, $this->char_set);
}
// --------------------------------------------------------------------
@@ -215,6 +219,8 @@ class CI_DB_oci8_driver extends CI_DB {
return @oci_execute($this->stmt_id, $this->commit_mode);
}
+ // --------------------------------------------------------------------
+
/**
* Generate a statement ID
*
@@ -234,7 +240,7 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Get cursor. Returns a cursor from the database
*
- * @return cursor id
+ * @return resource
*/
public function get_cursor()
{
@@ -262,7 +268,7 @@ class CI_DB_oci8_driver extends CI_DB {
*/
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)
{
@@ -298,6 +304,7 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Bind parameters
*
+ * @param array
* @return void
*/
protected function _bind_params($params)
@@ -326,6 +333,7 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool
* @return bool
*/
public function trans_begin($test_mode = FALSE)
@@ -464,11 +472,12 @@ class CI_DB_oci8_driver extends CI_DB {
*/
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 && $this->dbprefix != '')
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
{
- return $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;
@@ -486,7 +495,7 @@ class CI_DB_oci8_driver extends CI_DB {
*/
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" = '.$this->escape($table);
}
// --------------------------------------------------------------------
@@ -501,7 +510,7 @@ class CI_DB_oci8_driver extends CI_DB {
*/
protected function _field_data($table)
{
- return 'SELECT * FROM '.$table.' WHERE rownum = 1';
+ return 'SELECT * FROM '.$this->protect_identifiers($table).' WHERE rownum = 1';
}
// --------------------------------------------------------------------
@@ -633,8 +642,8 @@ class CI_DB_oci8_driver extends CI_DB {
protected function _limit($sql, $limit, $offset)
{
$this->limit_used = TRUE;
- return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($offset + $limit).')'
- .($offset != 0 ? ' WHERE rnum >= '.$offset : '');
+ return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($offset + $limit + 1).')'
+ .($offset ? ' WHERE rnum >= '.($offset + 1): '');
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/oci8/oci8_forge.php b/system/database/drivers/oci8/oci8_forge.php
index bd265b6e0..92e8c02ed 100644
--- a/system/database/drivers/oci8/oci8_forge.php
+++ b/system/database/drivers/oci8/oci8_forge.php
@@ -73,11 +73,22 @@ class CI_DB_oci8_forge extends CI_DB_forge {
{
$attributes = array_change_key_case($attributes, CASE_UPPER);
- $sql .= "\n\t".$this->db->protect_identifiers($field).' '.$attributes['TYPE']
- .((isset($attributes['UNSINGED']) && $attributes['UNSIGNED'] === TRUE) ? ' UNSIGNED' : '')
- .(isset($attributes['DEFAULT']) ? " DEFAULT '".$attributes['DEFAULT']."'" : '')
- .((isset($attributes['NULL']) && $attributes['NULL'] === TRUE) ? '' : ' NOT NULL')
- .(isset($attributes['CONSTRAINT']) ? ' CONSTRAINT '.$attributes['CONSTRAINT'] : '');
+ $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE'];
+
+ if (isset($attributes['UNSINGED']) && $attributes['UNSIGNED'] === TRUE)
+ {
+ $sql .= ' UNSIGNED';
+ }
+
+ if (isset($attributes['DEFAULT']))
+ {
+ $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
+ }
+
+ $sql .= (isset($attributes['NULL']) && $attributes['NULL'] === TRUE)
+ ? '' : ' NOT NULL';
+
+ empty($attributes['CONSTRAINT']) OR ' CONSTRAINT '.$attributes['CONSTRAINT'];
}
// don't add a comma on the end of the last field
@@ -89,22 +100,16 @@ class CI_DB_oci8_forge extends CI_DB_forge {
if (count($primary_keys) > 0)
{
- $primary_keys = $this->db->protect_identifiers($primary_keys);
- $sql .= ",\n\tCONSTRAINT ".$table.' PRIMARY 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).')';
}
@@ -132,7 +137,7 @@ class CI_DB_oci8_forge extends CI_DB_forge {
*/
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')
@@ -141,9 +146,9 @@ class CI_DB_oci8_forge extends CI_DB_forge {
}
return $sql.' '.$column_definition
- .($default_value != '' ? ' DEFAULT "'.$default_value.'"' : '')
+ .($default_value !== '' ? ' DEFAULT "'.$default_value.'"' : '')
.($null === NULL ? ' NULL' : ' NOT NULL')
- .($after_field != '' ? ' AFTER '.$this->db->protect_identifiers($after_field) : '');
+ .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
}
diff --git a/system/database/drivers/oci8/oci8_result.php b/system/database/drivers/oci8/oci8_result.php
index 6fb6c81f1..a2b600e6c 100644
--- a/system/database/drivers/oci8/oci8_result.php
+++ b/system/database/drivers/oci8/oci8_result.php
@@ -33,6 +33,7 @@
* @category Database
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
+ * @since 1.4.1
*/
class CI_DB_oci8_result extends CI_DB_result {
@@ -41,14 +42,16 @@ class CI_DB_oci8_result extends CI_DB_result {
public $limit_used;
public $commit_mode;
- /* Overwriting the parent here, so we have a way to know if it's
- * already called or not:
+ /**
+ * Constructor
+ *
+ * @param object
+ * @return void
*/
- 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;
@@ -56,33 +59,6 @@ class CI_DB_oci8_result extends CI_DB_result {
$driver_object->stmt_id = FALSE;
}
- /**
- * Number of rows in the result set.
- *
- * Oracle doesn't have a graceful way to return the number of rows
- * so we have to use what amounts to a hack.
- *
- * @return int
- */
- public function num_rows()
- {
- if ( ! is_int($this->num_rows))
- {
- if (count($this->result_array) > 0)
- {
- return $this->num_rows = count($this->result_array);
- }
- elseif (count($this->result_object) > 0)
- {
- return $this->num_rows = count($this->result_object);
- }
-
- return $this->num_rows = count($this->result_array());
- }
-
- return $this->num_rows;
- }
-
// --------------------------------------------------------------------
/**
@@ -191,450 +167,27 @@ class CI_DB_oci8_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string
* @return object
*/
- protected function _fetch_object()
- {
- $id = ($this->curs_id) ? $this->curs_id : $this->stmt_id;
- return oci_fetch_object($id);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Query result. Array version.
- *
- * @return array
- */
- public function result_array()
+ protected function _fetch_object($class_name = 'stdClass')
{
- if (count($this->result_array) > 0)
- {
- 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->row_data[$row_index++] = $row;
- }
-
- return $this->result_array = $this->row_data;
- }
+ $row = ($this->curs_id)
+ ? oci_fetch_object($this->curs_id)
+ : oci_fetch_object($this->stmt_id);
- // --------------------------------------------------------------------
-
- /**
- * Query result. "object" version.
- *
- * @return array
- */
- public function result_object()
- {
- if (count($this->result_object) > 0)
+ if ($class_name === 'stdClass' OR ! $row)
{
- return $this->result_object;
+ return $row;
}
- 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();
+ $class_name = new $class_name();
foreach ($row as $key => $value)
{
- $row_object->$key = $value;
+ $class_name->$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);
+ return $class_name;
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php
index 98fd806a8..8f0a474b0 100644
--- a/system/database/drivers/odbc/odbc_driver.php
+++ b/system/database/drivers/odbc/odbc_driver.php
@@ -49,12 +49,6 @@ class CI_DB_odbc_driver extends CI_DB {
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;
public function __construct($params)
@@ -64,7 +58,7 @@ class CI_DB_odbc_driver extends CI_DB {
$this->_random_keyword = ' RND('.time().')'; // database specific random keyword
// Legacy support for DSN in the hostname field
- if ($this->dsn == '')
+ if (empty($this->dsn))
{
$this->dsn = $this->hostname;
}
@@ -114,13 +108,8 @@ class CI_DB_odbc_driver extends CI_DB {
*/
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;
}
@@ -128,7 +117,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);
}
@@ -142,13 +131,8 @@ class CI_DB_odbc_driver extends CI_DB {
*/
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;
}
@@ -167,13 +151,8 @@ class CI_DB_odbc_driver extends CI_DB {
*/
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;
}
@@ -204,7 +183,6 @@ class CI_DB_odbc_driver extends CI_DB {
return $str;
}
- // ODBC doesn't require escaping
$str = remove_invisible_characters($str);
// escape LIKE condition wildcards
@@ -254,9 +232,9 @@ class CI_DB_odbc_driver extends CI_DB {
*/
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
@@ -277,7 +255,7 @@ class CI_DB_odbc_driver extends CI_DB {
*/
protected function _list_columns($table = '')
{
- return "SHOW COLUMNS FROM ".$table;
+ return 'SHOW COLUMNS FROM '.$table;
}
// --------------------------------------------------------------------
@@ -292,7 +270,7 @@ class CI_DB_odbc_driver extends CI_DB {
*/
protected function _field_data($table)
{
- return "SELECT TOP 1 FROM ".$table;
+ return 'SELECT TOP 1 FROM '.$table;
}
// --------------------------------------------------------------------
@@ -323,12 +301,7 @@ class CI_DB_odbc_driver extends CI_DB {
*/
protected function _from_tables($tables)
{
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return '('.implode(', ', $tables).')';
+ return is_array($tables) ? implode(', ', $tables) : $tables;
}
// --------------------------------------------------------------------
@@ -352,24 +325,6 @@ class CI_DB_odbc_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * 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)
- {
- // Does ODBC doesn't use the LIMIT clause?
- return $sql;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Close DB Connection
*
* @return void
diff --git a/system/database/drivers/odbc/odbc_forge.php b/system/database/drivers/odbc/odbc_forge.php
index d59b8a911..d17b046ee 100644
--- a/system/database/drivers/odbc/odbc_forge.php
+++ b/system/database/drivers/odbc/odbc_forge.php
@@ -34,7 +34,6 @@
*/
class CI_DB_odbc_forge extends CI_DB_forge {
- protected $_drop_database = 'DROP DATABASE %s';
protected $_drop_table = 'DROP TABLE %s';
/**
@@ -66,41 +65,30 @@ class CI_DB_odbc_forge extends CI_DB_forge {
// 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';
}
@@ -115,30 +103,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;
+ return $sql."\n)";
}
// --------------------------------------------------------------------
@@ -160,37 +140,18 @@ class CI_DB_odbc_forge extends CI_DB_forge {
*/
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 != '')
- {
- return $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) : '');
}
}
diff --git a/system/database/drivers/odbc/odbc_result.php b/system/database/drivers/odbc/odbc_result.php
index ecba5977e..48dc48dd9 100644
--- a/system/database/drivers/odbc/odbc_result.php
+++ b/system/database/drivers/odbc/odbc_result.php
@@ -33,11 +33,10 @@
* @category Database
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
+ * @since 1.3
*/
class CI_DB_odbc_result extends CI_DB_result {
- public $num_rows;
-
/**
* Number of rows in the result set
*
@@ -49,14 +48,22 @@ class CI_DB_odbc_result extends CI_DB_result {
{
return $this->num_rows;
}
+ elseif (($this->num_rows = @odbc_num_rows($this->result_id)) !== -1)
+ {
+ 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)
+ if (count($this->result_array) > 0)
{
- $this->num_rows = count($this->result_array());
+ return $this->num_rows = count($this->result_array);
+ }
+ elseif (count($this->result_object) > 0)
+ {
+ return $this->num_rows = count($this->result_object);
}
- return $this->num_rows;
+ return $this->num_rows = count($this->result_array());
}
// --------------------------------------------------------------------
@@ -148,14 +155,7 @@ class CI_DB_odbc_result extends CI_DB_result {
*/
protected function _fetch_assoc()
{
- if (function_exists('odbc_fetch_array'))
- {
- return odbc_fetch_array($this->result_id);
- }
- else
- {
- return $this->_odbc_fetch_array($this->result_id);
- }
+ return odbc_fetch_array($this->result_id);
}
// --------------------------------------------------------------------
@@ -165,141 +165,93 @@ class CI_DB_odbc_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string
* @return object
*/
- protected function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- if (function_exists('odbc_fetch_object'))
- {
- return odbc_fetch_object($this->result_id);
- }
- else
+ $row = odbc_fetch_object($this->result_id);
+
+ if ($class_name === 'stdClass' OR ! $row)
{
- return $this->_odbc_fetch_object($this->result_id);
+ return $row;
}
- }
-
- // --------------------------------------------------------------------
- /**
- * Result - object
- *
- * subsititutes the odbc_fetch_object function when
- * not available (odbc_fetch_object requires unixODBC)
- *
- * @return object
- */
- protected function _odbc_fetch_object(& $odbc_result)
- {
- $rs = array();
- $rs_obj = FALSE;
- if (odbc_fetch_into($odbc_result, $rs))
+ $class_name = new $class_name();
+ foreach ($row as $key => $value)
{
- foreach ($rs as $k => $v)
- {
- $field_name = odbc_field_name($odbc_result, $k+1);
- $rs_obj->$field_name = $v;
- }
+ $class_name->$key = $value;
}
- return $rs_obj;
+
+ return $class_name;
}
- // --------------------------------------------------------------------
+}
+
+// --------------------------------------------------------------------
+if ( ! function_exists('odbc_fetch_array'))
+{
/**
- * Result - array
+ * ODBC Fetch array
*
- * subsititutes the odbc_fetch_array function when
- * not available (odbc_fetch_array requires unixODBC)
+ * Emulates the native odbc_fetch_array() function when
+ * it is not available (odbc_fetch_array() requires unixODBC)
*
+ * @param resource
+ * @param int
* @return array
*/
- protected function _odbc_fetch_array(& $odbc_result)
+ function odbc_fetch_array(& $result, $rownumber = 1)
{
$rs = array();
- $rs_assoc = FALSE;
- if (odbc_fetch_into($odbc_result, $rs))
+ if ( ! odbc_fetch_into($result, $rs, $rownumber))
{
- $rs_assoc = array();
- foreach ($rs as $k => $v)
- {
- $field_name = odbc_field_name($odbc_result, $k+1);
- $rs_assoc[$field_name] = $v;
- }
+ return FALSE;
}
- return $rs_assoc;
- }
- // --------------------------------------------------------------------
-
- /**
- * Query result. Array version.
- *
- * @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)
+ $rs_assoc = array();
+ foreach ($rs as $k => $v)
{
- return array();
- }
- else
- {
- while ($row = $this->_fetch_assoc())
- {
- $this->result_array[] = $row;
- }
+ $field_name = odbc_field_name($result, $k+1);
+ $rs_assoc[$field_name] = $v;
}
- return $this->result_array;
+ return $rs_assoc;
}
+}
- // --------------------------------------------------------------------
+// --------------------------------------------------------------------
+if ( ! function_exists('odbc_fetch_object'))
+{
/**
- * Query result. Object version.
+ * ODBC Fetch object
*
- * @return array
+ * Emulates the native odbc_fetch_object() function when
+ * it is not available.
+ *
+ * @param resource
+ * @param int
+ * @return object
*/
- public function result_object()
+ function odbc_fetch_object(& $result, $rownumber = 1)
{
- 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];
- }
- }
- elseif ($this->result_id === FALSE)
+ $rs = array();
+ if ( ! odbc_fetch_into($result, $rs, $rownumber))
{
- return array();
+ return FALSE;
}
- else
+
+ $rs_object = new stdClass();
+ foreach ($rs as $k => $v)
{
- while ($row = $this->_fetch_object())
- {
- $this->result_object[] = $row;
- }
+ $field_name = odbc_field_name($result, $k+1);
+ $rs_object->$field_name = $v;
}
- return $this->result_object;
+ return $rs_object;
}
-
}
/* End of file odbc_result.php */
diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php
index ec7f3e19b..b36a3d927 100644
--- a/system/database/drivers/pdo/pdo_driver.php
+++ b/system/database/drivers/pdo/pdo_driver.php
@@ -42,145 +42,66 @@ class CI_DB_pdo_driver extends CI_DB {
public $dbdriver = 'pdo';
- // the character used to excape - not necessary for PDO
- protected $_escape_char = '';
+ // The character used to 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;
- // need to track the pdo driver and options
- public $pdodriver;
+ public $trans_enabled = FALSE;
+
+ // need to track the PDO options
public $options = array();
+ /**
+ * Constructor
+ *
+ * Validates the DSN string and/or detects the subdriver
+ *
+ * @param array
+ * @return void
+ */
public function __construct($params)
{
parent::__construct($params);
- if (preg_match('/([^;]+):/', $this->dsn, $match) && count($match) == 2)
+ 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);
+ $this->subdriver = $match[1];
+ return;
}
- else
+ // Legacy support for DSN specified in the hostname field
+ elseif (preg_match('/([^;]+):/', $this->hostname, $match) && count($match) === 2)
{
- // Try to build a complete DSN string from params
- $this->_connect_string($params);
+ $this->dsn = $this->hostname;
+ $this->hostname = NULL;
+ $this->subdriver = $match[1];
+ return;
}
-
- // clause and character used for LIKE escape sequences
- // this one depends on the driver being used
- if ($this->pdodriver === 'mysql')
- {
- $this->_escape_char = '`';
- $this->_like_escape_str = '';
- $this->_like_escape_chr = '\\';
- }
- elseif ($this->pdodriver === 'odbc')
- {
- $this->_like_escape_str = " {escape '%s'} ";
- }
- elseif ( ! in_array($this->pdodriver, array('sqlsrv', 'mssql', 'dblib', 'sybase')))
+ elseif (in_array($this->subdriver, array('mssql', 'sybase'), TRUE))
{
- $this->_escape_char = '"';
+ $this->subdriver = 'dblib';
}
-
- $this->trans_enabled = FALSE;
- $this->_random_keyword = ' RND('.time().')'; // database specific random keyword
- }
-
- /**
- * Connection String
- *
- * @param array
- * @return void
- */
- protected function _connect_string($params)
- {
- if (strpos($this->hostname, ':'))
+ elseif ($this->subdriver === '4D')
{
- // 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, ';').';';
- }
+ $this->subdriver = '4d';
}
- else
+ elseif ( ! in_array($this->subdriver, array('4d', 'cubrid', 'dblib', 'firebird', 'ibm', 'informix', 'mysql', 'oci', 'odbc', 'sqlite', 'sqlsrv'), TRUE))
{
- // Invalid DSN, display an error
- if ( ! array_key_exists('pdodriver', $params))
- {
- show_error('Invalid DB Connection String for PDO');
- }
+ log_message('error', 'PDO: Invalid or non-existent subdriver');
- // 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')))
+ if ($this->db_debug)
{
- $this->dsn .= 'host='.$this->hostname.';';
- }
-
- // 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.';';
+ show_error('Invalid or non-existent PDO subdriver');
}
}
- // 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.';';
- }
+ $this->dsn = NULL;
}
// --------------------------------------------------------------------
@@ -188,11 +109,27 @@ class CI_DB_pdo_driver extends CI_DB {
/**
* Non-persistent database connection
*
+ * @param bool
* @return object
*/
- public function db_connect()
+ public function db_connect($persistent = FALSE)
{
- return $this->_pdo_connect();
+ $this->options[PDO::ATTR_PERSISTENT] = $persistent;
+
+ // 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;
+ }
}
// --------------------------------------------------------------------
@@ -204,66 +141,37 @@ class CI_DB_pdo_driver extends CI_DB {
*/
public function db_pconnect()
{
- return $this->_pdo_connect(TRUE);
+ return $this->db_connect(TRUE);
}
// --------------------------------------------------------------------
/**
- * PDO connection
+ * Database version number
*
- * @param bool
- * @return object
+ * @return string
*/
- protected function _pdo_connect($persistent = FALSE)
+ public function 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))
+ if (isset($this->data_cache['version']))
{
- $this->options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES '.$this->char_set
- .( ! empty($this->db_collat) ? " COLLATE '".$this->dbcollat."'" : '');
+ return $this->data_cache['version'];
}
- // Connecting...
+ // Not all subdrivers support the getAttribute() method
try
{
- return new PDO($this->dsn, $this->username, $this->password, $this->options);
+ return $this->data_cache['version'] = $this->conn_id->getAttribute(PDO::ATTR_SERVER_VERSION);
}
catch (PDOException $e)
{
- if ($this->db_debug && empty($this->failover))
- {
- $this->display_error($e->getMessage(), '', TRUE);
- }
-
- return FALSE;
+ return parent::version();
}
}
// --------------------------------------------------------------------
/**
- * Database version number
- *
- * @return string
- */
- public function version()
- {
- return isset($this->data_cache['version'])
- ? $this->data_cache['version']
- : $this->data_cache['version'] = $this->conn_id->getAttribute(PDO::ATTR_SERVER_VERSION);
- }
-
- // --------------------------------------------------------------------
-
- /**
* Execute the query
*
* @param string an SQL query
@@ -358,7 +266,7 @@ class CI_DB_pdo_driver extends CI_DB {
$str = $this->conn_id->quote($str);
// If there are duplicated quotes, trim them away
- if (strpos($str, "'") === 0)
+ if ($str[0] === "'")
{
$str = substr($str, 1, -1);
}
@@ -396,69 +304,12 @@ class CI_DB_pdo_driver extends CI_DB {
*/
public function insert_id($name = NULL)
{
- if ($this->pdodriver === 'pgsql' && $name === NULL && $this->version() >= '8.1')
- {
- $query = $this->query('SELECT LASTVAL() AS ins_id');
- $query = $query->row();
- return $query->ins_id;
- }
-
return $this->conn_id->lastInsertId($name);
}
// --------------------------------------------------------------------
/**
- * 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)
- {
- 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 != '')
- {
- return FALSE;
- }
-
- 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 'SHOW COLUMNS FROM '.$this->escape_identifiers($table);
- }
-
- // --------------------------------------------------------------------
-
- /**
* Field data query
*
* Generates a platform-specific query so that the column data can be retrieved
@@ -468,23 +319,7 @@ class CI_DB_pdo_driver extends CI_DB {
*/
protected function _field_data($table)
{
- if ($this->pdodriver == 'mysql' or $this->pdodriver == 'pgsql')
- {
- // Analog function for mysql and postgre
- return 'SELECT * FROM '.$this->escape_identifiers($table).' LIMIT 1';
- }
- elseif ($this->pdodriver == 'oci')
- {
- // Analog function for oci
- return 'SELECT * FROM '.$this->escape_identifiers($table).' WHERE ROWNUM <= 1';
- }
- elseif ($this->pdodriver == 'sqlite')
- {
- // Analog function for sqlite
- return 'PRAGMA table_info('.$this->escape_identifiers($table).')';
- }
-
- return 'SELECT TOP 1 FROM '.$this->escape_identifiers($table);
+ return 'SELECT TOP 1 * FROM '.$this->protect_identifiers($table);
}
// --------------------------------------------------------------------
@@ -519,27 +354,6 @@ class CI_DB_pdo_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This 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)
- {
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return (count($tables) === 1) ? $tables[0] : '('.implode(', ', $tables).')';
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update_Batch statement
*
* Generates a platform-specific batch update string from the supplied data
@@ -551,8 +365,8 @@ class CI_DB_pdo_driver extends CI_DB {
*/
protected function _update_batch($table, $values, $index, $where = NULL)
{
- $ids = array();
- $where = ($where != '' && count($where) >=1) ? implode(" ", $where).' AND ' : '';
+ $ids = array();
+ $where = ($where !== '' && count($where) >=1) ? implode(" ", $where).' AND ' : '';
foreach ($values as $key => $val)
{
@@ -560,7 +374,7 @@ 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];
}
@@ -603,39 +417,10 @@ class CI_DB_pdo_driver extends CI_DB {
*/
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)
- {
- if ($this->pdodriver == 'cubrid' OR $this->pdodriver == 'sqlite')
- {
- $offset = ($offset == 0) ? '' : $offset.', ';
-
- return $sql.'LIMIT '.$offset.$limit;
- }
- else
- {
- $sql .= 'LIMIT '.$limit;
- $sql .= ($offset > 0) ? ' OFFSET '.$offset : '';
-
- return $sql;
- }
+ return 'TRUNCATE TABLE '.$table;
}
}
/* End of file pdo_driver.php */
-/* Location: ./system/database/drivers/pdo/pdo_driver.php */ \ No newline at end of file
+/* Location: ./system/database/drivers/pdo/pdo_driver.php */
diff --git a/system/database/drivers/pdo/pdo_forge.php b/system/database/drivers/pdo/pdo_forge.php
index ca8657a0f..34a6ee44e 100644
--- a/system/database/drivers/pdo/pdo_forge.php
+++ b/system/database/drivers/pdo/pdo_forge.php
@@ -34,7 +34,6 @@
*/
class CI_DB_pdo_forge extends CI_DB_forge {
- protected $_drop_database = 'DROP DATABASE %s';
protected $_drop_table = 'DROP TABLE %s';
/**
@@ -66,46 +65,38 @@ class CI_DB_pdo_forge extends CI_DB_forge {
// 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');
+ $numeric = array('SERIAL', 'INTEGER');
- $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 ( ! empty($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)))
+ if ( ! ($this->db->subdriver === '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';
}
@@ -120,30 +111,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;
+ return $sql."\n)";
}
// --------------------------------------------------------------------
@@ -165,37 +148,18 @@ class CI_DB_pdo_forge extends CI_DB_forge {
*/
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 != '')
- {
- return $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) : '');
}
}
diff --git a/system/database/drivers/pdo/pdo_result.php b/system/database/drivers/pdo/pdo_result.php
index 0b8937cc5..444406986 100644
--- a/system/database/drivers/pdo/pdo_result.php
+++ b/system/database/drivers/pdo/pdo_result.php
@@ -21,7 +21,7 @@
* @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.1.0
+ * @since Version 1.0
* @filesource
*/
@@ -33,72 +33,35 @@
* @category Database
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
+ * @since 2.1
*/
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
*
* @return int
*/
public function num_rows()
{
- if (empty($this->result_id) OR ! is_object($this->result_id))
+ if (is_int($this->num_rows))
{
- // invalid result handler
- return 0;
+ return $this->num_rows;
}
- elseif (($num_rows = $this->result_id->rowCount()) && $num_rows > 0)
+ elseif (count($this->result_array) > 0)
{
- // If rowCount return something, we're done.
- return $num_rows;
+ return $this->num_rows = count($this->result_array);
}
-
- // 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)
+ elseif (count($this->result_object) > 0)
{
- return $this->result_array();
+ return $this->num_rows = count($this->result_object);
}
-
- // 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())
+ elseif (($num_rows = $this->result_id->rowCount()) > 0)
{
- $this->result_assoc[] = $row;
- $this->result_object[] = (object) $row;
+ return $this->num_rows = $num_rows;
}
- // Save this as buffer and marked the fetch flag
- $this->result_array = $this->result_assoc;
- $this->is_fetched = TRUE;
-
- return $this->result_assoc;
+ return $this->num_rows = count($this->result_array());
}
// --------------------------------------------------------------------
@@ -124,12 +87,14 @@ class CI_DB_pdo_result extends CI_DB_result {
*/
public function list_fields()
{
- if ($this->db->db_debug)
+ $field_names = array();
+ for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
{
- return $this->db->display_error('db_unsuported_feature');
+ $field_names[$i] = @$this->result_id->getColumnMeta();
+ $field_names[$i] = $field_names[$i]['name'];
}
- return FALSE;
+ return $field_names;
}
// --------------------------------------------------------------------
@@ -240,11 +205,12 @@ class CI_DB_pdo_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string
* @return object
*/
- protected function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- return $this->result_id->fetch(PDO::FETCH_OBJ);
+ return $this->result_id->fetchObject($class_name);
}
}
diff --git a/system/database/drivers/pdo/subdrivers/index.html b/system/database/drivers/pdo/subdrivers/index.html
new file mode 100644
index 000000000..c942a79ce
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/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/pdo/subdrivers/pdo_4d_driver.php b/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php
new file mode 100644
index 000000000..e287f5c63
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php
@@ -0,0 +1,223 @@
+<?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.0
+ * @filesource
+ */
+
+/**
+ * PDO 4D 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_pdo_4d_driver extends CI_DB_pdo_driver {
+
+ public $subdriver = '4d';
+
+ // The character used for escaping
+ protected $_escape_char = array('[', ']');
+
+ protected $_random_keyword = ' RAND()';
+
+ /**
+ * Constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = '4D:host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);
+
+ empty($this->port) OR $this->dsn .= ';port='.$this->port;
+ empty($this->database) OR $this->dsn .= ';dbname='.$this->database;
+ empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;
+ }
+ elseif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 3) === FALSE)
+ {
+ $this->dsn .= ';charset='.$this->char_set;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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)
+ {
+ $sql = 'SELECT '.$this->escape_identifiers('TABLE_NAME').' FROM '.$this->escape_identifiers('_USER_TABLES');
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ $sql .= ' WHERE '.$this->escape_identifiers('TABLE_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 '.$this->escape_identifiers('COLUMN_NAME').' FROM '.$this->escape_identifiers('_USER_COLUMNS')
+ .' WHERE '.$this->escape_identifiers('TABLE_NAME').' = '.$this->escape($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)
+ {
+ return 'SELECT * FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE).' LIMIT 1';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * From Tables
+ *
+ * This 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 (ignored)
+ * @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;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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);
+
+ $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : '';
+
+ return 'DELETE FROM '.$table.$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)
+ {
+ return $sql.' LIMIT '.$limit.($offset ? ' OFFSET '.$offset : '');
+ }
+
+}
+
+/* End of file pdo_4d_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_4d_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php b/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php
new file mode 100644
index 000000000..05eeacfe6
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php
@@ -0,0 +1,189 @@
+<?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.0
+ * @filesource
+ */
+
+/**
+ * PDO CUBRID 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_pdo_cubrid_driver extends CI_DB_pdo_driver {
+
+ public $subdriver = 'cubrid';
+
+ protected $_escape_char = '`';
+
+ // clause and character used for LIKE escape sequences - not used in CUBRID
+ protected $_like_escape_str = '';
+ protected $_like_escape_chr = '\\';
+
+ protected $_random_keyword = ' RAND()';
+
+ /**
+ * Constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'cubrid:host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);
+
+ empty($this->port) OR $this->dsn .= ';port='.$this->port;
+ empty($this->database) OR $this->dsn .= ';dbname='.$this->database;
+ empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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)
+ {
+ $sql = 'SHOW TABLES';
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'";
+ }
+
+ 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 '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
+ *
+ * @param string the table name
+ * @return string
+ */
+ protected function _field_data($table)
+ {
+ return 'SELECT * FROM '.$this->protect_identifiers($table).' LIMIT 1';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update_Batch statement
+ *
+ * Generates a platform-specific batch update string from the supplied data
+ *
+ * @param string the table name
+ * @param array the update data
+ * @param array the where clause
+ * @return string
+ */
+ protected function _update_batch($table, $values, $index, $where = NULL)
+ {
+ $ids = array();
+ foreach ($values as $key => $val)
+ {
+ $ids[] = $val[$index];
+
+ foreach (array_keys($val) as $field)
+ {
+ if ($field !== $index)
+ {
+ $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
+ }
+ }
+ }
+
+ $cases = '';
+ foreach ($final as $k => $v)
+ {
+ $cases .= $k." = CASE \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).')';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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;
+ }
+
+}
+
+/* End of file pdo_cubrid_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php
new file mode 100644
index 000000000..7060c9eb9
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php
@@ -0,0 +1,265 @@
+<?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.0
+ * @filesource
+ */
+
+/**
+ * PDO DBLIB 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_pdo_dblib_driver extends CI_DB_pdo_driver {
+
+ public $subdriver = 'dblib';
+
+ protected $_random_keyword = ' NEWID()';
+
+ protected $_quoted_identifier;
+
+ /**
+ * Constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = $params['subdriver'].':host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);
+
+ if ( ! empty($this->port))
+ {
+ $this->dsn .= (DIRECTORY_SEPARATOR === '\\' ? ',' : ':').$this->port;
+ }
+
+ empty($this->database) OR $this->dsn .= ';dbname='.$this->database;
+ empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;
+ empty($this->appname) OR $this->dsn .= ';appname='.$this->appname;
+ }
+ else
+ {
+ if ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 6) === FALSE)
+ {
+ $this->dsn .= ';charset='.$this->char_set;
+ }
+
+ $this->subdriver = 'dblib';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Non-persistent database connection
+ *
+ * @param bool
+ * @return object
+ */
+ public function db_connect($persistent = FALSE)
+ {
+ $this->conn_id = parent::db_connect($persistent);
+
+ if ( ! is_object($this->conn_id))
+ {
+ return $this->conn_id;
+ }
+
+ // 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 $this->conn_id;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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 '.$this->escape_identifiers('name')
+ .' FROM '.$this->escape_identifiers('sysobjects')
+ .' WHERE '.$this->escape_identifiers('type')." = 'U'";
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ $sql .= ' AND '.$this->escape_identifiers('name')." LIKE '".$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql.' ORDER BY '.$this->escape_identifiers('name');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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 '.$this->escape_identifiers('column_name')
+ .' FROM '.$this->escape_identifiers('information_schema.columns')
+ .' WHERE '.$this->escape_identifiers('table_name').' = '.$this->escape($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * From Tables
+ *
+ * This 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 (ignored)
+ * @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;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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);
+
+ $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;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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 = $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 '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);
+ }
+
+}
+
+/* End of file pdo_dblib_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php */
diff --git a/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php b/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php
new file mode 100644
index 000000000..c074a9a78
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php
@@ -0,0 +1,262 @@
+<?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.0
+ * @filesource
+ */
+
+/**
+ * PDO Firebird 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_pdo_firebird_driver extends CI_DB_pdo_driver {
+
+ public $subdriver = 'firebird';
+
+ /**
+ * 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 $_random_keyword = ' RANDOM()'; // Currently not supported
+
+ /**
+ * Constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'firebird:';
+
+ if ( ! empty($this->database))
+ {
+ $this->dsn .= 'dbname='.$this->database;
+ }
+ elseif ( ! empty($this->hostname))
+ {
+ $this->dsn .= 'dbname='.$this->hostname;
+ }
+
+ empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;
+ empty($this->role) OR $this->dsn .= ';role='.$this->role;
+ }
+ elseif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 9) === FALSE)
+ {
+ $this->dsn .= ';charset='.$this->char_set;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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)
+ {
+ $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 === TRUE && $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($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)
+ {
+ return 'SELECT FIRST 1 * FROM '.$this->protect_identifiers($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * From Tables
+ *
+ * This 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);
+ }
+
+}
+
+/* End of file pdo_firebird_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php b/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php
new file mode 100644
index 000000000..832c03c96
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php
@@ -0,0 +1,262 @@
+<?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.0
+ * @filesource
+ */
+
+/**
+ * PDO IBM DB2 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_pdo_ibm_driver extends CI_DB_pdo_driver {
+
+ public $subdriver = 'ibm';
+
+ protected $_random_keyword = ' RAND()';
+
+ /**
+ * Constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'ibm:';
+
+ // Pre-defined DSN
+ if (empty($this->hostname) && empty($this->HOSTNAME) && empty($this->port) && empty($this->PORT))
+ {
+ if (isset($this->DSN))
+ {
+ $this->dsn .= 'DSN='.$this->DSN;
+ }
+ elseif ( ! empty($this->database))
+ {
+ $this->dsn .= 'DSN='.$this->database;
+ }
+
+ return;
+ }
+
+ $this->dsn .= 'DRIVER='.(isset($this->DRIVER) ? '{'.$this->DRIVER.'}' : '{IBM DB2 ODBC DRIVER}').';';
+
+ if (isset($this->DATABASE))
+ {
+ $this->dsn .= 'DATABASE='.$this->DATABASE.';';
+ }
+ elseif ( ! empty($this->database))
+ {
+ $this->dsn .= 'DATABASE='.$this->database.';';
+ }
+
+ if (isset($this->HOSTNAME))
+ {
+ $this->dsn .= 'HOSTNAME='.$this->HOSTNAME.';';
+ }
+ else
+ {
+ $this->dsn .= 'HOSTNAME='.(empty($this->hostname) ? '127.0.0.1;' : $this->hostname.';');
+ }
+
+ if (isset($this->PORT))
+ {
+ $this->dsn .= 'PORT='.$this->port.';';
+ }
+ elseif ( ! empty($this->port))
+ {
+ $this->dsn .= ';PORT='.$this->port.';';
+ }
+
+ $this->dsn .= 'PROTOCOL='.(isset($this->PROTOCOL) ? $this->PROTOCOL.';' : 'TCPIP;');
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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)
+ {
+ $sql = 'SELECT "tabname" FROM "syscat"."tables" WHERE "type" = \'T\'';
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ $sql .= ' AND "tabname" 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 "colname" FROM "syscat"."tables"
+ WHERE "syscat"."tabtype" = \'T\' AND "syscat"."tabname" = '.$this->escape($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)
+ {
+ return 'SELECT * FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE).' FETCH FIRST 1 ROWS ONLY';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * From Tables
+ *
+ * This 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 (ignored)
+ * @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;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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);
+
+ $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : '';
+
+ return 'DELETE FROM '.$table.$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)
+ {
+ $sql .= ' FETCH FIRST '.($limit + $offset).' ROWS ONLY';
+
+ return ($offset)
+ ? 'SELECT * FROM ('.$sql.') WHERE rownum > '.$offset
+ : $sql;
+ }
+
+}
+
+/* End of file pdo_ibm_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php b/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php
new file mode 100644
index 000000000..a3efc63dc
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php
@@ -0,0 +1,271 @@
+<?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.0
+ * @filesource
+ */
+
+/**
+ * PDO Informix 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_pdo_informix_driver extends CI_DB_pdo_driver {
+
+ public $subdriver = 'informix';
+
+ protected $_random_keyword = ' RAND()';
+
+ /**
+ * Constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'informix:';
+
+ // Pre-defined DSN
+ if (empty($this->hostname) && empty($this->host) && empty($this->port) && empty($this->service))
+ {
+ if (isset($this->DSN))
+ {
+ $this->dsn .= 'DSN='.$this->DSN;
+ }
+ elseif ( ! empty($this->database))
+ {
+ $this->dsn .= 'DSN='.$this->database;
+ }
+
+ return;
+ }
+
+ if (isset($this->host))
+ {
+ $this->dsn .= 'host='.$this->host;
+ }
+ else
+ {
+ $this->dsn .= 'host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);
+ }
+
+ if (isset($this->service))
+ {
+ $this->dsn .= '; service='.$this->service;
+ }
+ elseif ( ! empty($this->port))
+ {
+ $this->dsn .= '; service='.$this->port;
+ }
+
+ empty($this->database) OR $this->dsn .= '; database='.$this->database;
+ empty($this->server) OR $this->dsn .= '; server='.$this->server;
+
+ $this->dsn .= '; protocol='.(isset($this->protocol) ? $this->protocol : 'onsoctcp')
+ .'; EnableScrollableCursors=1';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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)
+ {
+ $sql = 'SELECT "tabname" FROM "systables" WHERE "tabid" > 99 AND "tabtype" = \'T\'';
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ $sql .= ' AND "tabname" 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 "colname" FROM "systables", "syscolumns"
+ WHERE "systables"."tabid" = "syscolumns"."tabid" AND "systables"."tabtype" = \'T\' AND "systables"."tabname" = '
+ .$this->escape($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)
+ {
+ return 'SELECT FIRST 1 * FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * From Tables
+ *
+ * This 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 (ignored)
+ * @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;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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 ONLY '.$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);
+
+ $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : '';
+
+ return 'DELETE FROM '.$table.$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)
+ {
+ $select = 'SELECT '.($offset ? 'SKIP '.$offset : '').'FIRST '.$limit.' ';
+ return preg_replace('/^(SELECT\s)/i', $select, $sql, 1);
+ }
+
+}
+
+/* End of file pdo_informix_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_informix_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
new file mode 100644
index 000000000..78afe246c
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
@@ -0,0 +1,217 @@
+<?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.0
+ * @filesource
+ */
+
+/**
+ * PDO MySQL 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_pdo_mysql_driver extends CI_DB_pdo_driver {
+
+ public $subdriver = 'mysql';
+
+ protected $_escape_char = '`';
+
+ // clause and character used for LIKE escape sequences - not used in MySQL
+ protected $_like_escape_str = '';
+ protected $_like_escape_chr = '\\';
+
+ protected $_random_keyword = ' RAND()';
+
+ /**
+ * Constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'mysql:host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);
+
+ empty($this->port) OR $this->dsn .= ';port='.$this->port;
+ empty($this->database) OR $this->dsn .= ';dbname='.$this->database;
+ empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;
+ }
+ elseif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 6) === FALSE && is_php('5.3.6'))
+ {
+ $this->dsn .= ';charset='.$this->char_set;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Non-persistent database connection
+ *
+ * @param bool
+ * @return object
+ */
+ public function db_connect($persistent = FALSE)
+ {
+ /* 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 ( ! is_php('5.3.6') && ! empty($this->char_set))
+ {
+ $this->options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES '.$this->char_set
+ .(empty($this->dbcollat) ? '' : ' COLLATE '.$this->dbcollat);
+ }
+
+ return parent::db_connect($persistent);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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)
+ {
+ $sql = 'SHOW TABLES';
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'";
+ }
+
+ 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 '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
+ *
+ * @param string the table name
+ * @return string
+ */
+ protected function _field_data($table)
+ {
+ return 'SELECT * FROM '.$this->protect_identifiers($table).' LIMIT 1';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update_Batch statement
+ *
+ * Generates a platform-specific batch update string from the supplied data
+ *
+ * @param string the table name
+ * @param array the update data
+ * @param array the where clause
+ * @return string
+ */
+ protected function _update_batch($table, $values, $index, $where = NULL)
+ {
+ $ids = array();
+ foreach ($values as $key => $val)
+ {
+ $ids[] = $val[$index];
+
+ foreach (array_keys($val) as $field)
+ {
+ if ($field !== $index)
+ {
+ $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
+ }
+ }
+ }
+
+ $cases = '';
+ foreach ($final as $k => $v)
+ {
+ $cases .= $k." = CASE \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).')';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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;
+ }
+
+}
+
+/* End of file pdo_mysql_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php b/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php
new file mode 100644
index 000000000..56ec1bce1
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php
@@ -0,0 +1,230 @@
+<?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.0
+ * @filesource
+ */
+
+/**
+ * PDO Oracle 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_pdo_oci_driver extends CI_DB_pdo_driver {
+
+ public $subdriver = 'oci';
+
+ /**
+ * 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(1) AS ';
+ protected $_random_keyword = ' ASC'; // Currently not supported
+
+ protected $_reserved_identifiers = array('*', 'rownum');
+
+ /**
+ * Constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'oci:dbname=';
+
+ // Oracle has a slightly different PDO DSN format (Easy Connect),
+ // which also supports pre-defined DSNs.
+ if (empty($this->hostname) && empty($this->port))
+ {
+ $this->dsn .= $this->database;
+ }
+ else
+ {
+ $this->dsn .= '//'.(empty($this->hostname) ? '127.0.0.1' : $this->hostname)
+ .(empty($this->port) ? '' : ':'.$this->port).'/';
+
+ empty($this->database) OR $this->dsn .= $this->database;
+ }
+
+ empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;
+ }
+ elseif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 4) === FALSE)
+ {
+ $this->dsn .= ';charset='.$this->char_set;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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)
+ {
+ $sql = 'SELECT "TABLE_NAME" FROM "ALL_TABLES"';
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ return $sql.' WHERE "TABLE_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 "COLUMN_NAME" FROM "all_tab_columns" WHERE "TABLE_NAME" = '.$this->escape($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)
+ {
+ return 'SELECT * FROM '.$this->protect_identifiers($table).' WHERE rownum = 1';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * From Tables
+ *
+ * This 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;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert_batch statement
+ *
+ * @param string the table name
+ * @param array the insert keys
+ * @param array the insert values
+ * @return string
+ */
+ protected function _insert_batch($table, $keys, $values)
+ {
+ $keys = implode(', ', $keys);
+ $sql = "INSERT ALL\n";
+
+ for ($i = 0, $c = count($values); $i < $c; $i++)
+ {
+ $sql .= ' INTO '.$table.' ('.$keys.') VALUES '.$values[$i]."\n";
+ }
+
+ return $sql.'SELECT * FROM dual';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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);
+ empty($limit) OR $conditions[] = 'rownum <= '.$limit;
+
+ 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)
+ {
+ return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($offset + $limit + 1).')'
+ .($offset ? ' WHERE rnum >= '.($offset + 1): '');
+ }
+
+}
+
+/* End of file pdo_oci_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_oci_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php
new file mode 100644
index 000000000..392754ff7
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php
@@ -0,0 +1,268 @@
+<?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.0
+ * @filesource
+ */
+
+/**
+ * PDO ODBC 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_pdo_odbc_driver extends CI_DB_pdo_driver {
+
+ public $subdriver = 'odbc';
+
+ // The character used for escaping - not used in ODBC
+ protected $_escape_char = '';
+
+ // clause and character used for LIKE escape sequences
+ protected $_like_escape_chr = '!';
+ protected $_like_escape_str = " {escape '%s'} ";
+
+ protected $_random_keyword = ' RAND()';
+
+ /**
+ * Constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'odbc:';
+
+ // Pre-defined DSN
+ if (empty($this->hostname) && empty($this->HOSTNAME) && empty($this->port) && empty($this->PORT))
+ {
+ if (isset($this->DSN))
+ {
+ $this->dsn .= 'DSN='.$this->DSN;
+ }
+ elseif ( ! empty($this->database))
+ {
+ $this->dsn .= 'DSN='.$this->database;
+ }
+
+ return;
+ }
+
+ // If the DSN is not pre-configured - try to build an IBM DB2 connection string
+ $this->dsn .= 'DRIVER='.(isset($this->DRIVER) ? '{'.$this->DRIVER.'}' : '{IBM DB2 ODBC DRIVER}').';';
+
+ if (isset($this->DATABASE))
+ {
+ $this->dsn .= 'DATABASE='.$this->DATABASE.';';
+ }
+ elseif ( ! empty($this->database))
+ {
+ $this->dsn .= 'DATABASE='.$this->database.';';
+ }
+
+ if (isset($this->HOSTNAME))
+ {
+ $this->dsn .= 'HOSTNAME='.$this->HOSTNAME.';';
+ }
+ else
+ {
+ $this->dsn .= 'HOSTNAME='.(empty($this->hostname) ? '127.0.0.1;' : $this->hostname.';');
+ }
+
+ if (isset($this->PORT))
+ {
+ $this->dsn .= 'PORT='.$this->port.';';
+ }
+ elseif ( ! empty($this->port))
+ {
+ $this->dsn .= ';PORT='.$this->port.';';
+ }
+
+ $this->dsn .= 'PROTOCOL='.(isset($this->PROTOCOL) ? $this->PROTOCOL.';' : 'TCPIP;');
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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)
+ {
+ $sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'";
+
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
+ {
+ return $sql." AND table_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 column_name FROM information_schema.columns WHERE table_name = '.$this->escape($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * From Tables
+ *
+ * This 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 (ignored)
+ * @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;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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
+ * @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);
+
+ $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : '';
+
+ return 'DELETE FROM '.$table.$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)
+ {
+ return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql);
+ }
+
+}
+
+/* End of file pdo_odbc_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php
new file mode 100644
index 000000000..9a476f143
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php
@@ -0,0 +1,341 @@
+<?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.0
+ * @filesource
+ */
+
+/**
+ * PDO PostgreSQL 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_pdo_pgsql_driver extends CI_DB_pdo_driver {
+
+ public $subdriver = 'pgsql';
+
+ protected $_random_keyword = ' RANDOM()';
+
+ /**
+ * Constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'pgsql:host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);
+
+ empty($this->port) OR $this->dsn .= ';port='.$this->port;
+ empty($this->database) OR $this->dsn .= ';dbname='.$this->database;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert ID
+ *
+ * @param string
+ * @return int
+ */
+ public function insert_id($name = NULL)
+ {
+ if ($name === NULL && version_compare($this->version(), '8.1', '>='))
+ {
+ $query = $this->query('SELECT LASTVAL() AS ins_id');
+ $query = $query->row();
+ return $query->ins_id;
+ }
+
+ return $this->conn_id->lastInsertId($name);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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)
+ {
+ $sql = 'SELECT "table_name" FROM "information_schema"."tables" WHERE "table_schema" = \'public\'';
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ return $sql.' AND "table_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 "column_name" FROM "information_schema"."columns" WHERE "table_name" = '.$this->escape($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)
+ {
+ return 'SELECT * FROM '.$this->protect_identifiers($table).' LIMIT 1';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * From Tables
+ *
+ * This 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 (ignored)
+ * @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;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update_Batch statement
+ *
+ * Generates a platform-specific batch update string from the supplied data
+ *
+ * @param string the table name
+ * @param array the update data
+ * @param array the where clause
+ * @return string
+ */
+ protected function _update_batch($table, $values, $index, $where = NULL)
+ {
+ $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];
+ }
+ }
+ }
+
+ $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).')';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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)
+ {
+ return $sql.' LIMIT '.$limit.($offset ? ' OFFSET '.$offset : '');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Where
+ *
+ * Called by where() or or_where()
+ *
+ * @param mixed
+ * @param mixed
+ * @param string
+ * @return object
+ */
+ protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL)
+ {
+ if ( ! is_array($key))
+ {
+ $key = array($key => $value);
+ }
+
+ // If the escape value was not set will will base it on the global setting
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
+
+ foreach ($key as $k => $v)
+ {
+ $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0)
+ ? $this->_group_get_type('')
+ : $this->_group_get_type($type);
+
+ $k = (($op = $this->_get_operator($k)) !== FALSE)
+ ? $this->protect_identifiers(substr($k, 0, strpos($k, $op)), FALSE, $escape).strstr($k, $op)
+ : $this->protect_identifiers($k, FALSE, $escape);
+
+ 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';
+ }
+
+ }
+
+ return $this;
+ }
+
+}
+
+/* End of file pdo_pgsql_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php b/system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php
new file mode 100644
index 000000000..bf0363f63
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php
@@ -0,0 +1,167 @@
+<?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.0
+ * @filesource
+ */
+
+/**
+ * PDO SQLite 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_pdo_sqlite_driver extends CI_DB_pdo_driver {
+
+ public $subdriver = 'sqlite';
+
+ /**
+ * 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 $_random_keyword = ' RANDOM()'; // Currently not supported
+
+ /**
+ * Constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'sqlite:';
+
+ if (empty($this->database) && empty($this->hostname))
+ {
+ $this->database = ':memory:';
+ }
+
+ $this->database = empty($this->database) ? $this->hostname : $this->database;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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)
+ {
+ $sql = 'SELECT "NAME" FROM "SQLITE_MASTER" WHERE "TYPE" = \'table\'';
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ return $sql.' AND "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 = '')
+ {
+ // 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 '.$this->protect_identifiers($table).' LIMIT 0,1';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Replace statement
+ *
+ * @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 this method maps to 'DELETE FROM table'
+ *
+ * @param string the table name
+ * @return string
+ */
+ protected function _truncate($table)
+ {
+ return 'DELETE FROM '.$table;
+ }
+
+}
+
+/* End of file pdo_sqlite_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php
new file mode 100644
index 000000000..f125b8f50
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php
@@ -0,0 +1,299 @@
+<?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.0
+ * @filesource
+ */
+
+/**
+ * PDO SQLSRV 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_pdo_sqlsrv_driver extends CI_DB_pdo_driver {
+
+ public $subdriver = 'sqlsrv';
+
+ protected $_random_keyword = ' NEWID()';
+
+ protected $_quoted_identifier;
+
+ /**
+ * Constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'sqlsrv:Server='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);
+
+ empty($this->port) OR $this->dsn .= ','.$this->port;
+ empty($this->database) OR $this->dsn .= ';Database='.$this->database;
+
+ // Some custom options
+
+ if (isset($this->QuotedId))
+ {
+ $this->dsn .= ';QuotedId='.$this->QuotedId;
+ $this->_quoted_identifier = (bool) $this->QuotedId;
+ }
+
+ if (isset($this->ConnectionPooling))
+ {
+ $this->dsn .= ';ConnectionPooling='.$this->ConnectionPooling;
+ }
+
+ if (isset($this->Encrypt))
+ {
+ $this->dsn .= ';Encrypt='.$this->Encrypt;
+ }
+
+ if (isset($this->TraceOn))
+ {
+ $this->dsn .= ';TraceOn='.$this->TraceOn;
+ }
+
+ if (isset($this->TrustServerCertificate))
+ {
+ $this->dsn .= ';TrustServerCertificate='.$this->TrustServerCertificate;
+ }
+
+ empty($this->APP) OR $this->dsn .= ';APP='.$this->APP;
+ empty($this->Failover_Partner) OR $this->dsn .= ';Failover_Partner='.$this->Failover_Partner;
+ empty($this->LoginTimeout) OR $this->dsn .= ';LoginTimeout='.$this->LoginTimeout;
+ empty($this->MultipleActiveResultSets) OR $this->dsn .= ';MultipleActiveResultSets='.$this->MultipleActiveResultSets;
+ empty($this->TraceFile) OR $this->dsn .= ';TraceFile='.$this->TraceFile;
+ empty($this->WSID) OR $this->dsn .= ';WSID='.$this->WSID;
+ }
+ elseif (preg_match('/QuotedId=(0|1)/', $this->dsn, $match))
+ {
+ $this->_quoted_identifier = (bool) $match[1];
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Non-persistent database connection
+ *
+ * @param bool
+ * @return object
+ */
+ public function db_connect($persistent = FALSE)
+ {
+ if ( ! empty($this->char_set) && preg_match('/utf[^8]*8/i', $this->char_set))
+ {
+ $this->options[PDO::SQLSRV_ENCODING_UTF8] = 1;
+ }
+
+ $this->conn_id = parent::db_connect($persistent);
+
+ if ( ! is_object($this->conn_id) OR is_bool($this->_quoted_identifier))
+ {
+ return $this->conn_id;
+ }
+
+ // 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 $this->conn_id;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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 '.$this->escape_identifiers('name')
+ .' FROM '.$this->escape_identifiers('sysobjects')
+ .' WHERE '.$this->escape_identifiers('type')." = 'U'";
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ $sql .= ' AND '.$this->escape_identifiers('name')." LIKE '".$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql.' ORDER BY '.$this->escape_identifiers('name');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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 '.$this->escape_identifiers('column_name')
+ .' FROM '.$this->escape_identifiers('information_schema.columns')
+ .' WHERE '.$this->escape_identifiers('table_name').' = '.$this->escape($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * From Tables
+ *
+ * This 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 (ignored)
+ * @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;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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);
+
+ $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;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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)
+ {
+ // 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);
+ }
+
+}
+
+/* End of file pdo_sqlsrv_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php */
diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php
index c2a188416..20b78673e 100644
--- a/system/database/drivers/postgre/postgre_driver.php
+++ b/system/database/drivers/postgre/postgre_driver.php
@@ -48,12 +48,6 @@ class CI_DB_postgre_driver extends CI_DB {
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
/**
@@ -356,13 +350,13 @@ class CI_DB_postgre_driver extends CI_DB {
$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')
+ if ($table === NULL && $v >= '8.1')
{
$sql = 'SELECT LASTVAL() AS ins_id';
}
- elseif ($table != NULL)
+ elseif ($table !== NULL)
{
- if ($column != NULL && $v >= '8.0')
+ if ($column !== NULL && $v >= '8.0')
{
$sql = 'SELECT pg_get_serial_sequence(\''.$table."', '".$column."') AS seq";
$query = $this->query($sql);
@@ -399,11 +393,13 @@ class CI_DB_postgre_driver extends CI_DB {
*/
protected function _list_tables($prefix_limit = FALSE)
{
- $sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'";
+ $sql = 'SELECT "table_name" FROM "information_schema"."tables" WHERE "table_schema" = \'public\'';
- if ($prefix_limit !== FALSE && $this->dbprefix != '')
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
{
- return $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;
@@ -421,7 +417,7 @@ class CI_DB_postgre_driver extends CI_DB {
*/
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" = '.$this->escape($table);
}
// --------------------------------------------------------------------
@@ -467,12 +463,7 @@ class CI_DB_postgre_driver extends CI_DB {
*/
protected function _from_tables($tables)
{
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return implode(', ', $tables);
+ return is_array($tables) ? implode(', ', $tables) : $tables;
}
// --------------------------------------------------------------------
@@ -528,7 +519,7 @@ class CI_DB_postgre_driver extends CI_DB {
foreach (array_keys($val) as $field)
{
- if ($field != $index)
+ if ($field !== $index)
{
$final[$field][] = 'WHEN '.$val[$index].' THEN '.$val[$field];
}
@@ -544,7 +535,7 @@ class CI_DB_postgre_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).')';
}
@@ -585,7 +576,7 @@ class CI_DB_postgre_driver extends CI_DB {
*/
protected function _limit($sql, $limit, $offset)
{
- return $sql.' LIMIT '.$limit.($offset == 0 ? '' : ' OFFSET '.$offset);
+ return $sql.' LIMIT '.$limit.($offset ? ' OFFSET '.$offset : '');
}
// --------------------------------------------------------------------
@@ -598,27 +589,31 @@ class CI_DB_postgre_driver extends CI_DB {
* @param mixed
* @param mixed
* @param string
+ * @param mixed
* @return object
- *
*/
protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL)
{
- $type = $this->_group_get_type($type);
-
if ( ! is_array($key))
{
$key = array($key => $value);
}
// If the escape value was not set will will base it on the global setting
- if ( ! is_bool($escape))
- {
- $escape = $this->_protect_identifiers;
- }
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
foreach ($key as $k => $v)
{
- $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) ? '' : $type;
+ $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0)
+ ? $this->_group_get_type('')
+ : $this->_group_get_type($type);
+
+ if ($escape === TRUE)
+ {
+ $k = (($op = $this->_get_operator($k)) !== FALSE)
+ ? $this->escape_identifiers(trim(substr($k, 0, strpos($k, $op)))).' '.strstr($k, $op)
+ : $this->escape_identifiers(trim($k));
+ }
if (is_null($v) && ! $this->_has_operator($k))
{
@@ -630,7 +625,6 @@ class CI_DB_postgre_driver extends CI_DB {
{
if ($escape === TRUE)
{
- $k = $this->protect_identifiers($k, FALSE, $escape);
$v = ' '.$this->escape($v);
}
elseif (is_bool($v))
@@ -643,10 +637,6 @@ class CI_DB_postgre_driver extends CI_DB {
$k .= ' = ';
}
}
- else
- {
- $k = $this->protect_identifiers($k, FALSE, $escape);
- }
$this->qb_where[] = $prefix.$k.$v;
if ($this->qb_caching === TRUE)
diff --git a/system/database/drivers/postgre/postgre_forge.php b/system/database/drivers/postgre/postgre_forge.php
index 94c97af50..c434e9510 100644
--- a/system/database/drivers/postgre/postgre_forge.php
+++ b/system/database/drivers/postgre/postgre_forge.php
@@ -58,7 +58,7 @@ class CI_DB_postgre_forge extends CI_DB_forge {
}
else
{
- $sql .= "\n\t".$this->db->protect_identifiers($field);
+ $sql .= "\n\t".$this->db->escape_identifiers($field);
$attributes = array_change_key_case($attributes, CASE_UPPER);
$is_unsigned = ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE);
@@ -107,10 +107,19 @@ class CI_DB_postgre_forge extends CI_DB_forge {
$sql .= '('.$attributes['CONSTRAINT'].')';
}
- $sql .= (isset($attributes['DEFAULT']) ? " DEFAULT '".$attributes['DEFAULT']."'" : '')
- .(( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE) ? ' NULL' : ' NOT NULL')
- // Added new attribute to create unqite fields. Also works with MySQL
- .(( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE) ? ' UNIQUE' : '');
+ if (isset($attributes['DEFAULT']))
+ {
+ $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
+ }
+
+ $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE)
+ ? ' NULL' : ' NOT NULL';
+
+ // Added new attribute to create unique fields. Also works with MySQL
+ if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)
+ {
+ $sql .= ' UNIQUE';
+ }
}
// don't add a comma on the end of the last field
@@ -139,26 +148,17 @@ class CI_DB_postgre_forge extends CI_DB_forge {
{
$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).' ('.$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);";
@@ -167,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).');';
}
}
}
@@ -205,16 +201,16 @@ class CI_DB_postgre_forge extends CI_DB_forge {
*/
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) : '');
+ .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
}
}
diff --git a/system/database/drivers/postgre/postgre_result.php b/system/database/drivers/postgre/postgre_result.php
index f913bc9eb..eb9d647e7 100644
--- a/system/database/drivers/postgre/postgre_result.php
+++ b/system/database/drivers/postgre/postgre_result.php
@@ -33,6 +33,7 @@
* @category Database
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
+ * @since 1.3
*/
class CI_DB_postgre_result extends CI_DB_result {
@@ -43,7 +44,9 @@ class CI_DB_postgre_result extends CI_DB_result {
*/
public function num_rows()
{
- return @pg_num_rows($this->result_id);
+ return is_int($this->num_rows)
+ ? $this->num_rows
+ : $this->num_rows = @pg_num_rows($this->result_id);
}
// --------------------------------------------------------------------
@@ -156,11 +159,12 @@ class CI_DB_postgre_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string
* @return object
*/
- protected function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- return pg_fetch_object($this->result_id);
+ return pg_fetch_object($this->result_id, NULL, $class_name);
}
}
diff --git a/system/database/drivers/sqlite/sqlite_driver.php b/system/database/drivers/sqlite/sqlite_driver.php
index d8b869c2e..19824dbbf 100644
--- a/system/database/drivers/sqlite/sqlite_driver.php
+++ b/system/database/drivers/sqlite/sqlite_driver.php
@@ -43,18 +43,12 @@ class CI_DB_sqlite_driver extends CI_DB {
public $dbdriver = 'sqlite';
// The character used to escape with - not needed for SQLite
- protected $_escape_char = '';
+ 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
/**
@@ -127,7 +121,9 @@ class CI_DB_sqlite_driver extends CI_DB {
*/
protected function _execute($sql)
{
- return @sqlite_query($this->conn_id, $sql);
+ return $this->is_write_type($sql)
+ ? @sqlite_exec($this->conn_id, $sql)
+ : @sqlite_query($this->conn_id, $sql);
}
// --------------------------------------------------------------------
@@ -139,13 +135,8 @@ class CI_DB_sqlite_driver extends CI_DB {
*/
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;
}
@@ -153,7 +144,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;
@@ -168,13 +159,8 @@ class CI_DB_sqlite_driver extends CI_DB {
*/
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;
}
@@ -192,13 +178,8 @@ class CI_DB_sqlite_driver extends CI_DB {
*/
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;
}
@@ -277,12 +258,13 @@ class CI_DB_sqlite_driver extends CI_DB {
*/
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;
}
@@ -314,7 +296,7 @@ class CI_DB_sqlite_driver extends CI_DB {
*/
protected function _field_data($table)
{
- return "SELECT * FROM ".$table." LIMIT 1";
+ return 'SELECT * FROM '.$this->escape_identifiers($table).' LIMIT 1';
}
// --------------------------------------------------------------------
@@ -337,27 +319,6 @@ class CI_DB_sqlite_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This 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)
- {
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return '('.implode(', ', $tables).')';
- }
-
- // --------------------------------------------------------------------
-
- /**
* Replace statement
*
* Generates a platform-specific replace string from the supplied data
@@ -393,32 +354,6 @@ class CI_DB_sqlite_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * 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)
- {
- if ($offset == 0)
- {
- $offset = '';
- }
- else
- {
- $offset .= ", ";
- }
-
- return $sql."LIMIT ".$offset.$limit;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Close DB Connection
*
* @return void
diff --git a/system/database/drivers/sqlite/sqlite_forge.php b/system/database/drivers/sqlite/sqlite_forge.php
index dd6f0f78d..e02e327f3 100644
--- a/system/database/drivers/sqlite/sqlite_forge.php
+++ b/system/database/drivers/sqlite/sqlite_forge.php
@@ -61,6 +61,14 @@ class CI_DB_sqlite_forge extends CI_DB_forge {
{
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;
}
@@ -97,41 +105,31 @@ class CI_DB_sqlite_forge extends CI_DB_forge {
// 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';
- }
- 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';
}
@@ -146,30 +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;
+ return $sql."\n)";
}
// --------------------------------------------------------------------
@@ -191,40 +181,21 @@ class CI_DB_sqlite_forge extends CI_DB_forge {
*/
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 != '')
- {
- return $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');
}
}
diff --git a/system/database/drivers/sqlite/sqlite_result.php b/system/database/drivers/sqlite/sqlite_result.php
index 741dc9d8d..eef9787a1 100644
--- a/system/database/drivers/sqlite/sqlite_result.php
+++ b/system/database/drivers/sqlite/sqlite_result.php
@@ -33,6 +33,7 @@
* @category Database
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
+ * @since 1.3
*/
class CI_DB_sqlite_result extends CI_DB_result {
@@ -43,7 +44,9 @@ class CI_DB_sqlite_result extends CI_DB_result {
*/
public function num_rows()
{
- return @sqlite_num_rows($this->result_id);
+ return is_int($this->num_rows)
+ ? $this->num_rows
+ : $this->num_rows = @sqlite_num_rows($this->result_id);
}
// --------------------------------------------------------------------
@@ -140,17 +143,12 @@ class CI_DB_sqlite_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string
* @return object
*/
- protected function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- if (function_exists('sqlite_fetch_object'))
- {
- return sqlite_fetch_object($this->result_id);
- }
-
- $arr = sqlite_fetch_array($this->result_id, SQLITE_ASSOC);
- return is_array($arr) ? (object) $arr : FALSE;
+ return sqlite_fetch_object($this->result_id, $class_name);
}
}
diff --git a/system/database/drivers/sqlite3/sqlite3_driver.php b/system/database/drivers/sqlite3/sqlite3_driver.php
index ea4cf2d4f..cc35d319f 100644
--- a/system/database/drivers/sqlite3/sqlite3_driver.php
+++ b/system/database/drivers/sqlite3/sqlite3_driver.php
@@ -50,12 +50,6 @@ class CI_DB_sqlite3_driver extends CI_DB {
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()';
/**
@@ -87,7 +81,7 @@ class CI_DB_sqlite3_driver extends CI_DB {
public function db_pconnect()
{
log_message('debug', 'SQLite3 doesn\'t support persistent connections');
- return $this->db_pconnect();
+ return $this->db_connect();
}
// --------------------------------------------------------------------
@@ -104,7 +98,7 @@ class CI_DB_sqlite3_driver extends CI_DB {
return $this->data_cache['version'];
}
- $version = $this->conn_id->version();
+ $version = SQLite3::version();
return $this->data_cache['version'] = $version['versionString'];
}
@@ -318,27 +312,6 @@ class CI_DB_sqlite3_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param string
- * @return string
- */
- protected function _from_tables($tables)
- {
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return '('.implode(', ', $tables).')';
- }
-
- // --------------------------------------------------------------------
-
- /**
* Replace statement
*
* Generates a platform-specific replace string from the supplied data
@@ -374,23 +347,6 @@ class CI_DB_sqlite3_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * 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
diff --git a/system/database/drivers/sqlite3/sqlite3_forge.php b/system/database/drivers/sqlite3/sqlite3_forge.php
index 20f1e6f63..6a76ba929 100644
--- a/system/database/drivers/sqlite3/sqlite3_forge.php
+++ b/system/database/drivers/sqlite3/sqlite3_forge.php
@@ -66,6 +66,14 @@ class CI_DB_sqlite3_forge extends CI_DB_forge {
{
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;
}
@@ -111,13 +119,27 @@ class CI_DB_sqlite3_forge extends CI_DB_forge {
{
$attributes = array_change_key_case($attributes, CASE_UPPER);
- $sql .= "\n\t".$this->db->protect_identifiers($field)
- .' '.$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).' '.$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
@@ -129,22 +151,16 @@ class CI_DB_sqlite3_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).')';
}
@@ -182,9 +198,9 @@ class CI_DB_sqlite3_forge extends CI_DB_forge {
return FALSE;
}
- return 'ALTER TABLE '.$this->db->protect_identifiers($table).' '.$alter_type.' '.$this->db->protect_identifiers($column_name)
+ return 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name)
.' '.$column_definition
- .($default_value != '' ? ' DEFAULT '.$default_value : '')
+ .($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');
}
diff --git a/system/database/drivers/sqlite3/sqlite3_result.php b/system/database/drivers/sqlite3/sqlite3_result.php
index 946b36557..8e9b9c15f 100644
--- a/system/database/drivers/sqlite3/sqlite3_result.php
+++ b/system/database/drivers/sqlite3/sqlite3_result.php
@@ -26,40 +26,21 @@
*/
/**
- * SQLite Result Class
+ * SQLite3 Result Class
*
* This class extends the parent result class: CI_DB_result
*
* @category Database
- * @author Andrey Andreev
- * @link http://codeigniter.com/user_guide/database/
+ * @author Andrey Andreev
+ * @link http://codeigniter.com/user_guide/database/
+ * @since 3.0
*/
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
@@ -153,443 +134,28 @@ class CI_DB_sqlite3_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string
* @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)
+ protected function _fetch_object($class_name = 'stdClass')
{
- // 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]))
+ // No native support for fetching rows as objects
+ if (($row = $this->result_id->fetchArray(SQLITE3_ASSOC)) === FALSE)
{
- $this->current_row = $n;
- return $this->result_object[$n];
+ return FALSE;
}
-
- $row = $this->row_array($n);
- // Cast only if the row exists
- if (count($row) > 0)
+ elseif ($class_name === 'stdClass')
{
- $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
+ $class_name = new $class_name();
+ foreach (array_keys($row) as $key)
{
- $n = 0;
+ $class_name->$key = $row[$key];
}
- 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);
+ return $class_name;
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php
index 961066da7..8bd18bd76 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_driver.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php
@@ -21,7 +21,7 @@
* @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
*/
@@ -43,19 +43,16 @@ class CI_DB_sqlsrv_driver extends CI_DB {
public $dbdriver = 'sqlsrv';
// The character used for escaping
- protected $_escape_char = '';
+ 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 = ' NEWID()'; // not currently supported
+ protected $_random_keyword = ' NEWID()';
+
+ // SQLSRV-specific properties
+ protected $_quoted_identifier = TRUE;
/**
* Non-persistent database connection
@@ -83,7 +80,15 @@ class CI_DB_sqlsrv_driver extends CI_DB {
unset($connection['UID'], $connection['PWD']);
}
- return sqlsrv_connect($this->hostname, $connection);
+ $this->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 $this->conn_id;
}
// --------------------------------------------------------------------
@@ -132,7 +137,7 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*/
protected function _execute($sql)
{
- return (is_write_type($sql) && stripos($sql, 'INSERT') === FALSE)
+ return ($this->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));
}
@@ -146,13 +151,8 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*/
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;
}
@@ -160,7 +160,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);
}
@@ -174,13 +174,8 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*/
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;
}
@@ -197,13 +192,8 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*/
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;
}
@@ -288,7 +278,17 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*/
protected function _list_tables($prefix_limit = FALSE)
{
- return "SELECT name FROM sysobjects WHERE type = 'U' ORDER BY name";
+ $sql = 'SELECT '.$this->escape_identifiers('name')
+ .' FROM '.$this->escape_identifiers('sysobjects')
+ .' WHERE '.$this->escape_identifiers('type')." = 'U'";
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ $sql .= ' AND '.$this->escape_identifiers('name')." LIKE '".$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_escape_like_str, $this->_escape_like_chr);
+ }
+
+ return $sql.' ORDER BY '.$this->escape_identifiers('name');
}
// --------------------------------------------------------------------
@@ -318,7 +318,7 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*/
protected function _field_data($table)
{
- return 'SELECT TOP 1 * FROM '.$table;
+ return 'SELECT TOP 1 * FROM '.$this->protect_identifiers($table);
}
// --------------------------------------------------------------------
@@ -372,12 +372,7 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*/
protected function _from_tables($tables)
{
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return implode(', ', $tables);
+ return is_array($tables) ? implode(', ', $tables) : $tables;
}
// --------------------------------------------------------------------
@@ -397,7 +392,7 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*/
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;
}
@@ -471,7 +466,29 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*/
protected function _limit($sql, $limit, $offset)
{
- return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.($limit + $offset).' ', $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);
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/sqlsrv/sqlsrv_forge.php b/system/database/drivers/sqlsrv/sqlsrv_forge.php
index c817c2c5d..ccdb36929 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_forge.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_forge.php
@@ -21,7 +21,7 @@
* @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
*/
@@ -44,7 +44,7 @@ class CI_DB_sqlsrv_forge extends CI_DB_forge {
* @param mixed primary key(s)
* @param mixed key(s)
* @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @return string
*/
protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
{
@@ -70,31 +70,25 @@ class CI_DB_sqlsrv_forge extends CI_DB_forge {
$sql .= "\n\t".$this->db->escape_identifiers($field).' '.$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';
}
@@ -109,22 +103,16 @@ 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).')';
}
@@ -152,29 +140,18 @@ class CI_DB_sqlsrv_forge extends CI_DB_forge {
*/
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."'";
- }
-
- $sql .= ($null === NULL) ? ' NULL' : ' NOT NULL';
-
- if ($after_field != '')
- {
- return $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) : '');
}
}
diff --git a/system/database/drivers/sqlsrv/sqlsrv_result.php b/system/database/drivers/sqlsrv/sqlsrv_result.php
index 0802677fc..fb7a68647 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_result.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_result.php
@@ -33,6 +33,7 @@
* @category Database
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
+ * @since 2.0.3
*/
class CI_DB_sqlsrv_result extends CI_DB_result {
@@ -43,7 +44,9 @@ class CI_DB_sqlsrv_result extends CI_DB_result {
*/
public function num_rows()
{
- return @sqlsrv_num_rows($this->result_id);
+ return is_int($this->num_rows)
+ ? $this->num_rows
+ : $this->num_rows = @sqlsrv_num_rows($this->result_id);
}
// --------------------------------------------------------------------
@@ -92,12 +95,12 @@ class CI_DB_sqlsrv_result extends CI_DB_result {
$retval = array();
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;
}
@@ -142,11 +145,12 @@ class CI_DB_sqlsrv_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string
* @return object
*/
- protected function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- return sqlsrv_fetch_object($this->result_id);
+ return sqlsrv_fetch_object($this->result_id, $class_name);
}
}
diff --git a/system/database/drivers/sqlsrv/sqlsrv_utility.php b/system/database/drivers/sqlsrv/sqlsrv_utility.php
index 394964b6a..d518cc15a 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_utility.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_utility.php
@@ -21,7 +21,7 @@
* @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
*/
@@ -41,7 +41,7 @@ class CI_DB_sqlsrv_utility extends CI_DB_utility {
* SQLSRV Export
*
* @param array Preferences
- * @return mixed
+ * @return bool
*/
protected function _backup($params = array())
{