DB_active_rec.php

Go to the documentation of this file.
00001 <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
00002 /**
00003  * CodeIgniter
00004  *
00005  * An open source application development framework for PHP 4.3.2 or newer
00006  *
00007  * @package             CodeIgniter
00008  * @author              ExpressionEngine Dev Team
00009  * @copyright   Copyright (c) 2006, EllisLab, Inc.
00010  * @license             http://codeigniter.com/user_guide/license.html
00011  * @link                http://codeigniter.com
00012  * @since               Version 1.0
00013  * @filesource
00014  */
00015 
00016 // ------------------------------------------------------------------------
00017 
00018 /**
00019  * Active Record Class
00020  *
00021  * This is the platform-independent base Active Record implementation class.
00022  *
00023  * @package             CodeIgniter
00024  * @subpackage  Drivers
00025  * @category    Database
00026  * @author              ExpressionEngine Dev Team
00027  * @link                http://codeigniter.com/user_guide/database/
00028  */
00029 class CI_DB_active_record extends CI_DB_driver {
00030 
00031         var $ar_select          = array();
00032         var $ar_distinct        = FALSE;
00033         var $ar_from            = array();
00034         var $ar_join            = array();
00035         var $ar_where           = array();
00036         var $ar_like            = array();
00037         var $ar_groupby         = array();
00038         var $ar_having          = array();
00039         var $ar_limit           = FALSE;
00040         var $ar_offset          = FALSE;
00041         var $ar_order           = FALSE;
00042         var $ar_orderby         = array();
00043         var $ar_set                     = array();      
00044         var $ar_wherein         = array();
00045         var $ar_aliased_tables          = array();
00046         var $ar_store_array     = array();
00047 
00048         // Active Record Caching variables
00049         var $ar_caching                 = FALSE;
00050         var $ar_cache_select    = array();
00051         var $ar_cache_from              = array();
00052         var $ar_cache_join              = array();
00053         var $ar_cache_where             = array();
00054         var $ar_cache_like              = array();
00055         var $ar_cache_groupby   = array();
00056         var $ar_cache_having    = array();
00057         var $ar_cache_limit             = FALSE;
00058         var $ar_cache_offset    = FALSE;
00059         var $ar_cache_order             = FALSE;
00060         var $ar_cache_orderby   = array();
00061         var $ar_cache_set               = array();      
00062 
00063 
00064         /**
00065          * DB Prefix
00066          *
00067          * Prepends a database prefix if one exists in configuration
00068          *
00069          * @access      public
00070          * @param       string  the table
00071          * @return      string
00072          */
00073         function dbprefix($table = '')
00074         {
00075                 if ($table == '')
00076                 {
00077                         $this->display_error('db_table_name_required');
00078                 }
00079 
00080                 return $this->dbprefix.$table;
00081         }
00082 
00083         // --------------------------------------------------------------------
00084 
00085         /**
00086          * Select
00087          *
00088          * Generates the SELECT portion of the query
00089          *
00090          * @access      public
00091          * @param       string
00092          * @return      object
00093          */
00094         function select($select = '*', $protect_identifiers = TRUE)
00095         {
00096                 if (is_string($select))
00097                 {
00098                         if ($protect_identifiers !== FALSE)
00099                         {
00100                                 $select = explode(',', $select);
00101                         }
00102                         else
00103                         {
00104                                 $select = array($select);
00105                         }
00106                 }
00107 
00108                 foreach ($select as $val)
00109                 {
00110                         $val = trim($val);
00111 
00112                         if ($val != '*' && $protect_identifiers !== FALSE)
00113                         {
00114                                 if (strpos($val, '.') !== FALSE)
00115                                 {
00116                                         $val = $this->dbprefix.$val;
00117                                 }
00118                                 else
00119                                 {
00120                                         $val = $this->_protect_identifiers($val);
00121                                 }
00122                         }
00123 
00124                         if ($val != '')
00125                         {
00126                                 $this->ar_select[] = $val;
00127                                 if ($this->ar_caching === TRUE)
00128                                 {
00129                                         $this->ar_cache_select[] = $val;
00130                                 }
00131                         }
00132                 }
00133                 return $this;
00134         }
00135 
00136         // --------------------------------------------------------------------
00137 
00138         /**
00139          * Select Max
00140          *
00141          * Generates a SELECT MAX(field) portion of a query
00142          *
00143          * @access      public
00144          * @param       string  the field
00145          * @param       string  an alias
00146          * @return      object
00147          */
00148         function select_max($select = '', $alias='')
00149         {
00150                 if ( ! is_string($select) OR $select == '')
00151                 {
00152                         $this->display_error('db_invalid_query');
00153                 }
00154         
00155                 $alias = ($alias != '') ? $alias : $select;
00156         
00157                 $sql = 'MAX('.$this->_protect_identifiers(trim($select)).') AS '.$this->_protect_identifiers(trim($alias));
00158 
00159                 $this->ar_select[] = $sql;
00160                 if ($this->ar_caching === TRUE)
00161                 {
00162                         $this->ar_cache_select[] = $sql;
00163                 }
00164                 
00165                 return $this;
00166         }
00167         
00168         // --------------------------------------------------------------------
00169 
00170         /**
00171          * Select Min
00172          *
00173          * Generates a SELECT MIN(field) portion of a query
00174          *
00175          * @access      public
00176          * @param       string  the field
00177          * @param       string  an alias
00178          * @return      object
00179          */
00180         function select_min($select = '', $alias='')
00181         {
00182                 if ( ! is_string($select) OR $select == '')
00183                 {
00184                         $this->display_error('db_invalid_query');
00185                 }
00186 
00187                 $alias = ($alias != '') ? $alias : $select;
00188         
00189                 $sql = 'MIN('.$this->_protect_identifiers(trim($select)).') AS '.$this->_protect_identifiers(trim($alias));
00190 
00191                 $this->ar_select[] = $sql;
00192                 if ($this->ar_caching === TRUE)
00193                 {
00194                         $this->ar_cache_select[] = $sql;
00195                 }
00196 
00197                 return $this;
00198         }
00199 
00200         // --------------------------------------------------------------------
00201 
00202         /**
00203          * Select Average
00204          *
00205          * Generates a SELECT AVG(field) portion of a query
00206          *
00207          * @access      public
00208          * @param       string  the field
00209          * @param       string  an alias
00210          * @return      object
00211          */
00212         function select_avg($select = '', $alias='')
00213         {
00214                 if ( ! is_string($select) OR $select == '')
00215                 {
00216                         $this->display_error('db_invalid_query');
00217                 }
00218 
00219                 $alias = ($alias != '') ? $alias : $select;
00220 
00221                 $sql = 'AVG('.$this->_protect_identifiers(trim($select)).') AS '.$this->_protect_identifiers(trim($alias));
00222 
00223                 $this->ar_select[] = $sql;
00224                 if ($this->ar_caching === TRUE)
00225                 {
00226                         $this->ar_cache_select[] = $sql;
00227                 }
00228 
00229                 return $this;
00230         }
00231 
00232         // --------------------------------------------------------------------
00233 
00234         /**
00235          * Select Sum
00236          *
00237          * Generates a SELECT SUM(field) portion of a query
00238          *
00239          * @access      public
00240          * @param       string  the field
00241          * @param       string  an alias
00242          * @return      object
00243          */
00244         function select_sum($select = '', $alias='')
00245         {
00246                 if ( ! is_string($select) OR $select == '')
00247                 {
00248                         $this->display_error('db_invalid_query');
00249                 }
00250 
00251                 $alias = ($alias != '') ? $alias : $select;
00252         
00253                 $sql = 'SUM('.$this->_protect_identifiers(trim($select)).') AS '.$this->_protect_identifiers(trim($alias));
00254 
00255                 $this->ar_select[] = $sql;
00256                 if ($this->ar_caching === TRUE)
00257                 {
00258                         $this->ar_cache_select[] = $sql;
00259                 }
00260 
00261                 return $this;
00262         }
00263 
00264         // --------------------------------------------------------------------
00265 
00266         /**
00267          * DISTINCT
00268          *
00269          * Sets a flag which tells the query string compiler to add DISTINCT
00270          *
00271          * @access      public
00272          * @param       bool
00273          * @return      object
00274          */
00275         function distinct($val = TRUE)
00276         {
00277                 $this->ar_distinct = (is_bool($val)) ? $val : TRUE;
00278                 return $this;
00279         }
00280         
00281         // --------------------------------------------------------------------
00282 
00283         /**
00284          * From
00285          *
00286          * Generates the FROM portion of the query
00287          *
00288          * @access      public
00289          * @param       mixed   can be a string or array
00290          * @return      object
00291          */
00292         function from($from)
00293         {
00294                 foreach ((array)$from as $val)
00295                 {
00296                         $this->ar_from[] = $this->_protect_identifiers($this->_track_aliases($val));
00297                         if ($this->ar_caching === TRUE)
00298                         {
00299                                 $this->ar_cache_from[] = $this->_protect_identifiers($this->_track_aliases($val));
00300                         }
00301                 }
00302 
00303                 return $this;
00304         }
00305 
00306         // --------------------------------------------------------------------
00307 
00308         /**
00309          * Join
00310          *
00311          * Generates the JOIN portion of the query
00312          *
00313          * @access      public
00314          * @param       string
00315          * @param       string  the join condition
00316          * @param       string  the type of join
00317          * @return      object
00318          */
00319         function join($table, $cond, $type = '')
00320         {               
00321                 if ($type != '')
00322                 {
00323                         $type = strtoupper(trim($type));
00324 
00325                         if ( ! in_array($type, array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER'), TRUE))
00326                         {
00327                                 $type = '';
00328                         }
00329                         else
00330                         {
00331                                 $type .= ' ';
00332                         }
00333                 }
00334 
00335                 // If a DB prefix is used we might need to add it to the column names
00336                 if ($this->dbprefix)
00337                 {
00338                         $this->_track_aliases($table);
00339 
00340                         // First we remove any existing prefixes in the condition to avoid duplicates
00341                         $cond = preg_replace('|('.$this->dbprefix.')([\w\.]+)([\W\s]+)|', "$2$3", $cond);
00342 
00343                         // Next we add the prefixes to the condition
00344                         $cond = preg_replace('|([\w\.]+)([\W\s]+)(.+)|', $this->dbprefix . "$1$2" . $this->dbprefix . "$3", $cond);
00345                 }
00346 
00347                 $join = $type.'JOIN '.$this->_protect_identifiers($this->dbprefix.$table, TRUE).' ON '.$cond;
00348 
00349                 $this->ar_join[] = $join;
00350                 if ($this->ar_caching === TRUE)
00351                 {
00352                         $this->ar_cache_join[] = $join;
00353                 }
00354 
00355                 return $this;
00356         }
00357 
00358         // --------------------------------------------------------------------
00359 
00360         /**
00361          * Where
00362          *
00363          * Generates the WHERE portion of the query. Separates
00364          * multiple calls with AND
00365          *
00366          * @access      public
00367          * @param       mixed
00368          * @param       mixed
00369          * @return      object
00370          */
00371         function where($key, $value = NULL, $escape = TRUE)
00372         {
00373                 return $this->_where($key, $value, 'AND ', $escape);
00374         }
00375         
00376         // --------------------------------------------------------------------
00377 
00378         /**
00379          * OR Where
00380          *
00381          * Generates the WHERE portion of the query. Separates
00382          * multiple calls with OR
00383          *
00384          * @access      public
00385          * @param       mixed
00386          * @param       mixed
00387          * @return      object
00388          */
00389         function or_where($key, $value = NULL, $escape = TRUE)
00390         {
00391                 return $this->_where($key, $value, 'OR ', $escape);
00392         }
00393 
00394         // --------------------------------------------------------------------
00395 
00396         /**
00397          * orwhere() is an alias of or_where()
00398          * this function is here for backwards compatibility, as
00399          * orwhere() has been deprecated
00400          */
00401         function orwhere($key, $value = NULL, $escape = TRUE)
00402         {
00403                 return $this->or_where($key, $value, $escape);
00404         }
00405 
00406         // --------------------------------------------------------------------
00407 
00408         /**
00409          * Where
00410          *
00411          * Called by where() or orwhere()
00412          *
00413          * @access      private
00414          * @param       mixed
00415          * @param       mixed
00416          * @param       string
00417          * @return      object
00418          */
00419         function _where($key, $value = NULL, $type = 'AND ', $escape = TRUE)
00420         {
00421                 if ( ! is_array($key))
00422                 {
00423                         $key = array($key => $value);
00424                 }
00425 
00426                 foreach ($key as $k => $v)
00427                 {
00428                         $prefix = (count($this->ar_where) == 0) ? '' : $type;
00429 
00430                         if (is_null($v) && ! $this->_has_operator($k))
00431                         {
00432                                 // value appears not to have been set, assign the test to IS NULL
00433                                 $k .= ' IS NULL';
00434                         }
00435                         
00436                         if ( ! is_null($v))
00437                         {
00438                                 if ($escape === TRUE)
00439                                 {
00440                                         // exception for "field<=" keys
00441                                         if ($this->_has_operator($k))
00442                                         {
00443                                                 $k =  preg_replace("/([A-Za-z_0-9]+)/", $this->_protect_identifiers('$1'), $k);
00444                                         }
00445                                         else
00446                                         {
00447                                                 $k = $this->_protect_identifiers($k);
00448                                         }
00449                                         
00450                                         $v = ' '.$this->escape($v);
00451                                 }
00452 
00453                                 if ( ! $this->_has_operator($k))
00454                                 {
00455                                         $k .= ' =';
00456                                 }
00457                         }
00458                         else
00459                         {
00460                                 if ($escape === TRUE)
00461                                 {
00462                                         $k = $this->_protect_identifiers($k, TRUE);
00463                                 }                               
00464                         }
00465 
00466                         $this->ar_where[] = $prefix.$k.$v;
00467                         
00468                         if ($this->ar_caching === TRUE)
00469                         {
00470                                 $this->ar_cache_where[] = $prefix.$k.$v;
00471                         }
00472                         
00473                 }
00474                 
00475                 return $this;
00476         }
00477 
00478         // --------------------------------------------------------------------
00479 
00480         /**
00481          * Where_in
00482          *
00483          * Generates a WHERE field IN ('item', 'item') SQL query joined with
00484          * AND if appropriate
00485          *
00486          * @access      public
00487          * @param       string  The field to search
00488          * @param       array   The values searched on
00489          * @return      object
00490          */
00491         function where_in($key = NULL, $values = NULL)
00492         {               
00493                 return $this->_where_in($key, $values);
00494         }
00495         
00496         // --------------------------------------------------------------------
00497 
00498         /**
00499          * Where_in_or
00500          *
00501          * Generates a WHERE field IN ('item', 'item') SQL query joined with
00502          * OR if appropriate
00503          *
00504          * @access      public
00505          * @param       string  The field to search
00506          * @param       array   The values searched on
00507          * @return      object
00508          */
00509         function or_where_in($key = NULL, $values = NULL)
00510         {
00511                 return $this->_where_in($key, $values, FALSE, 'OR ');
00512         }
00513 
00514         // --------------------------------------------------------------------
00515 
00516         /**
00517          * Where_not_in
00518          *
00519          * Generates a WHERE field NOT IN ('item', 'item') SQL query joined
00520          * with AND if appropriate
00521          *
00522          * @access      public
00523          * @param       string  The field to search
00524          * @param       array   The values searched on
00525          * @return      object
00526          */
00527         function where_not_in($key = NULL, $values = NULL)
00528         {
00529                 return $this->_where_in($key, $values, TRUE);
00530         }
00531         
00532         // --------------------------------------------------------------------
00533 
00534         /**
00535          * Where_not_in_or
00536          *
00537          * Generates a WHERE field NOT IN ('item', 'item') SQL query joined
00538          * with OR if appropriate
00539          *
00540          * @access      public
00541          * @param       string  The field to search
00542          * @param       array   The values searched on
00543          * @return      object
00544          */
00545         function or_where_not_in($key = NULL, $values = NULL)
00546         {
00547                 return $this->_where_in($key, $values, TRUE, 'OR ');
00548         }
00549 
00550         // --------------------------------------------------------------------
00551 
00552         /**
00553          * Where_in
00554          *
00555          * Called by where_in, where_in_or, where_not_in, where_not_in_or
00556          *
00557          * @access      public
00558          * @param       string  The field to search
00559          * @param       array   The values searched on
00560          * @param       boolean If the statement whould be IN or NOT IN
00561          * @param       string  
00562          * @return      object
00563          */
00564         function _where_in($key = NULL, $values = NULL, $not = FALSE, $type = 'AND ')
00565         {
00566                 if ($key === NULL OR ! is_array($values))
00567                 {
00568                         return;
00569                 }
00570 
00571                 $not = ($not) ? ' NOT ' : '';
00572 
00573                 foreach ($values as $value)
00574                 {
00575                         $this->ar_wherein[] = $this->escape($value);
00576                 }
00577 
00578                 $prefix = (count($this->ar_where) == 0) ? '' : $type;
00579  
00580                 $where_in = $prefix . $this->_protect_identifiers($key) . $not . " IN (" . implode(", ", $this->ar_wherein) . ") ";
00581 
00582                 $this->ar_where[] = $where_in;
00583                 if ($this->ar_caching === TRUE)
00584                 {
00585                         $this->ar_cache_where[] = $where_in;
00586                 }
00587 
00588                 // reset the array for multiple calls
00589                 $this->ar_wherein = array();
00590                 return $this;
00591         }
00592                 
00593         // --------------------------------------------------------------------
00594 
00595         /**
00596          * Like
00597          *
00598          * Generates a %LIKE% portion of the query. Separates
00599          * multiple calls with AND
00600          *
00601          * @access      public
00602          * @param       mixed
00603          * @param       mixed
00604          * @return      object
00605          */
00606         function like($field, $match = '', $side = 'both')
00607         {
00608                 return $this->_like($field, $match, 'AND ', $side);
00609         }
00610 
00611         // --------------------------------------------------------------------
00612 
00613         /**
00614          * Not Like
00615          *
00616          * Generates a NOT LIKE portion of the query. Separates
00617          * multiple calls with AND
00618          *
00619          * @access      public
00620          * @param       mixed
00621          * @param       mixed
00622          * @return      object
00623          */
00624         function not_like($field, $match = '', $side = 'both')
00625         {
00626                 return $this->_like($field, $match, 'AND ', $side, ' NOT');
00627         }
00628                 
00629         // --------------------------------------------------------------------
00630 
00631         /**
00632          * OR Like
00633          *
00634          * Generates a %LIKE% portion of the query. Separates
00635          * multiple calls with OR
00636          *
00637          * @access      public
00638          * @param       mixed
00639          * @param       mixed
00640          * @return      object
00641          */
00642         function or_like($field, $match = '', $side = 'both')
00643         {
00644                 return $this->_like($field, $match, 'OR ', $side);
00645         }
00646 
00647         // --------------------------------------------------------------------
00648 
00649         /**
00650          * OR Not Like
00651          *
00652          * Generates a NOT LIKE portion of the query. Separates
00653          * multiple calls with OR
00654          *
00655          * @access      public
00656          * @param       mixed
00657          * @param       mixed
00658          * @return      object
00659          */
00660         function or_not_like($field, $match = '', $side = 'both')
00661         {
00662                 return $this->_like($field, $match, 'OR ', $side, 'NOT ');
00663         }
00664         
00665         // --------------------------------------------------------------------
00666 
00667         /**
00668          * orlike() is an alias of or_like()
00669          * this function is here for backwards compatibility, as
00670          * orlike() has been deprecated
00671          */
00672         function orlike($field, $match = '', $side = 'both')
00673         {
00674                 return $this->or_like($field, $match, $side);
00675         }
00676         
00677         // --------------------------------------------------------------------
00678 
00679         /**
00680          * Like
00681          *
00682          * Called by like() or orlike()
00683          *
00684          * @access      private
00685          * @param       mixed
00686          * @param       mixed
00687          * @param       string
00688          * @return      object
00689          */
00690         function _like($field, $match = '', $type = 'AND ', $side = 'both', $not = '')
00691         {
00692                 if ( ! is_array($field))
00693                 {
00694                         $field = array($field => $match);
00695                 }
00696         
00697                 foreach ($field as $k => $v)
00698                 {               
00699 
00700                         $k = $this->_protect_identifiers($k);
00701 
00702                         $prefix = (count($this->ar_like) == 0) ? '' : $type;
00703 
00704                         $v = $this->escape_str($v);
00705 
00706                         if ($side == 'before')
00707                         {
00708                                 $like_statement = $prefix." $k $not LIKE '%{$v}'";
00709                         }
00710                         elseif ($side == 'after')
00711                         {
00712                                 $like_statement = $prefix." $k $not LIKE '{$v}%'";
00713                         }
00714                         else
00715                         {
00716                                 $like_statement = $prefix." $k $not LIKE '%{$v}%'";
00717                         }
00718                         
00719                         $this->ar_like[] = $like_statement;
00720                         if ($this->ar_caching === TRUE)
00721                         {
00722                                 $this->ar_cache_like[] = $like_statement;
00723                         }
00724                         
00725                 }
00726                 return $this;
00727         }
00728         
00729         // --------------------------------------------------------------------
00730 
00731         /**
00732          * GROUP BY
00733          *
00734          * @access      public
00735          * @param       string
00736          * @return      object
00737          */
00738         function group_by($by)
00739         {
00740                 if (is_string($by))
00741                 {
00742                         $by = explode(',', $by);
00743                 }
00744         
00745                 foreach ($by as $val)
00746                 {
00747                         $val = trim($val);
00748                 
00749                         if ($val != '')
00750                         {
00751                                 $this->ar_groupby[] = $this->_protect_identifiers($val);
00752                                 if ($this->ar_caching === TRUE)
00753                                 {
00754                                         $this->ar_cache_groupby[] = $this->_protect_identifiers($val);
00755                                 }
00756                         }
00757                 }
00758                 return $this;
00759         }
00760 
00761         // --------------------------------------------------------------------
00762 
00763         /**
00764          * groupby() is an alias of group_by()
00765          * this function is here for backwards compatibility, as
00766          * groupby() has been deprecated
00767          */
00768         function groupby($by)
00769         {
00770                 return $this->group_by($by);
00771         }       
00772 
00773         // --------------------------------------------------------------------
00774 
00775         /**
00776          * Sets the HAVING value
00777          *
00778          * Separates multiple calls with AND
00779          *
00780          * @access      public
00781          * @param       string
00782          * @param       string
00783          * @return      object
00784          */
00785         function having($key, $value = '', $escape = TRUE)
00786         {
00787                 return $this->_having($key, $value, 'AND ', $escape);
00788         }
00789 
00790         // --------------------------------------------------------------------
00791 
00792         /**
00793          * orhaving() is an alias of or_having()
00794          * this function is here for backwards compatibility, as
00795          * orhaving() has been deprecated
00796          */
00797 
00798         function orhaving($key, $value = '', $escape = TRUE)
00799         {
00800                 return $this->or_having($key, $value, $escape);
00801         }       
00802         // --------------------------------------------------------------------
00803 
00804         /**
00805          * Sets the OR HAVING value
00806          *
00807          * Separates multiple calls with OR
00808          *
00809          * @access      public
00810          * @param       string
00811          * @param       string
00812          * @return      object
00813          */
00814         function or_having($key, $value = '', $escape = TRUE)
00815         {
00816                 return $this->_having($key, $value, 'OR ', $escape);
00817         }
00818         
00819         // --------------------------------------------------------------------
00820 
00821         /**
00822          * Sets the HAVING values
00823          *
00824          * Called by having() or orhaving()
00825          *
00826          * @access      private
00827          * @param       string
00828 
00829          * @param       string
00830          * @return      object
00831          */
00832         function _having($key, $value = '', $type = 'AND ', $escape = TRUE)
00833         {
00834                 if ( ! is_array($key))
00835                 {
00836                         $key = array($key => $value);
00837                 }
00838         
00839                 foreach ($key as $k => $v)
00840                 {
00841                         $prefix = (count($this->ar_having) == 0) ? '' : $type;
00842 
00843                         if ($escape === TRUE)
00844                         {
00845                                 $k = $this->_protect_identifiers($k);
00846                         }
00847 
00848                         if ( ! $this->_has_operator($k))
00849                         {
00850                                 $k .= ' = ';
00851                         }
00852 
00853                         if ($v != '')
00854                         {
00855                                 $v = ' '.$this->escape_str($v);
00856                         }
00857                         
00858                         $this->ar_having[] = $prefix.$k.$v;
00859                         if ($this->ar_caching === TRUE)
00860                         {
00861                                 $this->ar_cache_having[] = $prefix.$k.$v;
00862                         }
00863                 }
00864                 
00865                 return $this;
00866         }
00867         
00868         // --------------------------------------------------------------------
00869 
00870         /**
00871          * Sets the ORDER BY value
00872          *
00873          * @access      public
00874          * @param       string
00875          * @param       string  direction: asc or desc
00876          * @return      object
00877          */
00878         function order_by($orderby, $direction = '')
00879         {
00880                 if (strtolower($direction) == 'random')
00881                 {
00882                         $orderby = ''; // Random results want or don't need a field name
00883                         $direction = $this->_random_keyword;
00884                 }
00885                 elseif (trim($direction) != '')
00886                 {
00887                         $direction = (in_array(strtoupper(trim($direction)), array('ASC', 'DESC'), TRUE)) ? ' '.$direction : ' ASC';
00888                 }
00889                 
00890                 $orderby_statement = $this->_protect_identifiers($orderby, TRUE).$direction;
00891                 
00892                 $this->ar_orderby[] = $orderby_statement;
00893                 if ($this->ar_caching === TRUE)
00894                 {
00895                         $this->ar_cache_orderby[] = $orderby_statement;
00896                 }
00897 
00898                 return $this;
00899         }
00900         
00901         // --------------------------------------------------------------------
00902 
00903         /**
00904          * orderby() is an alias of order_by()
00905          * this function is here for backwards compatibility, as
00906          * orderby() has been deprecated
00907          */
00908         function orderby($orderby, $direction = '')
00909         {
00910                 return $this->order_by($orderby, $direction);
00911         }
00912         
00913         // --------------------------------------------------------------------
00914 
00915         /**
00916          * Sets the LIMIT value
00917          *
00918          * @access      public
00919          * @param       integer the limit value
00920          * @param       integer the offset value
00921          * @return      object
00922          */
00923         function limit($value, $offset = '')
00924         {
00925                 $this->ar_limit = $value;
00926                 if ($this->ar_caching === TRUE)
00927                 {
00928                         $this->ar_cache_limit[] = $value;
00929                 }
00930 
00931                 if ($offset != '')
00932                 {
00933                         $this->ar_offset = $offset;
00934                         if ($this->ar_caching === TRUE)
00935                         {
00936                                 $this->ar_cache_offset[] = $offset;
00937                         }
00938                 }
00939                 
00940                 return $this;
00941         }
00942         
00943         // --------------------------------------------------------------------
00944 
00945         /**
00946          * Sets the OFFSET value
00947          *
00948          * @access      public
00949          * @param       integer the offset value
00950          * @return      object
00951          */
00952         function offset($offset)
00953         {
00954                 $this->ar_offset = $offset;
00955                 if ($this->ar_caching === TRUE)
00956                 {
00957                         $this->ar_cache_offset[] = $offset;
00958                 }
00959                         
00960                 return $this;
00961         }
00962         
00963         // --------------------------------------------------------------------
00964 
00965         /**
00966          * The "set" function.  Allows key/value pairs to be set for inserting or updating
00967          *
00968          * @access      public
00969          * @param       mixed
00970          * @param       string
00971          * @param       boolean
00972          * @return      object
00973          */
00974         function set($key, $value = '', $escape = TRUE)
00975         {
00976                 $key = $this->_object_to_array($key);
00977         
00978                 if ( ! is_array($key))
00979                 {
00980                         $key = array($key => $value);
00981                 }       
00982 
00983                 foreach ($key as $k => $v)
00984                 {
00985                         if ($escape === FALSE)
00986                         {
00987                                 $this->ar_set[$this->_protect_identifiers($k)] = $v;
00988                                 if ($this->ar_caching === TRUE)
00989                                 {
00990                                         $this->ar_cache_offset[$this->_protect_identifiers($k)] = $v;
00991                                 }
00992                         }
00993                         else
00994                         {
00995                                 $this->ar_set[$this->_protect_identifiers($k)] = $this->escape($v);
00996                                 if ($this->ar_caching === TRUE)
00997                                 {
00998                                         $this->ar_cache_offset[$this->_protect_identifiers($k)] = $this->escape($v);
00999                                 }
01000                         }
01001                 }
01002                 
01003                 return $this;
01004         }
01005         
01006         // --------------------------------------------------------------------
01007 
01008         /**
01009          * Get
01010          *
01011          * Compiles the select statement based on the other functions called
01012          * and runs the query
01013          *
01014          * @access      public
01015          * @param       string  the table
01016          * @param       string  the limit clause
01017          * @param       string  the offset clause
01018          * @return      object
01019          */
01020         function get($table = '', $limit = null, $offset = null)
01021         {
01022                 if ($table != '')
01023                 {
01024                         $this->_track_aliases($table);
01025                         $this->from($table);
01026                 }
01027                 
01028                 if ( ! is_null($limit))
01029                 {
01030                         $this->limit($limit, $offset);
01031                 }
01032                         
01033                 $sql = $this->_compile_select();
01034 
01035                 $result = $this->query($sql);
01036                 $this->_reset_select();
01037                 return $result;
01038         }
01039 
01040         /**
01041          * "Count All Results" query
01042          *
01043          * Generates a platform-specific query string that counts all records 
01044          * returned by an Active Record query.
01045          *
01046          * @access      public
01047          * @param       string
01048          * @return      string
01049          */
01050         function count_all_results($table = '')
01051         {
01052                 if ($table != '')
01053                 {
01054                         $this->_track_aliases($table);
01055                         $this->from($table);
01056                 }
01057                 
01058                 $sql = $this->_compile_select($this->_count_string . $this->_protect_identifiers('numrows'));
01059 
01060                 $query = $this->query($sql);
01061                 $this->_reset_select();
01062         
01063                 if ($query->num_rows() == 0)
01064                 {
01065                         return '0';
01066                 }
01067 
01068                 $row = $query->row();
01069                 return $row->numrows;
01070         }
01071 
01072         // --------------------------------------------------------------------
01073 
01074         /**
01075          * Get_Where
01076          *
01077          * Allows the where clause, limit and offset to be added directly
01078          *
01079          * @access      public
01080          * @param       string  the where clause
01081          * @param       string  the limit clause
01082          * @param       string  the offset clause
01083          * @return      object
01084          */
01085         function get_where($table = '', $where = null, $limit = null, $offset = null)
01086         {
01087                 if ($table != '')
01088                 {
01089                         $this->_track_aliases($table);
01090                         $this->from($table);
01091                 }
01092 
01093                 if ( ! is_null($where))
01094                 {
01095                         $this->where($where);
01096                 }
01097                 
01098                 if ( ! is_null($limit))
01099                 {
01100                         $this->limit($limit, $offset);
01101                 }
01102                         
01103                 $sql = $this->_compile_select();
01104 
01105                 $result = $this->query($sql);
01106                 $this->_reset_select();
01107                 return $result;
01108         }
01109 
01110         // --------------------------------------------------------------------
01111 
01112         /**
01113          * getwhere() is an alias of get_where()
01114          * this function is here for backwards compatibility, as
01115          * getwhere() has been deprecated
01116          */
01117         function getwhere($table = '', $where = null, $limit = null, $offset = null)
01118         {
01119                 return $this->get_where($table, $where, $limit, $offset);
01120         }
01121         
01122         // --------------------------------------------------------------------
01123 
01124         /**
01125          * Insert
01126          *
01127          * Compiles an insert string and runs the query
01128          *
01129          * @access      public
01130          * @param       string  the table to retrieve the results from
01131          * @param       array   an associative array of insert values
01132          * @return      object
01133          */
01134         function insert($table = '', $set = NULL)
01135         {
01136                 if ( ! is_null($set))
01137                 {
01138                         $this->set($set);
01139                 }
01140         
01141                 if (count($this->ar_set) == 0)
01142                 {
01143                         if ($this->db_debug)
01144                         {
01145                                 return $this->display_error('db_must_use_set');
01146                         }
01147                         return FALSE;
01148                 }
01149 
01150                 if ($table == '')
01151                 {
01152                         if ( ! isset($this->ar_from[0]))
01153                         {
01154                                 if ($this->db_debug)
01155                                 {
01156                                         return $this->display_error('db_must_set_table');
01157                                 }
01158                                 return FALSE;
01159                         }
01160                         
01161                         $table = $this->ar_from[0];
01162                 }
01163 
01164                 $sql = $this->_insert($this->_protect_identifiers($this->dbprefix.$table), array_keys($this->ar_set), array_values($this->ar_set));
01165                 
01166                 $this->_reset_write();
01167                 return $this->query($sql);              
01168         }
01169         
01170         // --------------------------------------------------------------------
01171 
01172         /**
01173          * Update
01174          *
01175          * Compiles an update string and runs the query
01176          *
01177          * @access      public
01178          * @param       string  the table to retrieve the results from
01179          * @param       array   an associative array of update values
01180          * @param       mixed   the where clause
01181          * @return      object
01182          */
01183         function update($table = '', $set = NULL, $where = NULL, $limit = NULL)
01184         {
01185                 if ( ! is_null($set))
01186                 {
01187                         $this->set($set);
01188                 }
01189         
01190                 if (count($this->ar_set) == 0)
01191                 {
01192                         if ($this->db_debug)
01193                         {
01194                                 return $this->display_error('db_must_use_set');
01195                         }
01196                         return FALSE;
01197                 }
01198 
01199                 if ($table == '')
01200                 {
01201                         if ( ! isset($this->ar_from[0]))
01202                         {
01203                                 if ($this->db_debug)
01204                                 {
01205                                         return $this->display_error('db_must_set_table');
01206                                 }
01207                                 return FALSE;
01208                         }
01209                         
01210                         $table = $this->ar_from[0];
01211                 }
01212                 
01213                 if ($where != NULL)
01214                 {
01215                         $this->where($where);
01216                 }
01217 
01218                 if ($limit != NULL)
01219                 {
01220                         $this->limit($limit);
01221                 }
01222                 
01223                 $sql = $this->_update($this->_protect_identifiers($this->dbprefix.$table), $this->ar_set, $this->ar_where, $this->ar_orderby, $this->ar_limit);
01224                 
01225                 $this->_reset_write();
01226                 return $this->query($sql);
01227         }
01228 
01229         // --------------------------------------------------------------------
01230 
01231         /**
01232          * Empty Table
01233          *
01234          * Compiles a delete string and runs "DELETE FROM table"
01235          *
01236          * @access      public
01237          * @param       string  the table to empty
01238          * @return      object
01239          */
01240         function empty_table($table = '')
01241         {
01242                 if ($table == '')
01243                 {
01244                         if ( ! isset($this->ar_from[0]))
01245                         {
01246                                 if ($this->db_debug)
01247                                 {
01248                                         return $this->display_error('db_must_set_table');
01249                                 }
01250                                 return FALSE;
01251                         }
01252 
01253                         $table = $this->ar_from[0];
01254                 }
01255                 else
01256                 {
01257                         $table = $this->_protect_identifiers($this->dbprefix.$table);
01258                 }
01259 
01260 
01261                 $sql = $this->_delete($table);
01262 
01263                 $this->_reset_write();
01264                 
01265                 return $this->query($sql);
01266         }
01267 
01268         // --------------------------------------------------------------------
01269 
01270         /**
01271          * Truncate
01272          *
01273          * Compiles a truncate string and runs the query
01274          * If the database does not support the truncate() command
01275          * This function maps to "DELETE FROM table"
01276          *
01277          * @access      public
01278          * @param       string  the table to truncate
01279          * @return      object
01280          */
01281         function truncate($table = '')
01282         {
01283                 if ($table == '')
01284                 {
01285                         if ( ! isset($this->ar_from[0]))
01286                         {
01287                                 if ($this->db_debug)
01288                                 {
01289                                         return $this->display_error('db_must_set_table');
01290                                 }
01291                                 return FALSE;
01292                         }
01293 
01294                         $table = $this->ar_from[0];
01295                 }
01296                 else
01297                 {
01298                         $table = $this->_protect_identifiers($this->dbprefix.$table);
01299                 }
01300 
01301 
01302                 $sql = $this->_truncate($table);
01303 
01304                 $this->_reset_write();
01305                 
01306                 return $this->query($sql);
01307         }
01308         
01309         // --------------------------------------------------------------------
01310 
01311         /**
01312          * Delete
01313          *
01314          * Compiles a delete string and runs the query
01315          *
01316          * @access      public
01317          * @param       mixed   the table(s) to delete from. String or array
01318          * @param       mixed   the where clause
01319          * @param       mixed   the limit clause
01320          * @param       boolean
01321          * @return      object
01322          */
01323         function delete($table = '', $where = '', $limit = NULL, $reset_data = TRUE)
01324         {
01325                 if ($table == '')
01326                 {
01327                         if ( ! isset($this->ar_from[0]))
01328                         {
01329                                 if ($this->db_debug)
01330                                 {
01331                                         return $this->display_error('db_must_set_table');
01332                                 }
01333                                 return FALSE;
01334                         }
01335 
01336                         $table = $this->ar_from[0];
01337                 }
01338                 elseif (is_array($table))
01339                 {
01340                         foreach($table as $single_table)
01341                         {
01342                                 $this->delete($single_table, $where, $limit, FALSE);
01343                         }
01344 
01345                         $this->_reset_write();
01346                         return;
01347                 }
01348                 else
01349                 {
01350                         $table = $this->_protect_identifiers($this->dbprefix.$table);
01351                 }
01352 
01353                 if ($where != '')
01354                 {
01355                         $this->where($where);
01356                 }
01357 
01358                 if ($limit != NULL)
01359                 {
01360                         $this->limit($limit);
01361                 }
01362 
01363                 if (count($this->ar_where) == 0 && count($this->ar_like) == 0)
01364                 {
01365                         if ($this->db_debug)
01366                         {
01367                                 return $this->display_error('db_del_must_use_where');
01368                         }
01369 
01370                         return FALSE;
01371                 }               
01372 
01373                 $sql = $this->_delete($table, $this->ar_where, $this->ar_like, $this->ar_limit);
01374 
01375                 if ($reset_data)
01376                 {
01377                         $this->_reset_write();
01378                 }
01379                 
01380                 return $this->query($sql);
01381         }
01382 
01383         // --------------------------------------------------------------------
01384 
01385         /**
01386          * Use Table - DEPRECATED
01387          *
01388          * @deprecated  use $this->db->from instead
01389          */
01390         function use_table($table)
01391         {
01392                 return $this->from($table);
01393         }
01394 
01395         // --------------------------------------------------------------------
01396 
01397         /**
01398          * Track Aliases
01399          *
01400          * Used to track SQL statements written with aliased tables.
01401          *
01402          * @access      private
01403          * @param       string  The table to inspect
01404          * @return      string
01405          */     
01406         function _track_aliases($table)
01407         {
01408                 // if a table alias is used we can recognize it by a space
01409                 if (strpos($table, " ") !== FALSE)
01410                 {
01411                         // if the alias is written with the AS keyowrd, get it out
01412                         $table = preg_replace('/ AS /i', ' ', $table); 
01413 
01414                         $this->ar_aliased_tables[] = trim(strrchr($table, " "));
01415                 }
01416 
01417                 return $this->dbprefix.$table;
01418         }
01419 
01420         // --------------------------------------------------------------------
01421 
01422         /**
01423          * Filter Table Aliases
01424          *
01425          * Intelligently removes database prefixes from aliased tables
01426          *
01427          * @access      private
01428          * @param       array   An array of compiled SQL
01429          * @return      array   Cleaned up statement with aliases accounted for
01430          */     
01431         function _filter_table_aliases($statements)
01432         {
01433 
01434                 foreach ($statements as $k => $v)
01435                 {
01436                         foreach ($this->ar_aliased_tables as $table)
01437                         {
01438                                 $statements[$k] = preg_replace('/(\w+\.\w+)/', $this->_protect_identifiers('$0'), $statements[$k]); // makes `table.field`
01439                                 $statements[$k] = str_replace($this->dbprefix.$table.'.', $table.'.', $statements[$k]);
01440                         }
01441                 }
01442                 return $statements;
01443         }
01444 
01445         // --------------------------------------------------------------------
01446 
01447         /**
01448          * Compile the SELECT statement
01449          *
01450          * Generates a query string based on which functions were used.
01451          * Should not be called directly.  The get() function calls it.
01452          *
01453          * @access      private
01454          * @return      string
01455          */
01456         function _compile_select($select_override = FALSE)
01457         {
01458                 $this->_merge_cache();
01459 
01460                 $sql = ( ! $this->ar_distinct) ? 'SELECT ' : 'SELECT DISTINCT ';
01461         
01462                 $sql .= (count($this->ar_select) == 0) ? '*' : implode(', ', $this->_filter_table_aliases($this->ar_select));
01463 
01464                 if ($select_override !== FALSE)
01465                 {
01466                         $sql = $select_override;
01467                 }
01468 
01469                 if (count($this->ar_from) > 0)
01470                 {
01471                         $sql .= "\nFROM ";
01472                         $sql .= $this->_from_tables($this->ar_from);
01473                 }
01474 
01475                 if (count($this->ar_join) > 0)
01476                 {
01477                         $sql .= "\n";
01478 
01479                         // special consideration for table aliases
01480                         if (count($this->ar_aliased_tables) > 0 && $this->dbprefix)
01481                         {
01482                                 $sql .= implode("\n", $this->_filter_table_aliases($this->ar_join));
01483                         }
01484                         else
01485                         {
01486                                 $sql .= implode("\n", $this->ar_join);
01487                         }
01488 
01489                 }
01490 
01491                 if (count($this->ar_where) > 0 OR count($this->ar_like) > 0)
01492                 {
01493                         $sql .= "\nWHERE ";
01494                 }
01495 
01496                 $sql .= implode("\n", $this->ar_where);
01497                 
01498                 if (count($this->ar_like) > 0)
01499                 {
01500                         if (count($this->ar_where) > 0)
01501                         {
01502                                 $sql .= " AND ";
01503                         }
01504 
01505                         $sql .= implode("\n", $this->ar_like);
01506                 }
01507                 
01508                 if (count($this->ar_groupby) > 0)
01509                 {
01510 
01511                         $sql .= "\nGROUP BY ";
01512                         
01513                         // special consideration for table aliases
01514                         if (count($this->ar_aliased_tables) > 0 && $this->dbprefix)
01515                         {
01516                                 $sql .= implode(", ", $this->_filter_table_aliases($this->ar_groupby));
01517                         }
01518                         else
01519                         {
01520                                 $sql .= implode(', ', $this->ar_groupby);
01521                         }
01522                 }
01523                 
01524                 if (count($this->ar_having) > 0)
01525                 {
01526                         $sql .= "\nHAVING ";
01527                         $sql .= implode("\n", $this->ar_having);
01528                 }
01529 
01530                 if (count($this->ar_orderby) > 0)
01531                 {
01532                         $sql .= "\nORDER BY ";
01533                         $sql .= implode(', ', $this->ar_orderby);
01534                         
01535                         if ($this->ar_order !== FALSE)
01536                         {
01537                                 $sql .= ($this->ar_order == 'desc') ? ' DESC' : ' ASC';
01538                         }               
01539                 }
01540                 
01541                 if (is_numeric($this->ar_limit))
01542                 {
01543                         $sql .= "\n";
01544                         $sql = $this->_limit($sql, $this->ar_limit, $this->ar_offset);
01545                 }
01546 
01547                 return $sql;
01548         }
01549 
01550         // --------------------------------------------------------------------
01551 
01552         /**
01553          * Object to Array
01554          *
01555          * Takes an object as input and converts the class variables to array key/vals
01556          *
01557          * @access      public
01558          * @param       object
01559          * @return      array
01560          */
01561         function _object_to_array($object)
01562         {
01563                 if ( ! is_object($object))
01564                 {
01565                         return $object;
01566                 }
01567                 
01568                 $array = array();
01569                 foreach (get_object_vars($object) as $key => $val)
01570                 {
01571                         // There are some built in keys we need to ignore for this conversion
01572                         if ( ! is_object($val) && ! is_array($val) && $key != '_parent_name' && $key != '_ci_scaffolding' && $key != '_ci_scaff_table')
01573   
01574                         {
01575                                 $array[$key] = $val;
01576                         }
01577                 }
01578         
01579                 return $array;
01580         }
01581         
01582         // --------------------------------------------------------------------
01583 
01584         /**
01585          * Start Cache
01586          *
01587          * Starts AR caching
01588          *
01589          * @access      public
01590          * @return      void
01591          */             
01592         function start_cache()
01593         {
01594                 $this->ar_caching = TRUE;
01595         }
01596 
01597         // --------------------------------------------------------------------
01598 
01599         /**
01600          * Stop Cache
01601          *
01602          * Stops AR caching
01603          *
01604          * @access      public
01605          * @return      void
01606          */             
01607         function stop_cache()
01608         {
01609                 $this->ar_caching = FALSE;
01610         }
01611 
01612 
01613         // --------------------------------------------------------------------
01614 
01615         /**
01616          * Flush Cache
01617          *
01618          * Empties the AR cache
01619          *
01620          * @access      public
01621          * @return      void
01622          */     
01623         function flush_cache()
01624         {       
01625                 $ar_reset_items = array(
01626                         'ar_cache_select' => array(), 
01627                         'ar_cache_from' => array(), 
01628                         'ar_cache_join' => array(),
01629                         'ar_cache_where' => array(), 
01630                         'ar_cache_like' => array(), 
01631                         'ar_cache_groupby' => array(), 
01632                         'ar_cache_having' =>array(), 
01633                         'ar_cache_orderby' => array(), 
01634                         'ar_cache_set' => array()
01635                 );
01636 
01637                 $this->_reset_run($ar_reset_items);     
01638         }
01639 
01640         // --------------------------------------------------------------------
01641 
01642         /**
01643          * Merge Cache
01644          *
01645          * When called, this function merges any cached AR arrays with 
01646          * locally called ones.
01647          *
01648          * @access      private
01649          * @return      void
01650          */
01651         function _merge_cache()
01652         {
01653                 $ar_items = array('select', 'from', 'join', 'where', 'like', 'groupby', 'having', 'orderby', 'set');
01654 
01655                 foreach ($ar_items as $ar_item)
01656                 {
01657                         $ar_cache_item = 'ar_cache_'.$ar_item;
01658                         $ar_item = 'ar_'.$ar_item;
01659                         $this->$ar_item = array_unique(array_merge($this->$ar_item, $this->$ar_cache_item));
01660                 }
01661         }
01662 
01663         // --------------------------------------------------------------------
01664 
01665         /**
01666          * Resets the active record values.  Called by the get() function
01667          *
01668          * @access      private
01669          * @param       array   An array of fields to reset
01670          * @return      void
01671          */
01672         function _reset_run($ar_reset_items)
01673         {
01674                 foreach ($ar_reset_items as $item => $default_value)
01675                 {
01676                         if ( ! in_array($item, $this->ar_store_array))
01677                         {
01678                                 $this->$item = $default_value;
01679                         }
01680                 }
01681         }
01682         
01683         // --------------------------------------------------------------------
01684 
01685         /**
01686          * Resets the active record values.  Called by the get() function
01687          *
01688          * @access      private
01689          * @return      void
01690          */
01691         function _reset_select()
01692         {
01693                 $ar_reset_items = array(
01694                         'ar_select' => array(), 
01695                         'ar_from' => array(), 
01696                         'ar_join' => array(), 
01697                         'ar_where' => array(), 
01698                         'ar_like' => array(), 
01699                         'ar_groupby' => array(), 
01700                         'ar_having' => array(), 
01701                         'ar_orderby' => array(), 
01702                         'ar_wherein' => array(), 
01703                         'ar_aliased_tables' => array(),
01704                         'ar_distinct' => FALSE, 
01705                         'ar_limit' => FALSE, 
01706                         'ar_offset' => FALSE, 
01707                         'ar_order' => FALSE,
01708                 );
01709                 
01710                 $this->_reset_run($ar_reset_items);
01711         }
01712         
01713         // --------------------------------------------------------------------
01714 
01715         /**
01716          * Resets the active record "write" values.
01717          *
01718          * Called by the insert() update() and delete() functions
01719          *
01720          * @access      private
01721          * @return      void
01722          */
01723         function _reset_write()
01724         {       
01725                 $ar_reset_items = array(
01726                         'ar_set' => array(), 
01727                         'ar_from' => array(), 
01728                         'ar_where' => array(), 
01729                         'ar_like' => array(),
01730                         'ar_orderby' => array(), 
01731                         'ar_limit' => FALSE, 
01732                         'ar_order' => FALSE
01733                 );
01734 
01735                 $this->_reset_run($ar_reset_items);
01736         }
01737         
01738 }
01739 
01740 /* End of file DB_active_rec.php */
01741 /* Location: ./system/database/DB_active_rec.php */