-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');\r
-/**\r
- * CodeIgniter\r
- *\r
- * An open source application development framework for PHP 4.3.2 or newer\r
- *\r
- * @package CodeIgniter\r
- * @author ExpressionEngine Dev Team\r
- * @copyright Copyright (c) 2008, EllisLab, Inc.\r
- * @license http://codeigniter.com/user_guide/license.html\r
- * @link http://codeigniter.com\r
- * @since Version 1.0\r
- * @filesource\r
- */\r
-\r
-// ------------------------------------------------------------------------\r
-\r
-/**\r
- * Active Record Class\r
- *\r
- * This is the platform-independent base Active Record implementation class.\r
- *\r
- * @package CodeIgniter\r
- * @subpackage Drivers\r
- * @category Database\r
- * @author ExpressionEngine Dev Team\r
- * @link http://codeigniter.com/user_guide/database/\r
- */\r
-class CI_DB_active_record extends CI_DB_driver {\r
-\r
- var $ar_select = array();\r
- var $ar_distinct = FALSE;\r
- var $ar_from = array();\r
- var $ar_join = array();\r
- var $ar_where = array();\r
- var $ar_like = array();\r
- var $ar_groupby = array();\r
- var $ar_having = array();\r
- var $ar_limit = FALSE;\r
- var $ar_offset = FALSE;\r
- var $ar_order = FALSE;\r
- var $ar_orderby = array();\r
- var $ar_set = array(); \r
- var $ar_wherein = array();\r
- var $ar_aliased_tables = array();\r
- var $ar_store_array = array();\r
- \r
- // Active Record Caching variables\r
- var $ar_caching = FALSE;\r
- var $ar_cache_exists = array();\r
- var $ar_cache_select = array();\r
- var $ar_cache_from = array();\r
- var $ar_cache_join = array();\r
- var $ar_cache_where = array();\r
- var $ar_cache_like = array();\r
- var $ar_cache_groupby = array();\r
- var $ar_cache_having = array();\r
- var $ar_cache_orderby = array();\r
- var $ar_cache_set = array(); \r
-\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Select\r
- *\r
- * Generates the SELECT portion of the query\r
- *\r
- * @access public\r
- * @param string\r
- * @return object\r
- */\r
- function select($select = '*', $escape = NULL)\r
- {\r
- // Set the global value if this was sepecified \r
- if (is_bool($escape))\r
- {\r
- $this->_protect_identifiers = $escape;\r
- }\r
- \r
- if (is_string($select))\r
- {\r
- $select = explode(',', $select);\r
- }\r
-\r
- foreach ($select as $val)\r
- {\r
- $val = trim($val);\r
-\r
- if ($val != '')\r
- {\r
- $this->ar_select[] = $val;\r
-\r
- if ($this->ar_caching === TRUE)\r
- {\r
- $this->ar_cache_select[] = $val;\r
- $this->ar_cache_exists[] = 'select';\r
- }\r
- }\r
- }\r
- return $this;\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Select Max\r
- *\r
- * Generates a SELECT MAX(field) portion of a query\r
- *\r
- * @access public\r
- * @param string the field\r
- * @param string an alias\r
- * @return object\r
- */\r
- function select_max($select = '', $alias = '')\r
- {\r
- return $this->_max_min_avg_sum($select, $alias, 'MAX');\r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Select Min\r
- *\r
- * Generates a SELECT MIN(field) portion of a query\r
- *\r
- * @access public\r
- * @param string the field\r
- * @param string an alias\r
- * @return object\r
- */\r
- function select_min($select = '', $alias = '')\r
- {\r
- return $this->_max_min_avg_sum($select, $alias, 'MIN');\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Select Average\r
- *\r
- * Generates a SELECT AVG(field) portion of a query\r
- *\r
- * @access public\r
- * @param string the field\r
- * @param string an alias\r
- * @return object\r
- */\r
- function select_avg($select = '', $alias = '')\r
- {\r
- return $this->_max_min_avg_sum($select, $alias, 'AVG');\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Select Sum\r
- *\r
- * Generates a SELECT SUM(field) portion of a query\r
- *\r
- * @access public\r
- * @param string the field\r
- * @param string an alias\r
- * @return object\r
- */\r
- function select_sum($select = '', $alias = '')\r
- {\r
- return $this->_max_min_avg_sum($select, $alias, 'SUM');\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Processing Function for the four functions above:\r
- *\r
- * select_max()\r
- * select_min()\r
- * select_avg()\r
- * select_sum()\r
- * \r
- * @access public\r
- * @param string the field\r
- * @param string an alias\r
- * @return object\r
- */\r
- function _max_min_avg_sum($select = '', $alias = '', $type = 'MAX')\r
- {\r
- if ( ! is_string($select) OR $select == '')\r
- {\r
- $this->display_error('db_invalid_query');\r
- }\r
- \r
- $type = strtoupper($type);\r
- \r
- if ( ! in_array($type, array('MAX', 'MIN', 'AVG', 'SUM')))\r
- {\r
- show_error('Invalid function type: '.$type);\r
- }\r
- \r
- if ($alias == '')\r
- {\r
- $alias = $this->_create_alias_from_table(trim($select));\r
- }\r
- \r
- $sql = $type.'('.$this->_protect_identifiers(trim($select)).') AS '.$alias;\r
-\r
- $this->ar_select[] = $sql;\r
- \r
- if ($this->ar_caching === TRUE)\r
- {\r
- $this->ar_cache_select[] = $sql;\r
- $this->ar_cache_exists[] = 'select';\r
- }\r
- \r
- return $this;\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Determines the alias name based on the table\r
- *\r
- * @access private\r
- * @param string\r
- * @return string\r
- */\r
- function _create_alias_from_table($item)\r
- {\r
- if (strpos($item, '.') !== FALSE)\r
- {\r
- return end(explode('.', $item));\r
- }\r
- \r
- return $item;\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * DISTINCT\r
- *\r
- * Sets a flag which tells the query string compiler to add DISTINCT\r
- *\r
- * @access public\r
- * @param bool\r
- * @return object\r
- */\r
- function distinct($val = TRUE)\r
- {\r
- $this->ar_distinct = (is_bool($val)) ? $val : TRUE;\r
- return $this;\r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * From\r
- *\r
- * Generates the FROM portion of the query\r
- *\r
- * @access public\r
- * @param mixed can be a string or array\r
- * @return object\r
- */\r
- function from($from)\r
- {\r
- foreach ((array)$from as $val)\r
- {\r
- // Extract any aliases that might exist. We use this information\r
- // in the _protect_identifiers to know whether to add a table prefix \r
- $this->_track_aliases($val);\r
-\r
- $this->ar_from[] = $this->_protect_identifiers($val, TRUE, NULL, FALSE);\r
- \r
- if ($this->ar_caching === TRUE)\r
- {\r
- $this->ar_cache_from[] = $this->_protect_identifiers($val, TRUE, NULL, FALSE);\r
- $this->ar_cache_exists[] = 'from';\r
- }\r
- }\r
-\r
- return $this;\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Join\r
- *\r
- * Generates the JOIN portion of the query\r
- *\r
- * @access public\r
- * @param string\r
- * @param string the join condition\r
- * @param string the type of join\r
- * @return object\r
- */\r
- function join($table, $cond, $type = '')\r
- { \r
- if ($type != '')\r
- {\r
- $type = strtoupper(trim($type));\r
-\r
- if ( ! in_array($type, array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER')))\r
- {\r
- $type = '';\r
- }\r
- else\r
- {\r
- $type .= ' ';\r
- }\r
- }\r
-\r
- // Extract any aliases that might exist. We use this information\r
- // in the _protect_identifiers to know whether to add a table prefix \r
- $this->_track_aliases($table);\r
-\r
- // Strip apart the condition and protect the identifiers\r
- if (preg_match('/([\w\.]+)([\W\s]+)(.+)/', $cond, $match))\r
- {\r
- $match[1] = $this->_protect_identifiers($match[1]);\r
- $match[3] = $this->_protect_identifiers($match[3]);\r
- \r
- $cond = $match[1].$match[2].$match[3]; \r
- }\r
- \r
- // Assemble the JOIN statement\r
- $join = $type.'JOIN '.$this->_protect_identifiers($table, TRUE, NULL, FALSE).' ON '.$cond;\r
-\r
- $this->ar_join[] = $join;\r
- if ($this->ar_caching === TRUE)\r
- {\r
- $this->ar_cache_join[] = $join;\r
- $this->ar_cache_exists[] = 'join';\r
- }\r
-\r
- return $this;\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Where\r
- *\r
- * Generates the WHERE portion of the query. Separates\r
- * multiple calls with AND\r
- *\r
- * @access public\r
- * @param mixed\r
- * @param mixed\r
- * @return object\r
- */\r
- function where($key, $value = NULL, $escape = TRUE)\r
- {\r
- return $this->_where($key, $value, 'AND ', $escape);\r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * OR Where\r
- *\r
- * Generates the WHERE portion of the query. Separates\r
- * multiple calls with OR\r
- *\r
- * @access public\r
- * @param mixed\r
- * @param mixed\r
- * @return object\r
- */\r
- function or_where($key, $value = NULL, $escape = TRUE)\r
- {\r
- return $this->_where($key, $value, 'OR ', $escape);\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * orwhere() is an alias of or_where()\r
- * this function is here for backwards compatibility, as\r
- * orwhere() has been deprecated\r
- */\r
- function orwhere($key, $value = NULL, $escape = TRUE)\r
- {\r
- return $this->or_where($key, $value, $escape);\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Where\r
- *\r
- * Called by where() or orwhere()\r
- *\r
- * @access private\r
- * @param mixed\r
- * @param mixed\r
- * @param string\r
- * @return object\r
- */\r
- function _where($key, $value = NULL, $type = 'AND ', $escape = NULL)\r
- {\r
- if ( ! is_array($key))\r
- {\r
- $key = array($key => $value);\r
- }\r
- \r
- // If the escape value was not set will will base it on the global setting\r
- if ( ! is_bool($escape))\r
- {\r
- $escape = $this->_protect_identifiers;\r
- }\r
-\r
- foreach ($key as $k => $v)\r
- {\r
- $prefix = (count($this->ar_where) == 0 AND count($this->ar_cache_where) == 0) ? '' : $type;\r
-\r
- if (is_null($v) && ! $this->_has_operator($k))\r
- {\r
- // value appears not to have been set, assign the test to IS NULL\r
- $k .= ' IS NULL';\r
- }\r
- \r
- if ( ! is_null($v))\r
- {\r
- if ($escape === TRUE)\r
- {\r
- $k = $this->_protect_identifiers($k, FALSE, $escape);\r
- \r
- $v = ' '.$this->escape($v);\r
- }\r
-\r
- if ( ! $this->_has_operator($k))\r
- {\r
- $k .= ' =';\r
- }\r
- }\r
- else\r
- {\r
- $k = $this->_protect_identifiers($k, FALSE, $escape); \r
- }\r
-\r
- $this->ar_where[] = $prefix.$k.$v;\r
- \r
- if ($this->ar_caching === TRUE)\r
- {\r
- $this->ar_cache_where[] = $prefix.$k.$v;\r
- $this->ar_cache_exists[] = 'where';\r
- }\r
- \r
- }\r
- \r
- return $this;\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Where_in\r
- *\r
- * Generates a WHERE field IN ('item', 'item') SQL query joined with\r
- * AND if appropriate\r
- *\r
- * @access public\r
- * @param string The field to search\r
- * @param array The values searched on\r
- * @return object\r
- */\r
- function where_in($key = NULL, $values = NULL)\r
- {\r
- return $this->_where_in($key, $values);\r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Where_in_or\r
- *\r
- * Generates a WHERE field IN ('item', 'item') SQL query joined with\r
- * OR if appropriate\r
- *\r
- * @access public\r
- * @param string The field to search\r
- * @param array The values searched on\r
- * @return object\r
- */\r
- function or_where_in($key = NULL, $values = NULL)\r
- {\r
- return $this->_where_in($key, $values, FALSE, 'OR ');\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Where_not_in\r
- *\r
- * Generates a WHERE field NOT IN ('item', 'item') SQL query joined\r
- * with AND if appropriate\r
- *\r
- * @access public\r
- * @param string The field to search\r
- * @param array The values searched on\r
- * @return object\r
- */\r
- function where_not_in($key = NULL, $values = NULL)\r
- {\r
- return $this->_where_in($key, $values, TRUE);\r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Where_not_in_or\r
- *\r
- * Generates a WHERE field NOT IN ('item', 'item') SQL query joined\r
- * with OR if appropriate\r
- *\r
- * @access public\r
- * @param string The field to search\r
- * @param array The values searched on\r
- * @return object\r
- */\r
- function or_where_not_in($key = NULL, $values = NULL)\r
- {\r
- return $this->_where_in($key, $values, TRUE, 'OR ');\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Where_in\r
- *\r
- * Called by where_in, where_in_or, where_not_in, where_not_in_or\r
- *\r
- * @access public\r
- * @param string The field to search\r
- * @param array The values searched on\r
- * @param boolean If the statement would be IN or NOT IN\r
- * @param string \r
- * @return object\r
- */\r
- function _where_in($key = NULL, $values = NULL, $not = FALSE, $type = 'AND ')\r
- {\r
- if ($key === NULL OR $values === NULL)\r
- {\r
- return;\r
- }\r
- \r
- if ( ! is_array($values))\r
- {\r
- $values = array($values);\r
- }\r
- \r
- $not = ($not) ? ' NOT' : '';\r
-\r
- foreach ($values as $value)\r
- {\r
- $this->ar_wherein[] = $this->escape($value);\r
- }\r
-\r
- $prefix = (count($this->ar_where) == 0) ? '' : $type;\r
- \r
- $where_in = $prefix . $this->_protect_identifiers($key) . $not . " IN (" . implode(", ", $this->ar_wherein) . ") ";\r
-\r
- $this->ar_where[] = $where_in;\r
- if ($this->ar_caching === TRUE)\r
- {\r
- $this->ar_cache_where[] = $where_in;\r
- $this->ar_cache_exists[] = 'where';\r
- }\r
-\r
- // reset the array for multiple calls\r
- $this->ar_wherein = array();\r
- return $this;\r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Like\r
- *\r
- * Generates a %LIKE% portion of the query. Separates\r
- * multiple calls with AND\r
- *\r
- * @access public\r
- * @param mixed\r
- * @param mixed\r
- * @return object\r
- */\r
- function like($field, $match = '', $side = 'both')\r
- {\r
- return $this->_like($field, $match, 'AND ', $side);\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Not Like\r
- *\r
- * Generates a NOT LIKE portion of the query. Separates\r
- * multiple calls with AND\r
- *\r
- * @access public\r
- * @param mixed\r
- * @param mixed\r
- * @return object\r
- */\r
- function not_like($field, $match = '', $side = 'both')\r
- {\r
- return $this->_like($field, $match, 'AND ', $side, 'NOT');\r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * OR Like\r
- *\r
- * Generates a %LIKE% portion of the query. Separates\r
- * multiple calls with OR\r
- *\r
- * @access public\r
- * @param mixed\r
- * @param mixed\r
- * @return object\r
- */\r
- function or_like($field, $match = '', $side = 'both')\r
- {\r
- return $this->_like($field, $match, 'OR ', $side);\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * OR Not Like\r
- *\r
- * Generates a NOT LIKE portion of the query. Separates\r
- * multiple calls with OR\r
- *\r
- * @access public\r
- * @param mixed\r
- * @param mixed\r
- * @return object\r
- */\r
- function or_not_like($field, $match = '', $side = 'both')\r
- {\r
- return $this->_like($field, $match, 'OR ', $side, 'NOT');\r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * orlike() is an alias of or_like()\r
- * this function is here for backwards compatibility, as\r
- * orlike() has been deprecated\r
- */\r
- function orlike($field, $match = '', $side = 'both')\r
- {\r
- return $this->or_like($field, $match, $side);\r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Like\r
- *\r
- * Called by like() or orlike()\r
- *\r
- * @access private\r
- * @param mixed\r
- * @param mixed\r
- * @param string\r
- * @return object\r
- */\r
- function _like($field, $match = '', $type = 'AND ', $side = 'both', $not = '')\r
- {\r
- if ( ! is_array($field))\r
- {\r
- $field = array($field => $match);\r
- }\r
- \r
- foreach ($field as $k => $v)\r
- {\r
- $k = $this->_protect_identifiers($k);\r
-\r
- $prefix = (count($this->ar_like) == 0) ? '' : $type;\r
-\r
- $v = $this->escape_str($v);\r
-\r
- if ($side == 'before')\r
- {\r
- $like_statement = $prefix." $k $not LIKE '%{$v}'";\r
- }\r
- elseif ($side == 'after')\r
- {\r
- $like_statement = $prefix." $k $not LIKE '{$v}%'";\r
- }\r
- else\r
- {\r
- $like_statement = $prefix." $k $not LIKE '%{$v}%'";\r
- }\r
- \r
- $this->ar_like[] = $like_statement;\r
- if ($this->ar_caching === TRUE)\r
- {\r
- $this->ar_cache_like[] = $like_statement;\r
- $this->ar_cache_exists[] = 'like';\r
- }\r
- \r
- }\r
- return $this;\r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * GROUP BY\r
- *\r
- * @access public\r
- * @param string\r
- * @return object\r
- */\r
- function group_by($by)\r
- {\r
- if (is_string($by))\r
- {\r
- $by = explode(',', $by);\r
- }\r
- \r
- foreach ($by as $val)\r
- {\r
- $val = trim($val);\r
- \r
- if ($val != '')\r
- {\r
- $this->ar_groupby[] = $this->_protect_identifiers($val);\r
- \r
- if ($this->ar_caching === TRUE)\r
- {\r
- $this->ar_cache_groupby[] = $this->_protect_identifiers($val);\r
- $this->ar_cache_exists[] = 'groupby';\r
- }\r
- }\r
- }\r
- return $this;\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * groupby() is an alias of group_by()\r
- * this function is here for backwards compatibility, as\r
- * groupby() has been deprecated\r
- */\r
- function groupby($by)\r
- {\r
- return $this->group_by($by);\r
- } \r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Sets the HAVING value\r
- *\r
- * Separates multiple calls with AND\r
- *\r
- * @access public\r
- * @param string\r
- * @param string\r
- * @return object\r
- */\r
- function having($key, $value = '', $escape = TRUE)\r
- {\r
- return $this->_having($key, $value, 'AND ', $escape);\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * orhaving() is an alias of or_having()\r
- * this function is here for backwards compatibility, as\r
- * orhaving() has been deprecated\r
- */\r
-\r
- function orhaving($key, $value = '', $escape = TRUE)\r
- {\r
- return $this->or_having($key, $value, $escape);\r
- } \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Sets the OR HAVING value\r
- *\r
- * Separates multiple calls with OR\r
- *\r
- * @access public\r
- * @param string\r
- * @param string\r
- * @return object\r
- */\r
- function or_having($key, $value = '', $escape = TRUE)\r
- {\r
- return $this->_having($key, $value, 'OR ', $escape);\r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Sets the HAVING values\r
- *\r
- * Called by having() or or_having()\r
- *\r
- * @access private\r
- * @param string\r
- * @param string\r
- * @return object\r
- */\r
- function _having($key, $value = '', $type = 'AND ', $escape = TRUE)\r
- {\r
- if ( ! is_array($key))\r
- {\r
- $key = array($key => $value);\r
- }\r
- \r
- foreach ($key as $k => $v)\r
- {\r
- $prefix = (count($this->ar_having) == 0) ? '' : $type;\r
-\r
- if ($escape === TRUE)\r
- {\r
- $k = $this->_protect_identifiers($k);\r
- }\r
-\r
- if ( ! $this->_has_operator($k))\r
- {\r
- $k .= ' = ';\r
- }\r
-\r
- if ($v != '')\r
- {\r
- $v = ' '.$this->escape_str($v);\r
- }\r
- \r
- $this->ar_having[] = $prefix.$k.$v;\r
- if ($this->ar_caching === TRUE)\r
- {\r
- $this->ar_cache_having[] = $prefix.$k.$v;\r
- $this->ar_cache_exists[] = 'having';\r
- }\r
- }\r
- \r
- return $this;\r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Sets the ORDER BY value\r
- *\r
- * @access public\r
- * @param string\r
- * @param string direction: asc or desc\r
- * @return object\r
- */\r
- function order_by($orderby, $direction = '')\r
- {\r
- if (strtolower($direction) == 'random')\r
- {\r
- $orderby = ''; // Random results want or don't need a field name\r
- $direction = $this->_random_keyword;\r
- }\r
- elseif (trim($direction) != '')\r
- {\r
- $direction = (in_array(strtoupper(trim($direction)), array('ASC', 'DESC'), TRUE)) ? ' '.$direction : ' ASC';\r
- }\r
- \r
- $orderby_statement = $this->_protect_identifiers($orderby).$direction;\r
- \r
- $this->ar_orderby[] = $orderby_statement;\r
- if ($this->ar_caching === TRUE)\r
- {\r
- $this->ar_cache_orderby[] = $orderby_statement;\r
- $this->ar_cache_exists[] = 'orderby';\r
- }\r
-\r
- return $this;\r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * orderby() is an alias of order_by()\r
- * this function is here for backwards compatibility, as\r
- * orderby() has been deprecated\r
- */\r
- function orderby($orderby, $direction = '')\r
- {\r
- return $this->order_by($orderby, $direction);\r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Sets the LIMIT value\r
- *\r
- * @access public\r
- * @param integer the limit value\r
- * @param integer the offset value\r
- * @return object\r
- */\r
- function limit($value, $offset = '')\r
- {\r
- $this->ar_limit = $value;\r
-\r
- if ($offset != '')\r
- {\r
- $this->ar_offset = $offset;\r
- }\r
- \r
- return $this;\r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Sets the OFFSET value\r
- *\r
- * @access public\r
- * @param integer the offset value\r
- * @return object\r
- */\r
- function offset($offset)\r
- {\r
- $this->ar_offset = $offset;\r
- return $this;\r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * The "set" function. Allows key/value pairs to be set for inserting or updating\r
- *\r
- * @access public\r
- * @param mixed\r
- * @param string\r
- * @param boolean\r
- * @return object\r
- */\r
- function set($key, $value = '', $escape = TRUE)\r
- {\r
- $key = $this->_object_to_array($key);\r
- \r
- if ( ! is_array($key))\r
- {\r
- $key = array($key => $value);\r
- } \r
-\r
- foreach ($key as $k => $v)\r
- {\r
- if ($escape === FALSE)\r
- {\r
- $this->ar_set[$this->_protect_identifiers($k)] = $v;\r
- }\r
- else\r
- {\r
- $this->ar_set[$this->_protect_identifiers($k)] = $this->escape($v);\r
- }\r
- }\r
- \r
- return $this;\r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Get\r
- *\r
- * Compiles the select statement based on the other functions called\r
- * and runs the query\r
- *\r
- * @access public\r
- * @param string the table\r
- * @param string the limit clause\r
- * @param string the offset clause\r
- * @return object\r
- */\r
- function get($table = '', $limit = null, $offset = null)\r
- {\r
- if ($table != '')\r
- {\r
- $this->_track_aliases($table);\r
- $this->from($table);\r
- }\r
- \r
- if ( ! is_null($limit))\r
- {\r
- $this->limit($limit, $offset);\r
- }\r
- \r
- $sql = $this->_compile_select();\r
-\r
- $result = $this->query($sql);\r
- $this->_reset_select();\r
- return $result;\r
- }\r
-\r
- /**\r
- * "Count All Results" query\r
- *\r
- * Generates a platform-specific query string that counts all records \r
- * returned by an Active Record query.\r
- *\r
- * @access public\r
- * @param string\r
- * @return string\r
- */\r
- function count_all_results($table = '')\r
- {\r
- if ($table != '')\r
- {\r
- $this->_track_aliases($table);\r
- $this->from($table);\r
- }\r
- \r
- $sql = $this->_compile_select($this->_count_string . $this->_protect_identifiers('numrows'));\r
-\r
- $query = $this->query($sql);\r
- $this->_reset_select();\r
- \r
- if ($query->num_rows() == 0)\r
- {\r
- return '0';\r
- }\r
-\r
- $row = $query->row();\r
- return $row->numrows;\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Get_Where\r
- *\r
- * Allows the where clause, limit and offset to be added directly\r
- *\r
- * @access public\r
- * @param string the where clause\r
- * @param string the limit clause\r
- * @param string the offset clause\r
- * @return object\r
- */\r
- function get_where($table = '', $where = null, $limit = null, $offset = null)\r
- {\r
- if ($table != '')\r
- {\r
- $this->from($table);\r
- }\r
-\r
- if ( ! is_null($where))\r
- {\r
- $this->where($where);\r
- }\r
- \r
- if ( ! is_null($limit))\r
- {\r
- $this->limit($limit, $offset);\r
- }\r
- \r
- $sql = $this->_compile_select();\r
-\r
- $result = $this->query($sql);\r
- $this->_reset_select();\r
- return $result;\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * getwhere() is an alias of get_where()\r
- * this function is here for backwards compatibility, as\r
- * getwhere() has been deprecated\r
- */\r
- function getwhere($table = '', $where = null, $limit = null, $offset = null)\r
- {\r
- return $this->get_where($table, $where, $limit, $offset);\r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Insert\r
- *\r
- * Compiles an insert string and runs the query\r
- *\r
- * @access public\r
- * @param string the table to retrieve the results from\r
- * @param array an associative array of insert values\r
- * @return object\r
- */\r
- function insert($table = '', $set = NULL)\r
- { \r
- if ( ! is_null($set))\r
- {\r
- $this->set($set);\r
- }\r
- \r
- if (count($this->ar_set) == 0)\r
- {\r
- if ($this->db_debug)\r
- {\r
- return $this->display_error('db_must_use_set');\r
- }\r
- return FALSE;\r
- }\r
-\r
- if ($table == '')\r
- {\r
- if ( ! isset($this->ar_from[0]))\r
- {\r
- if ($this->db_debug)\r
- {\r
- return $this->display_error('db_must_set_table');\r
- }\r
- return FALSE;\r
- }\r
- \r
- $table = $this->ar_from[0];\r
- }\r
-\r
- $sql = $this->_insert($this->_protect_identifiers($table, TRUE, NULL, FALSE), array_keys($this->ar_set), array_values($this->ar_set));\r
- \r
- $this->_reset_write();\r
- return $this->query($sql); \r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Update\r
- *\r
- * Compiles an update string and runs the query\r
- *\r
- * @access public\r
- * @param string the table to retrieve the results from\r
- * @param array an associative array of update values\r
- * @param mixed the where clause\r
- * @return object\r
- */\r
- function update($table = '', $set = NULL, $where = NULL, $limit = NULL)\r
- {\r
- // Combine any cached components with the current statements\r
- $this->_merge_cache();\r
-\r
- if ( ! is_null($set))\r
- {\r
- $this->set($set);\r
- }\r
- \r
- if (count($this->ar_set) == 0)\r
- {\r
- if ($this->db_debug)\r
- {\r
- return $this->display_error('db_must_use_set');\r
- }\r
- return FALSE;\r
- }\r
-\r
- if ($table == '')\r
- {\r
- if ( ! isset($this->ar_from[0]))\r
- {\r
- if ($this->db_debug)\r
- {\r
- return $this->display_error('db_must_set_table');\r
- }\r
- return FALSE;\r
- }\r
- \r
- $table = $this->ar_from[0];\r
- }\r
- \r
- if ($where != NULL)\r
- {\r
- $this->where($where);\r
- }\r
-\r
- if ($limit != NULL)\r
- {\r
- $this->limit($limit);\r
- }\r
- \r
- $sql = $this->_update($this->_protect_identifiers($table, TRUE, NULL, FALSE), $this->ar_set, $this->ar_where, $this->ar_orderby, $this->ar_limit);\r
- \r
- $this->_reset_write();\r
- return $this->query($sql);\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Empty Table\r
- *\r
- * Compiles a delete string and runs "DELETE FROM table"\r
- *\r
- * @access public\r
- * @param string the table to empty\r
- * @return object\r
- */\r
- function empty_table($table = '')\r
- {\r
- if ($table == '')\r
- {\r
- if ( ! isset($this->ar_from[0]))\r
- {\r
- if ($this->db_debug)\r
- {\r
- return $this->display_error('db_must_set_table');\r
- }\r
- return FALSE;\r
- }\r
-\r
- $table = $this->ar_from[0];\r
- }\r
- else\r
- {\r
- $table = $this->_protect_identifiers($table, TRUE, NULL, FALSE);\r
- }\r
-\r
- $sql = $this->_delete($table);\r
-\r
- $this->_reset_write();\r
- \r
- return $this->query($sql);\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Truncate\r
- *\r
- * Compiles a truncate string and runs the query\r
- * If the database does not support the truncate() command\r
- * This function maps to "DELETE FROM table"\r
- *\r
- * @access public\r
- * @param string the table to truncate\r
- * @return object\r
- */\r
- function truncate($table = '')\r
- {\r
- if ($table == '')\r
- {\r
- if ( ! isset($this->ar_from[0]))\r
- {\r
- if ($this->db_debug)\r
- {\r
- return $this->display_error('db_must_set_table');\r
- }\r
- return FALSE;\r
- }\r
-\r
- $table = $this->ar_from[0];\r
- }\r
- else\r
- {\r
- $table = $this->_protect_identifiers($table, TRUE, NULL, FALSE);\r
- }\r
-\r
- $sql = $this->_truncate($table);\r
-\r
- $this->_reset_write();\r
- \r
- return $this->query($sql);\r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Delete\r
- *\r
- * Compiles a delete string and runs the query\r
- *\r
- * @access public\r
- * @param mixed the table(s) to delete from. String or array\r
- * @param mixed the where clause\r
- * @param mixed the limit clause\r
- * @param boolean\r
- * @return object\r
- */\r
- function delete($table = '', $where = '', $limit = NULL, $reset_data = TRUE)\r
- {\r
- // Combine any cached components with the current statements\r
- $this->_merge_cache();\r
-\r
- if ($table == '')\r
- {\r
- if ( ! isset($this->ar_from[0]))\r
- {\r
- if ($this->db_debug)\r
- {\r
- return $this->display_error('db_must_set_table');\r
- }\r
- return FALSE;\r
- }\r
-\r
- $table = $this->ar_from[0];\r
- }\r
- elseif (is_array($table))\r
- {\r
- foreach($table as $single_table)\r
- {\r
- $this->delete($single_table, $where, $limit, FALSE);\r
- }\r
-\r
- $this->_reset_write();\r
- return;\r
- }\r
- else\r
- {\r
- $table = $this->_protect_identifiers($table, TRUE, NULL, FALSE);\r
- }\r
-\r
- if ($where != '')\r
- {\r
- $this->where($where);\r
- }\r
-\r
- if ($limit != NULL)\r
- {\r
- $this->limit($limit);\r
- }\r
-\r
- if (count($this->ar_where) == 0 && count($this->ar_like) == 0)\r
- {\r
- if ($this->db_debug)\r
- {\r
- return $this->display_error('db_del_must_use_where');\r
- }\r
-\r
- return FALSE;\r
- } \r
-\r
- $sql = $this->_delete($table, $this->ar_where, $this->ar_like, $this->ar_limit);\r
-\r
- if ($reset_data)\r
- {\r
- $this->_reset_write();\r
- }\r
- \r
- return $this->query($sql);\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * DB Prefix\r
- *\r
- * Prepends a database prefix if one exists in configuration\r
- *\r
- * @access public\r
- * @param string the table\r
- * @return string\r
- */\r
- function dbprefix($table = '')\r
- {\r
- if ($table == '')\r
- {\r
- $this->display_error('db_table_name_required');\r
- }\r
-\r
- return $this->dbprefix.$table;\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Track Aliases\r
- *\r
- * Used to track SQL statements written with aliased tables.\r
- *\r
- * @access private\r
- * @param string The table to inspect\r
- * @return string\r
- */ \r
- function _track_aliases($table)\r
- {\r
- if (is_array($table))\r
- {\r
- foreach ($table as $t)\r
- {\r
- $this->_track_aliases($t);\r
- }\r
- return;\r
- }\r
- \r
- // Does the string contain a comma? If so, we need to separate\r
- // the string into discreet statements\r
- if (strpos($table, ',') !== FALSE)\r
- {\r
- return $this->_track_aliases(explode(',', $table));\r
- }\r
- \r
- // if a table alias is used we can recognize it by a space\r
- if (strpos($table, " ") !== FALSE)\r
- {\r
- // if the alias is written with the AS keyword, remove it\r
- $table = preg_replace('/ AS /i', ' ', $table);\r
- \r
- // Grab the alias\r
- $table = trim(strrchr($table, " "));\r
- \r
- // Store the alias, if it doesn't already exist\r
- if ( ! in_array($table, $this->ar_aliased_tables))\r
- {\r
- $this->ar_aliased_tables[] = $table;\r
- }\r
- }\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Compile the SELECT statement\r
- *\r
- * Generates a query string based on which functions were used.\r
- * Should not be called directly. The get() function calls it.\r
- *\r
- * @access private\r
- * @return string\r
- */\r
- function _compile_select($select_override = FALSE)\r
- {\r
- // Combine any cached components with the current statements\r
- $this->_merge_cache();\r
-\r
- // ----------------------------------------------------------------\r
- \r
- // Write the "select" portion of the query\r
-\r
- if ($select_override !== FALSE)\r
- {\r
- $sql = $select_override;\r
- }\r
- else\r
- {\r
- $sql = ( ! $this->ar_distinct) ? 'SELECT ' : 'SELECT DISTINCT ';\r
- \r
- if (count($this->ar_select) == 0)\r
- {\r
- $sql .= '*'; \r
- }\r
- else\r
- { \r
- // Cycle through the "select" portion of the query and prep each column name.\r
- // The reason we protect identifiers here rather then in the select() function\r
- // is because until the user calls the from() function we don't know if there are aliases\r
- foreach ($this->ar_select as $key => $val)\r
- {\r
- $this->ar_select[$key] = $this->_protect_identifiers($val);\r
- }\r
- \r
- $sql .= implode(', ', $this->ar_select);\r
- }\r
- }\r
-\r
- // ----------------------------------------------------------------\r
- \r
- // Write the "FROM" portion of the query\r
-\r
- if (count($this->ar_from) > 0)\r
- {\r
- $sql .= "\nFROM ";\r
-\r
- $sql .= $this->_from_tables($this->ar_from);\r
- }\r
-\r
- // ----------------------------------------------------------------\r
- \r
- // Write the "JOIN" portion of the query\r
-\r
- if (count($this->ar_join) > 0)\r
- {\r
- $sql .= "\n";\r
-\r
- $sql .= implode("\n", $this->ar_join);\r
- }\r
-\r
- // ----------------------------------------------------------------\r
- \r
- // Write the "WHERE" portion of the query\r
-\r
- if (count($this->ar_where) > 0 OR count($this->ar_like) > 0)\r
- {\r
- $sql .= "\n";\r
-\r
- $sql .= "WHERE ";\r
- }\r
-\r
- $sql .= implode("\n", $this->ar_where);\r
-\r
- // ----------------------------------------------------------------\r
- \r
- // Write the "LIKE" portion of the query\r
- \r
- if (count($this->ar_like) > 0)\r
- {\r
- if (count($this->ar_where) > 0)\r
- {\r
- $sql .= "\nAND ";\r
- }\r
-\r
- $sql .= implode("\n", $this->ar_like);\r
- }\r
-\r
- // ----------------------------------------------------------------\r
- \r
- // Write the "GROUP BY" portion of the query\r
- \r
- if (count($this->ar_groupby) > 0)\r
- {\r
- $sql .= "\nGROUP BY ";\r
- \r
- $sql .= implode(', ', $this->ar_groupby);\r
- }\r
-\r
- // ----------------------------------------------------------------\r
- \r
- // Write the "HAVING" portion of the query\r
- \r
- if (count($this->ar_having) > 0)\r
- {\r
- $sql .= "\nHAVING ";\r
- $sql .= implode("\n", $this->ar_having);\r
- }\r
-\r
- // ----------------------------------------------------------------\r
- \r
- // Write the "ORDER BY" portion of the query\r
-\r
- if (count($this->ar_orderby) > 0)\r
- {\r
- $sql .= "\nORDER BY ";\r
- $sql .= implode(', ', $this->ar_orderby);\r
- \r
- if ($this->ar_order !== FALSE)\r
- {\r
- $sql .= ($this->ar_order == 'desc') ? ' DESC' : ' ASC';\r
- } \r
- }\r
-\r
- // ----------------------------------------------------------------\r
- \r
- // Write the "LIMIT" portion of the query\r
- \r
- if (is_numeric($this->ar_limit))\r
- {\r
- $sql .= "\n";\r
- $sql = $this->_limit($sql, $this->ar_limit, $this->ar_offset);\r
- }\r
-\r
- return $sql;\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Object to Array\r
- *\r
- * Takes an object as input and converts the class variables to array key/vals\r
- *\r
- * @access public\r
- * @param object\r
- * @return array\r
- */\r
- function _object_to_array($object)\r
- {\r
- if ( ! is_object($object))\r
- {\r
- return $object;\r
- }\r
- \r
- $array = array();\r
- foreach (get_object_vars($object) as $key => $val)\r
- {\r
- // There are some built in keys we need to ignore for this conversion\r
- if ( ! is_object($val) && ! is_array($val) && $key != '_parent_name' && $key != '_ci_scaffolding' && $key != '_ci_scaff_table')\r
- {\r
- $array[$key] = $val;\r
- }\r
- }\r
- \r
- return $array;\r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Start Cache\r
- *\r
- * Starts AR caching\r
- *\r
- * @access public\r
- * @return void\r
- */ \r
- function start_cache()\r
- {\r
- $this->ar_caching = TRUE;\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Stop Cache\r
- *\r
- * Stops AR caching\r
- *\r
- * @access public\r
- * @return void\r
- */ \r
- function stop_cache()\r
- {\r
- $this->ar_caching = FALSE;\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Flush Cache\r
- *\r
- * Empties the AR cache\r
- *\r
- * @access public\r
- * @return void\r
- */ \r
- function flush_cache()\r
- { \r
- $this->_reset_run(\r
- array(\r
- 'ar_cache_select' => array(), \r
- 'ar_cache_from' => array(), \r
- 'ar_cache_join' => array(),\r
- 'ar_cache_where' => array(), \r
- 'ar_cache_like' => array(), \r
- 'ar_cache_groupby' => array(), \r
- 'ar_cache_having' => array(), \r
- 'ar_cache_orderby' => array(), \r
- 'ar_cache_set' => array(),\r
- 'ar_cache_exists' => array()\r
- )\r
- ); \r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Merge Cache\r
- *\r
- * When called, this function merges any cached AR arrays with \r
- * locally called ones.\r
- *\r
- * @access private\r
- * @return void\r
- */\r
- function _merge_cache()\r
- {\r
- if (count($this->ar_cache_exists) == 0)\r
- {\r
- return;\r
- }\r
-\r
- foreach ($this->ar_cache_exists as $val)\r
- {\r
- $ar_variable = 'ar_'.$val;\r
- $ar_cache_var = 'ar_cache_'.$val;\r
-\r
- if (count($this->$ar_cache_var) == 0)\r
- {\r
- continue;\r
- }\r
-\r
- $this->$ar_variable = array_unique(array_merge($this->$ar_cache_var, $this->$ar_variable));\r
- }\r
-\r
- // If we are "protecting identifiers" we need to examine the "from"\r
- // portion of the query to determine if there are any aliases\r
- if ($this->_protect_identifiers === TRUE AND count($this->ar_cache_from) > 0)\r
- {\r
- $this->_track_aliases($this->ar_from);\r
- }\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Resets the active record values. Called by the get() function\r
- *\r
- * @access private\r
- * @param array An array of fields to reset\r
- * @return void\r
- */\r
- function _reset_run($ar_reset_items)\r
- {\r
- foreach ($ar_reset_items as $item => $default_value)\r
- {\r
- if ( ! in_array($item, $this->ar_store_array))\r
- {\r
- $this->$item = $default_value;\r
- }\r
- }\r
- }\r
-\r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Resets the active record values. Called by the get() function\r
- *\r
- * @access private\r
- * @return void\r
- */\r
- function _reset_select()\r
- {\r
- $ar_reset_items = array(\r
- 'ar_select' => array(), \r
- 'ar_from' => array(), \r
- 'ar_join' => array(), \r
- 'ar_where' => array(), \r
- 'ar_like' => array(), \r
- 'ar_groupby' => array(), \r
- 'ar_having' => array(), \r
- 'ar_orderby' => array(), \r
- 'ar_wherein' => array(), \r
- 'ar_aliased_tables' => array(),\r
- 'ar_distinct' => FALSE, \r
- 'ar_limit' => FALSE, \r
- 'ar_offset' => FALSE, \r
- 'ar_order' => FALSE,\r
- );\r
- \r
- $this->_reset_run($ar_reset_items);\r
- }\r
- \r
- // --------------------------------------------------------------------\r
-\r
- /**\r
- * Resets the active record "write" values.\r
- *\r
- * Called by the insert() update() and delete() functions\r
- *\r
- * @access private\r
- * @return void\r
- */\r
- function _reset_write()\r
- { \r
- $ar_reset_items = array(\r
- 'ar_set' => array(), \r
- 'ar_from' => array(), \r
- 'ar_where' => array(), \r
- 'ar_like' => array(),\r
- 'ar_orderby' => array(), \r
- 'ar_limit' => FALSE, \r
- 'ar_order' => FALSE\r
- );\r
-\r
- $this->_reset_run($ar_reset_items);\r
- }\r
- \r
-}\r
-\r
-/* End of file DB_active_rec.php */\r
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 4.3.2 or newer
+ *
+ * @package CodeIgniter
+ * @author ExpressionEngine Dev Team
+ * @copyright Copyright (c) 2008, EllisLab, Inc.
+ * @license http://codeigniter.com/user_guide/license.html
+ * @link http://codeigniter.com
+ * @since Version 1.0
+ * @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_select = array();
+ var $ar_distinct = FALSE;
+ var $ar_from = array();
+ var $ar_join = array();
+ var $ar_where = array();
+ var $ar_like = array();
+ var $ar_groupby = array();
+ var $ar_having = array();
+ var $ar_limit = FALSE;
+ var $ar_offset = FALSE;
+ var $ar_order = FALSE;
+ var $ar_orderby = array();
+ 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_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();
+
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Select
+ *
+ * Generates the SELECT portion of the query
+ *
+ * @access public
+ * @param string
+ * @return object
+ */
+ function select($select = '*', $escape = NULL)
+ {
+ // Set the global value if this was sepecified
+ if (is_bool($escape))
+ {
+ $this->_protect_identifiers = $escape;
+ }
+
+ if (is_string($select))
+ {
+ $select = explode(',', $select);
+ }
+
+ foreach ($select as $val)
+ {
+ $val = trim($val);
+
+ if ($val != '')
+ {
+ $this->ar_select[] = $val;
+
+ if ($this->ar_caching === TRUE)
+ {
+ $this->ar_cache_select[] = $val;
+ $this->ar_cache_exists[] = 'select';
+ }
+ }
+ }
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Select Max
+ *
+ * Generates a SELECT MAX(field) portion of a query
+ *
+ * @access public
+ * @param string the field
+ * @param string an alias
+ * @return object
+ */
+ 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
+ *
+ * @access public
+ * @param string the field
+ * @param string an alias
+ * @return object
+ */
+ 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
+ *
+ * @access public
+ * @param string the field
+ * @param string an alias
+ * @return object
+ */
+ 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
+ *
+ * @access public
+ * @param string the field
+ * @param string an alias
+ * @return object
+ */
+ 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()
+ *
+ * @access public
+ * @param string the field
+ * @param string an alias
+ * @return object
+ */
+ 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[] = $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
+ *
+ * @access private
+ * @param string
+ * @return string
+ */
+ 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
+ *
+ * @access public
+ * @param bool
+ * @return object
+ */
+ function distinct($val = TRUE)
+ {
+ $this->ar_distinct = (is_bool($val)) ? $val : TRUE;
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * From
+ *
+ * Generates the FROM portion of the query
+ *
+ * @access public
+ * @param mixed can be a string or array
+ * @return object
+ */
+ function from($from)
+ {
+ foreach ((array)$from as $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->_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
+ *
+ * @access public
+ * @param string
+ * @param string the join condition
+ * @param string the type of join
+ * @return object
+ */
+ 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[] = $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
+ *
+ * @access public
+ * @param mixed
+ * @param mixed
+ * @return object
+ */
+ 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
+ *
+ * @access public
+ * @param mixed
+ * @param mixed
+ * @return object
+ */
+ function or_where($key, $value = NULL, $escape = TRUE)
+ {
+ return $this->_where($key, $value, 'OR ', $escape);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * orwhere() is an alias of or_where()
+ * this function is here for backwards compatibility, as
+ * orwhere() has been deprecated
+ */
+ function orwhere($key, $value = NULL, $escape = TRUE)
+ {
+ return $this->or_where($key, $value, $escape);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Where
+ *
+ * Called by where() or orwhere()
+ *
+ * @access private
+ * @param mixed
+ * @param mixed
+ * @param string
+ * @return object
+ */
+ 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) == 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[] = $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
+ *
+ * @access public
+ * @param string The field to search
+ * @param array The values searched on
+ * @return object
+ */
+ 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
+ *
+ * @access public
+ * @param string The field to search
+ * @param array The values searched on
+ * @return object
+ */
+ 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
+ *
+ * @access public
+ * @param string The field to search
+ * @param array The values searched on
+ * @return object
+ */
+ 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
+ *
+ * @access public
+ * @param string The field to search
+ * @param array The values searched on
+ * @return object
+ */
+ 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
+ *
+ * @access public
+ * @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
+ */
+ 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->escape($value);
+ }
+
+ $prefix = (count($this->ar_where) == 0) ? '' : $type;
+
+ $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;
+ $this->ar_cache_exists[] = 'where';
+ }
+
+ // reset the array for multiple calls
+ $this->ar_wherein = array();
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Like
+ *
+ * Generates a %LIKE% portion of the query. Separates
+ * multiple calls with AND
+ *
+ * @access public
+ * @param mixed
+ * @param mixed
+ * @return object
+ */
+ 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
+ *
+ * @access public
+ * @param mixed
+ * @param mixed
+ * @return object
+ */
+ 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
+ *
+ * @access public
+ * @param mixed
+ * @param mixed
+ * @return object
+ */
+ 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
+ *
+ * @access public
+ * @param mixed
+ * @param mixed
+ * @return object
+ */
+ function or_not_like($field, $match = '', $side = 'both')
+ {
+ return $this->_like($field, $match, 'OR ', $side, 'NOT');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * orlike() is an alias of or_like()
+ * this function is here for backwards compatibility, as
+ * orlike() has been deprecated
+ */
+ function orlike($field, $match = '', $side = 'both')
+ {
+ return $this->or_like($field, $match, $side);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Like
+ *
+ * Called by like() or orlike()
+ *
+ * @access private
+ * @param mixed
+ * @param mixed
+ * @param string
+ * @return object
+ */
+ 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) == 0) ? '' : $type;
+
+ $v = $this->escape_str($v);
+
+ if ($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}%'";
+ }
+
+ $this->ar_like[] = $like_statement;
+ if ($this->ar_caching === TRUE)
+ {
+ $this->ar_cache_like[] = $like_statement;
+ $this->ar_cache_exists[] = 'like';
+ }
+
+ }
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * GROUP BY
+ *
+ * @access public
+ * @param string
+ * @return object
+ */
+ function group_by($by)
+ {
+ if (is_string($by))
+ {
+ $by = explode(',', $by);
+ }
+
+ foreach ($by as $val)
+ {
+ $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);
+ $this->ar_cache_exists[] = 'groupby';
+ }
+ }
+ }
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * groupby() is an alias of group_by()
+ * this function is here for backwards compatibility, as
+ * groupby() has been deprecated
+ */
+ function groupby($by)
+ {
+ return $this->group_by($by);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Sets the HAVING value
+ *
+ * Separates multiple calls with AND
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return object
+ */
+ function having($key, $value = '', $escape = TRUE)
+ {
+ return $this->_having($key, $value, 'AND ', $escape);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * orhaving() is an alias of or_having()
+ * this function is here for backwards compatibility, as
+ * orhaving() has been deprecated
+ */
+
+ function orhaving($key, $value = '', $escape = TRUE)
+ {
+ return $this->or_having($key, $value, $escape);
+ }
+ // --------------------------------------------------------------------
+
+ /**
+ * Sets the OR HAVING value
+ *
+ * Separates multiple calls with OR
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return object
+ */
+ function or_having($key, $value = '', $escape = TRUE)
+ {
+ return $this->_having($key, $value, 'OR ', $escape);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Sets the HAVING values
+ *
+ * Called by having() or or_having()
+ *
+ * @access private
+ * @param string
+ * @param string
+ * @return object
+ */
+ 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) == 0) ? '' : $type;
+
+ if ($escape === TRUE)
+ {
+ $k = $this->_protect_identifiers($k);
+ }
+
+ if ( ! $this->_has_operator($k))
+ {
+ $k .= ' = ';
+ }
+
+ if ($v != '')
+ {
+ $v = ' '.$this->escape_str($v);
+ }
+
+ $this->ar_having[] = $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
+ *
+ * @access public
+ * @param string
+ * @param string direction: asc or desc
+ * @return object
+ */
+ 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';
+ }
+
+ $orderby_statement = $this->_protect_identifiers($orderby).$direction;
+
+ $this->ar_orderby[] = $orderby_statement;
+ if ($this->ar_caching === TRUE)
+ {
+ $this->ar_cache_orderby[] = $orderby_statement;
+ $this->ar_cache_exists[] = 'orderby';
+ }
+
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * orderby() is an alias of order_by()
+ * this function is here for backwards compatibility, as
+ * orderby() has been deprecated
+ */
+ function orderby($orderby, $direction = '')
+ {
+ return $this->order_by($orderby, $direction);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Sets the LIMIT value
+ *
+ * @access public
+ * @param integer the limit value
+ * @param integer the offset value
+ * @return object
+ */
+ function limit($value, $offset = '')
+ {
+ $this->ar_limit = $value;
+
+ if ($offset != '')
+ {
+ $this->ar_offset = $offset;
+ }
+
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Sets the OFFSET value
+ *
+ * @access public
+ * @param integer the offset value
+ * @return object
+ */
+ function offset($offset)
+ {
+ $this->ar_offset = $offset;
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * The "set" function. Allows key/value pairs to be set for inserting or updating
+ *
+ * @access public
+ * @param mixed
+ * @param string
+ * @param boolean
+ * @return object
+ */
+ 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->_protect_identifiers($k)] = $v;
+ }
+ else
+ {
+ $this->ar_set[$this->_protect_identifiers($k)] = $this->escape($v);
+ }
+ }
+
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get
+ *
+ * Compiles the select statement based on the other functions called
+ * and runs the query
+ *
+ * @access public
+ * @param string the table
+ * @param string the limit clause
+ * @param string the offset clause
+ * @return object
+ */
+ 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.
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ 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 $row->numrows;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get_Where
+ *
+ * Allows the where clause, limit and offset to be added directly
+ *
+ * @access public
+ * @param string the where clause
+ * @param string the limit clause
+ * @param string the offset clause
+ * @return object
+ */
+ 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;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * getwhere() is an alias of get_where()
+ * this function is here for backwards compatibility, as
+ * getwhere() has been deprecated
+ */
+ function getwhere($table = '', $where = null, $limit = null, $offset = null)
+ {
+ return $this->get_where($table, $where, $limit, $offset);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert
+ *
+ * Compiles an insert string and runs the query
+ *
+ * @access public
+ * @param string the table to retrieve the results from
+ * @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) == 0)
+ {
+ if ($this->db_debug)
+ {
+ return $this->display_error('db_must_use_set');
+ }
+ return FALSE;
+ }
+
+ if ($table == '')
+ {
+ if ( ! isset($this->ar_from[0]))
+ {
+ if ($this->db_debug)
+ {
+ return $this->display_error('db_must_set_table');
+ }
+ return FALSE;
+ }
+
+ $table = $this->ar_from[0];
+ }
+
+ $sql = $this->_insert($this->_protect_identifiers($table, TRUE, NULL, FALSE), array_keys($this->ar_set), array_values($this->ar_set));
+
+ $this->_reset_write();
+ return $this->query($sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update
+ *
+ * Compiles an update string and runs the query
+ *
+ * @access public
+ * @param string the table to retrieve the results from
+ * @param array an associative array of update values
+ * @param mixed the where clause
+ * @return object
+ */
+ 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) == 0)
+ {
+ if ($this->db_debug)
+ {
+ return $this->display_error('db_must_use_set');
+ }
+ return FALSE;
+ }
+
+ if ($table == '')
+ {
+ if ( ! isset($this->ar_from[0]))
+ {
+ if ($this->db_debug)
+ {
+ return $this->display_error('db_must_set_table');
+ }
+ return FALSE;
+ }
+
+ $table = $this->ar_from[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_where, $this->ar_orderby, $this->ar_limit);
+
+ $this->_reset_write();
+ return $this->query($sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Empty Table
+ *
+ * Compiles a delete string and runs "DELETE FROM table"
+ *
+ * @access public
+ * @param string the table to empty
+ * @return object
+ */
+ function empty_table($table = '')
+ {
+ if ($table == '')
+ {
+ if ( ! isset($this->ar_from[0]))
+ {
+ if ($this->db_debug)
+ {
+ return $this->display_error('db_must_set_table');
+ }
+ return FALSE;
+ }
+
+ $table = $this->ar_from[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"
+ *
+ * @access public
+ * @param string the table to truncate
+ * @return object
+ */
+ function truncate($table = '')
+ {
+ if ($table == '')
+ {
+ if ( ! isset($this->ar_from[0]))
+ {
+ if ($this->db_debug)
+ {
+ return $this->display_error('db_must_set_table');
+ }
+ return FALSE;
+ }
+
+ $table = $this->ar_from[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
+ *
+ * @access public
+ * @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
+ */
+ 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[0]))
+ {
+ if ($this->db_debug)
+ {
+ return $this->display_error('db_must_set_table');
+ }
+ return FALSE;
+ }
+
+ $table = $this->ar_from[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) == 0 && count($this->ar_like) == 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_like, $this->ar_limit);
+
+ if ($reset_data)
+ {
+ $this->_reset_write();
+ }
+
+ return $this->query($sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * DB Prefix
+ *
+ * Prepends a database prefix if one exists in configuration
+ *
+ * @access public
+ * @param string the table
+ * @return string
+ */
+ function dbprefix($table = '')
+ {
+ if ($table == '')
+ {
+ $this->display_error('db_table_name_required');
+ }
+
+ return $this->dbprefix.$table;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Track Aliases
+ *
+ * Used to track SQL statements written with aliased tables.
+ *
+ * @access private
+ * @param string The table to inspect
+ * @return string
+ */
+ 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('/ AS /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_aliased_tables[] = $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.
+ *
+ * @access private
+ * @return string
+ */
+ 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) ? 'SELECT ' : 'SELECT DISTINCT ';
+
+ if (count($this->ar_select) == 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 as $key => $val)
+ {
+ $this->ar_select[$key] = $this->_protect_identifiers($val);
+ }
+
+ $sql .= implode(', ', $this->ar_select);
+ }
+ }
+
+ // ----------------------------------------------------------------
+
+ // Write the "FROM" portion of the query
+
+ if (count($this->ar_from) > 0)
+ {
+ $sql .= "\nFROM ";
+
+ $sql .= $this->_from_tables($this->ar_from);
+ }
+
+ // ----------------------------------------------------------------
+
+ // Write the "JOIN" portion of the query
+
+ if (count($this->ar_join) > 0)
+ {
+ $sql .= "\n";
+
+ $sql .= implode("\n", $this->ar_join);
+ }
+
+ // ----------------------------------------------------------------
+
+ // Write the "WHERE" portion of the query
+
+ if (count($this->ar_where) > 0 OR count($this->ar_like) > 0)
+ {
+ $sql .= "\n";
+
+ $sql .= "WHERE ";
+ }
+
+ $sql .= implode("\n", $this->ar_where);
+
+ // ----------------------------------------------------------------
+
+ // Write the "LIKE" portion of the query
+
+ if (count($this->ar_like) > 0)
+ {
+ if (count($this->ar_where) > 0)
+ {
+ $sql .= "\nAND ";
+ }
+
+ $sql .= implode("\n", $this->ar_like);
+ }
+
+ // ----------------------------------------------------------------
+
+ // Write the "GROUP BY" portion of the query
+
+ if (count($this->ar_groupby) > 0)
+ {
+ $sql .= "\nGROUP BY ";
+
+ $sql .= implode(', ', $this->ar_groupby);
+ }
+
+ // ----------------------------------------------------------------
+
+ // Write the "HAVING" portion of the query
+
+ if (count($this->ar_having) > 0)
+ {
+ $sql .= "\nHAVING ";
+ $sql .= implode("\n", $this->ar_having);
+ }
+
+ // ----------------------------------------------------------------
+
+ // Write the "ORDER BY" portion of the query
+
+ if (count($this->ar_orderby) > 0)
+ {
+ $sql .= "\nORDER BY ";
+ $sql .= implode(', ', $this->ar_orderby);
+
+ if ($this->ar_order !== FALSE)
+ {
+ $sql .= ($this->ar_order == 'desc') ? ' DESC' : ' ASC';
+ }
+ }
+
+ // ----------------------------------------------------------------
+
+ // Write the "LIMIT" portion of the query
+
+ if (is_numeric($this->ar_limit))
+ {
+ $sql .= "\n";
+ $sql = $this->_limit($sql, $this->ar_limit, $this->ar_offset);
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Object to Array
+ *
+ * Takes an object as input and converts the class variables to array key/vals
+ *
+ * @access public
+ * @param object
+ * @return array
+ */
+ 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' && $key != '_ci_scaffolding' && $key != '_ci_scaff_table')
+ {
+ $array[$key] = $val;
+ }
+ }
+
+ return $array;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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()
+ {
+ $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()
+ )
+ );
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Merge Cache
+ *
+ * When called, this function merges any cached AR arrays with
+ * locally called ones.
+ *
+ * @access private
+ * @return void
+ */
+ 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);
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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
+ * @return void
+ */
+ function _reset_select()
+ {
+ $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);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Resets the active record "write" values.
+ *
+ * Called by the insert() update() and delete() functions
+ *
+ * @access private
+ * @return void
+ */
+ function _reset_write()
+ {
+ $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);
+ }
+
+}
+
+/* End of file DB_active_rec.php */