-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Active Record parallel queries
Category:Core | Category:Core::Database | Category:Core::Community
This is a replacement of the system/database/DB_active_rec.php file, allowing you to use several CI Active Record threads at the same time without overlapping. See the relevant forum thread.
Sample code:
$this->db->set_identifier('my_first_query');
$this->db->from('blabla');
$this->db->where('blibli');
$this->db->set_identifier('my_second_query');
$this->db->from('tatata');
$this->db->where('tititi');
$this->db->set_identifier('my_first_query');
$first_query = $this->db->get();
$this->db->set_identifier('my_second_query');
$second_query = $this->db->get();
It's fully backward compatible, and you could use it also this way (adding two lines around the code to protect from other AR calls):
$this->db->set_identifier("my unique string that I won't use twice unless it's really clean");
$query = $this->db->getwhere('a_table', array('id' => $id));
$result = $query->first_row();
$this->db->set_identifier('default');
Some apps (like Rapyd in dataset.php around line 253) tweak some AR variables without using the public functions. You'll have to hack them if you want to use the new DB_active_rec.php. For example in Rapyd, the lines
// ...
$this->db->ar_limit = FALSE;
// ...
$this->db->ar_select = array('COUNT(*) AS totalrows');
// ...
$this->db->ar_orderby = array();
// ...
$this->db->ar_order = FALSE;
becomes
// ...
$this->db->ar_limit['default'] = FALSE;
// ...
$this->db->ar_select['default'] = array('COUNT(*) AS totalrows');
// ...
$this->db->ar_orderby['default'] = array();
// ...
$this->db->ar_order['default'] = FALSE;
Here is a piece of the code of this new file.
<?php
/**
* Active Record Class
*
* This is the platform-independent base Active Record implementation class.
*
* Changes by Christophe Gragnic on 2007/06/14 are:
* vars now arrays of old vars
* added var $ar_identifier and its setter
* everywhere you had $this->ar_somevar, you now have
* $this->ar_somevar[$this->ar_identifier]
*
* Those changes allow us to use Active Record parallel queries.
* The "identifier" is a simple string (default:'default').
* Backward compatible, set_identifier('some_identifier') is optional.
*
* Sample code:
* $this->db->set_identifier('my_first_query');
* $this->db->from('blabla');
* $this->db->where('blibli');
*
* $this->db->set_identifier('my_second_query');
* $this->db->from('tatata');
* $this->db->where('tititi');
*
* $this->db->set_identifier('my_first_query');
* $first_query = $this->db->get();
*
* $this->db->set_identifier('my_second_query');
* $second_query = $this->db->get();
*
* @package CodeIgniter
* @subpackage Drivers
* @category Database
* @author Rick Ellis
* @author Christophe Gragnic (grahack) for the identifier stuff only
* @link http://www.codeigniter.com/user_guide/database/
*/
class CI_DB_active_record extends CI_DB_driver {
var $ar_identifier = 'default';
var $ar_select = array('default' => array());
var $ar_distinct = array('default' => FALSE);
var $ar_from = array('default' => array());
var $ar_join = array('default' => array());
var $ar_where = array('default' => array());
var $ar_like = array('default' => array());
var $ar_groupby = array('default' => array());
var $ar_having = array('default' => array());
var $ar_limit = array('default' => FALSE);
var $ar_offset = array('default' => FALSE);
var $ar_order = array('default' => FALSE);
var $ar_orderby = array('default' => array());
var $ar_set = array('default' => array());
/**
* Set_identifier
*
* Chooses the channel to use
*
* @access public
* @param string
* @return object
*/
function set_identifier($identifier = 'default')
{
if ( ! is_string($identifier))
{
$identifier = 'default';
}
$this->ar_identifier = $identifier;
// we have to init the values only if it is a new key
// let's check on the first array
if ( ! array_key_exists($identifier, $this->ar_select))
{
$this->ar_select [$identifier] = array();
$this->ar_distinct [$identifier] = FALSE;
$this->ar_from [$identifier] = array();
$this->ar_join [$identifier] = array();
$this->ar_where [$identifier] = array();
$this->ar_like [$identifier] = array();
$this->ar_groupby [$identifier] = array();
$this->ar_having [$identifier] = array();
$this->ar_limit [$identifier] = FALSE;
$this->ar_offset [$identifier] = FALSE;
$this->ar_order [$identifier] = FALSE;
$this->ar_orderby [$identifier] = array();
$this->ar_set [$identifier] = array();
}
return $this;
}
version 1.7.2 edited by Afro Radio Head Loved this added feature, so I had to update it File:DB_active_rec_v1.7.2.zip
Here is the new source. Hope this helps smbdy:
don't forget to change (seems it's a Codeigniter bug in line 712 in 2.1.3) in _delete function in all db_driver files like database/driver/mysql/mysql_driver.php to:
$conditions .= implode("\n", $where);
or delete function will not work.
Main code:
<?php
if (!defined('BASEPATH'))
exit('No direct script access allowed');
/**
* CodeIgniter
*
* An open source application development framework for PHP 5.1.6 or newer
*
* @package CodeIgniter
* @author ExpressionEngine Dev Team, Lev Zabudko
* @copyright Copyright (c) 2008 - 2011, EllisLab, Inc.
* @license http://codeigniter.com/user_guide/license.html, AS IS
* @link http://codeigniter.com, https://www.facebook.com/LevZabudko
* @since Version 1.0u
* @filesource
*/
// ------------------------------------------------------------------------
/**
* Active Record Class
*
* This is the platform-independent base Active Record implementation class.
*
* @package CodeIgniter
* @subpackage Drivers
* @category Database
* @author ExpressionEngine Dev Team
* @link http://codeigniter.com/user_guide/database/
*/
class CI_DB_active_record extends CI_DB_driver
{
var $ar_identifier = 'default';
var $ar_select = array('default' => array());
var $ar_distinct = array('default' => FALSE);
var $ar_from = array('default' => array());
var $ar_join = array('default' => array());
var $ar_where = array('default' => array());
var $ar_like = array('default' => array());
var $ar_groupby = array('default' => array());
var $ar_having = array('default' => array());
var $ar_keys = array('default' => array());
var $ar_limit = array('default' => FALSE);
var $ar_offset = array('default' => FALSE);
var $ar_order = array('default' => FALSE);
var $ar_orderby = array('default' => array());
var $ar_set = array('default' => array());
var $ar_wherein = array('default' => array());
var $ar_aliased_tables = array('default' => array());
var $ar_store_array = array('default' => array());
var $ar_no_escape = array('default' => array());
// Active Record Caching variables
var $ar_caching = FALSE;
var $ar_cache_exists = array();
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_orderby = array();
var $ar_cache_set = array();
var $ar_cache_no_escape = array();
/**
* Set_identifier
*
* Chooses the channel to use
*
* @access public
* @param string
* @return object
*/
function set_identifier($identifier = 'default')
{
if (!is_string($identifier))
{
$identifier = 'default';
}
$this->ar_identifier = $identifier;
// we have to init the values only if it is a new key
// let's check on the first array
if (!array_key_exists($identifier, $this->ar_select))
{
$this->ar_select [$identifier] = array();
$this->ar_distinct [$identifier] = FALSE;
$this->ar_from [$identifier] = array();
$this->ar_join [$identifier] = array();
$this->ar_where [$identifier] = array();
$this->ar_like [$identifier] = array();
$this->ar_groupby [$identifier] = array();
$this->ar_having [$identifier] = array();
$this->ar_limit [$identifier] = FALSE;
$this->ar_offset [$identifier] = FALSE;
$this->ar_order [$identifier] = FALSE;
$this->ar_orderby [$identifier] = array();
$this->ar_set [$identifier] = array();
$this->ar_keys [$identifier] = array();
$this->ar_wherein [$identifier] = array();
$this->ar_aliased_tables [$identifier] = array();
$this->ar_store_array [$identifier] = array();
}
return $this;
}
// --------------------------------------------------------------------
/**
* Select
*
* Generates the SELECT portion of the query
*
* @param string
* @return object
*/
public function select($select = '*', $escape = NULL)
{
if (is_string($select))
{
$select = explode(',', $select);
}
foreach ($select as $val)
{
$val = trim($val);
if ($val != '')
{
$this->ar_select[$this->ar_identifier][] = $val;
$this->ar_no_escape[$this->ar_identifier][] = $escape;
if ($this->ar_caching === TRUE)
{
$this->ar_cache_select[] = $val;
$this->ar_cache_exists[] = 'select';
$this->ar_cache_no_escape[] = $escape;
}
}
}
return $this;
}
// --------------------------------------------------------------------
/**
* Select Max
*
* Generates a SELECT MAX(field) portion of a query
*
* @param string the field
* @param string an alias
* @return object
*/
public function select_max($select = '', $alias = '')
{
return $this->_max_min_avg_sum($select, $alias, 'MAX');
}
// --------------------------------------------------------------------
/**
* Select Min
*
* Generates a SELECT MIN(field) portion of a query
*
* @param string the field
* @param string an alias
* @return object
*/
public function select_min($select = '', $alias = '')
{
return $this->_max_min_avg_sum($select, $alias, 'MIN');
}
// --------------------------------------------------------------------
/**
* Select Average
*
* Generates a SELECT AVG(field) portion of a query
*
* @param string the field
* @param string an alias
* @return object
*/
public function select_avg($select = '', $alias = '')
{
return $this->_max_min_avg_sum($select, $alias, 'AVG');
}
// --------------------------------------------------------------------
/**
* Select Sum
*
* Generates a SELECT SUM(field) portion of a query
*
* @param string the field
* @param string an alias
* @return object
*/
public function select_sum($select = '', $alias = '')
{
return $this->_max_min_avg_sum($select, $alias, 'SUM');
}
// --------------------------------------------------------------------
/**
* Processing Function for the four functions above:
*
* select_max()
* select_min()
* select_avg()
* select_sum()
*
* @param string the field
* @param string an alias
* @return object
*/
protected function _max_min_avg_sum($select = '', $alias = '', $type = 'MAX')
{
if (!is_string($select) OR $select == '')
{
$this->display_error('db_invalid_query');
}
$type = strtoupper($type);
if (!in_array($type, array('MAX', 'MIN', 'AVG', 'SUM')))
{
show_error('Invalid function type: ' . $type);
}
if ($alias == '')
{
$alias = $this->_create_alias_from_table(trim($select));
}
$sql = $type . '(' . $this->_protect_identifiers(trim($select)) . ') AS ' . $alias;
$this->ar_select[$this->ar_identifier][] = $sql;
if ($this->ar_caching === TRUE)
{
$this->ar_cache_select[] = $sql;
$this->ar_cache_exists[] = 'select';
}
return $this;
}
// --------------------------------------------------------------------
/**
* Determines the alias name based on the table
*
* @param string
* @return string
*/
protected function _create_alias_from_table($item)
{
if (strpos($item, '.') !== FALSE)
{
return end(explode('.', $item));
}
return $item;
}
// --------------------------------------------------------------------
/**
* DISTINCT
*
* Sets a flag which tells the query string compiler to add DISTINCT
*
* @param bool
* @return object
*/
public function distinct($val = TRUE)
{
$this->ar_distinct[$this->ar_identifier] = (is_bool($val)) ? $val : TRUE;
return $this;
}
// --------------------------------------------------------------------
/**
* From
*
* Generates the FROM portion of the query
*
* @param mixed can be a string or array
* @return object
*/
public function from($from)
{
foreach ((array) $from as $val)
{
if (strpos($val, ',') !== FALSE)
{
foreach (explode(',', $val) as $v)
{
$v = trim($v);
$this->_track_aliases($v);
$this->ar_from[$this->ar_identifier][] = $this->_protect_identifiers($v, TRUE, NULL, FALSE);
if ($this->ar_caching === TRUE)
{
$this->ar_cache_from[] = $this->_protect_identifiers($v, TRUE, NULL, FALSE);
$this->ar_cache_exists[] = 'from';
}
}
} else
{
$val = trim($val);
// Extract any aliases that might exist. We use this information
// in the _protect_identifiers to know whether to add a table prefix
$this->_track_aliases($val);
$this->ar_from[$this->ar_identifier][] = $this->_protect_identifiers($val, TRUE, NULL, FALSE);
if ($this->ar_caching === TRUE)
{
$this->ar_cache_from[] = $this->_protect_identifiers($val, TRUE, NULL, FALSE);
$this->ar_cache_exists[] = 'from';
}
}
}
return $this;
}
// --------------------------------------------------------------------
/**
* Join
*
* Generates the JOIN portion of the query
*
* @param string
* @param string the join condition
* @param string the type of join
* @return object
*/
public function join($table, $cond, $type = '')
{
if ($type != '')
{
$type = strtoupper(trim($type));
if (!in_array($type, array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER')))
{
$type = '';
} else
{
$type .= ' ';
}
}
// Extract any aliases that might exist. We use this information
// in the _protect_identifiers to know whether to add a table prefix
$this->_track_aliases($table);
// Strip apart the condition and protect the identifiers
if (preg_match('/([\w\.]+)([\W\s]+)(.+)/', $cond, $match))
{
$match[1] = $this->_protect_identifiers($match[1]);
$match[3] = $this->_protect_identifiers($match[3]);
$cond = $match[1] . $match[2] . $match[3];
}
// Assemble the JOIN statement
$join = $type . 'JOIN ' . $this->_protect_identifiers($table, TRUE, NULL, FALSE) . ' ON ' . $cond;
$this->ar_join[$this->ar_identifier][] = $join;
if ($this->ar_caching === TRUE)
{
$this->ar_cache_join[] = $join;
$this->ar_cache_exists[] = 'join';
}
return $this;
}
// --------------------------------------------------------------------
/**
* Where
*
* Generates the WHERE portion of the query. Separates
* multiple calls with AND
*
* @param mixed
* @param mixed
* @return object
*/
public function where($key, $value = NULL, $escape = TRUE)
{
return $this->_where($key, $value, 'AND ', $escape);
}
// --------------------------------------------------------------------
/**
* OR Where
*
* Generates the WHERE portion of the query. Separates
* multiple calls with OR
*
* @param mixed
* @param mixed
* @return object
*/
public function or_where($key, $value = NULL, $escape = TRUE)
{
return $this->_where($key, $value, 'OR ', $escape);
}
// --------------------------------------------------------------------
/**
* Where
*
* Called by where() or or_where()
*
* @param mixed
* @param mixed
* @param string
* @return object
*/
protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL)
{
if (!is_array($key))
{
$key = array($key => $value);
}
// If the escape value was not set will will base it on the global setting
if (!is_bool($escape))
{
$escape = $this->_protect_identifiers;
}
foreach ($key as $k => $v)
{
$prefix = (count($this->ar_where[$this->ar_identifier]) == 0 AND count($this->ar_cache_where) == 0) ? '' : $type;
if (is_null($v) && !$this->_has_operator($k))
{
// value appears not to have been set, assign the test to IS NULL
$k .= ' IS NULL';
}
if (!is_null($v))
{
if ($escape === TRUE)
{
$k = $this->_protect_identifiers($k, FALSE, $escape);
$v = ' ' . $this->escape($v);
}
if (!$this->_has_operator($k))
{
$k .= ' = ';
}
} else
{
$k = $this->_protect_identifiers($k, FALSE, $escape);
}
$this->ar_where[$this->ar_identifier][] = $prefix . $k . $v;
if ($this->ar_caching === TRUE)
{
$this->ar_cache_where[] = $prefix . $k . $v;
$this->ar_cache_exists[] = 'where';
}
}
return $this;
}
// --------------------------------------------------------------------
/**
* Where_in
*
* Generates a WHERE field IN ('item', 'item') SQL query joined with
* AND if appropriate
*
* @param string The field to search
* @param array The values searched on
* @return object
*/
public function where_in($key = NULL, $values = NULL)
{
return $this->_where_in($key, $values);
}
// --------------------------------------------------------------------
/**
* Where_in_or
*
* Generates a WHERE field IN ('item', 'item') SQL query joined with
* OR if appropriate
*
* @param string The field to search
* @param array The values searched on
* @return object
*/
public function or_where_in($key = NULL, $values = NULL)
{
return $this->_where_in($key, $values, FALSE, 'OR ');
}
// --------------------------------------------------------------------
/**
* Where_not_in
*
* Generates a WHERE field NOT IN ('item', 'item') SQL query joined
* with AND if appropriate
*
* @param string The field to search
* @param array The values searched on
* @return object
*/
public function where_not_in($key = NULL, $values = NULL)
{
return $this->_where_in($key, $values, TRUE);
}
// --------------------------------------------------------------------
/**
* Where_not_in_or
*
* Generates a WHERE field NOT IN ('item', 'item') SQL query joined
* with OR if appropriate
*
* @param string The field to search
* @param array The values searched on
* @return object
*/
public function or_where_not_in($key = NULL, $values = NULL)
{
return $this->_where_in($key, $values, TRUE, 'OR ');
}
// --------------------------------------------------------------------
/**
* Where_in
*
* Called by where_in, where_in_or, where_not_in, where_not_in_or
*
* @param string The field to search
* @param array The values searched on
* @param boolean If the statement would be IN or NOT IN
* @param string
* @return object
*/
protected function _where_in($key = NULL, $values = NULL, $not = FALSE, $type = 'AND ')
{
if ($key === NULL OR $values === NULL)
{
return;
}
if (!is_array($values))
{
$values = array($values);
}
$not = ($not) ? ' NOT' : '';
foreach ($values as $value)
{
$this->ar_wherein[$this->ar_identifier][] = $this->escape($value);
}
$prefix = (count($this->ar_where[$this->ar_identifier]) == 0) ? '' : $type;
$where_in = $prefix . $this->_protect_identifiers($key) . $not . " IN (" . implode(", ", $this->ar_wherein[$this->ar_identifier]) . ") ";
$this->ar_where[$this->ar_identifier][] = $where_in;
if ($this->ar_caching === TRUE)
{
$this->ar_cache_where[] = $where_in;
$this->ar_cache_exists[] = 'where';
}
// reset the array for multiple calls
$this->ar_wherein[$this->ar_identifier] = array();
return $this;
}
// --------------------------------------------------------------------
/**
* Like
*
* Generates a %LIKE% portion of the query. Separates
* multiple calls with AND
*
* @param mixed
* @param mixed
* @return object
*/
public function like($field, $match = '', $side = 'both')
{
return $this->_like($field, $match, 'AND ', $side);
}
// --------------------------------------------------------------------
/**
* Not Like
*
* Generates a NOT LIKE portion of the query. Separates
* multiple calls with AND
*
* @param mixed
* @param mixed
* @return object
*/
public function not_like($field, $match = '', $side = 'both')
{
return $this->_like($field, $match, 'AND ', $side, 'NOT');
}
// --------------------------------------------------------------------
/**
* OR Like
*
* Generates a %LIKE% portion of the query. Separates
* multiple calls with OR
*
* @param mixed
* @param mixed
* @return object
*/
public function or_like($field, $match = '', $side = 'both')
{
return $this->_like($field, $match, 'OR ', $side);
}
// --------------------------------------------------------------------
/**
* OR Not Like
*
* Generates a NOT LIKE portion of the query. Separates
* multiple calls with OR
*
* @param mixed
* @param mixed
* @return object
*/
public function or_not_like($field, $match = '', $side = 'both')
{
return $this->_like($field, $match, 'OR ', $side, 'NOT');
}
// --------------------------------------------------------------------
/**
* Like
*
* Called by like() or orlike()
*
* @param mixed
* @param mixed
* @param string
* @return object
*/
protected function _like($field, $match = '', $type = 'AND ', $side = 'both', $not = '')
{
if (!is_array($field))
{
$field = array($field => $match);
}
foreach ($field as $k => $v)
{
$k = $this->_protect_identifiers($k);
$prefix = (count($this->ar_like[$this->ar_identifier]) == 0) ? '' : $type;
$v = $this->escape_like_str($v);
if ($side == 'none')
{
$like_statement = $prefix . " $k $not LIKE '{$v}'";
} elseif ($side == 'before')
{
$like_statement = $prefix . " $k $not LIKE '%{$v}'";
} elseif ($side == 'after')
{
$like_statement = $prefix . " $k $not LIKE '{$v}%'";
} else
{
$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);
}
$this->ar_like[$this->ar_identifier][] = $like_statement;
if ($this->ar_caching === TRUE)
{
$this->ar_cache_like[] = $like_statement;
$this->ar_cache_exists[] = 'like';
}
}
return $this;
}
// --------------------------------------------------------------------
/**
* GROUP BY
*
* @param string
* @return object
*/
public function group_by($by)
{
if (is_string($by))
{
$by = explode(',', $by);
}
foreach ($by as $val)
{
$val = trim($val);
if ($val != '')
{
$this->ar_groupby[$this->ar_identifier][] = $this->_protect_identifiers($val);
if ($this->ar_caching === TRUE)
{
$this->ar_cache_groupby[] = $this->_protect_identifiers($val);
$this->ar_cache_exists[] = 'groupby';
}
}
}
return $this;
}
// --------------------------------------------------------------------
/**
* Sets the HAVING value
*
* Separates multiple calls with AND
*
* @param string
* @param string
* @return object
*/
public function having($key, $value = '', $escape = TRUE)
{
return $this->_having($key, $value, 'AND ', $escape);
}
// --------------------------------------------------------------------
/**
* Sets the OR HAVING value
*
* Separates multiple calls with OR
*
* @param string
* @param string
* @return object
*/
public function or_having($key, $value = '', $escape = TRUE)
{
return $this->_having($key, $value, 'OR ', $escape);
}
// --------------------------------------------------------------------
/**
* Sets the HAVING values
*
* Called by having() or or_having()
*
* @param string
* @param string
* @return object
*/
protected function _having($key, $value = '', $type = 'AND ', $escape = TRUE)
{
if (!is_array($key))
{
$key = array($key => $value);
}
foreach ($key as $k => $v)
{
$prefix = (count($this->ar_having[$this->ar_identifier]) == 0) ? '' : $type;
if ($escape === TRUE)
{
$k = $this->_protect_identifiers($k);
}
if (!$this->_has_operator($k))
{
$k .= ' = ';
}
if ($v != '')
{
$v = ' ' . $this->escape($v);
}
$this->ar_having[$this->ar_identifier][] = $prefix . $k . $v;
if ($this->ar_caching === TRUE)
{
$this->ar_cache_having[] = $prefix . $k . $v;
$this->ar_cache_exists[] = 'having';
}
}
return $this;
}
// --------------------------------------------------------------------
/**
* Sets the ORDER BY value
*
* @param string
* @param string direction: asc or desc
* @return object
*/
public function order_by($orderby, $direction = '')
{
if (strtolower($direction) == 'random')
{
$orderby = ''; // Random results want or don't need a field name
$direction = $this->_random_keyword;
} elseif (trim($direction) != '')
{
$direction = (in_array(strtoupper(trim($direction)), array('ASC', 'DESC'), TRUE)) ? ' ' . $direction : ' ASC';
}
if (strpos($orderby, ',') !== FALSE)
{
$temp = array();
foreach (explode(',', $orderby) as $part)
{
$part = trim($part);
if (!in_array($part, $this->ar_aliased_tables))
{
$part = $this->_protect_identifiers(trim($part));
}
$temp[] = $part;
}
$orderby = implode(', ', $temp);
} else if ($direction != $this->_random_keyword)
{
$orderby = $this->_protect_identifiers($orderby);
}
$orderby_statement = $orderby . $direction;
$this->ar_orderby[$this->ar_identifier][] = $orderby_statement;
if ($this->ar_caching === TRUE)
{
$this->ar_cache_orderby[] = $orderby_statement;
$this->ar_cache_exists[] = 'orderby';
}
return $this;
}
// --------------------------------------------------------------------
/**
* Sets the LIMIT value
*
* @param integer the limit value
* @param integer the offset value
* @return object
*/
public function limit($value, $offset = '')
{
$this->ar_limit[$this->ar_identifier] = (int) $value;
if ($offset != '')
{
$this->ar_offset[$this->ar_identifier] = (int) $offset;
}
return $this;
}
// --------------------------------------------------------------------
/**
* Sets the OFFSET value
*
* @param integer the offset value
* @return object
*/
public function offset($offset)
{
$this->ar_offset[$this->ar_identifier] = $offset;
return $this;
}
// --------------------------------------------------------------------
/**
* The "set" function. Allows key/value pairs to be set for inserting or updating
*
* @param mixed
* @param string
* @param boolean
* @return object
*/
public function set($key, $value = '', $escape = TRUE)
{
$key = $this->_object_to_array($key);
if (!is_array($key))
{
$key = array($key => $value);
}
foreach ($key as $k => $v)
{
if ($escape === FALSE)
{
$this->ar_set[$this->ar_identifier][$this->_protect_identifiers($k)] = $v;
} else
{
$this->ar_set[$this->ar_identifier][$this->_protect_identifiers($k, FALSE, TRUE)] = $this->escape($v);
}
}
return $this;
}
// --------------------------------------------------------------------
/**
* Get
*
* Compiles the select statement based on the other functions called
* and runs the query
*
* @param string the table
* @param string the limit clause
* @param string the offset clause
* @return object
*/
public function get($table = '', $limit = null, $offset = null)
{
if ($table != '')
{
$this->_track_aliases($table);
$this->from($table);
}
if (!is_null($limit))
{
$this->limit($limit, $offset);
}
$sql = $this->_compile_select();
$result = $this->query($sql);
$this->_reset_select();
return $result;
}
/**
* "Count All Results" query
*
* Generates a platform-specific query string that counts all records
* returned by an Active Record query.
*
* @param string
* @return string
*/
public function count_all_results($table = '')
{
if ($table != '')
{
$this->_track_aliases($table);
$this->from($table);
}
$sql = $this->_compile_select($this->_count_string . $this->_protect_identifiers('numrows'));
$query = $this->query($sql);
$this->_reset_select();
if ($query->num_rows() == 0)
{
return 0;
}
$row = $query->row();
return (int) $row->numrows;
}
// --------------------------------------------------------------------
/**
* Get_Where
*
* Allows the where clause, limit and offset to be added directly
*
* @param string the where clause
* @param string the limit clause
* @param string the offset clause
* @return object
*/
public function get_where($table = '', $where = null, $limit = null, $offset = null)
{
if ($table != '')
{
$this->from($table);
}
if (!is_null($where))
{
$this->where($where);
}
if (!is_null($limit))
{
$this->limit($limit, $offset);
}
$sql = $this->_compile_select();
$result = $this->query($sql);
$this->_reset_select();
return $result;
}
// --------------------------------------------------------------------
/**
* Insert_Batch
*
* Compiles batch insert strings and runs the queries
*
* @param string the table to retrieve the results from
* @param array an associative array of insert values
* @return object
*/
public function insert_batch($table = '', $set = NULL)
{
if (!is_null($set))
{
$this->set_insert_batch($set);
}
if (count($this->ar_set[$this->ar_identifier]) == 0)
{
if ($this->db_debug)
{
//No valid data array. Folds in cases where keys and values did not match up
return $this->display_error('db_must_use_set');
}
return FALSE;
}
if ($table == '')
{
if (!isset($this->ar_from[$this->ar_identifier][0]))
{
if ($this->db_debug)
{
return $this->display_error('db_must_set_table');
}
return FALSE;
}
$table = $this->ar_from[$this->ar_identifier][0];
}
// Batch this baby
for ($i = 0, $total = count($this->ar_set[$this->ar_identifier]); $i < $total; $i = $i + 100)
{
$sql = $this->_insert_batch($this->_protect_identifiers($table, TRUE, NULL, FALSE), $this->ar_keys[$this->ar_identifier], array_slice($this->ar_set[$this->ar_identifier], $i, 100));
//echo $sql;
$this->query($sql);
}
$this->_reset_write();
return TRUE;
}
// --------------------------------------------------------------------
/**
* The "set_insert_batch" function. Allows key/value pairs to be set for batch inserts
*
* @param mixed
* @param string
* @param boolean
* @return object
*/
public function set_insert_batch($key, $value = '', $escape = TRUE)
{
$key = $this->_object_to_array_batch($key);
if (!is_array($key))
{
$key = array($key => $value);
}
$keys = array_keys(current($key));
sort($keys);
foreach ($key as $row)
{
if (count(array_diff($keys, array_keys($row))) > 0 OR count(array_diff(array_keys($row), $keys)) > 0)
{
// batch function above returns an error on an empty array
$this->ar_set[$this->ar_identifier][] = array();
return;
}
ksort($row); // puts $row in the same order as our keys
if ($escape === FALSE)
{
$this->ar_set[$this->ar_identifier][] = '(' . implode(',', $row) . ')';
} else
{
$clean = array();
foreach ($row as $value)
{
$clean[] = $this->escape($value);
}
$this->ar_set[$this->ar_identifier][] = '(' . implode(',', $clean) . ')';
}
}
foreach ($keys as $k)
{
$this->ar_keys[$this->ar_identifier][] = $this->_protect_identifiers($k);
}
return $this;
}
// --------------------------------------------------------------------
/**
* Insert
*
* Compiles an insert string and runs the query
*
* @param string the table to insert data into
* @param array an associative array of insert values
* @return object
*/
function insert($table = '', $set = NULL)
{
if (!is_null($set))
{
$this->set($set);
}
if (count($this->ar_set[$this->ar_identifier]) == 0)
{
if ($this->db_debug)
{
return $this->display_error('db_must_use_set');
}
return FALSE;
}
if ($table == '')
{
if (!isset($this->ar_from[$this->ar_identifier][0]))
{
if ($this->db_debug)
{
return $this->display_error('db_must_set_table');
}
return FALSE;
}
$table = $this->ar_from[$this->ar_identifier][0];
}
$sql = $this->_insert($this->_protect_identifiers($table, TRUE, NULL, FALSE), array_keys($this->ar_set[$this->ar_identifier]), array_values($this->ar_set[$this->ar_identifier]));
$this->_reset_write();
return $this->query($sql);
}
// --------------------------------------------------------------------
/**
* Replace
*
* Compiles an replace into string and runs the query
*
* @param string the table to replace data into
* @param array an associative array of insert values
* @return object
*/
public function replace($table = '', $set = NULL)
{
if (!is_null($set))
{
$this->set($set);
}
if (count($this->ar_set[$this->ar_identifier]) == 0)
{
if ($this->db_debug)
{
return $this->display_error('db_must_use_set');
}
return FALSE;
}
if ($table == '')
{
if (!isset($this->ar_from[$this->ar_identifier][0]))
{
if ($this->db_debug)
{
return $this->display_error('db_must_set_table');
}
return FALSE;
}
$table = $this->ar_from[$this->ar_identifier][0];
}
$sql = $this->_replace($this->_protect_identifiers($table, TRUE, NULL, FALSE), array_keys($this->ar_set[$this->ar_identifier]), array_values($this->ar_set[$this->ar_identifier]));
$this->_reset_write();
return $this->query($sql);
}
// --------------------------------------------------------------------
/**
* Update
*
* Compiles an update string and runs the query
*
* @param string the table to retrieve the results from
* @param array an associative array of update values
* @param mixed the where clause
* @return object
*/
public function update($table = '', $set = NULL, $where = NULL, $limit = NULL)
{
// Combine any cached components with the current statements
$this->_merge_cache();
if (!is_null($set))
{
$this->set($set);
}
if (count($this->ar_set[$this->ar_identifier]) == 0)
{
if ($this->db_debug)
{
return $this->display_error('db_must_use_set');
}
return FALSE;
}
if ($table == '')
{
if (!isset($this->ar_from[$this->ar_identifier][0]))
{
if ($this->db_debug)
{
return $this->display_error('db_must_set_table');
}
return FALSE;
}
$table = $this->ar_from[$this->ar_identifier][0];
}
if ($where != NULL)
{
$this->where($where);
}
if ($limit != NULL)
{
$this->limit($limit);
}
$sql = $this->_update($this->_protect_identifiers($table, TRUE, NULL, FALSE), $this->ar_set[$this->ar_identifier], $this->ar_where[$this->ar_identifier], $this->ar_orderby[$this->ar_identifier], $this->ar_limit[$this->ar_identifier]);
$this->_reset_write();
return $this->query($sql);
}
// --------------------------------------------------------------------
/**
* Update_Batch
*
* Compiles an update string and runs the query
*
* @param string the table to retrieve the results from
* @param array an associative array of update values
* @param string the where key
* @return object
*/
public function update_batch($table = '', $set = NULL, $index = NULL)
{
// Combine any cached components with the current statements
$this->_merge_cache();
if (is_null($index))
{
if ($this->db_debug)
{
return $this->display_error('db_must_use_index');
}
return FALSE;
}
if (!is_null($set))
{
$this->set_update_batch($set, $index);
}
if (count($this->ar_set[$this->ar_identifier]) == 0)
{
if ($this->db_debug)
{
return $this->display_error('db_must_use_set');
}
return FALSE;
}
if ($table == '')
{
if (!isset($this->ar_from[$this->ar_identifier][0]))
{
if ($this->db_debug)
{
return $this->display_error('db_must_set_table');
}
return FALSE;
}
$table = $this->ar_from[$this->ar_identifier][0];
}
// Batch this baby
for ($i = 0, $total = count($this->ar_set[$this->ar_identifier]); $i < $total; $i = $i + 100)
{
$sql = $this->_update_batch($this->_protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->ar_set[$this->ar_identifier], $i, 100), $this->_protect_identifiers($index), $this->ar_where[$this->ar_identifier]);
$this->query($sql);
}
$this->_reset_write();
}
// --------------------------------------------------------------------
/**
* The "set_update_batch" function. Allows key/value pairs to be set for batch updating
*
* @param array
* @param string
* @param boolean
* @return object
*/
public function set_update_batch($key, $index = '', $escape = TRUE)
{
$key = $this->_object_to_array_batch($key);
if (!is_array($key))
{
// @todo error
}
foreach ($key as $k => $v)
{
$index_set = FALSE;
$clean = array();
foreach ($v as $k2 => $v2)
{
if ($k2 == $index)
{
$index_set = TRUE;
} else
{
$not[] = $k . '-' . $v;
}
if ($escape === FALSE)
{
$clean[$this->_protect_identifiers($k2)] = $v2;
} else
{
$clean[$this->_protect_identifiers($k2)] = $this->escape($v2);
}
}
if ($index_set == FALSE)
{
return $this->display_error('db_batch_missing_index');
}
$this->ar_set[$this->ar_identifier][] = $clean;
}
return $this;
}
// --------------------------------------------------------------------
/**
* Empty Table
*
* Compiles a delete string and runs "DELETE FROM table"
*
* @param string the table to empty
* @return object
*/
public function empty_table($table = '')
{
if ($table == '')
{
if (!isset($this->ar_from[$this->ar_identifier][0]))
{
if ($this->db_debug)
{
return $this->display_error('db_must_set_table');
}
return FALSE;
}
$table = $this->ar_from[$this->ar_identifier][0];
} else
{
$table = $this->_protect_identifiers($table, TRUE, NULL, FALSE);
}
$sql = $this->_delete($table);
$this->_reset_write();
return $this->query($sql);
}
// --------------------------------------------------------------------
/**
* Truncate
*
* Compiles a truncate string and runs the query
* If the database does not support the truncate() command
* This function maps to "DELETE FROM table"
*
* @param string the table to truncate
* @return object
*/
public function truncate($table = '')
{
if ($table == '')
{
if (!isset($this->ar_from[$this->ar_identifier][0]))
{
if ($this->db_debug)
{
return $this->display_error('db_must_set_table');
}
return FALSE;
}
$table = $this->ar_from[$this->ar_identifier][0];
} else
{
$table = $this->_protect_identifiers($table, TRUE, NULL, FALSE);
}
$sql = $this->_truncate($table);
$this->_reset_write();
return $this->query($sql);
}
// --------------------------------------------------------------------
/**
* Delete
*
* Compiles a delete string and runs the query
*
* @param mixed the table(s) to delete from. String or array
* @param mixed the where clause
* @param mixed the limit clause
* @param boolean
* @return object
*/
public function delete($table = '', $where = '', $limit = NULL, $reset_data = TRUE)
{
// Combine any cached components with the current statements
$this->_merge_cache();
if ($table == '')
{
if (!isset($this->ar_from[$this->ar_identifier][0]))
{
if ($this->db_debug)
{
return $this->display_error('db_must_set_table');
}
return FALSE;
}
$table = $this->ar_from[$this->ar_identifier][0];
} elseif (is_array($table))
{
foreach ($table as $single_table)
{
$this->delete($single_table, $where, $limit, FALSE);
}
$this->_reset_write();
return;
} else
{
$table = $this->_protect_identifiers($table, TRUE, NULL, FALSE);
}
if ($where != '')
{
$this->where($where);
}
if ($limit != NULL)
{
$this->limit($limit);
}
if (count($this->ar_where[$this->ar_identifier]) == 0 && count($this->ar_wherein[$this->ar_identifier]) == 0 && count($this->ar_like[$this->ar_identifier]) == 0)
{
if ($this->db_debug)
{
return $this->display_error('db_del_must_use_where');
}
return FALSE;
}
$sql = $this->_delete($table, $this->ar_where[$this->ar_identifier], $this->ar_like[$this->ar_identifier], $this->ar_limit[$this->ar_identifier]);
if ($reset_data)
{
$this->_reset_write();
}
return $this->query($sql);
}
// --------------------------------------------------------------------
/**
* DB Prefix
*
* Prepends a database prefix if one exists in configuration
*
* @param string the table
* @return string
*/
public function dbprefix($table = '')
{
if ($table == '')
{
$this->display_error('db_table_name_required');
}
return $this->dbprefix . $table;
}
// --------------------------------------------------------------------
/**
* Set DB Prefix
*
* Set's the DB Prefix to something new without needing to reconnect
*
* @param string the prefix
* @return string
*/
public function set_dbprefix($prefix = '')
{
return $this->dbprefix = $prefix;
}
// --------------------------------------------------------------------
/**
* Track Aliases
*
* Used to track SQL statements written with aliased tables.
*
* @param string The table to inspect
* @return string
*/
protected function _track_aliases($table)
{
if (is_array($table))
{
foreach ($table as $t)
{
$this->_track_aliases($t);
}
return;
}
// Does the string contain a comma? If so, we need to separate
// the string into discreet statements
if (strpos($table, ',') !== FALSE)
{
return $this->_track_aliases(explode(',', $table));
}
// if a table alias is used we can recognize it by a space
if (strpos($table, " ") !== FALSE)
{
// if the alias is written with the AS keyword, remove it
$table = preg_replace('/\s+AS\s+/i', ' ', $table);
// Grab the alias
$table = trim(strrchr($table, " "));
// Store the alias, if it doesn't already exist
if (!in_array($table, $this->ar_aliased_tables[$this->ar_identifier]))
{
$this->ar_aliased_tables[$this->ar_identifier][] = $table;
}
}
}
// --------------------------------------------------------------------
/**
* Compile the SELECT statement
*
* Generates a query string based on which functions were used.
* Should not be called directly. The get() function calls it.
*
* @return string
*/
protected function _compile_select($select_override = FALSE)
{
// Combine any cached components with the current statements
$this->_merge_cache();
// ----------------------------------------------------------------
// Write the "select" portion of the query
if ($select_override !== FALSE)
{
$sql = $select_override;
} else
{
$sql = (!$this->ar_distinct[$this->ar_identifier]) ? 'SELECT ' : 'SELECT DISTINCT ';
if (count($this->ar_select[$this->ar_identifier]) == 0)
{
$sql .= '*';
} else
{
// Cycle through the "select" portion of the query and prep each column name.
// The reason we protect identifiers here rather then in the select() function
// is because until the user calls the from() function we don't know if there are aliases
foreach ($this->ar_select[$this->ar_identifier] as $key => $val)
{
$no_escape = isset($this->ar_no_escape[$this->ar_identifier][$key]) ? $this->ar_no_escape[$this->ar_identifier][$key] : NULL;
$this->ar_select[$this->ar_identifier][$key] = $this->_protect_identifiers($val, FALSE, $no_escape);
}
$sql .= implode(', ', $this->ar_select[$this->ar_identifier]);
}
}
// ----------------------------------------------------------------
// Write the "FROM" portion of the query
if (count($this->ar_from[$this->ar_identifier]) > 0)
{
$sql .= "\nFROM ";
$sql .= $this->_from_tables($this->ar_from[$this->ar_identifier]);
}
// ----------------------------------------------------------------
// Write the "JOIN" portion of the query
if (count($this->ar_join[$this->ar_identifier]) > 0)
{
$sql .= "\n";
$sql .= implode("\n", $this->ar_join[$this->ar_identifier]);
}
// ----------------------------------------------------------------
// Write the "WHERE" portion of the query
if (count($this->ar_where[$this->ar_identifier]) > 0 OR count($this->ar_like[$this->ar_identifier]) > 0)
{
$sql .= "\nWHERE ";
}
$sql .= implode("\n", $this->ar_where[$this->ar_identifier]);
// ----------------------------------------------------------------
// Write the "LIKE" portion of the query
if (count($this->ar_like[$this->ar_identifier]) > 0)
{
if (count($this->ar_where[$this->ar_identifier]) > 0)
{
$sql .= "\nAND ";
}
$sql .= implode("\n", $this->ar_like[$this->ar_identifier]);
}
// ----------------------------------------------------------------
// Write the "GROUP BY" portion of the query
if (count($this->ar_groupby[$this->ar_identifier]) > 0)
{
$sql .= "\nGROUP BY ";
$sql .= implode(', ', $this->ar_groupby[$this->ar_identifier]);
}
// ----------------------------------------------------------------
// Write the "HAVING" portion of the query
if (count($this->ar_having[$this->ar_identifier]) > 0)
{
$sql .= "\nHAVING ";
$sql .= implode("\n", $this->ar_having[$this->ar_identifier]);
}
// ----------------------------------------------------------------
// Write the "ORDER BY" portion of the query
if (count($this->ar_orderby[$this->ar_identifier]) > 0)
{
$sql .= "\nORDER BY ";
$sql .= implode(', ', $this->ar_orderby[$this->ar_identifier]);
if ($this->ar_order[$this->ar_identifier] !== FALSE)
{
$sql .= ($this->ar_order[$this->ar_identifier] == 'desc') ? ' DESC' : ' ASC';
}
}
// ----------------------------------------------------------------
// Write the "LIMIT" portion of the query
if (is_numeric($this->ar_limit[$this->ar_identifier]))
{
$sql .= "\n";
$sql = $this->_limit($sql, $this->ar_limit[$this->ar_identifier], $this->ar_offset[$this->ar_identifier]);
}
return $sql;
}
// --------------------------------------------------------------------
/**
* Object to Array
*
* Takes an object as input and converts the class variables to array key/vals
*
* @param object
* @return array
*/
public function _object_to_array($object)
{
if (!is_object($object))
{
return $object;
}
$array = array();
foreach (get_object_vars($object) as $key => $val)
{
// There are some built in keys we need to ignore for this conversion
if (!is_object($val) && !is_array($val) && $key != '_parent_name')
{
$array[$key] = $val;
}
}
return $array;
}
// --------------------------------------------------------------------
/**
* Object to Array
*
* Takes an object as input and converts the class variables to array key/vals
*
* @param object
* @return array
*/
public function _object_to_array_batch($object)
{
if (!is_object($object))
{
return $object;
}
$array = array();
$out = get_object_vars($object);
$fields = array_keys($out);
foreach ($fields as $val)
{
// There are some built in keys we need to ignore for this conversion
if ($val != '_parent_name')
{
$i = 0;
foreach ($out[$val] as $data)
{
$array[$i][$val] = $data;
$i++;
}
}
}
return $array;
}
// --------------------------------------------------------------------
/**
* Start Cache
*
* Starts AR caching
*
* @return void
*/
public function start_cache()
{
$this->ar_caching = TRUE;
}
// --------------------------------------------------------------------
/**
* Stop Cache
*
* Stops AR caching
*
* @return void
*/
public function stop_cache()
{
$this->ar_caching = FALSE;
}
// --------------------------------------------------------------------
/**
* Flush Cache
*
* Empties the AR cache
*
* @access public
* @return void
*/
public function flush_cache()
{
$this->_reset_run(array(
'ar_cache_select' => array(),
'ar_cache_from' => array(),
'ar_cache_join' => array(),
'ar_cache_where' => array(),
'ar_cache_like' => array(),
'ar_cache_groupby' => array(),
'ar_cache_having' => array(),
'ar_cache_orderby' => array(),
'ar_cache_set' => array(),
'ar_cache_exists' => array(),
'ar_cache_no_escape' => array()
));
}
// --------------------------------------------------------------------
/**
* Merge Cache
*
* When called, this function merges any cached AR arrays with
* locally called ones.
*
* @return void
*/
protected function _merge_cache()
{
if (count($this->ar_cache_exists) == 0)
{
return;
}
foreach ($this->ar_cache_exists as $val)
{
$ar_variable = 'ar_' . $val;
$ar_cache_var = 'ar_cache_' . $val;
if (count($this->$ar_cache_var) == 0)
{
continue;
}
$this->$ar_variable = array_unique(array_merge($this->$ar_cache_var, $this->$ar_variable));
}
// If we are "protecting identifiers" we need to examine the "from"
// portion of the query to determine if there are any aliases
if ($this->_protect_identifiers === TRUE AND count($this->ar_cache_from) > 0)
{
$this->_track_aliases($this->ar_from[$this->ar_identifier]);
}
$this->ar_no_escape[$this->ar_identifier] = $this->ar_cache_no_escape;
}
// --------------------------------------------------------------------
/**
* Resets the active record values. Called by the get() function
*
* @param array An array of fields to reset
* @return void
*/
protected 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
*
* @return void
*/
protected function _reset_select()
{
$ar_reset_items = array(
'ar_select' => array($this->ar_identifier => array()),
'ar_from' => array($this->ar_identifier => array()),
'ar_join' => array($this->ar_identifier => array()),
'ar_where' => array($this->ar_identifier => array()),
'ar_like' => array($this->ar_identifier => array()),
'ar_groupby' => array($this->ar_identifier => array()),
'ar_having' => array($this->ar_identifier => array()),
'ar_orderby' => array($this->ar_identifier => array()),
'ar_wherein' => array($this->ar_identifier => array()),
'ar_aliased_tables' => array($this->ar_identifier => array()),
'ar_no_escape' => array($this->ar_identifier => array()),
'ar_distinct' => array($this->ar_identifier => FALSE),
'ar_limit' => array($this->ar_identifier => FALSE),
'ar_offset' => array($this->ar_identifier => FALSE),
'ar_order' => array($this->ar_identifier => FALSE),
);
foreach ($this->ar_select as $ident => $val)
{
if ($ident != $this->ar_identifier)
{
$ar_reset_items['ar_select'][$ident] = $this->ar_select[$ident];
$ar_reset_items['ar_from'][$ident] = $this->ar_from[$ident];
$ar_reset_items['ar_join'][$ident] = $this->ar_join[$ident];
$ar_reset_items['ar_where'][$ident] = $this->ar_where[$ident];
$ar_reset_items['ar_like'][$ident] = $this->ar_like[$ident];
$ar_reset_items['ar_groupby'][$ident] = $this->ar_groupby[$ident];
$ar_reset_items['ar_having'][$ident] = $this->ar_having[$ident];
$ar_reset_items['ar_orderby'][$ident] = $this->ar_orderby[$ident];
$ar_reset_items['ar_wherein'][$ident] = $this->ar_wherein[$ident];
$ar_reset_items['ar_aliased_tables'][$ident] = $this->ar_aliased_tables[$ident];
$ar_reset_items['ar_no_escape'][$ident] = $this->ar_no_escape[$ident];
$ar_reset_items['ar_distinct'][$ident] = $this->ar_distinct[$ident];
$ar_reset_items['ar_limit'][$ident] = $this->ar_limit[$ident];
$ar_reset_items['ar_offset'][$ident] = $this->ar_offset[$ident];
$ar_reset_items['ar_order'][$ident] = $this->ar_order[$ident];
}
}
$this->_reset_run($ar_reset_items);
}
// --------------------------------------------------------------------
/**
* Resets the active record "write" values.
*
* Called by the insert() update() insert_batch() update_batch() and delete() functions
*
* @return void
*/
protected function _reset_write()
{
$ar_reset_items = array(
'ar_set' => array($this->ar_identifier => array()),
'ar_from' => array($this->ar_identifier => array()),
'ar_where' => array($this->ar_identifier => array()),
'ar_like' => array($this->ar_identifier => array()),
'ar_orderby' => array($this->ar_identifier => array()),
'ar_keys' => array($this->ar_identifier => array()),
'ar_limit' => array($this->ar_identifier => FALSE),
'ar_order' => array($this->ar_identifier => FALSE)
);
$this->_reset_run($ar_reset_items);
}
}
/* End of file DB_active_rec.php */
/* Location: ./system/database/DB_active_rec.php */