summaryrefslogtreecommitdiffstats
path: root/system/database
diff options
context:
space:
mode:
authorDerek Allard <derek.allard@ellislab.com>2008-02-05 00:20:34 +0100
committerDerek Allard <derek.allard@ellislab.com>2008-02-05 00:20:34 +0100
commit9b3e7b5f2d4ec4feae793ef90454506addbb19e1 (patch)
tree866d6efe488c04a118cdb015991452e56d1722ec /system/database
parent613c6f605666031aa5b60c2dca568ac2d3a3c264 (diff)
Added and documented Active Record caching.
Made AR fully database-prefix aware
Diffstat (limited to 'system/database')
-rw-r--r--system/database/DB_active_rec.php313
-rw-r--r--system/database/drivers/mssql/mssql_driver.php7
-rw-r--r--system/database/drivers/mysql/mysql_driver.php7
-rw-r--r--system/database/drivers/mysqli/mysqli_driver.php7
-rw-r--r--system/database/drivers/oci8/oci8_driver.php7
-rw-r--r--system/database/drivers/odbc/odbc_driver.php7
-rw-r--r--system/database/drivers/postgre/postgre_driver.php9
-rw-r--r--system/database/drivers/sqlite/sqlite_driver.php7
8 files changed, 322 insertions, 42 deletions
diff --git a/system/database/DB_active_rec.php b/system/database/DB_active_rec.php
index e93b99e3d..b3bf02a8b 100644
--- a/system/database/DB_active_rec.php
+++ b/system/database/DB_active_rec.php
@@ -43,6 +43,23 @@ class CI_DB_active_record extends CI_DB_driver {
var $ar_set = array();
var $ar_wherein = array();
var $ar_aliased_tables = array();
+ var $ar_store_array = array();
+
+ // Active Record Caching variables
+ var $ar_caching = FALSE;
+ var $ar_cache_select = array();
+ var $ar_cache_from = array();
+ var $ar_cache_join = array();
+ var $ar_cache_where = array();
+ var $ar_cache_like = array();
+ var $ar_cache_groupby = array();
+ var $ar_cache_having = array();
+ var $ar_cache_limit = FALSE;
+ var $ar_cache_offset = FALSE;
+ var $ar_cache_order = FALSE;
+ var $ar_cache_orderby = array();
+ var $ar_cache_set = array();
+
/**
* DB Prefix
@@ -87,12 +104,23 @@ class CI_DB_active_record extends CI_DB_driver {
if ($val != '*' && $protect_identifiers !== FALSE)
{
- $val = $this->_protect_identifiers($val);
+ if (strpos($val, '.') !== FALSE)
+ {
+ $val = $this->dbprefix.$val;
+ }
+ else
+ {
+ $val = $this->_protect_identifiers($val);
+ }
}
if ($val != '')
{
$this->ar_select[] = $val;
+ if ($this->ar_caching === TRUE)
+ {
+ $this->ar_cache_select[] = $val;
+ }
}
}
return $this;
@@ -122,6 +150,10 @@ class CI_DB_active_record extends CI_DB_driver {
$sql = 'MAX('.$this->_protect_identifiers(trim($select)).') AS '.$this->_protect_identifiers(trim($alias));
$this->ar_select[] = $sql;
+ if ($this->ar_caching === TRUE)
+ {
+ $this->ar_cache_select[] = $sql;
+ }
return $this;
}
@@ -150,7 +182,11 @@ class CI_DB_active_record extends CI_DB_driver {
$sql = 'MIN('.$this->_protect_identifiers(trim($select)).') AS '.$this->_protect_identifiers(trim($alias));
$this->ar_select[] = $sql;
-
+ if ($this->ar_caching === TRUE)
+ {
+ $this->ar_cache_select[] = $sql;
+ }
+
return $this;
}
@@ -178,7 +214,11 @@ class CI_DB_active_record extends CI_DB_driver {
$sql = 'AVG('.$this->_protect_identifiers(trim($select)).') AS '.$this->_protect_identifiers(trim($alias));
$this->ar_select[] = $sql;
-
+ if ($this->ar_caching === TRUE)
+ {
+ $this->ar_cache_select[] = $sql;
+ }
+
return $this;
}
@@ -206,7 +246,11 @@ class CI_DB_active_record extends CI_DB_driver {
$sql = 'SUM('.$this->_protect_identifiers(trim($select)).') AS '.$this->_protect_identifiers(trim($alias));
$this->ar_select[] = $sql;
-
+ if ($this->ar_caching === TRUE)
+ {
+ $this->ar_cache_select[] = $sql;
+ }
+
return $this;
}
@@ -243,6 +287,10 @@ class CI_DB_active_record extends CI_DB_driver {
foreach ((array)$from as $val)
{
$this->ar_from[] = $this->_protect_identifiers($this->_track_aliases($val));
+ if ($this->ar_caching === TRUE)
+ {
+ $this->ar_cache_from[] = $this->_protect_identifiers($val);
+ }
}
return $this;
@@ -289,7 +337,14 @@ class CI_DB_active_record extends CI_DB_driver {
$cond = preg_replace('|([\w\.]+)([\W\s]+)(.+)|', $this->dbprefix . "$1$2" . $this->dbprefix . "$3", $cond);
}
- $this->ar_join[] = $type.'JOIN '.$this->_protect_identifiers($this->dbprefix.$table, TRUE).' ON '.$cond;
+ $join = $type.'JOIN '.$this->_protect_identifiers($this->dbprefix.$table, TRUE).' ON '.$cond;
+
+ $this->ar_join[] = $join;
+ if ($this->ar_caching === TRUE)
+ {
+ $this->ar_cache_join[] = $join;
+ }
+
return $this;
}
@@ -360,7 +415,7 @@ class CI_DB_active_record extends CI_DB_driver {
{
$key = array($key => $value);
}
-
+
foreach ($key as $k => $v)
{
$prefix = (count($this->ar_where) == 0) ? '' : $type;
@@ -393,10 +448,18 @@ class CI_DB_active_record extends CI_DB_driver {
}
$v = ' '.$this->escape($v);
-
}
-
+ else
+ {
+ $k = $this->_protect_identifiers($k, TRUE);
+ }
+
$this->ar_where[] = $prefix.$k.$v;
+ if ($this->ar_caching === TRUE)
+ {
+ $this->ar_cache_where[] = $prefix.$k.$v;
+ }
+
}
return $this;
}
@@ -507,7 +570,13 @@ class CI_DB_active_record extends CI_DB_driver {
$prefix = (count($this->ar_where) == 0) ? '' : $type;
- $this->ar_where[] = $prefix . $this->_protect_identifiers($key) . $not . " IN (" . implode(", ", $this->ar_wherein) . ") ";
+ $where_in = $prefix . $this->_protect_identifiers($key) . $not . " IN (" . implode(", ", $this->ar_wherein) . ") ";
+
+ $this->ar_where[] = $where_in;
+ if ($this->ar_caching === TRUE)
+ {
+ $this->ar_cache_where[] = $where_in;
+ }
// reset the array for multiple calls
$this->ar_wherein = array();
@@ -629,16 +698,23 @@ class CI_DB_active_record extends CI_DB_driver {
if ($side == 'before')
{
- $this->ar_like[] = $prefix." $k $not LIKE '%{$v}'";
+ $like_statement = $prefix." $k $not LIKE '%{$v}'";
}
elseif ($side == 'after')
{
- $this->ar_like[] = $prefix." $k $not LIKE '{$v}%'";
+ $like_statement = $prefix." $k $not LIKE '{$v}%'";
}
else
{
- $this->ar_like[] = $prefix." $k $not LIKE '%{$v}%'";
+ $like_statement = $prefix." $k $not LIKE '%{$v}%'";
}
+
+ $this->ar_like[] = $like_statement;
+ if ($this->ar_caching === TRUE)
+ {
+ $this->ar_cache_like[] = $like_statement;
+ }
+
}
return $this;
}
@@ -664,7 +740,13 @@ class CI_DB_active_record extends CI_DB_driver {
$val = trim($val);
if ($val != '')
+ {
$this->ar_groupby[] = $this->_protect_identifiers($val);
+ if ($this->ar_caching === TRUE)
+ {
+ $this->ar_cache_groupby[] = $this->_protect_identifiers($val);
+ }
+ }
}
return $this;
}
@@ -724,6 +806,7 @@ class CI_DB_active_record extends CI_DB_driver {
*
* @access private
* @param string
+
* @param string
* @return object
*/
@@ -737,14 +820,20 @@ class CI_DB_active_record extends CI_DB_driver {
foreach ($key as $k => $v)
{
$prefix = (count($this->ar_having) == 0) ? '' : $type;
+ $k = $this->_protect_identifiers($k);
if ($v != '')
{
- $v = ' '.$this->escape($v);
+ $v = ' '.$this->escape_str($v);
}
$this->ar_having[] = $prefix.$k.$v;
+ if ($this->ar_caching === TRUE)
+ {
+ $this->ar_cache_having[] = $prefix.$k.$v;
+ }
}
+
return $this;
}
@@ -770,7 +859,14 @@ class CI_DB_active_record extends CI_DB_driver {
$direction = (in_array(strtoupper(trim($direction)), array('ASC', 'DESC'), TRUE)) ? ' '.$direction : ' ASC';
}
- $this->ar_orderby[] = $this->_protect_identifiers($orderby, TRUE).$direction;
+ $orderby_statement = $this->_protect_identifiers($orderby, TRUE).$direction;
+
+ $this->ar_orderby[] = $orderby_statement;
+ if ($this->ar_caching === TRUE)
+ {
+ $this->ar_cache_orderby[] = $orderby_statement;
+ }
+
return $this;
}
@@ -799,9 +895,19 @@ class CI_DB_active_record extends CI_DB_driver {
function limit($value, $offset = '')
{
$this->ar_limit = $value;
-
+ if ($this->ar_caching === TRUE)
+ {
+ $this->ar_cache_limit[] = $value;
+ }
+
if ($offset != '')
+ {
$this->ar_offset = $offset;
+ if ($this->ar_caching === TRUE)
+ {
+ $this->ar_cache_offset[] = $offset;
+ }
+ }
return $this;
}
@@ -815,9 +921,14 @@ class CI_DB_active_record extends CI_DB_driver {
* @param integer the offset value
* @return object
*/
- function offset($value)
+ function offset($offset)
{
- $this->ar_offset = $value;
+ $this->ar_offset = $offset;
+ if ($this->ar_caching === TRUE)
+ {
+ $this->ar_cache_offset[] = $offset;
+ }
+
return $this;
}
@@ -846,12 +957,19 @@ class CI_DB_active_record extends CI_DB_driver {
if ($escape === FALSE)
{
$this->ar_set[$this->_protect_identifiers($k)] = $v;
+ if ($this->ar_caching === TRUE)
+ {
+ $this->ar_cache_offset[$this->_protect_identifiers($k)] = $v;
+ }
}
else
{
$this->ar_set[$this->_protect_identifiers($k)] = $this->escape($v);
+ if ($this->ar_caching === TRUE)
+ {
+ $this->ar_cache_offset[$this->_protect_identifiers($k)] = $this->escape($v);
+ }
}
-
}
return $this;
@@ -1331,6 +1449,11 @@ class CI_DB_active_record extends CI_DB_driver {
*/
function _compile_select($select_override = FALSE)
{
+ if ($this->ar_caching === TRUE)
+ {
+ $this->_merge_cache();
+ }
+
$sql = ( ! $this->ar_distinct) ? 'SELECT ' : 'SELECT DISTINCT ';
$sql .= (count($this->ar_select) == 0) ? '*' : implode(', ', $this->ar_select);
@@ -1456,6 +1579,107 @@ class CI_DB_active_record extends CI_DB_driver {
// --------------------------------------------------------------------
/**
+ * Start Cache
+ *
+ * Starts AR caching
+ *
+ * @access public
+ * @return void
+ */
+ function start_cache()
+ {
+ $this->ar_caching = TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Stop Cache
+ *
+ * Stops AR caching
+ *
+ * @access public
+ * @return void
+ */
+ function stop_cache()
+ {
+ $this->ar_caching = FALSE;
+ }
+
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Flush Cache
+ *
+ * Empties the AR cache
+ *
+ * @access public
+ * @return void
+ */
+ function flush_cache()
+ {
+ $ar_reset_items = array(
+ 'ar_cache_select' => array(),
+ 'ar_cache_from' => array(),
+ 'ar_cache_join' => array(),
+ 'ar_cache_where' => array(),
+ 'ar_cache_like' => array(),
+ 'ar_cache_groupby' => array(),
+ 'ar_cache_having' =>array(),
+ 'ar_cache_orderby' => array(),
+ 'ar_cache_set' => array()
+ );
+
+ $this->_reset_run($ar_reset_items);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Merge Cache
+ *
+ * When called, this function merges any cached AR arrays with
+ * locally called ones.
+ *
+ * @access private
+ * @return void
+ */
+ function _merge_cache()
+ {
+ $ar_items = array('select', 'from', 'join', 'where', 'like', 'groupby', 'having', 'orderby', 'set');
+
+ foreach ($ar_items as $ar_item)
+ {
+ $ar_cache_item = 'ar_cache_'.$ar_item;
+ $ar_item = 'ar_'.$ar_item;
+ $this->$ar_item = array_unique(array_merge($this->$ar_item, $this->$ar_cache_item));
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Resets the active record values. Called by the get() function
+ *
+ * @access private
+ * @param array An array of fields to reset
+ * @return void
+ */
+ function _reset_run($ar_reset_items)
+ {
+ foreach ($ar_reset_items as $item => $default_value)
+ {
+ if (!in_array($item, $this->ar_store_array))
+ {
+ $this->$item = $default_value;
+ }
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Resets the active record values. Called by the get() function
*
* @access private
@@ -1463,20 +1687,24 @@ class CI_DB_active_record extends CI_DB_driver {
*/
function _reset_select()
{
- $this->ar_select = array();
- $this->ar_distinct = FALSE;
- $this->ar_from = array();
- $this->ar_join = array();
- $this->ar_where = array();
- $this->ar_like = array();
- $this->ar_groupby = array();
- $this->ar_having = array();
- $this->ar_limit = FALSE;
- $this->ar_offset = FALSE;
- $this->ar_order = FALSE;
- $this->ar_orderby = array();
- $this->ar_wherein = array();
- $this->ar_aliased_tables = array();
+ $ar_reset_items = array(
+ 'ar_select' => array(),
+ 'ar_from' => array(),
+ 'ar_join' => array(),
+ 'ar_where' => array(),
+ 'ar_like' => array(),
+ 'ar_groupby' => array(),
+ 'ar_having' => array(),
+ 'ar_orderby' => array(),
+ 'ar_wherein' => array(),
+ 'ar_aliased_tables' => array(),
+ 'ar_distinct' => FALSE,
+ 'ar_limit' => FALSE,
+ 'ar_offset' => FALSE,
+ 'ar_order' => FALSE,
+ );
+
+ $this->_reset_run($ar_reset_items);
}
// --------------------------------------------------------------------
@@ -1490,16 +1718,19 @@ class CI_DB_active_record extends CI_DB_driver {
* @return void
*/
function _reset_write()
- {
- $this->ar_set = array();
- $this->ar_from = array();
- $this->ar_where = array();
- $this->ar_like = array();
- $this->ar_limit = FALSE;
- $this->ar_order = FALSE;
- $this->ar_orderby = array();
+ {
+ $ar_reset_items = array(
+ 'ar_set' => array(),
+ 'ar_from' => array(),
+ 'ar_where' => array(),
+ 'ar_like' => array(),
+ 'ar_orderby' => array(),
+ 'ar_limit' => FALSE,
+ 'ar_order' => FALSE
+ );
+
+ $this->_reset_run($ar_reset_items);
}
}
-
?> \ No newline at end of file
diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php
index ad747d4ad..ecd404b52 100644
--- a/system/database/drivers/mssql/mssql_driver.php
+++ b/system/database/drivers/mssql/mssql_driver.php
@@ -433,6 +433,13 @@ class CI_DB_mssql_driver extends CI_DB {
function _protect_identifiers($item, $affect_spaces = TRUE, $first_word_only = FALSE)
{
// MSSQL doesn't use backticks
+ if (strpos($item, '.') !== FALSE)
+ {
+ $aliased_tables = implode(".",$this->ar_aliased_tables).'.';
+ $table_name = substr($item, 0, strpos($item, '.')+1);
+ $item = (strpos($aliased_tables, $table_name) !== FALSE) ? $item = $item : $this->dbprefix.$item;
+ }
+
return $item;
}
diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php
index f00257250..a5082d1b3 100644
--- a/system/database/drivers/mysql/mysql_driver.php
+++ b/system/database/drivers/mysql/mysql_driver.php
@@ -454,6 +454,13 @@ class CI_DB_mysql_driver extends CI_DB {
// we may need "`item1` `item2`" and not "`item1 item2`"
if (ctype_alnum($item) === FALSE)
{
+ if (strpos($item, '.') !== FALSE)
+ {
+ $aliased_tables = implode(".",$this->ar_aliased_tables).'.';
+ $table_name = substr($item, 0, strpos($item, '.')+1);
+ $item = (strpos($aliased_tables, $table_name) !== FALSE) ? $item = $item : $this->dbprefix.$item;
+ }
+
// This function may get "field >= 1", and need it to return "`field` >= 1"
$lbound = ($first_word_only === TRUE) ? '' : '|\s|\(';
diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index b2e97f927..9e7cc0c9f 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -448,6 +448,13 @@ class CI_DB_mysqli_driver extends CI_DB {
// we may need "`item1` `item2`" and not "`item1 item2`"
if (ctype_alnum($item) === FALSE)
{
+ if (strpos($item, '.') !== FALSE)
+ {
+ $aliased_tables = implode(".",$this->ar_aliased_tables).'.';
+ $table_name = substr($item, 0, strpos($item, '.')+1);
+ $item = (strpos($aliased_tables, $table_name) !== FALSE) ? $item = $item : $this->dbprefix.$item;
+ }
+
// This function may get "field >= 1", and need it to return "`field` >= 1"
$lbound = ($first_word_only === TRUE) ? '' : '|\s|\(';
diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php
index ddc0fba99..aa2aeca42 100644
--- a/system/database/drivers/oci8/oci8_driver.php
+++ b/system/database/drivers/oci8/oci8_driver.php
@@ -559,6 +559,13 @@ class CI_DB_oci8_driver extends CI_DB {
// we may need "`item1` `item2`" and not "`item1 item2`"
if (ctype_alnum($item) === FALSE)
{
+ if (strpos($item, '.') !== FALSE)
+ {
+ $aliased_tables = implode(".",$this->ar_aliased_tables).'.';
+ $table_name = substr($item, 0, strpos($item, '.')+1);
+ $item = (strpos($aliased_tables, $table_name) !== FALSE) ? $item = $item : $this->dbprefix.$item;
+ }
+
// This function may get "field >= 1", and need it to return "`field` >= 1"
$lbound = ($first_word_only === TRUE) ? '' : '|\s|\(';
diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php
index 03c0e6a86..88fff4365 100644
--- a/system/database/drivers/odbc/odbc_driver.php
+++ b/system/database/drivers/odbc/odbc_driver.php
@@ -424,6 +424,13 @@ class CI_DB_odbc_driver extends CI_DB {
// we may need "`item1` `item2`" and not "`item1 item2`"
if (ctype_alnum($item) === FALSE)
{
+ if (strpos($item, '.') !== FALSE)
+ {
+ $aliased_tables = implode(".",$this->ar_aliased_tables).'.';
+ $table_name = substr($item, 0, strpos($item, '.')+1);
+ $item = (strpos($aliased_tables, $table_name) !== FALSE) ? $item = $item : $this->dbprefix.$item;
+ }
+
// This function may get "field >= 1", and need it to return "`field` >= 1"
$lbound = ($first_word_only === TRUE) ? '' : '|\s|\(';
diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php
index e72981348..ae8bd86eb 100644
--- a/system/database/drivers/postgre/postgre_driver.php
+++ b/system/database/drivers/postgre/postgre_driver.php
@@ -444,6 +444,13 @@ class CI_DB_postgre_driver extends CI_DB {
// we may need ""item1" "item2"" and not ""item1 item2""
if (ctype_alnum($item) === FALSE)
{
+ if (strpos($item, '.') !== FALSE)
+ {
+ $aliased_tables = implode(".",$this->ar_aliased_tables).'.';
+ $table_name = substr($item, 0, strpos($item, '.')+1);
+ $item = (strpos($aliased_tables, $table_name) !== FALSE) ? $item = $item : $this->dbprefix.$item;
+ }
+
// This function may get "field >= 1", and need it to return ""field" >= 1"
$lbound = ($first_word_only === TRUE) ? '' : '|\s|\(';
@@ -486,7 +493,7 @@ class CI_DB_postgre_driver extends CI_DB {
$tables = array($tables);
}
- return implode(', ', $tables);
+ return '('.implode(', ', $tables).')';
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/sqlite/sqlite_driver.php b/system/database/drivers/sqlite/sqlite_driver.php
index 38febca29..dad5eeedf 100644
--- a/system/database/drivers/sqlite/sqlite_driver.php
+++ b/system/database/drivers/sqlite/sqlite_driver.php
@@ -440,6 +440,13 @@ class CI_DB_sqlite_driver extends CI_DB {
// we may need "`item1` `item2`" and not "`item1 item2`"
if (ctype_alnum($item) === FALSE)
{
+ if (strpos($item, '.') !== FALSE)
+ {
+ $aliased_tables = implode(".",$this->ar_aliased_tables).'.';
+ $table_name = substr($item, 0, strpos($item, '.')+1);
+ $item = (strpos($aliased_tables, $table_name) !== FALSE) ? $item = $item : $this->dbprefix.$item;
+ }
+
// This function may get "field >= 1", and need it to return "`field` >= 1"
$lbound = ($first_word_only === TRUE) ? '' : '|\s|\(';