summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--system/core/Common.php18
-rw-r--r--system/core/Config.php2
-rw-r--r--system/core/Security.php2
-rw-r--r--system/core/URI.php7
-rw-r--r--system/database/DB_driver.php47
-rw-r--r--system/database/DB_query_builder.php479
-rw-r--r--system/database/DB_result.php19
-rw-r--r--system/database/drivers/cubrid/cubrid_driver.php10
-rw-r--r--system/database/drivers/ibase/ibase_driver.php51
-rw-r--r--system/database/drivers/mssql/mssql_driver.php61
-rw-r--r--system/database/drivers/mysql/mysql_driver.php10
-rw-r--r--system/database/drivers/mysqli/mysqli_driver.php10
-rw-r--r--system/database/drivers/oci8/oci8_driver.php25
-rw-r--r--system/database/drivers/odbc/odbc_driver.php34
-rw-r--r--system/database/drivers/pdo/pdo_driver.php13
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_4d_driver.php43
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php10
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php55
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php46
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php37
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_informix_driver.php43
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php10
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_oci_driver.php25
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php43
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php83
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php57
-rw-r--r--system/database/drivers/postgre/postgre_driver.php85
-rw-r--r--system/database/drivers/sqlsrv/sqlsrv_driver.php57
-rw-r--r--system/libraries/Pagination.php4
-rw-r--r--tests/codeigniter/core/URI_test.php12
-rw-r--r--tests/codeigniter/database/query_builder/like_test.php16
-rw-r--r--tests/mocks/database/schema/skeleton.php3
-rw-r--r--user_guide_src/source/changelog.rst6
-rw-r--r--user_guide_src/source/general/common_functions.rst26
34 files changed, 651 insertions, 798 deletions
diff --git a/system/core/Common.php b/system/core/Common.php
index 341402c6b..2dd31d3e9 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -330,6 +330,24 @@ if ( ! function_exists('get_mimes'))
// ------------------------------------------------------------------------
+if ( ! function_exists('is_https'))
+{
+ /**
+ * Is HTTPS?
+ *
+ * Determines if the application is accessed via an encrypted
+ * (HTTPS) connection.
+ *
+ * @return bool
+ */
+ function is_https()
+ {
+ return ( ! empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off');
+ }
+}
+
+// ------------------------------------------------------------------------
+
if ( ! function_exists('show_error'))
{
/**
diff --git a/system/core/Config.php b/system/core/Config.php
index 8e4f998ef..e78128c76 100644
--- a/system/core/Config.php
+++ b/system/core/Config.php
@@ -75,7 +75,7 @@ class CI_Config {
{
if (isset($_SERVER['HTTP_HOST']))
{
- $base_url = ( ! empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') ? 'https' : 'http';
+ $base_url = is_https() ? 'https' : 'http';
$base_url .= '://'.$_SERVER['HTTP_HOST']
.str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']);
}
diff --git a/system/core/Security.php b/system/core/Security.php
index b22d2cf19..2fbc5b34c 100644
--- a/system/core/Security.php
+++ b/system/core/Security.php
@@ -198,7 +198,7 @@ class CI_Security {
$expire = time() + $this->_csrf_expire;
$secure_cookie = (bool) config_item('cookie_secure');
- if ($secure_cookie && (empty($_SERVER['HTTPS']) OR strtolower($_SERVER['HTTPS']) === 'off'))
+ if ($secure_cookie && ! is_https())
{
return FALSE;
}
diff --git a/system/core/URI.php b/system/core/URI.php
index 6a8b1a5ac..15e6a5599 100644
--- a/system/core/URI.php
+++ b/system/core/URI.php
@@ -165,11 +165,8 @@ class CI_URI {
*/
protected function _set_uri_string($str)
{
- // Filter out control characters
- $str = remove_invisible_characters($str, FALSE);
-
- // If the URI contains only a slash we'll kill it
- $this->uri_string = ($str === '/') ? '' : $str;
+ // Filter out control characters and trim slashes
+ $this->uri_string = trim(remove_invisible_characters($str, FALSE), '/');
}
// --------------------------------------------------------------------
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index fef388bbf..b7b19d207 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -1124,30 +1124,19 @@ abstract class CI_DB_driver {
*
* @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())
+ protected function _update($table, $values)
{
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 : '');
+ .$this->_compile_wh('qb_where')
+ .$this->_compile_order_by()
+ .($this->qb_limit ? ' LIMIT '.$this->qb_limit : '');
}
// --------------------------------------------------------------------
@@ -1160,7 +1149,7 @@ abstract class CI_DB_driver {
*/
protected function _has_operator($str)
{
- return (bool) preg_match('/(\s|<|>|!|=|IS NULL|IS NOT NULL|BETWEEN)/i', trim($str));
+ return (bool) preg_match('/(<|>|!|=|\sIS NULL|\sIS NOT NULL|\sBETWEEN|\sLIKE|\sIN\s*\(|\s)/i', trim($str));
}
// --------------------------------------------------------------------
@@ -1173,8 +1162,30 @@ abstract class CI_DB_driver {
*/
protected function _get_operator($str)
{
- return preg_match('/(=|!|<|>| IS NULL| IS NOT NULL| BETWEEN)/i', $str, $match)
- ? $match[1] : FALSE;
+ static $_operators;
+
+ if (empty($_operators))
+ {
+ $_les = ($this->_like_escape_str !== '')
+ ? '\s+'.preg_quote(trim(sprintf($this->_like_escape_str, $this->_like_escape_chr)))
+ : '';
+ $_operators = array(
+ '\s*(?:<|>|!)?=\s*', // =, <=, >=, !=
+ '\s*<>?\s*', // <, <>
+ '\s*>\s*', // >
+ '\s+IS NULL', // IS NULL
+ '\s+IS NOT NULL', // IS NOT NULL
+ '\s+BETWEEN\s+\S+\s+AND\s+\S+', // BETWEEN value AND value
+ '\s+IN\s*\([^\)]+\)', // IN(list)
+ '\s+NOT IN\s*\([^\)]+\)', // NOT IN (list)
+ '\s+LIKE\s+\S+'.$_les, // LIKE 'expr'[ ESCAPE '%s']
+ '\s+NOT LIKE\s+\S+'.$_les // NOT LIKE 'expr'[ ESCAPE '%s']
+ );
+
+ }
+
+ return preg_match('/'.implode('|', $_operators).'/i', $str, $match)
+ ? $match[0] : FALSE;
}
// --------------------------------------------------------------------
diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php
index 54510ec2e..1ab165835 100644
--- a/system/database/DB_query_builder.php
+++ b/system/database/DB_query_builder.php
@@ -47,7 +47,6 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
protected $qb_from = array();
protected $qb_join = array();
protected $qb_where = array();
- protected $qb_like = array();
protected $qb_groupby = array();
protected $qb_having = array();
protected $qb_keys = array();
@@ -55,7 +54,6 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
protected $qb_offset = FALSE;
protected $qb_orderby = array();
protected $qb_set = array();
- protected $qb_wherein = array();
protected $qb_aliased_tables = array();
protected $qb_store_array = array();
protected $qb_where_group_started = FALSE;
@@ -417,7 +415,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
*/
public function where($key, $value = NULL, $escape = NULL)
{
- return $this->_where($key, $value, 'AND ', $escape);
+ return $this->_wh('qb_where', $key, $value, 'AND ', $escape);
}
// --------------------------------------------------------------------
@@ -435,24 +433,27 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
*/
public function or_where($key, $value = NULL, $escape = NULL)
{
- return $this->_where($key, $value, 'OR ', $escape);
+ return $this->_wh('qb_where', $key, $value, 'OR ', $escape);
}
// --------------------------------------------------------------------
/**
- * Where
+ * WHERE, HAVING
*
- * Called by where() or or_where()
+ * Called by where(), or_where(), having(), or_having()
*
+ * @param string 'qb_where' or 'qb_having'
* @param mixed
* @param mixed
* @param string
- * @param mixed
+ * @param bool
* @return object
*/
- protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL)
+ protected function _wh($qb_key, $key, $value = NULL, $type = 'AND ', $escape = NULL)
{
+ $qb_cache_key = ($qb_key === 'qb_having') ? 'qb_cache_having' : 'qb_cache_where';
+
if ( ! is_array($key))
{
$key = array($key => $value);
@@ -463,17 +464,10 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
foreach ($key as $k => $v)
{
- $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0)
+ $prefix = (count($this->$qb_key) === 0 && count($this->$qb_cache_key) === 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))
{
// value appears not to have been set, assign the test to IS NULL
@@ -484,7 +478,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
{
if ($escape === TRUE)
{
- $v = ' '.$this->escape($v);
+ $v = ' '.(is_int($v) ? $v : $this->escape($v));
}
if ( ! $this->_has_operator($k))
@@ -493,11 +487,11 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
}
}
- $this->qb_where[] = $prefix.$k.$v;
+ $this->{$qb_key}[] = array('condition' => $prefix.$k.$v, 'escape' => $escape);
if ($this->qb_caching === TRUE)
{
- $this->qb_cache_where[] = $prefix.$k.$v;
- $this->qb_cache_exists[] = 'where';
+ $this->{$qb_cache_key}[] = array('condition' => $prefix.$k.$v, 'escape' => $escape);
+ $this->qb_cache_exists[] = substr($qb_key, 3);
}
}
@@ -602,27 +596,25 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$not = ($not) ? ' NOT' : '';
+ $where_in = array();
foreach ($values as $value)
{
- $this->qb_wherein[] = $this->escape($value);
- }
-
- if ($escape === TRUE)
- {
- $key = $this->escape_identifiers(trim($key));
+ $where_in[] = $this->escape($value);
}
$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).') ';
+ $where_in = array(
+ 'condition' => $prefix.$key.$not.' IN('.implode(', ', $where_in).')',
+ 'escape' => $escape
+ );
+ $this->qb_where[] = $where_in;
if ($this->qb_caching === TRUE)
{
$this->qb_cache_where[] = $where_in;
$this->qb_cache_exists[] = 'where';
}
- // reset the array for multiple calls
- $this->qb_wherein = array();
return $this;
}
@@ -635,12 +627,14 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* multiple calls with AND
*
* @param mixed
- * @param mixed
+ * @param string
+ * @param string
+ * @param bool
* @return object
*/
- public function like($field, $match = '', $side = 'both')
+ public function like($field, $match = '', $side = 'both', $escape = NULL)
{
- return $this->_like($field, $match, 'AND ', $side);
+ return $this->_like($field, $match, 'AND ', $side, '', $escape);
}
// --------------------------------------------------------------------
@@ -652,12 +646,14 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* multiple calls with AND
*
* @param mixed
- * @param mixed
+ * @param string
+ * @param string
+ * @param bool
* @return object
*/
- public function not_like($field, $match = '', $side = 'both')
+ public function not_like($field, $match = '', $side = 'both', $escape = NULL)
{
- return $this->_like($field, $match, 'AND ', $side, 'NOT');
+ return $this->_like($field, $match, 'AND ', $side, 'NOT', $escape);
}
// --------------------------------------------------------------------
@@ -669,12 +665,14 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* multiple calls with OR
*
* @param mixed
- * @param mixed
+ * @param string
+ * @param string
+ * @param bool
* @return object
*/
- public function or_like($field, $match = '', $side = 'both')
+ public function or_like($field, $match = '', $side = 'both', $escape = NULL)
{
- return $this->_like($field, $match, 'OR ', $side);
+ return $this->_like($field, $match, 'OR ', $side, '', $escape);
}
// --------------------------------------------------------------------
@@ -686,12 +684,14 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* multiple calls with OR
*
* @param mixed
- * @param mixed
+ * @param string
+ * @param string
+ * @param bool
* @return object
*/
- public function or_not_like($field, $match = '', $side = 'both')
+ public function or_not_like($field, $match = '', $side = 'both', $escape = NULL)
{
- return $this->_like($field, $match, 'OR ', $side, 'NOT');
+ return $this->_like($field, $match, 'OR ', $side, 'NOT', $escape);
}
// --------------------------------------------------------------------
@@ -699,56 +699,60 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
/**
* Like
*
- * Called by like() or orlike()
+ * Called by like(), or_like(), not_like, or_not_like()
*
* @param mixed
- * @param mixed
* @param string
+ * @param string
+ * @param string
+ * @param string
+ * @param bool
* @return object
*/
- protected function _like($field, $match = '', $type = 'AND ', $side = 'both', $not = '')
+ protected function _like($field, $match = '', $type = 'AND ', $side = 'both', $not = '', $escape = NULL)
{
if ( ! is_array($field))
{
$field = array($field => $match);
}
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
+ $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0)
+ ? $this->_group_get_type('') : $this->_group_get_type($type);
+
foreach ($field as $k => $v)
{
- $k = $this->protect_identifiers($k);
- $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 !== '')
{
- $like_statement = $like_statement.sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ $like_statement .= sprintf($this->_like_escape_str, $this->_like_escape_chr);
}
- $this->qb_like[] = $like_statement;
+ $this->qb_where[] = array('condition' => $like_statement, 'escape' => $escape);
if ($this->qb_caching === TRUE)
{
- $this->qb_cache_like[] = $like_statement;
- $this->qb_cache_exists[] = 'like';
+ $this->qb_cache_where[] = $like_statement;
+ $this->qb_cache_exists[] = 'where';
}
-
}
return $this;
@@ -769,11 +773,15 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$this->qb_where_group_started = TRUE;
$prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) ? '' : $type;
- $this->qb_where[] = $value = $prefix.$not.str_repeat(' ', ++$this->qb_where_group_count).' (';
+ $where = array(
+ 'condition' => $prefix.$not.str_repeat(' ', ++$this->qb_where_group_count).' (',
+ 'escape' => FALSE
+ );
+ $this->qb_where[] = $where;
if ($this->qb_caching)
{
- $this->qb_cache_where[] = $value;
+ $this->qb_cache_where[] = $where;
}
return $this;
@@ -825,11 +833,15 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
public function group_end()
{
$this->qb_where_group_started = FALSE;
- $this->qb_where[] = $value = str_repeat(' ', $this->qb_where_group_count--) . ')';
+ $where = array(
+ 'condition' => str_repeat(' ', $this->qb_where_group_count--).')',
+ 'escape' => FALSE
+ );
+ $this->qb_where[] = $where;
if ($this->qb_caching)
{
- $this->qb_cache_where[] = $value;
+ $this->qb_cache_where[] = $where;
}
return $this;
@@ -862,13 +874,18 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* GROUP BY
*
* @param string
+ * @param bool
* @return object
*/
- public function group_by($by)
+ public function group_by($by, $escape = NULL)
{
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
+
if (is_string($by))
{
- $by = explode(',', $by);
+ $by = ($escape === TRUE)
+ ? explode(',', $by)
+ : array($by);
}
foreach ($by as $val)
@@ -877,8 +894,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
if ($val !== '')
{
- $this->qb_groupby[] = $val = $this->protect_identifiers($val);
+ $val = array('field' => $val, 'escape' => $escape);
+ $this->qb_groupby[] = $val;
if ($this->qb_caching === TRUE)
{
$this->qb_cache_groupby[] = $val;
@@ -902,9 +920,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* @param bool
* @return object
*/
- public function having($key, $value = '', $escape = NULL)
+ public function having($key, $value = NULL, $escape = NULL)
{
- return $this->_having($key, $value, 'AND ', $escape);
+ return $this->_wh('qb_having', $key, $value, 'AND ', $escape);
}
// --------------------------------------------------------------------
@@ -919,60 +937,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* @param bool
* @return object
*/
- public function or_having($key, $value = '', $escape = NULL)
- {
- return $this->_having($key, $value, 'OR ', $escape);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Sets the HAVING values
- *
- * Called by having() or or_having()
- *
- * @param string
- * @param string
- * @param string
- * @param bool
- * @return object
- */
- protected function _having($key, $value = '', $type = 'AND ', $escape = NULL)
+ public function or_having($key, $value = NULL, $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;
-
- $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 !== '')
- {
- $v = ' '.$this->escape($v);
- }
-
- $this->qb_having[] = $prefix.$k.$v;
- if ($this->qb_caching === TRUE)
- {
- $this->qb_cache_having[] = $prefix.$k.$v;
- $this->qb_cache_exists[] = 'having';
- }
- }
-
- return $this;
+ return $this->_wh('qb_having', $key, $value, 'OR ', $escape);
}
// --------------------------------------------------------------------
@@ -981,54 +948,50 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* Sets the ORDER BY value
*
* @param string
- * @param string direction: asc or desc
+ * @param string direction: ASC or DESC
* @param bool enable field name escaping
* @return object
*/
public function order_by($orderby, $direction = '', $escape = NULL)
{
- if (strtolower($direction) === 'random')
+ $direction = trim($direction);
+
+ if (strtolower($direction) === 'random' OR $orderby === $this->_random_keyword)
+ {
+ // Random ordered results don't need a field name
+ $orderby = $this->_random_keyword;
+ $direction = '';
+ }
+ elseif (empty($orderby))
{
- $orderby = ''; // Random results want or don't need a field name
- $direction = $this->_random_keyword;
+ return $this;
}
- elseif (trim($direction) !== '')
+ elseif ($direction !== '')
{
- $direction = in_array(strtoupper(trim($direction)), array('ASC', 'DESC'), TRUE) ? ' '.$direction : ' ASC';
+ $direction = in_array(strtoupper(trim($direction)), array('ASC', 'DESC'), TRUE) ? ' '.$direction : '';
}
is_bool($escape) OR $escape = $this->_protect_identifiers;
- if ($escape === TRUE && strpos($orderby, ',') !== FALSE)
+ if ($escape === FALSE)
{
- $temp = array();
- foreach (explode(',', $orderby) as $part)
- {
- $part = trim($part);
- if ( ! in_array($part, $this->qb_aliased_tables))
- {
- $part = preg_match('/^(.+)\s+(ASC|DESC)$/i', $part, $matches)
- ? $this->protect_identifiers(rtrim($matches[1])).' '.$matches[2]
- : $this->protect_identifiers($part);
- }
-
- $temp[] = $part;
- }
-
- $orderby = implode(', ', $temp);
+ $qb_orderby[] = array(array('field' => $orderby, 'direction' => $direction, $escape => FALSE));
}
- elseif ($direction !== $this->_random_keyword && $escape === TRUE)
+ else
{
- $orderby = preg_match('/^(.+)\s+(ASC|DESC)$/i', $orderby, $matches)
- ? $this->protect_identifiers(rtrim($matches[1])).' '.$matches[2]
- : $this->protect_identifiers($orderby);
+ $qb_orderby = array();
+ foreach (explode(',', $orderby) as $field)
+ {
+ $qb_orderby[] = ($direction === '' && preg_match('/\s+(ASC|DESC)$/i', rtrim($field), $match, PREG_OFFSET_CAPTURE))
+ ? array('field' => ltrim(substr($field, 0, $match[0][1])), 'direction' => ' '.$match[1][0], 'escape' => TRUE)
+ : array('field' => trim($field), 'direction' => $direction, 'escape' => TRUE);
+ }
}
- $this->qb_orderby[] = $orderby_statement = $orderby.$direction;
-
+ $this->qb_orderby = array_merge($this->qb_orderby, $qb_orderby);
if ($this->qb_caching === TRUE)
{
- $this->qb_cache_orderby[] = $orderby_statement;
+ $this->qb_cache_orderby = array_merge($this->qb_cache_orderby, $qb_orderby);
$this->qb_cache_exists[] = 'orderby';
}
@@ -1044,7 +1007,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* @param int the offset value
* @return object
*/
- public function limit($value, $offset = NULL)
+ public function limit($value, $offset = FALSE)
{
is_null($value) OR $this->qb_limit = (int) $value;
empty($offset) OR $this->qb_offset = (int) $offset;
@@ -1074,13 +1037,11 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* 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)
+ protected function _limit($sql)
{
- return $sql.' LIMIT '.($offset ? $offset.', ' : '').$limit;
+ return $sql.' LIMIT '.($this->qb_offset ? $this->qb_offset.', ' : '').$this->qb_limit;
}
// --------------------------------------------------------------------
@@ -1557,7 +1518,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
return FALSE;
}
- $sql = $this->_update($this->protect_identifiers($this->qb_from[0], TRUE, NULL, FALSE), $this->qb_set, $this->qb_where, $this->qb_orderby, $this->qb_limit);
+ $sql = $this->_update($this->protect_identifiers($this->qb_from[0], TRUE, NULL, FALSE), $this->qb_set);
if ($reset === TRUE)
{
@@ -1604,7 +1565,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$this->limit($limit);
}
- $sql = $this->_update($this->protect_identifiers($this->qb_from[0], TRUE, NULL, FALSE), $this->qb_set, $this->qb_where, $this->qb_orderby, $this->qb_limit, $this->qb_like);
+ $sql = $this->_update($this->protect_identifiers($this->qb_from[0], TRUE, NULL, FALSE), $this->qb_set);
$this->_reset_write();
return $this->query($sql);
@@ -1686,7 +1647,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
// Batch this baby
for ($i = 0, $total = count($this->qb_set); $i < $total; $i += 100)
{
- $this->query($this->_update_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->qb_set, $i, 100), $this->protect_identifiers($index), $this->qb_where));
+ $this->query($this->_update_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->qb_set, $i, 100), $this->protect_identifiers($index)));
}
$this->_reset_write();
@@ -1851,7 +1812,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* @param mixed the where clause
* @param mixed the limit clause
* @param bool
- * @return object
+ * @return mixed
*/
public function delete($table = '', $where = '', $limit = NULL, $reset_data = TRUE)
{
@@ -1871,10 +1832,8 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
{
foreach ($table as $single_table)
{
- $this->delete($single_table, $where, $limit, FALSE);
+ $this->delete($single_table, $where, $limit, $reset_data);
}
-
- $this->_reset_write();
return;
}
else
@@ -1892,12 +1851,12 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$this->limit($limit);
}
- if (count($this->qb_where) === 0 && count($this->qb_wherein) === 0 && count($this->qb_like) === 0)
+ if (count($this->qb_where) === 0)
{
return ($this->db_debug) ? $this->display_error('db_del_must_use_where') : FALSE;
}
- $sql = $this->_delete($table, $this->qb_where, $this->qb_like, $this->qb_limit);
+ $sql = $this->_delete($table);
if ($reset_data)
{
$this->_reset_write();
@@ -1914,21 +1873,12 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* 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)
+ protected function _delete($table)
{
- $conditions = array();
-
- empty($where) OR $conditions[] = implode(' ', $where);
- empty($like) OR $conditions[] = implode(' ', $like);
-
- return 'DELETE FROM '.$table
- .(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : '')
- .($limit ? ' LIMIT '.(int) $limit : '');
+ return 'DELETE FROM '.$table.$this->_compile_wh('qb_where')
+ .($this->qb_limit ? ' LIMIT '.$this->qb_limit : '');
}
// --------------------------------------------------------------------
@@ -2066,50 +2016,154 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$sql .= "\n".implode("\n", $this->qb_join);
}
- // Write the "WHERE" portion of the query
- if (count($this->qb_where) > 0 OR count($this->qb_like) > 0)
+ $sql .= $this->_compile_wh('qb_where')
+ .$this->_compile_group_by()
+ .$this->_compile_wh('qb_having')
+ .$this->_compile_order_by(); // ORDER BY
+
+ // LIMIT
+ if ($this->qb_limit)
{
- $sql .= "\nWHERE ";
+ return $this->_limit($sql."\n");
}
- $sql .= implode("\n", $this->qb_where);
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
- // Write the "LIKE" portion of the query
- if (count($this->qb_like) > 0)
+ /**
+ * Compile WHERE, HAVING statements
+ *
+ * Escapes identifiers in WHERE and HAVING statements at execution time.
+ *
+ * Required so that aliases are tracked properly, regardless of wether
+ * where(), or_where(), having(), or_having are called prior to from(),
+ * join() and dbprefix is added only if needed.
+ *
+ * @param string 'qb_where' or 'qb_having'
+ * @return string SQL statement
+ */
+ protected function _compile_wh($qb_key)
+ {
+ if (count($this->$qb_key) > 0)
{
- if (count($this->qb_where) > 0)
+ for ($i = 0, $c = count($this->$qb_key); $i < $c; $i++)
{
- $sql .= "\nAND ";
+ if ($this->{$qb_key}[$i]['escape'] === FALSE)
+ {
+ $this->{$qb_key}[$i] = $this->{$qb_key}[$i]['condition'];
+ continue;
+ }
+
+ // Split multiple conditions
+ $conditions = preg_split(
+ '/(\s*AND\s+|\s*OR\s+)/i',
+ $this->{$qb_key}[$i]['condition'],
+ -1,
+ PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY
+ );
+
+ for ($ci = 0, $cc = count($conditions); $ci < $cc; $ci++)
+ {
+ if (($op = $this->_get_operator($conditions[$ci])) === FALSE
+ OR ! preg_match('/^(\(?)(.*)('.preg_quote($op).')\s*(.*(?<!\)))?(\)?)$/i', $conditions[$ci], $matches))
+ {
+ continue;
+ }
+
+ // $matches = array(
+ // 0 => '(test <= foo)', /* the whole thing */
+ // 1 => '(', /* optional */
+ // 2 => 'test', /* the field name */
+ // 3 => ' <= ', /* $op */
+ // 4 => 'foo', /* optional, if $op is e.g. 'IS NULL' */
+ // 5 => ')' /* optional */
+ // );
+
+ if ( ! empty($matches[4]))
+ {
+ $this->_is_literal($matches[4]) OR $matches[4] = $this->protect_identifiers(trim($matches[4]));
+ $matches[4] = ' '.$matches[4];
+ }
+
+ $conditions[$ci] = $matches[1].$this->protect_identifiers(trim($matches[2]))
+ .' '.trim($matches[3]).$matches[4].$matches[5];
+ }
+
+ $this->{$qb_key}[$i] = implode('', $conditions);
}
- $sql .= implode("\n", $this->qb_like);
+ return ($qb_key === 'qb_having' ? "\nHAVING " : "\nWHERE ")
+ .implode("\n", $this->$qb_key);
}
- // Write the "GROUP BY" portion of the query
+ return '';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Compile GROUP BY
+ *
+ * Escapes identifiers in GROUP BY statements at execution time.
+ *
+ * Required so that aliases are tracked properly, regardless of wether
+ * group_by() is called prior to from(), join() and dbprefix is added
+ * only if needed.
+ *
+ * @return string SQL statement
+ */
+ protected function _compile_group_by()
+ {
if (count($this->qb_groupby) > 0)
{
- $sql .= "\nGROUP BY ".implode(', ', $this->qb_groupby);
- }
+ for ($i = 0, $c = count($this->qb_groupby); $i < $c; $i++)
+ {
+ $this->qb_groupby[$i] = ($this->qb_groupby[$i]['escape'] === FALSE OR $this->_is_literal($this->qb_groupby[$i]['field']))
+ ? $this->qb_groupby[$i]['field']
+ : $this->protect_identifiers($this->qb_groupby[$i]['field']);
+ }
- // Write the "HAVING" portion of the query
- if (count($this->qb_having) > 0)
- {
- $sql .= "\nHAVING ".implode("\n", $this->qb_having);
+ return "\nGROUP BY ".implode(', ', $this->qb_groupby);
}
- // Write the "ORDER BY" portion of the query
+ return '';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Compile ORDER BY
+ *
+ * Escapes identifiers in ORDER BY statements at execution time.
+ *
+ * Required so that aliases are tracked properly, regardless of wether
+ * order_by() is called prior to from(), join() and dbprefix is added
+ * only if needed.
+ *
+ * @return string SQL statement
+ */
+ protected function _compile_order_by()
+ {
if (count($this->qb_orderby) > 0)
{
- $sql .= "\nORDER BY ".implode(', ', $this->qb_orderby);
- }
+ $sql = "\nORDER BY ";
- // Write the "LIMIT" portion of the query
- if (is_numeric($this->qb_limit))
- {
- return $this->_limit($sql."\n", $this->qb_limit, $this->qb_offset);
+ for ($i = 0, $c = count($this->qb_orderby); $i < $c; $i++)
+ {
+ if ($this->qb_orderby[$i]['escape'] !== FALSE && ! $this->_is_literal($this->qb_orderby[$i]['field']))
+ {
+ $this->qb_orderby[$i]['field'] = $this->protect_identifiers($this->qb_orderby[$i]['field']);
+ }
+
+ $this->qb_orderby[$i] = $this->qb_orderby[$i]['field'].$this->qb_orderby[$i]['direction'];
+ }
+
+ return "\nORDER BY ".implode(', ', $this->qb_orderby);
}
- return $sql;
+ return '';
}
// --------------------------------------------------------------------
@@ -2276,6 +2330,36 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
// --------------------------------------------------------------------
/**
+ * Is literal
+ *
+ * Determines if a string represents a literal value or a field name
+ *
+ * @param string
+ * @return bool
+ */
+ protected function _is_literal($str)
+ {
+ $str = trim($str);
+
+ if (empty($str))
+ {
+ return TRUE;
+ }
+
+ static $_str;
+
+ if (empty($_str))
+ {
+ $_str = ($this->_escape_char !== '"')
+ ? array('"', "'") : array("'");
+ }
+
+ return (ctype_digit($str) OR in_array($str[0], $_str, TRUE));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Reset Query Builder values.
*
* Publicly-visible method to reset the QB values.
@@ -2321,11 +2405,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
'qb_from' => array(),
'qb_join' => array(),
'qb_where' => array(),
- 'qb_like' => array(),
'qb_groupby' => array(),
'qb_having' => array(),
'qb_orderby' => array(),
- 'qb_wherein' => array(),
'qb_aliased_tables' => array(),
'qb_no_escape' => array(),
'qb_distinct' => FALSE,
@@ -2350,7 +2432,6 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
'qb_set' => array(),
'qb_from' => array(),
'qb_where' => array(),
- 'qb_like' => array(),
'qb_orderby' => array(),
'qb_keys' => array(),
'qb_limit' => FALSE
diff --git a/system/database/DB_result.php b/system/database/DB_result.php
index d44df6c02..e747044d8 100644
--- a/system/database/DB_result.php
+++ b/system/database/DB_result.php
@@ -251,27 +251,24 @@ class CI_DB_result {
/**
* Query result. Acts as a wrapper function for the following functions.
*
- * @param string
+ * @param mixed
* @param string can be "object" or "array"
- * @return mixed either a result object or array
+ * @return mixed
*/
public function row($n = 0, $type = 'object')
{
if ( ! is_numeric($n))
{
// We cache the row data for subsequent uses
- if ( ! is_array($this->row_data))
- {
- $this->row_data = $this->row_array(0);
- }
+ is_array($this->row_data) OR $this->row_data = $this->row_array(0);
- // array_key_exists() instead of isset() to allow for MySQL NULL values
- if (array_key_exists($n, $this->row_data))
+ // array_key_exists() instead of isset() to allow for NULL values
+ if (empty($this->row_data) OR ! array_key_exists($n, $this->row_data))
{
- return $this->row_data[$n];
+ return NULL;
}
- // reset the $n variable if the result was not achieved
- $n = 0;
+
+ return $this->row_data[$n];
}
if ($type === 'object') return $this->row_object($n);
diff --git a/system/database/drivers/cubrid/cubrid_driver.php b/system/database/drivers/cubrid/cubrid_driver.php
index 01d0ee39e..7f8f297bb 100644
--- a/system/database/drivers/cubrid/cubrid_driver.php
+++ b/system/database/drivers/cubrid/cubrid_driver.php
@@ -394,10 +394,10 @@ class CI_DB_cubrid_driver extends CI_DB {
*
* @param string the table name
* @param array the update data
- * @param array the where clause
+ * @param string the where key
* @return string
*/
- protected function _update_batch($table, $values, $index, $where = NULL)
+ protected function _update_batch($table, $values, $index)
{
$ids = array();
foreach ($values as $key => $val)
@@ -421,9 +421,9 @@ class CI_DB_cubrid_driver extends CI_DB {
.'ELSE '.$k.' END, ';
}
- return 'UPDATE '.$table.' SET '.substr($cases, 0, -2)
- .' WHERE '.(($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '')
- .$index.' IN ('.implode(',', $ids).')';
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
+
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/ibase/ibase_driver.php b/system/database/drivers/ibase/ibase_driver.php
index ab1d1b88d..96d6f6526 100644
--- a/system/database/drivers/ibase/ibase_driver.php
+++ b/system/database/drivers/ibase/ibase_driver.php
@@ -281,7 +281,10 @@ class CI_DB_ibase_driver extends CI_DB {
*/
protected function _field_data($table)
{
- return $this->_limit('SELECT * FROM '.$this->protect_identifiers($table), 1, NULL);
+ $this->qb_limit = 1;
+ $sql = $this->_limit('SELECT * FROM '.$this->protect_identifiers($table));
+ $this->qb_limit = 0;
+ return $sql;
}
// --------------------------------------------------------------------
@@ -308,29 +311,12 @@ class CI_DB_ibase_driver extends CI_DB {
*
* @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())
+ protected function _update($table, $values)
{
- 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) : '');
+ $this->qb_limit = FALSE;
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
@@ -359,19 +345,12 @@ class CI_DB_ibase_driver extends CI_DB {
* 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)
+ protected function _delete($table)
{
- $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) : '');
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
@@ -382,22 +361,20 @@ class CI_DB_ibase_driver extends CI_DB {
* 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)
+ protected function _limit($sql)
{
// Limit clause depends on if Interbase or Firebird
if (stripos($this->version(), 'firebird') !== FALSE)
{
- $select = 'FIRST '. (int) $limit
- .($offset ? ' SKIP '. (int) $offset : '');
+ $select = 'FIRST '.$this->qb_limit
+ .($this->qb_offset ? ' SKIP '.$this->qb_offset : '');
}
else
{
$select = 'ROWS '
- .($offset ? (int) $offset.' TO '.($limit + $offset) : (int) $limit);
+ .($this->qb_offset ? $this->qb_offset.' TO '.($this->qb_limit + $this->qb_offset) : $this->qb_limit);
}
return preg_replace('`SELECT`i', 'SELECT '.$select, $sql);
diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php
index a5ace02e6..4369bbefb 100644
--- a/system/database/drivers/mssql/mssql_driver.php
+++ b/system/database/drivers/mssql/mssql_driver.php
@@ -368,27 +368,13 @@ class CI_DB_mssql_driver extends CI_DB {
*
* @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())
+ protected function _update($table, $values)
{
- 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 '.$where;
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
@@ -417,23 +403,16 @@ class CI_DB_mssql_driver extends CI_DB {
* 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)
+ protected function _delete($table)
{
- $conditions = array();
-
- empty($where) OR $conditions[] = implode(' ', $where);
- empty($like) OR $conditions[] = implode(' ', $like);
-
- $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : '';
+ if ($this->qb_limit)
+ {
+ return 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete';
+ }
- return ($limit)
- ? 'WITH ci_delete AS (SELECT TOP '.$limit.' * FROM '.$table.$conditions.') DELETE FROM ci_delete'
- : 'DELETE FROM '.$table.$conditions;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
@@ -444,33 +423,25 @@ class CI_DB_mssql_driver extends CI_DB {
* 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)
+ protected function _limit($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;
+ $limit = $this->qb_offset + $this->qb_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))
+ if (version_compare($this->version(), '9', '>=') && $this->qb_offset && ! empty($this->qb_orderby))
{
- $orderby = 'ORDER BY '.implode(', ', $this->qb_orderby);
+ $orderby = $this->_compile_order_by();
// We have to strip the ORDER BY clause
$sql = trim(substr($sql, 0, strrpos($sql, $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)
+ .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($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;
+ ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit;
}
return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql);
diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php
index 99bf55942..ce9f73011 100644
--- a/system/database/drivers/mysql/mysql_driver.php
+++ b/system/database/drivers/mysql/mysql_driver.php
@@ -427,10 +427,10 @@ class CI_DB_mysql_driver extends CI_DB {
*
* @param string the table name
* @param array the update data
- * @param array the where clause
+ * @param string the where key
* @return string
*/
- protected function _update_batch($table, $values, $index, $where = NULL)
+ protected function _update_batch($table, $values, $index)
{
$ids = array();
foreach ($values as $key => $val)
@@ -454,9 +454,9 @@ class CI_DB_mysql_driver extends CI_DB {
.'ELSE '.$k.' END, ';
}
- return 'UPDATE '.$table.' SET '.substr($cases, 0, -2)
- .' WHERE '.(($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '')
- .$index.' IN('.implode(',', $ids).')';
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
+
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index dc72ecc5f..91ab13a3c 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -417,10 +417,10 @@ class CI_DB_mysqli_driver extends CI_DB {
*
* @param string the table name
* @param array the update data
- * @param array the where clause
+ * @param string the where key
* @return string
*/
- protected function _update_batch($table, $values, $index, $where = NULL)
+ protected function _update_batch($table, $values, $index)
{
$ids = array();
foreach ($values as $key => $val)
@@ -444,11 +444,9 @@ class CI_DB_mysqli_driver extends CI_DB {
.'ELSE '.$k.' END, ';
}
- $where = ($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '';
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
- return 'UPDATE '.$table.' SET '.substr($cases, 0, -2)
- .' WHERE '.(($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '')
- .$index.' IN('.implode(',', $ids).')';
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php
index 72cbce5c1..8e4f4ef9d 100644
--- a/system/database/drivers/oci8/oci8_driver.php
+++ b/system/database/drivers/oci8/oci8_driver.php
@@ -591,20 +591,17 @@ class CI_DB_oci8_driver extends CI_DB {
* 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)
+ protected function _delete($table)
{
- $conditions = array();
-
- empty($where) OR $conditions[] = implode(' ', $where);
- empty($like) OR $conditions[] = implode(' ', $like);
- empty($limit) OR $conditions[] = 'rownum <= '.$limit;
+ if ($this->qb_limit)
+ {
+ $this->where('rownum <= ',$this->qb_limit, FALSE);
+ $this->qb_limit = FALSE;
+ }
- return 'DELETE FROM '.$table.(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : '');
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
@@ -615,15 +612,13 @@ class CI_DB_oci8_driver extends CI_DB {
* 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)
+ protected function _limit($sql)
{
$this->limit_used = TRUE;
- return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($offset + $limit + 1).')'
- .($offset ? ' WHERE rnum >= '.($offset + 1): '');
+ return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($this->qb_offset + $this->qb_limit + 1).')'
+ .($this->qb_offset ? ' WHERE rnum >= '.($this->qb_offset + 1): '');
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php
index c1f6ccfe2..741b7419f 100644
--- a/system/database/drivers/odbc/odbc_driver.php
+++ b/system/database/drivers/odbc/odbc_driver.php
@@ -289,6 +289,24 @@ class CI_DB_odbc_driver extends CI_DB {
// --------------------------------------------------------------------
/**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @param string the table name
+ * @param array the update data
+ * @return string
+ */
+ protected function _update($table, $values)
+ {
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Truncate statement
*
* Generates a platform-specific truncate string from the supplied data
@@ -307,6 +325,22 @@ class CI_DB_odbc_driver extends CI_DB {
// --------------------------------------------------------------------
/**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @param string the table name
+ * @return string
+ */
+ protected function _delete($table)
+ {
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Close DB Connection
*
* @return void
diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php
index 0ffe3bc13..f4509b17c 100644
--- a/system/database/drivers/pdo/pdo_driver.php
+++ b/system/database/drivers/pdo/pdo_driver.php
@@ -356,14 +356,12 @@ class CI_DB_pdo_driver extends CI_DB {
*
* @param string the table name
* @param array the update data
- * @param array the where clause
+ * @param string the where key
* @return string
*/
- protected function _update_batch($table, $values, $index, $where = NULL)
+ protected function _update_batch($table, $values, $index)
{
$ids = array();
- $where = ($where !== '' && count($where) >=1) ? implode(' ', $where).' AND ' : '';
-
foreach ($values as $key => $val)
{
$ids[] = $val[$index];
@@ -377,9 +375,7 @@ class CI_DB_pdo_driver extends CI_DB {
}
}
- $sql = 'UPDATE '.$table.' SET ';
$cases = '';
-
foreach ($final as $k => $v)
{
$cases .= $k.' = CASE '."\n";
@@ -392,10 +388,9 @@ class CI_DB_pdo_driver extends CI_DB {
$cases .= 'ELSE '.$k.' END, ';
}
- $sql .= substr($cases, 0, -2);
- $sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')';
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
- return $sql;
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php b/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php
index efc0500a5..438d312a1 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php
@@ -136,27 +136,13 @@ class CI_DB_pdo_4d_driver extends CI_DB_pdo_driver {
*
* @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())
+ protected function _update($table, $values)
{
- 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;
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
@@ -167,21 +153,12 @@ class CI_DB_pdo_4d_driver extends CI_DB_pdo_driver {
* 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)
+ protected function _delete($table)
{
- $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;
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
@@ -192,13 +169,11 @@ class CI_DB_pdo_4d_driver extends CI_DB_pdo_driver {
* 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)
+ protected function _limit($sql)
{
- return $sql.' LIMIT '.$limit.($offset ? ' OFFSET '.$offset : '');
+ return $sql.' LIMIT '.$this->qb_limit.($this->qb_offset ? ' OFFSET '.$this->qb_offset : '');
}
}
diff --git a/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php b/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php
index cb18a5c10..d2a484d9e 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php
@@ -129,10 +129,10 @@ class CI_DB_pdo_cubrid_driver extends CI_DB_pdo_driver {
*
* @param string the table name
* @param array the update data
- * @param array the where clause
+ * @param string the where key
* @return string
*/
- protected function _update_batch($table, $values, $index, $where = NULL)
+ protected function _update_batch($table, $values, $index)
{
$ids = array();
foreach ($values as $key => $val)
@@ -156,9 +156,9 @@ class CI_DB_pdo_cubrid_driver extends CI_DB_pdo_driver {
.'ELSE '.$k.' END), ';
}
- return 'UPDATE '.$table.' SET '.substr($cases, 0, -2)
- .' WHERE '.(($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '')
- .$index.' IN('.implode(',', $ids).')';
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
+
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php
index 7c4b008b2..782bb53c0 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php
@@ -159,27 +159,13 @@ class CI_DB_pdo_dblib_driver extends CI_DB_pdo_driver {
*
* @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())
+ protected function _update($table, $values)
{
- 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;
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
@@ -190,23 +176,16 @@ class CI_DB_pdo_dblib_driver extends CI_DB_pdo_driver {
* 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)
+ protected function _delete($table)
{
- $conditions = array();
-
- empty($where) OR $conditions[] = implode(' ', $where);
- empty($like) OR $conditions[] = implode(' ', $like);
-
- $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : '';
+ if ($this->qb_limit)
+ {
+ return 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete';
+ }
- return ($limit)
- ? 'WITH ci_delete AS (SELECT TOP '.$limit.' * FROM '.$table.$conditions.') DELETE FROM ci_delete'
- : 'DELETE FROM '.$table.$conditions;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
@@ -217,27 +196,25 @@ class CI_DB_pdo_dblib_driver extends CI_DB_pdo_driver {
* 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)
+ protected function _limit($sql)
{
- $limit = $offset + $limit;
+ $limit = $this->qb_offset + $this->qb_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))
+ if (version_compare($this->version(), '9', '>=') && $this->qb_offset && ! empty($this->qb_orderby))
{
- $orderby = 'ORDER BY '.implode(', ', $this->qb_orderby);
+ $orderby = $this->_compile_order_by();
// We have to strip the ORDER BY clause
$sql = trim(substr($sql, 0, strrpos($sql, $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)
+ .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($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;
+ ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit;
}
return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql);
diff --git a/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php b/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php
index 6fba764a9..32d1f219a 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php
@@ -145,29 +145,12 @@ class CI_DB_pdo_firebird_driver extends CI_DB_pdo_driver {
*
* @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())
+ protected function _update($table, $values)
{
- 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) : '');
+ $this->qb_limit = FALSE;
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
@@ -196,19 +179,12 @@ class CI_DB_pdo_firebird_driver extends CI_DB_pdo_driver {
* 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)
+ protected function _delete($table)
{
- $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) : '');
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
@@ -219,22 +195,20 @@ class CI_DB_pdo_firebird_driver extends CI_DB_pdo_driver {
* 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)
+ protected function _limit($sql)
{
// Limit clause depends on if Interbase or Firebird
if (stripos($this->version(), 'firebird') !== FALSE)
{
- $select = 'FIRST '. (int) $limit
- .($offset > 0 ? ' SKIP '. (int) $offset : '');
+ $select = 'FIRST '.$this->qb_limit
+ .($this->qb_offset > 0 ? ' SKIP '.$this->qb_offset : '');
}
else
{
$select = 'ROWS '
- .($offset > 0 ? (int) $offset.' TO '.($limit + $offset) : (int) $limit);
+ .($this->qb_offset > 0 ? $this->qb_offset.' TO '.($this->qb_limit + $this->qb_offset) : $this->qb_limit);
}
return preg_replace('`SELECT`i', 'SELECT '.$select, $sql);
diff --git a/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php b/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php
index 399182e12..22a5f928c 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php
@@ -171,27 +171,13 @@ class CI_DB_pdo_ibm_driver extends CI_DB_pdo_driver {
*
* @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())
+ protected function _update($table, $values)
{
- 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;
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
@@ -202,21 +188,12 @@ class CI_DB_pdo_ibm_driver extends CI_DB_pdo_driver {
* 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)
+ protected function _delete($table)
{
- $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;
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php b/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php
index 028121540..8dd430184 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php
@@ -165,27 +165,13 @@ class CI_DB_pdo_informix_driver extends CI_DB_pdo_driver {
*
* @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())
+ protected function _update($table, $values)
{
- 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;
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
@@ -214,21 +200,12 @@ class CI_DB_pdo_informix_driver extends CI_DB_pdo_driver {
* 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)
+ protected function _delete($table)
{
- $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;
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
@@ -239,13 +216,11 @@ class CI_DB_pdo_informix_driver extends CI_DB_pdo_driver {
* 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)
+ protected function _limit($sql)
{
- $select = 'SELECT '.($offset ? 'SKIP '.$offset : '').'FIRST '.$limit.' ';
+ $select = 'SELECT '.($this->qb_offset ? 'SKIP '.$this->qb_offset : '').'FIRST '.$this->qb_limit.' ';
return preg_replace('/^(SELECT\s)/i', $select, $sql, 1);
}
diff --git a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
index a54311712..0fb5d8f12 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
@@ -164,10 +164,10 @@ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver {
*
* @param string the table name
* @param array the update data
- * @param array the where clause
+ * @param string the where key
* @return string
*/
- protected function _update_batch($table, $values, $index, $where = NULL)
+ protected function _update_batch($table, $values, $index)
{
$ids = array();
foreach ($values as $key => $val)
@@ -191,9 +191,9 @@ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver {
.'ELSE '.$k.' END), ';
}
- return 'UPDATE '.$table.' SET '.substr($cases, 0, -2)
- .' WHERE '.(($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '')
- .$index.' IN('.implode(',', $ids).')';
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
+
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php b/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php
index d584d1f5b..b03218fad 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php
@@ -174,20 +174,17 @@ class CI_DB_pdo_oci_driver extends CI_DB_pdo_driver {
* 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)
+ protected function _delete($table)
{
- $conditions = array();
-
- empty($where) OR $conditions[] = implode(' ', $where);
- empty($like) OR $conditions[] = implode(' ', $like);
- empty($limit) OR $conditions[] = 'rownum <= '.$limit;
+ if ($this->qb_limit)
+ {
+ $this->where('rownum <= ',$this->qb_limit, FALSE);
+ $this->qb_limit = FALSE;
+ }
- return 'DELETE FROM '.$table.(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : '');
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
@@ -198,14 +195,12 @@ class CI_DB_pdo_oci_driver extends CI_DB_pdo_driver {
* 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)
+ protected function _limit($sql)
{
- return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($offset + $limit + 1).')'
- .($offset ? ' WHERE rnum >= '.($offset + 1): '');
+ return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($this->qb_offset + $this->qb_limit + 1).')'
+ .($this->qb_offset ? ' WHERE rnum >= '.($this->qb_offset + 1): '');
}
}
diff --git a/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php
index e7ab3fd50..5944d55f4 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php
@@ -162,27 +162,13 @@ class CI_DB_pdo_odbc_driver extends CI_DB_pdo_driver {
*
* @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())
+ protected function _update($table, $values)
{
- 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;
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
@@ -211,21 +197,12 @@ class CI_DB_pdo_odbc_driver extends CI_DB_pdo_driver {
* 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)
+ protected function _delete($table)
{
- $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;
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
@@ -236,13 +213,11 @@ class CI_DB_pdo_odbc_driver extends CI_DB_pdo_driver {
* 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)
+ protected function _limit($sql)
{
- return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql);
+ return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$this->qb_limit.' ', $sql);
}
}
diff --git a/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php
index 2a687812a..74d56e6b8 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php
@@ -148,27 +148,13 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver {
*
* @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())
+ protected function _update($table, $values)
{
- 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;
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
@@ -180,10 +166,10 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver {
*
* @param string the table name
* @param array the update data
- * @param array the where clause
+ * @param string the where key
* @return string
*/
- protected function _update_batch($table, $values, $index, $where = NULL)
+ protected function _update_batch($table, $values, $index)
{
$ids = array();
foreach ($values as $key => $val)
@@ -202,14 +188,14 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver {
$cases = '';
foreach ($final as $k => $v)
{
- $cases .= $k.' = (CASE '.$k."\n"
+ $cases .= $k.' = (CASE '.$index."\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).')';
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
+
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
}
// --------------------------------------------------------------------
@@ -220,19 +206,12 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver {
* 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)
+ protected function _delete($table)
{
- $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) : '');
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
@@ -243,29 +222,31 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver {
* 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)
+ protected function _limit($sql)
{
- return $sql.' LIMIT '.$limit.($offset ? ' OFFSET '.$offset : '');
+ return $sql.' LIMIT '.$this->qb_limit.($this->qb_offset ? ' OFFSET '.$this->qb_offset : '');
}
// --------------------------------------------------------------------
/**
- * Where
+ * WHERE, HAVING
*
- * Called by where() or or_where()
+ * Called by where(), or_where(), having(), or_having()
*
+ * @param string 'qb_where' or 'qb_having'
* @param mixed
* @param mixed
* @param string
+ * @param bool
* @return object
*/
- protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL)
+ protected function _wh($qb_key, $key, $value = NULL, $type = 'AND ', $escape = NULL)
{
+ $qb_cache_key = ($qb_key === 'qb_having') ? 'qb_cache_having' : 'qb_cache_where';
+
if ( ! is_array($key))
{
$key = array($key => $value);
@@ -276,14 +257,10 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver {
foreach ($key as $k => $v)
{
- $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0)
+ $prefix = (count($this->$qb_key) === 0 && count($this->$qb_cache_key) === 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
@@ -292,13 +269,13 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver {
if ( ! is_null($v))
{
- if ($escape === TRUE)
+ if (is_bool($v))
{
- $v = ' '.$this->escape($v);
+ $v = ' '.($v ? 'TRUE' : 'FALSE');
}
- elseif (is_bool($v))
+ elseif ($escape === TRUE)
{
- $v = ($v ? ' TRUE' : ' FALSE');
+ $v = ' '.(is_int($v) ? $v : $this->escape($v));
}
if ( ! $this->_has_operator($k))
@@ -307,11 +284,11 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver {
}
}
- $this->qb_where[] = $prefix.$k.$v;
+ $this->{$qb_key}[] = array('condition' => $prefix.$k.$v, 'escape' => $escape);
if ($this->qb_caching === TRUE)
{
- $this->qb_cache_where[] = $prefix.$k.$v;
- $this->qb_cache_exists[] = 'where';
+ $this->{$qb_cache_key}[] = array('condition' => $prefix.$k.$v, 'escape' => $escape);
+ $this->qb_cache_exists[] = substr($qb_key, 3);
}
}
diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php
index 3154fddb9..64be355f8 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php
@@ -188,27 +188,13 @@ class CI_DB_pdo_sqlsrv_driver extends CI_DB_pdo_driver {
*
* @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())
+ protected function _update($table, $values)
{
- 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;
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
@@ -219,23 +205,16 @@ class CI_DB_pdo_sqlsrv_driver extends CI_DB_pdo_driver {
* 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)
+ protected function _delete($table)
{
- $conditions = array();
-
- empty($where) OR $conditions[] = implode(' ', $where);
- empty($like) OR $conditions[] = implode(' ', $like);
-
- $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : '';
+ if ($this->qb_limit)
+ {
+ return 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete';
+ }
- return ($limit)
- ? 'WITH ci_delete AS (SELECT TOP '.$limit.' * FROM '.$table.$conditions.') DELETE FROM ci_delete'
- : 'DELETE FROM '.$table.$conditions;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
@@ -246,32 +225,30 @@ class CI_DB_pdo_sqlsrv_driver extends CI_DB_pdo_driver {
* 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)
+ protected function _limit($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';
+ return $sql.' OFFSET '.(int) $this->qb_offset.' ROWS FETCH NEXT '.$this->qb_limit.' ROWS ONLY';
}
- $limit = $offset + $limit;
+ $limit = $this->qb_offset + $this->qb_limit;
// An ORDER BY clause is required for ROW_NUMBER() to work
- if ($offset && ! empty($this->qb_orderby))
+ if ($this->qb_offset && ! empty($this->qb_orderby))
{
- $orderby = 'ORDER BY '.implode(', ', $this->qb_orderby);
+ $orderby = $this->_compile_order_by();
// We have to strip the ORDER BY clause
$sql = trim(substr($sql, 0, strrpos($sql, $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)
+ .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($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;
+ ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit;
}
return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql);
diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php
index 2a91a8959..19f384ccc 100644
--- a/system/database/drivers/postgre/postgre_driver.php
+++ b/system/database/drivers/postgre/postgre_driver.php
@@ -463,27 +463,13 @@ class CI_DB_postgre_driver extends CI_DB {
*
* @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())
+ protected function _update($table, $values)
{
- 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;
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
@@ -495,10 +481,10 @@ class CI_DB_postgre_driver extends CI_DB {
*
* @param string the table name
* @param array the update data
- * @param array the where clause
+ * @param string the where key
* @return string
*/
- protected function _update_batch($table, $values, $index, $where = NULL)
+ protected function _update_batch($table, $values, $index)
{
$ids = array();
foreach ($values as $key => $val)
@@ -522,9 +508,9 @@ class CI_DB_postgre_driver extends CI_DB {
.'ELSE '.$k.' END), ';
}
- return 'UPDATE '.$table.' SET '.substr($cases, 0, -2)
- .' WHERE '.(($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '')
- .$index.' IN('.implode(',', $ids).')';
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
+
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
}
// --------------------------------------------------------------------
@@ -535,19 +521,12 @@ class CI_DB_postgre_driver extends CI_DB {
* 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)
+ protected function _delete($table)
{
- $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) : '');
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
@@ -558,30 +537,31 @@ class CI_DB_postgre_driver extends CI_DB {
* 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)
+ protected function _limit($sql)
{
- return $sql.' LIMIT '.$limit.($offset ? ' OFFSET '.$offset : '');
+ return $sql.' LIMIT '.$this->qb_limit.($this->qb_offset ? ' OFFSET '.$this->qb_offset : '');
}
// --------------------------------------------------------------------
/**
- * Where
+ * WHERE, HAVING
*
- * Called by where() or or_where()
+ * Called by where(), or_where(), having(), or_having()
*
+ * @param string 'qb_where' or 'qb_having'
* @param mixed
* @param mixed
* @param string
- * @param mixed
+ * @param bool
* @return object
*/
- protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL)
+ protected function _wh($qb_key, $key, $value = NULL, $type = 'AND ', $escape = NULL)
{
+ $qb_cache_key = ($qb_key === 'qb_having') ? 'qb_cache_having' : 'qb_cache_where';
+
if ( ! is_array($key))
{
$key = array($key => $value);
@@ -592,17 +572,10 @@ class CI_DB_postgre_driver extends CI_DB {
foreach ($key as $k => $v)
{
- $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0)
+ $prefix = (count($this->$qb_key) === 0 && count($this->$qb_cache_key) === 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))
{
// value appears not to have been set, assign the test to IS NULL
@@ -611,13 +584,13 @@ class CI_DB_postgre_driver extends CI_DB {
if ( ! is_null($v))
{
- if ($escape === TRUE)
+ if (is_bool($v))
{
- $v = ' '.$this->escape($v);
+ $v = ' '.($v ? 'TRUE' : 'FALSE');
}
- elseif (is_bool($v))
+ elseif ($escape === TRUE)
{
- $v = ($v ? ' TRUE' : ' FALSE');
+ $v = ' '.(is_int($v) ? $v : $this->escape($v));
}
if ( ! $this->_has_operator($k))
@@ -626,11 +599,11 @@ class CI_DB_postgre_driver extends CI_DB {
}
}
- $this->qb_where[] = $prefix.$k.$v;
+ $this->{$qb_key}[] = array('condition' => $prefix.$k.$v, 'escape' => $escape);
if ($this->qb_caching === TRUE)
{
- $this->qb_cache_where[] = $prefix.$k.$v;
- $this->qb_cache_exists[] = 'where';
+ $this->{$qb_cache_key}[] = array('condition' => $prefix.$k.$v, 'escape' => $escape);
+ $this->qb_cache_exists[] = substr($qb_key, 3);
}
}
diff --git a/system/database/drivers/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php
index be321ff11..31a0d9d10 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_driver.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php
@@ -365,27 +365,13 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*
* @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())
+ protected function _update($table, $values)
{
- 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;
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
@@ -414,23 +400,16 @@ class CI_DB_sqlsrv_driver extends CI_DB {
* 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)
+ protected function _delete($table)
{
- $conditions = array();
-
- empty($where) OR $conditions[] = implode(' ', $where);
- empty($like) OR $conditions[] = implode(' ', $like);
-
- $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : '';
+ if ($this->qb_limit)
+ {
+ return 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete';
+ }
- return ($limit)
- ? 'WITH ci_delete AS (SELECT TOP '.$limit.' * FROM '.$table.$conditions.') DELETE FROM ci_delete'
- : 'DELETE FROM '.$table.$conditions;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
@@ -441,32 +420,30 @@ class CI_DB_sqlsrv_driver extends CI_DB {
* 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)
+ protected function _limit($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';
+ return $sql.' OFFSET '.(int) $this->qb_offset.' ROWS FETCH NEXT '.$this->qb_limit.' ROWS ONLY';
}
- $limit = $offset + $limit;
+ $limit = $this->qb_offset + $this->qb_limit;
// An ORDER BY clause is required for ROW_NUMBER() to work
- if ($offset && ! empty($this->qb_orderby))
+ if ($this->qb_offset && ! empty($this->qb_orderby))
{
- $orderby = 'ORDER BY '.implode(', ', $this->qb_orderby);
+ $orderby = $this->_compile_order_by();
// We have to strip the ORDER BY clause
$sql = trim(substr($sql, 0, strrpos($sql, $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)
+ .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($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;
+ ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit;
}
return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql);
diff --git a/system/libraries/Pagination.php b/system/libraries/Pagination.php
index e1e729bb0..36b57b332 100644
--- a/system/libraries/Pagination.php
+++ b/system/libraries/Pagination.php
@@ -157,7 +157,7 @@ class CI_Pagination {
// See if we are using a prefix or suffix on links
if ($this->prefix !== '' OR $this->suffix !== '')
{
- $this->cur_page = (int) str_replace(array($this->prefix, $this->suffix), '', $CI->uri->segment($this->uri_segment));
+ $this->cur_page = (int) str_replace(array($this->prefix, $this->suffix), '', $CI->uri->rsegment($this->uri_segment));
}
if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE)
@@ -169,7 +169,7 @@ class CI_Pagination {
}
elseif ( ! $this->cur_page && $CI->uri->segment($this->uri_segment) !== $base_page)
{
- $this->cur_page = (int) $CI->uri->segment($this->uri_segment);
+ $this->cur_page = (int) $CI->uri->rsegment($this->uri_segment);
}
// Set current page to 1 if it's not valid or if using page numbers instead of offset
diff --git a/tests/codeigniter/core/URI_test.php b/tests/codeigniter/core/URI_test.php
index 60ed1a4e9..e2deabe51 100644
--- a/tests/codeigniter/core/URI_test.php
+++ b/tests/codeigniter/core/URI_test.php
@@ -40,13 +40,13 @@ class URI_test extends CI_TestCase {
'/index.php?/controller/method/?var=foo' => 'controller/method'
);
- foreach($requests as $request => $expected)
+ foreach ($requests as $request => $expected)
{
$_SERVER['SCRIPT_NAME'] = '/index.php';
$_SERVER['REQUEST_URI'] = $request;
$this->uri->_fetch_uri_string();
- $this->assertEquals($expected, $this->uri->uri_string );
+ $this->assertEquals($expected, $this->uri->uri_string);
}
// Test a subfolder
@@ -60,10 +60,10 @@ class URI_test extends CI_TestCase {
unset($_SERVER['REQUEST_URI']);
// life to path info
- $_SERVER['PATH_INFO'] = $a = '/controller/method/';
+ $_SERVER['PATH_INFO'] = '/controller/method/';
$this->uri->_fetch_uri_string();
- $this->assertEquals($a, $this->uri->uri_string);
+ $this->assertEquals('controller/method', $this->uri->uri_string);
// death to path info
// At this point your server must be seriously drunk
@@ -72,7 +72,7 @@ class URI_test extends CI_TestCase {
$_SERVER['QUERY_STRING'] = '/controller/method/';
$this->uri->_fetch_uri_string();
- $this->assertEquals($a, $this->uri->uri_string);
+ $this->assertEquals('controller/method', $this->uri->uri_string);
// At this point your server is a labotomy victim
unset($_SERVER['QUERY_STRING']);
@@ -80,7 +80,7 @@ class URI_test extends CI_TestCase {
$_GET['/controller/method/'] = '';
$this->uri->_fetch_uri_string();
- $this->assertEquals($a, $this->uri->uri_string);
+ $this->assertEquals('controller/method', $this->uri->uri_string);
// Test coverage implies that these will work
// uri_protocol: REQUEST_URI
diff --git a/tests/codeigniter/database/query_builder/like_test.php b/tests/codeigniter/database/query_builder/like_test.php
index 5f3e52228..2736fbe0b 100644
--- a/tests/codeigniter/database/query_builder/like_test.php
+++ b/tests/codeigniter/database/query_builder/like_test.php
@@ -87,4 +87,20 @@ class Like_test extends CI_TestCase {
$this->assertEquals('Musician', $jobs[2]['name']);
}
+ // ------------------------------------------------------------------------
+
+ /**
+ * GitHub issue #273
+ *
+ * @see ./mocks/schema/skeleton.php
+ */
+ public function test_like_spaces_and_tabs()
+ {
+ $spaces = $this->db->like('value', ' ')->get('misc')->result_array();
+ $tabs = $this->db->like('value', "\t")->get('misc')->result_array();
+
+ $this->assertEquals(1, count($spaces));
+ $this->assertEquals(1, count($tabs));
+ }
+
} \ No newline at end of file
diff --git a/tests/mocks/database/schema/skeleton.php b/tests/mocks/database/schema/skeleton.php
index 69e3c187e..d72244528 100644
--- a/tests/mocks/database/schema/skeleton.php
+++ b/tests/mocks/database/schema/skeleton.php
@@ -129,7 +129,8 @@ class Mock_Database_Schema_Skeleton {
),
'misc' => array(
array('id' => 1, 'key' => '\\xxxfoo456', 'value' => 'Entry with \\xxx'),
- array('id' => 2, 'key' => '\\%foo456', 'value' => 'Entry with \\%')
+ array('id' => 2, 'key' => '\\%foo456', 'value' => 'Entry with \\%'),
+ array('id' => 3, 'key' => 'spaces and tabs', 'value' => ' One two three tab')
)
);
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 4ee382fce..f0a61d45d 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -233,10 +233,11 @@ Release Date: Not Released
- Modified ``valid_ip()`` to use PHP's ``filter_var()``.
- Added support for arrays and network addresses (e.g. 192.168.1.1/24) for use with the *proxy_ips* setting.
- :doc:`Common functions <general/common_functions>` changes include:
- - Added ``get_mimes()`` function to return the *config/mimes.php* array.
+ - Added function ``get_mimes()`` to return the *config/mimes.php* array.
- Added support for HTTP code 303 ("See Other") in ``set_status_header()``.
- Removed redundant conditional to determine HTTP server protocol in ``set_status_header()``.
- Changed ``_exception_handler()`` to respect php.ini *display_errors* setting.
+ - Added function ``is_https()`` to check if a secure connection is used.
- Added support for HTTP-Only cookies with new config option *cookie_httponly* (default FALSE).
- Renamed method ``_call_hook()`` to ``call_hook()`` in the :doc:`Hooks Library <general/hooks>`.
- :doc:`Output Library <libraries/output>` changes include:
@@ -369,6 +370,9 @@ Bug fixes for 3.0
- Fixed a bug (#1897) - :doc:`Email Library <libraries/email>` triggered PHP E_WARNING errors when *mail* protocol used and ``to()`` is never called.
- Fixed a bug (#1409) - :doc:`Email Library <libraries/email>` didn't properly handle multibyte characters when applying Q-encoding to headers.
- Fixed a bug where :doc:`Email Library <libraries/email>` didn't honor it's *wordwrap* setting while handling alternative messages.
+- Fixed a bug (#1476, #1909) - :doc:`Pagination Library <libraries/pagination>` didn't take into account actual routing when determining the current page.
+- Fixed a bug (#1766) - :doc:`Query Builder <database/query_builder>` didn't always take into account the *dbprefix* setting.
+- Fixed a bug (#779) - :doc:`URI Class <libraries/uri>` didn't always trim slashes from the *uri_string* as shown in the documentation.
Version 2.1.3
=============
diff --git a/user_guide_src/source/general/common_functions.rst b/user_guide_src/source/general/common_functions.rst
index 99126f900..f3d48ac91 100644
--- a/user_guide_src/source/general/common_functions.rst
+++ b/user_guide_src/source/general/common_functions.rst
@@ -7,7 +7,7 @@ defined, and are available to you at any point. These do not require
loading any libraries or helpers.
is_php('version_number')
-==========================
+========================
is_php() determines of the PHP version being used is greater than the
supplied version_number.
@@ -24,7 +24,7 @@ greater than the supplied version number. Returns FALSE if the installed
version of PHP is lower than the supplied version number.
is_really_writable('path/to/file')
-====================================
+==================================
is_writable() returns TRUE on Windows servers when you really can't
write to the file as the OS reports to PHP as FALSE only if the
@@ -44,7 +44,7 @@ recommended on platforms where this information may be unreliable.
}
config_item('item_key')
-=========================
+=======================
The :doc:`Config library <../libraries/config>` is the preferred way of
accessing configuration information, however config_item() can be used
@@ -56,8 +56,8 @@ show_error('message'), show_404('page'), log_message('level', 'message')
These are each outlined on the :doc:`Error Handling <errors>` page.
-set_status_header(code, 'text');
-================================
+set_status_header(code, 'text')
+===============================
Permits you to manually set a server status header. Example::
@@ -68,19 +68,25 @@ Permits you to manually set a server status header. Example::
a full list of headers.
remove_invisible_characters($str)
-===================================
+=================================
This function prevents inserting null characters between ascii
characters, like Java\\0script.
html_escape($mixed)
-====================
+===================
-This function provides short cut for htmlspecialchars() function. It
+This function provides short cut for ``htmlspecialchars()`` function. It
accepts string and array. To prevent Cross Site Scripting (XSS), it is
very useful.
get_mimes()
-=============
+===========
-This function returns the MIMEs array from config/mimes.php. \ No newline at end of file
+This function returns the MIMEs array *from config/mimes.php*.
+
+is_https()
+==========
+
+Returns TRUE if a secure (HTTPS) connection is used and FALSE
+in any other case (including non-HTTP requests). \ No newline at end of file