blob: 3e9923e6fb383077c7df7bef77adca590e9c8f8d [file] [log] [blame]
Derek Allard2067d1a2008-11-13 22:59:24 +00001<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
2/**
3 * CodeIgniter
4 *
5 * An open source application development framework for PHP 4.3.2 or newer
6 *
7 * @package CodeIgniter
8 * @author ExpressionEngine Dev Team
Derek Jones7f3719f2010-01-05 13:35:37 +00009 * @copyright Copyright (c) 2008 - 2010, EllisLab, Inc.
Derek Allard2067d1a2008-11-13 22:59:24 +000010 * @license http://codeigniter.com/user_guide/license.html
11 * @link http://codeigniter.com
12 * @since Version 1.0
13 * @filesource
14 */
15
16// ------------------------------------------------------------------------
17
18/**
19 * Active Record Class
20 *
21 * This is the platform-independent base Active Record implementation class.
22 *
23 * @package CodeIgniter
24 * @subpackage Drivers
25 * @category Database
26 * @author ExpressionEngine Dev Team
27 * @link http://codeigniter.com/user_guide/database/
28 */
29class CI_DB_active_record extends CI_DB_driver {
30
31 var $ar_select = array();
32 var $ar_distinct = FALSE;
33 var $ar_from = array();
34 var $ar_join = array();
35 var $ar_where = array();
36 var $ar_like = array();
37 var $ar_groupby = array();
38 var $ar_having = array();
39 var $ar_limit = FALSE;
40 var $ar_offset = FALSE;
41 var $ar_order = FALSE;
42 var $ar_orderby = array();
43 var $ar_set = array();
44 var $ar_wherein = array();
45 var $ar_aliased_tables = array();
46 var $ar_store_array = array();
47
48 // Active Record Caching variables
49 var $ar_caching = FALSE;
50 var $ar_cache_exists = array();
51 var $ar_cache_select = array();
52 var $ar_cache_from = array();
53 var $ar_cache_join = array();
54 var $ar_cache_where = array();
55 var $ar_cache_like = array();
56 var $ar_cache_groupby = array();
57 var $ar_cache_having = array();
58 var $ar_cache_orderby = array();
59 var $ar_cache_set = array();
60
61
62 // --------------------------------------------------------------------
63
64 /**
65 * Select
66 *
67 * Generates the SELECT portion of the query
68 *
69 * @access public
70 * @param string
71 * @return object
72 */
73 function select($select = '*', $escape = NULL)
74 {
75 // Set the global value if this was sepecified
76 if (is_bool($escape))
77 {
78 $this->_protect_identifiers = $escape;
79 }
80
81 if (is_string($select))
82 {
83 $select = explode(',', $select);
84 }
85
86 foreach ($select as $val)
87 {
88 $val = trim($val);
89
90 if ($val != '')
91 {
92 $this->ar_select[] = $val;
93
94 if ($this->ar_caching === TRUE)
95 {
96 $this->ar_cache_select[] = $val;
97 $this->ar_cache_exists[] = 'select';
98 }
99 }
100 }
101 return $this;
102 }
103
104 // --------------------------------------------------------------------
105
106 /**
107 * Select Max
108 *
109 * Generates a SELECT MAX(field) portion of a query
110 *
111 * @access public
112 * @param string the field
113 * @param string an alias
114 * @return object
115 */
116 function select_max($select = '', $alias = '')
117 {
118 return $this->_max_min_avg_sum($select, $alias, 'MAX');
119 }
120
121 // --------------------------------------------------------------------
122
123 /**
124 * Select Min
125 *
126 * Generates a SELECT MIN(field) portion of a query
127 *
128 * @access public
129 * @param string the field
130 * @param string an alias
131 * @return object
132 */
133 function select_min($select = '', $alias = '')
134 {
135 return $this->_max_min_avg_sum($select, $alias, 'MIN');
136 }
137
138 // --------------------------------------------------------------------
139
140 /**
141 * Select Average
142 *
143 * Generates a SELECT AVG(field) portion of a query
144 *
145 * @access public
146 * @param string the field
147 * @param string an alias
148 * @return object
149 */
150 function select_avg($select = '', $alias = '')
151 {
152 return $this->_max_min_avg_sum($select, $alias, 'AVG');
153 }
154
155 // --------------------------------------------------------------------
156
157 /**
158 * Select Sum
159 *
160 * Generates a SELECT SUM(field) portion of a query
161 *
162 * @access public
163 * @param string the field
164 * @param string an alias
165 * @return object
166 */
167 function select_sum($select = '', $alias = '')
168 {
169 return $this->_max_min_avg_sum($select, $alias, 'SUM');
170 }
171
172 // --------------------------------------------------------------------
173
174 /**
175 * Processing Function for the four functions above:
176 *
177 * select_max()
178 * select_min()
179 * select_avg()
180 * select_sum()
181 *
182 * @access public
183 * @param string the field
184 * @param string an alias
185 * @return object
186 */
187 function _max_min_avg_sum($select = '', $alias = '', $type = 'MAX')
188 {
189 if ( ! is_string($select) OR $select == '')
190 {
191 $this->display_error('db_invalid_query');
192 }
193
194 $type = strtoupper($type);
195
196 if ( ! in_array($type, array('MAX', 'MIN', 'AVG', 'SUM')))
197 {
198 show_error('Invalid function type: '.$type);
199 }
200
201 if ($alias == '')
202 {
203 $alias = $this->_create_alias_from_table(trim($select));
204 }
205
206 $sql = $type.'('.$this->_protect_identifiers(trim($select)).') AS '.$alias;
207
208 $this->ar_select[] = $sql;
209
210 if ($this->ar_caching === TRUE)
211 {
212 $this->ar_cache_select[] = $sql;
213 $this->ar_cache_exists[] = 'select';
214 }
215
216 return $this;
217 }
218
219 // --------------------------------------------------------------------
220
221 /**
222 * Determines the alias name based on the table
223 *
224 * @access private
225 * @param string
226 * @return string
227 */
228 function _create_alias_from_table($item)
229 {
230 if (strpos($item, '.') !== FALSE)
231 {
232 return end(explode('.', $item));
233 }
234
235 return $item;
236 }
237
238 // --------------------------------------------------------------------
239
240 /**
241 * DISTINCT
242 *
243 * Sets a flag which tells the query string compiler to add DISTINCT
244 *
245 * @access public
246 * @param bool
247 * @return object
248 */
249 function distinct($val = TRUE)
250 {
251 $this->ar_distinct = (is_bool($val)) ? $val : TRUE;
252 return $this;
253 }
254
255 // --------------------------------------------------------------------
256
257 /**
258 * From
259 *
260 * Generates the FROM portion of the query
261 *
262 * @access public
263 * @param mixed can be a string or array
264 * @return object
265 */
266 function from($from)
267 {
268 foreach ((array)$from as $val)
269 {
270 if (strpos($val, ',') !== FALSE)
271 {
272 foreach (explode(',', $val) as $v)
273 {
274 $v = trim($v);
275 $this->_track_aliases($v);
276
277 $this->ar_from[] = $this->_protect_identifiers($v, TRUE, NULL, FALSE);
278
279 if ($this->ar_caching === TRUE)
280 {
281 $this->ar_cache_from[] = $this->_protect_identifiers($v, TRUE, NULL, FALSE);
282 $this->ar_cache_exists[] = 'from';
283 }
284 }
285
286 }
287 else
288 {
289 $val = trim($val);
290
291 // Extract any aliases that might exist. We use this information
292 // in the _protect_identifiers to know whether to add a table prefix
293 $this->_track_aliases($val);
294
295 $this->ar_from[] = $this->_protect_identifiers($val, TRUE, NULL, FALSE);
296
297 if ($this->ar_caching === TRUE)
298 {
299 $this->ar_cache_from[] = $this->_protect_identifiers($val, TRUE, NULL, FALSE);
300 $this->ar_cache_exists[] = 'from';
301 }
302 }
303 }
304
305 return $this;
306 }
307
308 // --------------------------------------------------------------------
309
310 /**
311 * Join
312 *
313 * Generates the JOIN portion of the query
314 *
315 * @access public
316 * @param string
317 * @param string the join condition
318 * @param string the type of join
319 * @return object
320 */
321 function join($table, $cond, $type = '')
322 {
323 if ($type != '')
324 {
325 $type = strtoupper(trim($type));
326
327 if ( ! in_array($type, array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER')))
328 {
329 $type = '';
330 }
331 else
332 {
333 $type .= ' ';
334 }
335 }
336
337 // Extract any aliases that might exist. We use this information
338 // in the _protect_identifiers to know whether to add a table prefix
339 $this->_track_aliases($table);
340
341 // Strip apart the condition and protect the identifiers
342 if (preg_match('/([\w\.]+)([\W\s]+)(.+)/', $cond, $match))
343 {
344 $match[1] = $this->_protect_identifiers($match[1]);
345 $match[3] = $this->_protect_identifiers($match[3]);
346
347 $cond = $match[1].$match[2].$match[3];
348 }
349
350 // Assemble the JOIN statement
351 $join = $type.'JOIN '.$this->_protect_identifiers($table, TRUE, NULL, FALSE).' ON '.$cond;
352
353 $this->ar_join[] = $join;
354 if ($this->ar_caching === TRUE)
355 {
356 $this->ar_cache_join[] = $join;
357 $this->ar_cache_exists[] = 'join';
358 }
359
360 return $this;
361 }
362
363 // --------------------------------------------------------------------
364
365 /**
366 * Where
367 *
368 * Generates the WHERE portion of the query. Separates
369 * multiple calls with AND
370 *
371 * @access public
372 * @param mixed
373 * @param mixed
374 * @return object
375 */
376 function where($key, $value = NULL, $escape = TRUE)
377 {
378 return $this->_where($key, $value, 'AND ', $escape);
379 }
380
381 // --------------------------------------------------------------------
382
383 /**
384 * OR Where
385 *
386 * Generates the WHERE portion of the query. Separates
387 * multiple calls with OR
388 *
389 * @access public
390 * @param mixed
391 * @param mixed
392 * @return object
393 */
394 function or_where($key, $value = NULL, $escape = TRUE)
395 {
396 return $this->_where($key, $value, 'OR ', $escape);
397 }
398
399 // --------------------------------------------------------------------
400
401 /**
402 * orwhere() is an alias of or_where()
403 * this function is here for backwards compatibility, as
404 * orwhere() has been deprecated
405 */
406 function orwhere($key, $value = NULL, $escape = TRUE)
407 {
408 return $this->or_where($key, $value, $escape);
409 }
410
411 // --------------------------------------------------------------------
412
413 /**
414 * Where
415 *
416 * Called by where() or orwhere()
417 *
418 * @access private
419 * @param mixed
420 * @param mixed
421 * @param string
422 * @return object
423 */
424 function _where($key, $value = NULL, $type = 'AND ', $escape = NULL)
425 {
426 if ( ! is_array($key))
427 {
428 $key = array($key => $value);
429 }
430
431 // If the escape value was not set will will base it on the global setting
432 if ( ! is_bool($escape))
433 {
434 $escape = $this->_protect_identifiers;
435 }
436
437 foreach ($key as $k => $v)
438 {
439 $prefix = (count($this->ar_where) == 0 AND count($this->ar_cache_where) == 0) ? '' : $type;
440
441 if (is_null($v) && ! $this->_has_operator($k))
442 {
443 // value appears not to have been set, assign the test to IS NULL
444 $k .= ' IS NULL';
445 }
446
447 if ( ! is_null($v))
448 {
449 if ($escape === TRUE)
450 {
451 $k = $this->_protect_identifiers($k, FALSE, $escape);
452
453 $v = ' '.$this->escape($v);
454 }
455
456 if ( ! $this->_has_operator($k))
457 {
458 $k .= ' =';
459 }
460 }
461 else
462 {
463 $k = $this->_protect_identifiers($k, FALSE, $escape);
464 }
465
466 $this->ar_where[] = $prefix.$k.$v;
467
468 if ($this->ar_caching === TRUE)
469 {
470 $this->ar_cache_where[] = $prefix.$k.$v;
471 $this->ar_cache_exists[] = 'where';
472 }
473
474 }
475
476 return $this;
477 }
478
479 // --------------------------------------------------------------------
480
481 /**
482 * Where_in
483 *
484 * Generates a WHERE field IN ('item', 'item') SQL query joined with
485 * AND if appropriate
486 *
487 * @access public
488 * @param string The field to search
489 * @param array The values searched on
490 * @return object
491 */
492 function where_in($key = NULL, $values = NULL)
493 {
494 return $this->_where_in($key, $values);
495 }
496
497 // --------------------------------------------------------------------
498
499 /**
500 * Where_in_or
501 *
502 * Generates a WHERE field IN ('item', 'item') SQL query joined with
503 * OR if appropriate
504 *
505 * @access public
506 * @param string The field to search
507 * @param array The values searched on
508 * @return object
509 */
510 function or_where_in($key = NULL, $values = NULL)
511 {
512 return $this->_where_in($key, $values, FALSE, 'OR ');
513 }
514
515 // --------------------------------------------------------------------
516
517 /**
518 * Where_not_in
519 *
520 * Generates a WHERE field NOT IN ('item', 'item') SQL query joined
521 * with AND if appropriate
522 *
523 * @access public
524 * @param string The field to search
525 * @param array The values searched on
526 * @return object
527 */
528 function where_not_in($key = NULL, $values = NULL)
529 {
530 return $this->_where_in($key, $values, TRUE);
531 }
532
533 // --------------------------------------------------------------------
534
535 /**
536 * Where_not_in_or
537 *
538 * Generates a WHERE field NOT IN ('item', 'item') SQL query joined
539 * with OR if appropriate
540 *
541 * @access public
542 * @param string The field to search
543 * @param array The values searched on
544 * @return object
545 */
546 function or_where_not_in($key = NULL, $values = NULL)
547 {
548 return $this->_where_in($key, $values, TRUE, 'OR ');
549 }
550
551 // --------------------------------------------------------------------
552
553 /**
554 * Where_in
555 *
556 * Called by where_in, where_in_or, where_not_in, where_not_in_or
557 *
558 * @access public
559 * @param string The field to search
560 * @param array The values searched on
561 * @param boolean If the statement would be IN or NOT IN
562 * @param string
563 * @return object
564 */
565 function _where_in($key = NULL, $values = NULL, $not = FALSE, $type = 'AND ')
566 {
567 if ($key === NULL OR $values === NULL)
568 {
569 return;
570 }
571
572 if ( ! is_array($values))
573 {
574 $values = array($values);
575 }
576
577 $not = ($not) ? ' NOT' : '';
578
579 foreach ($values as $value)
580 {
581 $this->ar_wherein[] = $this->escape($value);
582 }
583
584 $prefix = (count($this->ar_where) == 0) ? '' : $type;
585
586 $where_in = $prefix . $this->_protect_identifiers($key) . $not . " IN (" . implode(", ", $this->ar_wherein) . ") ";
587
588 $this->ar_where[] = $where_in;
589 if ($this->ar_caching === TRUE)
590 {
591 $this->ar_cache_where[] = $where_in;
592 $this->ar_cache_exists[] = 'where';
593 }
594
595 // reset the array for multiple calls
596 $this->ar_wherein = array();
597 return $this;
598 }
599
600 // --------------------------------------------------------------------
601
602 /**
603 * Like
604 *
605 * Generates a %LIKE% portion of the query. Separates
606 * multiple calls with AND
607 *
608 * @access public
609 * @param mixed
610 * @param mixed
611 * @return object
612 */
613 function like($field, $match = '', $side = 'both')
614 {
615 return $this->_like($field, $match, 'AND ', $side);
616 }
617
618 // --------------------------------------------------------------------
619
620 /**
621 * Not Like
622 *
623 * Generates a NOT LIKE portion of the query. Separates
624 * multiple calls with AND
625 *
626 * @access public
627 * @param mixed
628 * @param mixed
629 * @return object
630 */
631 function not_like($field, $match = '', $side = 'both')
632 {
633 return $this->_like($field, $match, 'AND ', $side, 'NOT');
634 }
635
636 // --------------------------------------------------------------------
637
638 /**
639 * OR Like
640 *
641 * Generates a %LIKE% portion of the query. Separates
642 * multiple calls with OR
643 *
644 * @access public
645 * @param mixed
646 * @param mixed
647 * @return object
648 */
649 function or_like($field, $match = '', $side = 'both')
650 {
651 return $this->_like($field, $match, 'OR ', $side);
652 }
653
654 // --------------------------------------------------------------------
655
656 /**
657 * OR Not Like
658 *
659 * Generates a NOT LIKE portion of the query. Separates
660 * multiple calls with OR
661 *
662 * @access public
663 * @param mixed
664 * @param mixed
665 * @return object
666 */
667 function or_not_like($field, $match = '', $side = 'both')
668 {
669 return $this->_like($field, $match, 'OR ', $side, 'NOT');
670 }
671
672 // --------------------------------------------------------------------
673
674 /**
675 * orlike() is an alias of or_like()
676 * this function is here for backwards compatibility, as
677 * orlike() has been deprecated
678 */
679 function orlike($field, $match = '', $side = 'both')
680 {
681 return $this->or_like($field, $match, $side);
682 }
683
684 // --------------------------------------------------------------------
685
686 /**
687 * Like
688 *
689 * Called by like() or orlike()
690 *
691 * @access private
692 * @param mixed
693 * @param mixed
694 * @param string
695 * @return object
696 */
697 function _like($field, $match = '', $type = 'AND ', $side = 'both', $not = '')
698 {
699 if ( ! is_array($field))
700 {
701 $field = array($field => $match);
702 }
703
704 foreach ($field as $k => $v)
705 {
706 $k = $this->_protect_identifiers($k);
707
708 $prefix = (count($this->ar_like) == 0) ? '' : $type;
709
Derek Jonese4ed5832009-02-20 21:44:59 +0000710 $v = $this->escape_like_str($v);
Derek Allard2067d1a2008-11-13 22:59:24 +0000711
712 if ($side == 'before')
713 {
714 $like_statement = $prefix." $k $not LIKE '%{$v}'";
715 }
716 elseif ($side == 'after')
717 {
718 $like_statement = $prefix." $k $not LIKE '{$v}%'";
719 }
720 else
721 {
722 $like_statement = $prefix." $k $not LIKE '%{$v}%'";
723 }
Derek Jonesd10e8962010-03-02 17:10:36 -0600724
Derek Jonese4ed5832009-02-20 21:44:59 +0000725 // some platforms require an escape sequence definition for LIKE wildcards
726 if ($this->_like_escape_str != '')
727 {
Greg Aker0d424892010-01-26 02:14:44 +0000728 $like_statement = $like_statement.sprintf($this->_like_escape_str, $this->_like_escape_chr);
Derek Jonese4ed5832009-02-20 21:44:59 +0000729 }
Derek Jonesd10e8962010-03-02 17:10:36 -0600730
Derek Allard2067d1a2008-11-13 22:59:24 +0000731 $this->ar_like[] = $like_statement;
732 if ($this->ar_caching === TRUE)
733 {
734 $this->ar_cache_like[] = $like_statement;
735 $this->ar_cache_exists[] = 'like';
736 }
737
738 }
739 return $this;
740 }
741
742 // --------------------------------------------------------------------
743
744 /**
745 * GROUP BY
746 *
747 * @access public
748 * @param string
749 * @return object
750 */
751 function group_by($by)
752 {
753 if (is_string($by))
754 {
755 $by = explode(',', $by);
756 }
757
758 foreach ($by as $val)
759 {
760 $val = trim($val);
761
762 if ($val != '')
763 {
764 $this->ar_groupby[] = $this->_protect_identifiers($val);
765
766 if ($this->ar_caching === TRUE)
767 {
768 $this->ar_cache_groupby[] = $this->_protect_identifiers($val);
769 $this->ar_cache_exists[] = 'groupby';
770 }
771 }
772 }
773 return $this;
774 }
775
776 // --------------------------------------------------------------------
777
778 /**
779 * groupby() is an alias of group_by()
780 * this function is here for backwards compatibility, as
781 * groupby() has been deprecated
782 */
783 function groupby($by)
784 {
785 return $this->group_by($by);
786 }
787
788 // --------------------------------------------------------------------
789
790 /**
791 * Sets the HAVING value
792 *
793 * Separates multiple calls with AND
794 *
795 * @access public
796 * @param string
797 * @param string
798 * @return object
799 */
800 function having($key, $value = '', $escape = TRUE)
801 {
802 return $this->_having($key, $value, 'AND ', $escape);
803 }
804
805 // --------------------------------------------------------------------
806
807 /**
808 * orhaving() is an alias of or_having()
809 * this function is here for backwards compatibility, as
810 * orhaving() has been deprecated
811 */
812
813 function orhaving($key, $value = '', $escape = TRUE)
814 {
815 return $this->or_having($key, $value, $escape);
816 }
817 // --------------------------------------------------------------------
818
819 /**
820 * Sets the OR HAVING value
821 *
822 * Separates multiple calls with OR
823 *
824 * @access public
825 * @param string
826 * @param string
827 * @return object
828 */
829 function or_having($key, $value = '', $escape = TRUE)
830 {
831 return $this->_having($key, $value, 'OR ', $escape);
832 }
833
834 // --------------------------------------------------------------------
835
836 /**
837 * Sets the HAVING values
838 *
839 * Called by having() or or_having()
840 *
841 * @access private
842 * @param string
843 * @param string
844 * @return object
845 */
846 function _having($key, $value = '', $type = 'AND ', $escape = TRUE)
847 {
848 if ( ! is_array($key))
849 {
850 $key = array($key => $value);
851 }
852
853 foreach ($key as $k => $v)
854 {
855 $prefix = (count($this->ar_having) == 0) ? '' : $type;
856
857 if ($escape === TRUE)
858 {
859 $k = $this->_protect_identifiers($k);
860 }
861
862 if ( ! $this->_has_operator($k))
863 {
864 $k .= ' = ';
865 }
866
867 if ($v != '')
868 {
869 $v = ' '.$this->escape_str($v);
870 }
871
872 $this->ar_having[] = $prefix.$k.$v;
873 if ($this->ar_caching === TRUE)
874 {
875 $this->ar_cache_having[] = $prefix.$k.$v;
876 $this->ar_cache_exists[] = 'having';
877 }
878 }
879
880 return $this;
881 }
882
883 // --------------------------------------------------------------------
884
885 /**
886 * Sets the ORDER BY value
887 *
888 * @access public
889 * @param string
890 * @param string direction: asc or desc
891 * @return object
892 */
893 function order_by($orderby, $direction = '')
894 {
895 if (strtolower($direction) == 'random')
896 {
897 $orderby = ''; // Random results want or don't need a field name
898 $direction = $this->_random_keyword;
899 }
900 elseif (trim($direction) != '')
901 {
902 $direction = (in_array(strtoupper(trim($direction)), array('ASC', 'DESC'), TRUE)) ? ' '.$direction : ' ASC';
903 }
904
905
906 if (strpos($orderby, ',') !== FALSE)
907 {
908 $temp = array();
909 foreach (explode(',', $orderby) as $part)
910 {
911 $part = trim($part);
912 if ( ! in_array($part, $this->ar_aliased_tables))
913 {
914 $part = $this->_protect_identifiers(trim($part));
915 }
916
917 $temp[] = $part;
918 }
919
920 $orderby = implode(', ', $temp);
921 }
Derek Allarde37ab382009-02-03 16:13:57 +0000922 else if ($direction != $this->_random_keyword)
Derek Allard2067d1a2008-11-13 22:59:24 +0000923 {
924 $orderby = $this->_protect_identifiers($orderby);
925 }
926
927 $orderby_statement = $orderby.$direction;
928
929 $this->ar_orderby[] = $orderby_statement;
930 if ($this->ar_caching === TRUE)
931 {
932 $this->ar_cache_orderby[] = $orderby_statement;
933 $this->ar_cache_exists[] = 'orderby';
934 }
935
936 return $this;
937 }
938
939 // --------------------------------------------------------------------
940
941 /**
942 * orderby() is an alias of order_by()
943 * this function is here for backwards compatibility, as
944 * orderby() has been deprecated
945 */
946 function orderby($orderby, $direction = '')
947 {
948 return $this->order_by($orderby, $direction);
949 }
950
951 // --------------------------------------------------------------------
952
953 /**
954 * Sets the LIMIT value
955 *
956 * @access public
957 * @param integer the limit value
958 * @param integer the offset value
959 * @return object
960 */
961 function limit($value, $offset = '')
962 {
963 $this->ar_limit = $value;
964
965 if ($offset != '')
966 {
967 $this->ar_offset = $offset;
968 }
969
970 return $this;
971 }
972
973 // --------------------------------------------------------------------
974
975 /**
976 * Sets the OFFSET value
977 *
978 * @access public
979 * @param integer the offset value
980 * @return object
981 */
982 function offset($offset)
983 {
984 $this->ar_offset = $offset;
985 return $this;
986 }
987
988 // --------------------------------------------------------------------
989
990 /**
991 * The "set" function. Allows key/value pairs to be set for inserting or updating
992 *
993 * @access public
994 * @param mixed
995 * @param string
996 * @param boolean
997 * @return object
998 */
999 function set($key, $value = '', $escape = TRUE)
1000 {
1001 $key = $this->_object_to_array($key);
1002
1003 if ( ! is_array($key))
1004 {
1005 $key = array($key => $value);
1006 }
1007
1008 foreach ($key as $k => $v)
1009 {
1010 if ($escape === FALSE)
1011 {
1012 $this->ar_set[$this->_protect_identifiers($k)] = $v;
1013 }
1014 else
1015 {
1016 $this->ar_set[$this->_protect_identifiers($k)] = $this->escape($v);
1017 }
1018 }
1019
1020 return $this;
1021 }
1022
1023 // --------------------------------------------------------------------
1024
1025 /**
1026 * Get
1027 *
1028 * Compiles the select statement based on the other functions called
1029 * and runs the query
1030 *
1031 * @access public
1032 * @param string the table
1033 * @param string the limit clause
1034 * @param string the offset clause
1035 * @return object
1036 */
1037 function get($table = '', $limit = null, $offset = null)
1038 {
1039 if ($table != '')
1040 {
1041 $this->_track_aliases($table);
1042 $this->from($table);
1043 }
1044
1045 if ( ! is_null($limit))
1046 {
1047 $this->limit($limit, $offset);
1048 }
1049
1050 $sql = $this->_compile_select();
1051
1052 $result = $this->query($sql);
1053 $this->_reset_select();
1054 return $result;
1055 }
1056
1057 /**
1058 * "Count All Results" query
1059 *
1060 * Generates a platform-specific query string that counts all records
1061 * returned by an Active Record query.
1062 *
1063 * @access public
1064 * @param string
1065 * @return string
1066 */
1067 function count_all_results($table = '')
1068 {
1069 if ($table != '')
1070 {
1071 $this->_track_aliases($table);
1072 $this->from($table);
1073 }
1074
1075 $sql = $this->_compile_select($this->_count_string . $this->_protect_identifiers('numrows'));
1076
1077 $query = $this->query($sql);
1078 $this->_reset_select();
1079
1080 if ($query->num_rows() == 0)
1081 {
1082 return '0';
1083 }
1084
1085 $row = $query->row();
1086 return $row->numrows;
1087 }
1088
1089 // --------------------------------------------------------------------
1090
1091 /**
1092 * Get_Where
1093 *
1094 * Allows the where clause, limit and offset to be added directly
1095 *
1096 * @access public
1097 * @param string the where clause
1098 * @param string the limit clause
1099 * @param string the offset clause
1100 * @return object
1101 */
1102 function get_where($table = '', $where = null, $limit = null, $offset = null)
1103 {
1104 if ($table != '')
1105 {
1106 $this->from($table);
1107 }
1108
1109 if ( ! is_null($where))
1110 {
1111 $this->where($where);
1112 }
1113
1114 if ( ! is_null($limit))
1115 {
1116 $this->limit($limit, $offset);
1117 }
1118
1119 $sql = $this->_compile_select();
1120
1121 $result = $this->query($sql);
1122 $this->_reset_select();
1123 return $result;
1124 }
1125
1126 // --------------------------------------------------------------------
1127
1128 /**
1129 * getwhere() is an alias of get_where()
1130 * this function is here for backwards compatibility, as
1131 * getwhere() has been deprecated
1132 */
1133 function getwhere($table = '', $where = null, $limit = null, $offset = null)
1134 {
1135 return $this->get_where($table, $where, $limit, $offset);
1136 }
Derek Jonesd10e8962010-03-02 17:10:36 -06001137
1138 // --------------------------------------------------------------------
1139
1140 /**
1141 * Insert_Batch
1142 *
1143 * Compiles batch insert strings and runs the queries
1144 *
1145 * @access public
1146 * @param string the table to retrieve the results from
1147 * @param array an associative array of insert values
1148 * @return object
1149 */
1150 function insert_batch($table = '', $set = NULL)
1151 {
1152 if ( ! is_null($set))
1153 {
1154 $this->set_insert_batch($set);
1155 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001156
Derek Jonesd10e8962010-03-02 17:10:36 -06001157 if (count($this->ar_set) == 0)
1158 {
1159 if ($this->db_debug)
1160 {
1161 //No valid data array. Folds in cases where keys and values did not match up
1162 return $this->display_error('db_must_use_set');
1163 }
1164 return FALSE;
1165 }
1166
1167 if ($table == '')
1168 {
1169 if ( ! isset($this->ar_from[0]))
1170 {
1171 if ($this->db_debug)
1172 {
1173 return $this->display_error('db_must_set_table');
1174 }
1175 return FALSE;
1176 }
1177
1178 $table = $this->ar_from[0];
1179 }
1180
1181 // Batch this baby
1182 for ($i = 0, $total = count($this->ar_set); $i < $total; $i = $i + 100)
1183 {
1184
1185 $sql = $this->_insert_batch($this->_protect_identifiers($table, TRUE, NULL, FALSE), $this->ar_keys, array_slice($this->ar_set, $i, 100));
1186
1187 //echo $sql;
1188
1189 $this->query($sql);
1190 }
1191
1192 $this->_reset_write();
1193
1194
1195 return TRUE;
1196 }
1197
1198 // --------------------------------------------------------------------
1199
1200 /**
1201 * The "set_insert_batch" function. Allows key/value pairs to be set for batch inserts
1202 *
1203 * @access public
1204 * @param mixed
1205 * @param string
1206 * @param boolean
1207 * @return object
1208 */
1209
1210 function set_insert_batch($key, $value = '', $escape = TRUE)
1211 {
1212 $key = $this->_object_to_array_batch($key);
1213
1214 if ( ! is_array($key))
1215 {
1216 $key = array($key => $value);
1217 }
1218
1219 $keys = array_keys(current($key));
1220 sort($keys);
1221
1222 foreach ($key as $row)
1223 {
1224 if (count(array_diff($keys, array_keys($row))) > 0 OR count(array_diff(array_keys($row), $keys)) > 0)
1225 {
1226 // batch function above returns an error on an empty array
1227 $this->ar_set[] = array();
1228 return;
1229 }
1230
1231 ksort($row); // puts $row in the same order as our keys
1232
1233 if ($escape === FALSE)
1234 {
1235 $this->ar_set[] = '('.implode(',', $row).')';
1236 }
1237 else
1238 {
1239 $clean = array();
1240
1241 foreach($row as $value)
1242 {
1243 $clean[] = $this->escape($value);
1244 }
1245
1246 $this->ar_set[] = '('.implode(',', $clean).')';
1247 }
1248 }
1249
1250 foreach ($keys as $k)
1251 {
1252 $this->ar_keys[] = $this->_protect_identifiers($k);
1253 }
1254
1255 return $this;
1256 }
1257
Derek Allard2067d1a2008-11-13 22:59:24 +00001258 // --------------------------------------------------------------------
1259
1260 /**
1261 * Insert
1262 *
1263 * Compiles an insert string and runs the query
1264 *
1265 * @access public
1266 * @param string the table to retrieve the results from
1267 * @param array an associative array of insert values
1268 * @return object
1269 */
1270 function insert($table = '', $set = NULL)
1271 {
1272 if ( ! is_null($set))
1273 {
1274 $this->set($set);
1275 }
1276
1277 if (count($this->ar_set) == 0)
1278 {
1279 if ($this->db_debug)
1280 {
1281 return $this->display_error('db_must_use_set');
1282 }
1283 return FALSE;
1284 }
1285
1286 if ($table == '')
1287 {
1288 if ( ! isset($this->ar_from[0]))
1289 {
1290 if ($this->db_debug)
1291 {
1292 return $this->display_error('db_must_set_table');
1293 }
1294 return FALSE;
1295 }
1296
1297 $table = $this->ar_from[0];
1298 }
1299
1300 $sql = $this->_insert($this->_protect_identifiers($table, TRUE, NULL, FALSE), array_keys($this->ar_set), array_values($this->ar_set));
1301
1302 $this->_reset_write();
1303 return $this->query($sql);
1304 }
1305
Derek Jonesd10e8962010-03-02 17:10:36 -06001306 function replace($table = '', $set = NULL)
1307 {
1308 if ( ! is_null($set))
1309 {
1310 $this->set($set);
1311 }
1312
1313 if (count($this->ar_set) == 0)
1314 {
1315 if ($this->db_debug)
1316 {
1317 return $this->display_error('db_must_use_set');
1318 }
1319 return FALSE;
1320 }
1321
1322 if ($table == '')
1323 {
1324 if ( ! isset($this->ar_from[0]))
1325 {
1326 if ($this->db_debug)
1327 {
1328 return $this->display_error('db_must_set_table');
1329 }
1330 return FALSE;
1331 }
1332
1333 $table = $this->ar_from[0];
1334 }
1335
1336 $sql = $this->_replace($this->_protect_identifiers($table, TRUE, NULL, FALSE), array_keys($this->ar_set), array_values($this->ar_set));
1337
1338 $this->_reset_write();
1339 return $this->query($sql);
1340 }
1341
Derek Allard2067d1a2008-11-13 22:59:24 +00001342 // --------------------------------------------------------------------
1343
1344 /**
1345 * Update
1346 *
1347 * Compiles an update string and runs the query
1348 *
1349 * @access public
1350 * @param string the table to retrieve the results from
1351 * @param array an associative array of update values
1352 * @param mixed the where clause
1353 * @return object
1354 */
1355 function update($table = '', $set = NULL, $where = NULL, $limit = NULL)
1356 {
1357 // Combine any cached components with the current statements
1358 $this->_merge_cache();
1359
1360 if ( ! is_null($set))
1361 {
1362 $this->set($set);
1363 }
1364
1365 if (count($this->ar_set) == 0)
1366 {
1367 if ($this->db_debug)
1368 {
1369 return $this->display_error('db_must_use_set');
1370 }
1371 return FALSE;
1372 }
1373
1374 if ($table == '')
1375 {
1376 if ( ! isset($this->ar_from[0]))
1377 {
1378 if ($this->db_debug)
1379 {
1380 return $this->display_error('db_must_set_table');
1381 }
1382 return FALSE;
1383 }
1384
1385 $table = $this->ar_from[0];
1386 }
1387
1388 if ($where != NULL)
1389 {
1390 $this->where($where);
1391 }
1392
1393 if ($limit != NULL)
1394 {
1395 $this->limit($limit);
1396 }
1397
1398 $sql = $this->_update($this->_protect_identifiers($table, TRUE, NULL, FALSE), $this->ar_set, $this->ar_where, $this->ar_orderby, $this->ar_limit);
1399
1400 $this->_reset_write();
1401 return $this->query($sql);
1402 }
1403
Derek Jonesd10e8962010-03-02 17:10:36 -06001404
1405 // --------------------------------------------------------------------
1406
1407 /**
1408 * Update_Batch
1409 *
1410 * Compiles an update string and runs the query
1411 *
1412 * @access public
1413 * @param string the table to retrieve the results from
1414 * @param array an associative array of update values
1415 * @param string the where key
1416 * @return object
1417 */
1418 function update_batch($table = '', $set = NULL, $index = NULL)
1419 {
1420 // Combine any cached components with the current statements
1421 $this->_merge_cache();
1422
1423 if (is_null($index))
1424 {
1425 if ($this->db_debug)
1426 {
1427 return $this->display_error('db_myst_use_index');
1428 }
1429
1430 return FALSE;
1431 }
1432
1433 if ( ! is_null($set))
1434 {
1435 $this->set_update_batch($set, $index);
1436 }
1437
1438 if (count($this->ar_set) == 0)
1439 {
1440 if ($this->db_debug)
1441 {
1442 return $this->display_error('db_must_use_set');
1443 }
1444
1445 return FALSE;
1446 }
1447
1448 if ($table == '')
1449 {
1450 if ( ! isset($this->ar_from[0]))
1451 {
1452 if ($this->db_debug)
1453 {
1454 return $this->display_error('db_must_set_table');
1455 }
1456 return FALSE;
1457 }
1458
1459 $table = $this->ar_from[0];
1460 }
1461
1462 // Batch this baby
1463 for ($i = 0, $total = count($this->ar_set); $i < $total; $i = $i + 100)
1464 {
1465 $sql = $this->_update_batch($this->_protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->ar_set, $i, 100), $this->_protect_identifiers($index), $this->ar_where);
1466
1467 $this->query($sql);
1468 }
1469
1470 $this->_reset_write();
1471 }
1472
1473 // --------------------------------------------------------------------
1474
1475 /**
1476 * The "set_update_batch" function. Allows key/value pairs to be set for batch updating
1477 *
1478 * @access public
1479 * @param array
1480 * @param string
1481 * @param boolean
1482 * @return object
1483 */
1484
1485 function set_update_batch($key, $index = '', $escape = TRUE)
1486 {
1487 $key = $this->_object_to_array_batch($key);
1488
1489 if ( ! is_array($key))
1490 {
1491 // @todo error
1492 }
1493
1494 foreach ($key as $k => $v)
1495 {
1496 $index_set = FALSE;
1497 $clean = array();
1498
1499 foreach($v as $k2 => $v2)
1500 {
1501 if ($k2 == $index)
1502 {
1503 $index_set = TRUE;
1504 }
1505 else
1506 {
1507 $not[] = $k.'-'.$v;
1508 }
1509
1510 if ($escape === FALSE)
1511 {
1512 $clean[$this->_protect_identifiers($k2)] = $v2;
1513 }
1514 else
1515 {
1516 $clean[$this->_protect_identifiers($k2)] = $this->escape($v2);
1517 }
1518 }
1519
1520 if ($index_set == FALSE)
1521 {
1522 return $this->display_error('db_batch_missing_index');
1523 }
1524
1525 $this->ar_set[] = $clean;
1526 }
1527
1528 return $this;
1529 }
1530
Derek Allard2067d1a2008-11-13 22:59:24 +00001531 // --------------------------------------------------------------------
1532
1533 /**
1534 * Empty Table
1535 *
1536 * Compiles a delete string and runs "DELETE FROM table"
1537 *
1538 * @access public
1539 * @param string the table to empty
1540 * @return object
1541 */
1542 function empty_table($table = '')
1543 {
1544 if ($table == '')
1545 {
1546 if ( ! isset($this->ar_from[0]))
1547 {
1548 if ($this->db_debug)
1549 {
1550 return $this->display_error('db_must_set_table');
1551 }
1552 return FALSE;
1553 }
1554
1555 $table = $this->ar_from[0];
1556 }
1557 else
1558 {
1559 $table = $this->_protect_identifiers($table, TRUE, NULL, FALSE);
1560 }
1561
1562 $sql = $this->_delete($table);
1563
1564 $this->_reset_write();
1565
1566 return $this->query($sql);
1567 }
1568
1569 // --------------------------------------------------------------------
1570
1571 /**
1572 * Truncate
1573 *
1574 * Compiles a truncate string and runs the query
1575 * If the database does not support the truncate() command
1576 * This function maps to "DELETE FROM table"
1577 *
1578 * @access public
1579 * @param string the table to truncate
1580 * @return object
1581 */
1582 function truncate($table = '')
1583 {
1584 if ($table == '')
1585 {
1586 if ( ! isset($this->ar_from[0]))
1587 {
1588 if ($this->db_debug)
1589 {
1590 return $this->display_error('db_must_set_table');
1591 }
1592 return FALSE;
1593 }
1594
1595 $table = $this->ar_from[0];
1596 }
1597 else
1598 {
1599 $table = $this->_protect_identifiers($table, TRUE, NULL, FALSE);
1600 }
1601
1602 $sql = $this->_truncate($table);
1603
1604 $this->_reset_write();
1605
1606 return $this->query($sql);
1607 }
1608
1609 // --------------------------------------------------------------------
1610
1611 /**
1612 * Delete
1613 *
1614 * Compiles a delete string and runs the query
1615 *
1616 * @access public
1617 * @param mixed the table(s) to delete from. String or array
1618 * @param mixed the where clause
1619 * @param mixed the limit clause
1620 * @param boolean
1621 * @return object
1622 */
1623 function delete($table = '', $where = '', $limit = NULL, $reset_data = TRUE)
1624 {
1625 // Combine any cached components with the current statements
1626 $this->_merge_cache();
1627
1628 if ($table == '')
1629 {
1630 if ( ! isset($this->ar_from[0]))
1631 {
1632 if ($this->db_debug)
1633 {
1634 return $this->display_error('db_must_set_table');
1635 }
1636 return FALSE;
1637 }
1638
1639 $table = $this->ar_from[0];
1640 }
1641 elseif (is_array($table))
1642 {
1643 foreach($table as $single_table)
1644 {
1645 $this->delete($single_table, $where, $limit, FALSE);
1646 }
1647
1648 $this->_reset_write();
1649 return;
1650 }
1651 else
1652 {
1653 $table = $this->_protect_identifiers($table, TRUE, NULL, FALSE);
1654 }
1655
1656 if ($where != '')
1657 {
1658 $this->where($where);
1659 }
1660
1661 if ($limit != NULL)
1662 {
1663 $this->limit($limit);
1664 }
1665
Derek Allard03d783b2009-05-03 19:45:45 +00001666 if (count($this->ar_where) == 0 && count($this->ar_wherein) == 0 && count($this->ar_like) == 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001667 {
1668 if ($this->db_debug)
1669 {
1670 return $this->display_error('db_del_must_use_where');
1671 }
1672
1673 return FALSE;
1674 }
1675
1676 $sql = $this->_delete($table, $this->ar_where, $this->ar_like, $this->ar_limit);
1677
1678 if ($reset_data)
1679 {
1680 $this->_reset_write();
1681 }
1682
1683 return $this->query($sql);
1684 }
1685
1686 // --------------------------------------------------------------------
1687
1688 /**
1689 * DB Prefix
1690 *
1691 * Prepends a database prefix if one exists in configuration
1692 *
1693 * @access public
1694 * @param string the table
1695 * @return string
1696 */
1697 function dbprefix($table = '')
1698 {
1699 if ($table == '')
1700 {
1701 $this->display_error('db_table_name_required');
1702 }
1703
1704 return $this->dbprefix.$table;
1705 }
1706
1707 // --------------------------------------------------------------------
1708
1709 /**
1710 * Track Aliases
1711 *
1712 * Used to track SQL statements written with aliased tables.
1713 *
1714 * @access private
1715 * @param string The table to inspect
1716 * @return string
1717 */
1718 function _track_aliases($table)
1719 {
1720 if (is_array($table))
1721 {
1722 foreach ($table as $t)
1723 {
1724 $this->_track_aliases($t);
1725 }
1726 return;
1727 }
1728
1729 // Does the string contain a comma? If so, we need to separate
1730 // the string into discreet statements
1731 if (strpos($table, ',') !== FALSE)
1732 {
1733 return $this->_track_aliases(explode(',', $table));
1734 }
1735
1736 // if a table alias is used we can recognize it by a space
1737 if (strpos($table, " ") !== FALSE)
1738 {
1739 // if the alias is written with the AS keyword, remove it
1740 $table = preg_replace('/ AS /i', ' ', $table);
1741
1742 // Grab the alias
1743 $table = trim(strrchr($table, " "));
1744
1745 // Store the alias, if it doesn't already exist
1746 if ( ! in_array($table, $this->ar_aliased_tables))
1747 {
1748 $this->ar_aliased_tables[] = $table;
1749 }
1750 }
1751 }
1752
1753 // --------------------------------------------------------------------
1754
1755 /**
1756 * Compile the SELECT statement
1757 *
1758 * Generates a query string based on which functions were used.
1759 * Should not be called directly. The get() function calls it.
1760 *
1761 * @access private
1762 * @return string
1763 */
1764 function _compile_select($select_override = FALSE)
1765 {
1766 // Combine any cached components with the current statements
1767 $this->_merge_cache();
1768
1769 // ----------------------------------------------------------------
1770
1771 // Write the "select" portion of the query
1772
1773 if ($select_override !== FALSE)
1774 {
1775 $sql = $select_override;
1776 }
1777 else
1778 {
1779 $sql = ( ! $this->ar_distinct) ? 'SELECT ' : 'SELECT DISTINCT ';
1780
1781 if (count($this->ar_select) == 0)
1782 {
1783 $sql .= '*';
1784 }
1785 else
1786 {
1787 // Cycle through the "select" portion of the query and prep each column name.
1788 // The reason we protect identifiers here rather then in the select() function
1789 // is because until the user calls the from() function we don't know if there are aliases
1790 foreach ($this->ar_select as $key => $val)
1791 {
1792 $this->ar_select[$key] = $this->_protect_identifiers($val);
1793 }
1794
1795 $sql .= implode(', ', $this->ar_select);
1796 }
1797 }
1798
1799 // ----------------------------------------------------------------
1800
1801 // Write the "FROM" portion of the query
1802
1803 if (count($this->ar_from) > 0)
1804 {
1805 $sql .= "\nFROM ";
1806
1807 $sql .= $this->_from_tables($this->ar_from);
1808 }
1809
1810 // ----------------------------------------------------------------
1811
1812 // Write the "JOIN" portion of the query
1813
1814 if (count($this->ar_join) > 0)
1815 {
1816 $sql .= "\n";
1817
1818 $sql .= implode("\n", $this->ar_join);
1819 }
1820
1821 // ----------------------------------------------------------------
1822
1823 // Write the "WHERE" portion of the query
1824
1825 if (count($this->ar_where) > 0 OR count($this->ar_like) > 0)
1826 {
1827 $sql .= "\n";
1828
1829 $sql .= "WHERE ";
1830 }
1831
1832 $sql .= implode("\n", $this->ar_where);
1833
1834 // ----------------------------------------------------------------
1835
1836 // Write the "LIKE" portion of the query
1837
1838 if (count($this->ar_like) > 0)
1839 {
1840 if (count($this->ar_where) > 0)
1841 {
1842 $sql .= "\nAND ";
1843 }
1844
1845 $sql .= implode("\n", $this->ar_like);
1846 }
1847
1848 // ----------------------------------------------------------------
1849
1850 // Write the "GROUP BY" portion of the query
1851
1852 if (count($this->ar_groupby) > 0)
1853 {
1854 $sql .= "\nGROUP BY ";
1855
1856 $sql .= implode(', ', $this->ar_groupby);
1857 }
1858
1859 // ----------------------------------------------------------------
1860
1861 // Write the "HAVING" portion of the query
1862
1863 if (count($this->ar_having) > 0)
1864 {
1865 $sql .= "\nHAVING ";
1866 $sql .= implode("\n", $this->ar_having);
1867 }
1868
1869 // ----------------------------------------------------------------
1870
1871 // Write the "ORDER BY" portion of the query
1872
1873 if (count($this->ar_orderby) > 0)
1874 {
1875 $sql .= "\nORDER BY ";
1876 $sql .= implode(', ', $this->ar_orderby);
1877
1878 if ($this->ar_order !== FALSE)
1879 {
1880 $sql .= ($this->ar_order == 'desc') ? ' DESC' : ' ASC';
1881 }
1882 }
1883
1884 // ----------------------------------------------------------------
1885
1886 // Write the "LIMIT" portion of the query
1887
1888 if (is_numeric($this->ar_limit))
1889 {
1890 $sql .= "\n";
1891 $sql = $this->_limit($sql, $this->ar_limit, $this->ar_offset);
1892 }
1893
1894 return $sql;
1895 }
1896
1897 // --------------------------------------------------------------------
1898
1899 /**
1900 * Object to Array
1901 *
1902 * Takes an object as input and converts the class variables to array key/vals
1903 *
1904 * @access public
1905 * @param object
1906 * @return array
1907 */
1908 function _object_to_array($object)
1909 {
1910 if ( ! is_object($object))
1911 {
1912 return $object;
1913 }
1914
1915 $array = array();
1916 foreach (get_object_vars($object) as $key => $val)
1917 {
1918 // There are some built in keys we need to ignore for this conversion
Derek Jonescf579552010-03-11 09:13:34 -06001919 if ( ! is_object($val) && ! is_array($val) && $key != '_parent_name')
Derek Allard2067d1a2008-11-13 22:59:24 +00001920 {
1921 $array[$key] = $val;
1922 }
1923 }
Derek Jonesd10e8962010-03-02 17:10:36 -06001924
1925 return $array;
1926 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001927
Derek Jonesd10e8962010-03-02 17:10:36 -06001928 // --------------------------------------------------------------------
1929
1930 /**
1931 * Object to Array
1932 *
1933 * Takes an object as input and converts the class variables to array key/vals
1934 *
1935 * @access public
1936 * @param object
1937 * @return array
1938 */
1939 function _object_to_array_batch($object)
1940 {
1941 if ( ! is_object($object))
1942 {
1943 return $object;
1944 }
1945
1946 $array = array();
1947 $out = get_object_vars($object);
1948 $fields = array_keys($out);
1949
1950 foreach ($fields as $val)
1951 {
1952 // There are some built in keys we need to ignore for this conversion
Derek Jonescf579552010-03-11 09:13:34 -06001953 if ($val != '_parent_name')
Derek Jonesd10e8962010-03-02 17:10:36 -06001954 {
1955
1956 $i = 0;
1957 foreach ($out[$val] as $data)
1958 {
1959 $array[$i][$val] = $data;
1960 $i++;
1961 }
1962 }
1963 }
1964
Derek Allard2067d1a2008-11-13 22:59:24 +00001965 return $array;
1966 }
1967
1968 // --------------------------------------------------------------------
1969
1970 /**
1971 * Start Cache
1972 *
1973 * Starts AR caching
1974 *
1975 * @access public
1976 * @return void
1977 */
1978 function start_cache()
1979 {
1980 $this->ar_caching = TRUE;
1981 }
1982
1983 // --------------------------------------------------------------------
1984
1985 /**
1986 * Stop Cache
1987 *
1988 * Stops AR caching
1989 *
1990 * @access public
1991 * @return void
1992 */
1993 function stop_cache()
1994 {
1995 $this->ar_caching = FALSE;
1996 }
1997
1998 // --------------------------------------------------------------------
1999
2000 /**
2001 * Flush Cache
2002 *
2003 * Empties the AR cache
2004 *
2005 * @access public
2006 * @return void
2007 */
2008 function flush_cache()
2009 {
2010 $this->_reset_run(
2011 array(
2012 'ar_cache_select' => array(),
2013 'ar_cache_from' => array(),
2014 'ar_cache_join' => array(),
2015 'ar_cache_where' => array(),
2016 'ar_cache_like' => array(),
2017 'ar_cache_groupby' => array(),
2018 'ar_cache_having' => array(),
2019 'ar_cache_orderby' => array(),
2020 'ar_cache_set' => array(),
2021 'ar_cache_exists' => array()
2022 )
2023 );
2024 }
2025
2026 // --------------------------------------------------------------------
2027
2028 /**
2029 * Merge Cache
2030 *
2031 * When called, this function merges any cached AR arrays with
2032 * locally called ones.
2033 *
2034 * @access private
2035 * @return void
2036 */
2037 function _merge_cache()
2038 {
2039 if (count($this->ar_cache_exists) == 0)
2040 {
2041 return;
2042 }
2043
2044 foreach ($this->ar_cache_exists as $val)
2045 {
2046 $ar_variable = 'ar_'.$val;
2047 $ar_cache_var = 'ar_cache_'.$val;
2048
2049 if (count($this->$ar_cache_var) == 0)
2050 {
2051 continue;
2052 }
2053
2054 $this->$ar_variable = array_unique(array_merge($this->$ar_cache_var, $this->$ar_variable));
2055 }
2056
2057 // If we are "protecting identifiers" we need to examine the "from"
2058 // portion of the query to determine if there are any aliases
2059 if ($this->_protect_identifiers === TRUE AND count($this->ar_cache_from) > 0)
2060 {
2061 $this->_track_aliases($this->ar_from);
2062 }
2063 }
2064
2065 // --------------------------------------------------------------------
2066
2067 /**
2068 * Resets the active record values. Called by the get() function
2069 *
2070 * @access private
2071 * @param array An array of fields to reset
2072 * @return void
2073 */
2074 function _reset_run($ar_reset_items)
2075 {
2076 foreach ($ar_reset_items as $item => $default_value)
2077 {
2078 if ( ! in_array($item, $this->ar_store_array))
2079 {
2080 $this->$item = $default_value;
2081 }
2082 }
2083 }
2084
2085 // --------------------------------------------------------------------
2086
2087 /**
2088 * Resets the active record values. Called by the get() function
2089 *
2090 * @access private
2091 * @return void
2092 */
2093 function _reset_select()
2094 {
2095 $ar_reset_items = array(
2096 'ar_select' => array(),
2097 'ar_from' => array(),
2098 'ar_join' => array(),
2099 'ar_where' => array(),
2100 'ar_like' => array(),
2101 'ar_groupby' => array(),
2102 'ar_having' => array(),
2103 'ar_orderby' => array(),
2104 'ar_wherein' => array(),
2105 'ar_aliased_tables' => array(),
2106 'ar_distinct' => FALSE,
2107 'ar_limit' => FALSE,
2108 'ar_offset' => FALSE,
2109 'ar_order' => FALSE,
2110 );
2111
2112 $this->_reset_run($ar_reset_items);
2113 }
2114
2115 // --------------------------------------------------------------------
2116
2117 /**
2118 * Resets the active record "write" values.
2119 *
2120 * Called by the insert() update() and delete() functions
2121 *
2122 * @access private
2123 * @return void
2124 */
2125 function _reset_write()
2126 {
2127 $ar_reset_items = array(
2128 'ar_set' => array(),
2129 'ar_from' => array(),
2130 'ar_where' => array(),
2131 'ar_like' => array(),
2132 'ar_orderby' => array(),
2133 'ar_limit' => FALSE,
2134 'ar_order' => FALSE
2135 );
2136
2137 $this->_reset_run($ar_reset_items);
2138 }
2139
2140}
2141
2142/* End of file DB_active_rec.php */
Derek Jonesa3ffbbb2008-05-11 18:18:29 +00002143/* Location: ./system/database/DB_active_rec.php */