blob: b9bbb5016afbf429a42ee59b867a7c790c2ace31 [file] [log] [blame]
Andrey Andreevc5536aa2012-11-01 17:33:58 +02001<?php
Derek Allard2067d1a2008-11-13 22:59:24 +00002/**
3 * CodeIgniter
4 *
Andrey Andreevfe9309d2015-01-09 17:48:58 +02005 * An open source application development framework for PHP
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +02007 * This content is released under the MIT License (MIT)
WanWizard7219c072011-12-28 14:09:05 +01008 *
Andrey Andreevcce6bd12018-01-09 11:32:02 +02009 * Copyright (c) 2014 - 2018, British Columbia Institute of Technology
WanWizard7219c072011-12-28 14:09:05 +010010 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020011 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
Derek Jonesf4a4bd82011-10-20 12:18:42 -050017 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020018 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 * THE SOFTWARE.
28 *
29 * @package CodeIgniter
30 * @author EllisLab Dev Team
Andrey Andreev1924e872016-01-11 12:55:34 +020031 * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
Andrey Andreevcce6bd12018-01-09 11:32:02 +020032 * @copyright Copyright (c) 2014 - 2018, British Columbia Institute of Technology (http://bcit.ca/)
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020033 * @license http://opensource.org/licenses/MIT MIT License
Andrey Andreevbd202c92016-01-11 12:50:18 +020034 * @link https://codeigniter.com
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020035 * @since Version 1.0.0
Derek Allard2067d1a2008-11-13 22:59:24 +000036 * @filesource
37 */
Andrey Andreevc5536aa2012-11-01 17:33:58 +020038defined('BASEPATH') OR exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +000039
Derek Allard2067d1a2008-11-13 22:59:24 +000040/**
Jamie Rumbelow7efad202012-02-19 12:37:00 +000041 * Query Builder Class
Derek Allard2067d1a2008-11-13 22:59:24 +000042 *
Jamie Rumbelow7efad202012-02-19 12:37:00 +000043 * This is the platform-independent base Query Builder implementation class.
Derek Allard2067d1a2008-11-13 22:59:24 +000044 *
45 * @package CodeIgniter
46 * @subpackage Drivers
47 * @category Database
Derek Jonesf4a4bd82011-10-20 12:18:42 -050048 * @author EllisLab Dev Team
Andrey Andreevbd202c92016-01-11 12:50:18 +020049 * @link https://codeigniter.com/user_guide/database/
Derek Allard2067d1a2008-11-13 22:59:24 +000050 */
Jamie Rumbelowd6ce1e92012-04-26 13:27:35 +010051
52abstract class CI_DB_query_builder extends CI_DB_driver {
Derek Allard2067d1a2008-11-13 22:59:24 +000053
Andrey Andreevae85eb42012-11-02 01:42:31 +020054 /**
55 * Return DELETE SQL flag
56 *
57 * @var bool
58 */
WanWizard7219c072011-12-28 14:09:05 +010059 protected $return_delete_sql = FALSE;
Andrey Andreevae85eb42012-11-02 01:42:31 +020060
61 /**
62 * Reset DELETE data flag
63 *
64 * @var bool
65 */
WanWizard7219c072011-12-28 14:09:05 +010066 protected $reset_delete_data = FALSE;
67
Andrey Andreevae85eb42012-11-02 01:42:31 +020068 /**
69 * QB SELECT data
70 *
71 * @var array
72 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +000073 protected $qb_select = array();
Andrey Andreevae85eb42012-11-02 01:42:31 +020074
75 /**
76 * QB DISTINCT flag
77 *
78 * @var bool
79 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +000080 protected $qb_distinct = FALSE;
Andrey Andreevae85eb42012-11-02 01:42:31 +020081
82 /**
83 * QB FROM data
84 *
85 * @var array
86 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +000087 protected $qb_from = array();
Andrey Andreevae85eb42012-11-02 01:42:31 +020088
89 /**
90 * QB JOIN data
91 *
92 * @var array
93 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +000094 protected $qb_join = array();
Andrey Andreevae85eb42012-11-02 01:42:31 +020095
96 /**
97 * QB WHERE data
98 *
99 * @var array
100 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000101 protected $qb_where = array();
Andrey Andreevae85eb42012-11-02 01:42:31 +0200102
103 /**
104 * QB GROUP BY data
105 *
106 * @var array
107 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000108 protected $qb_groupby = array();
Andrey Andreevae85eb42012-11-02 01:42:31 +0200109
110 /**
111 * QB HAVING data
112 *
113 * @var array
114 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000115 protected $qb_having = array();
Andrey Andreevae85eb42012-11-02 01:42:31 +0200116
117 /**
118 * QB keys
119 *
120 * @var array
121 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000122 protected $qb_keys = array();
Andrey Andreevae85eb42012-11-02 01:42:31 +0200123
124 /**
125 * QB LIMIT data
126 *
127 * @var int
128 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000129 protected $qb_limit = FALSE;
Andrey Andreevae85eb42012-11-02 01:42:31 +0200130
131 /**
132 * QB OFFSET data
133 *
134 * @var int
135 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000136 protected $qb_offset = FALSE;
Andrey Andreevae85eb42012-11-02 01:42:31 +0200137
138 /**
139 * QB ORDER BY data
140 *
141 * @var array
142 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000143 protected $qb_orderby = array();
Andrey Andreevae85eb42012-11-02 01:42:31 +0200144
145 /**
146 * QB data sets
147 *
148 * @var array
149 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000150 protected $qb_set = array();
Andrey Andreevae85eb42012-11-02 01:42:31 +0200151
152 /**
Andrey Andreev8338bbb2016-12-12 14:17:52 +0200153 * QB data set for update_batch()
154 *
155 * @var array
156 */
157 protected $qb_set_ub = array();
158
159 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +0200160 * QB aliased tables list
161 *
162 * @var array
163 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000164 protected $qb_aliased_tables = array();
Andrey Andreevae85eb42012-11-02 01:42:31 +0200165
166 /**
167 * QB WHERE group started flag
168 *
169 * @var bool
170 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000171 protected $qb_where_group_started = FALSE;
Andrey Andreevae85eb42012-11-02 01:42:31 +0200172
173 /**
174 * QB WHERE group count
175 *
176 * @var int
177 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000178 protected $qb_where_group_count = 0;
Barry Mienydd671972010-10-04 16:33:58 +0200179
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000180 // Query Builder Caching variables
Andrey Andreevae85eb42012-11-02 01:42:31 +0200181
182 /**
183 * QB Caching flag
184 *
185 * @var bool
186 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000187 protected $qb_caching = FALSE;
Andrey Andreevae85eb42012-11-02 01:42:31 +0200188
189 /**
190 * QB Cache exists list
191 *
192 * @var array
193 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000194 protected $qb_cache_exists = array();
Andrey Andreevae85eb42012-11-02 01:42:31 +0200195
196 /**
197 * QB Cache SELECT data
198 *
199 * @var array
200 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000201 protected $qb_cache_select = array();
Andrey Andreevae85eb42012-11-02 01:42:31 +0200202
203 /**
204 * QB Cache FROM data
205 *
206 * @var array
207 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000208 protected $qb_cache_from = array();
Andrey Andreevae85eb42012-11-02 01:42:31 +0200209
210 /**
211 * QB Cache JOIN data
212 *
213 * @var array
214 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000215 protected $qb_cache_join = array();
Andrey Andreevae85eb42012-11-02 01:42:31 +0200216
217 /**
Andrey Andreev437ffe02017-01-17 12:44:19 +0200218 * QB Cache aliased tables list
219 *
220 * @var array
221 */
222 protected $qb_cache_aliased_tables = array();
223
224 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +0200225 * QB Cache WHERE data
226 *
227 * @var array
228 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000229 protected $qb_cache_where = array();
Andrey Andreevae85eb42012-11-02 01:42:31 +0200230
231 /**
232 * QB Cache GROUP BY data
233 *
234 * @var array
235 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000236 protected $qb_cache_groupby = array();
Andrey Andreevae85eb42012-11-02 01:42:31 +0200237
238 /**
239 * QB Cache HAVING data
240 *
241 * @var array
242 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000243 protected $qb_cache_having = array();
Andrey Andreevae85eb42012-11-02 01:42:31 +0200244
245 /**
246 * QB Cache ORDER BY data
247 *
248 * @var array
249 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000250 protected $qb_cache_orderby = array();
Andrey Andreevae85eb42012-11-02 01:42:31 +0200251
252 /**
253 * QB Cache data sets
254 *
255 * @var array
256 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000257 protected $qb_cache_set = array();
WanWizard7219c072011-12-28 14:09:05 +0100258
Andrey Andreevae85eb42012-11-02 01:42:31 +0200259 /**
260 * QB No Escape data
261 *
262 * @var array
263 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000264 protected $qb_no_escape = array();
Andrey Andreevae85eb42012-11-02 01:42:31 +0200265
266 /**
267 * QB Cache No Escape data
268 *
269 * @var array
270 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000271 protected $qb_cache_no_escape = array();
Derek Allard2067d1a2008-11-13 22:59:24 +0000272
Andrey Andreevae85eb42012-11-02 01:42:31 +0200273 // --------------------------------------------------------------------
274
Derek Allard2067d1a2008-11-13 22:59:24 +0000275 /**
276 * Select
277 *
278 * Generates the SELECT portion of the query
279 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000280 * @param string
Andrey Andreev42870232012-06-12 01:30:20 +0300281 * @param mixed
Andrew Podner4296a652012-12-17 07:51:15 -0500282 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000283 */
Phil Sturgeon9789f322011-07-15 15:14:05 -0600284 public function select($select = '*', $escape = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000285 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000286 if (is_string($select))
287 {
288 $select = explode(',', $select);
289 }
290
Vivek Dinesh33578d22014-02-06 09:46:07 +0530291 // If the escape value was not set, we will base it on the global setting
Andrey Andreev42870232012-06-12 01:30:20 +0300292 is_bool($escape) OR $escape = $this->_protect_identifiers;
293
Derek Allard2067d1a2008-11-13 22:59:24 +0000294 foreach ($select as $val)
295 {
296 $val = trim($val);
297
Alex Bilbie48a2baf2012-06-02 11:09:54 +0100298 if ($val !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000299 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000300 $this->qb_select[] = $val;
301 $this->qb_no_escape[] = $escape;
Derek Allard2067d1a2008-11-13 22:59:24 +0000302
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000303 if ($this->qb_caching === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000304 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000305 $this->qb_cache_select[] = $val;
306 $this->qb_cache_exists[] = 'select';
307 $this->qb_cache_no_escape[] = $escape;
Derek Allard2067d1a2008-11-13 22:59:24 +0000308 }
309 }
310 }
Andrey Andreev24276a32012-01-08 02:44:38 +0200311
Derek Allard2067d1a2008-11-13 22:59:24 +0000312 return $this;
313 }
314
315 // --------------------------------------------------------------------
316
317 /**
318 * Select Max
319 *
320 * Generates a SELECT MAX(field) portion of a query
321 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000322 * @param string the field
323 * @param string an alias
Andrew Podner4296a652012-12-17 07:51:15 -0500324 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000325 */
Phil Sturgeon9789f322011-07-15 15:14:05 -0600326 public function select_max($select = '', $alias = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000327 {
328 return $this->_max_min_avg_sum($select, $alias, 'MAX');
329 }
Barry Mienydd671972010-10-04 16:33:58 +0200330
Derek Allard2067d1a2008-11-13 22:59:24 +0000331 // --------------------------------------------------------------------
332
333 /**
334 * Select Min
335 *
336 * Generates a SELECT MIN(field) portion of a query
337 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000338 * @param string the field
339 * @param string an alias
Andrew Podner4296a652012-12-17 07:51:15 -0500340 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000341 */
Phil Sturgeon9789f322011-07-15 15:14:05 -0600342 public function select_min($select = '', $alias = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000343 {
344 return $this->_max_min_avg_sum($select, $alias, 'MIN');
345 }
346
347 // --------------------------------------------------------------------
348
349 /**
350 * Select Average
351 *
352 * Generates a SELECT AVG(field) portion of a query
353 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000354 * @param string the field
355 * @param string an alias
Andrew Podner4296a652012-12-17 07:51:15 -0500356 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000357 */
Phil Sturgeon9789f322011-07-15 15:14:05 -0600358 public function select_avg($select = '', $alias = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000359 {
360 return $this->_max_min_avg_sum($select, $alias, 'AVG');
361 }
362
363 // --------------------------------------------------------------------
364
365 /**
366 * Select Sum
367 *
368 * Generates a SELECT SUM(field) portion of a query
369 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000370 * @param string the field
371 * @param string an alias
Andrew Podner4296a652012-12-17 07:51:15 -0500372 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000373 */
Phil Sturgeon9789f322011-07-15 15:14:05 -0600374 public function select_sum($select = '', $alias = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000375 {
376 return $this->_max_min_avg_sum($select, $alias, 'SUM');
377 }
378
379 // --------------------------------------------------------------------
380
381 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +0200382 * SELECT [MAX|MIN|AVG|SUM]()
Derek Allard2067d1a2008-11-13 22:59:24 +0000383 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200384 * @used-by select_max()
385 * @used-by select_min()
386 * @used-by select_avg()
387 * @used-by select_sum()
Barry Mienydd671972010-10-04 16:33:58 +0200388 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200389 * @param string $select Field name
390 * @param string $alias
391 * @param string $type
Andrew Podner4296a652012-12-17 07:51:15 -0500392 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000393 */
Phil Sturgeon9789f322011-07-15 15:14:05 -0600394 protected function _max_min_avg_sum($select = '', $alias = '', $type = 'MAX')
Derek Allard2067d1a2008-11-13 22:59:24 +0000395 {
Alex Bilbie48a2baf2012-06-02 11:09:54 +0100396 if ( ! is_string($select) OR $select === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000397 {
398 $this->display_error('db_invalid_query');
399 }
Barry Mienydd671972010-10-04 16:33:58 +0200400
Derek Allard2067d1a2008-11-13 22:59:24 +0000401 $type = strtoupper($type);
Barry Mienydd671972010-10-04 16:33:58 +0200402
Derek Allard2067d1a2008-11-13 22:59:24 +0000403 if ( ! in_array($type, array('MAX', 'MIN', 'AVG', 'SUM')))
404 {
405 show_error('Invalid function type: '.$type);
406 }
Barry Mienydd671972010-10-04 16:33:58 +0200407
Alex Bilbie48a2baf2012-06-02 11:09:54 +0100408 if ($alias === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000409 {
410 $alias = $this->_create_alias_from_table(trim($select));
411 }
Barry Mienydd671972010-10-04 16:33:58 +0200412
Andrey Andreev5b55c152013-08-06 14:14:32 +0300413 $sql = $type.'('.$this->protect_identifiers(trim($select)).') AS '.$this->escape_identifiers(trim($alias));
Andrey Andreev7b5eb732012-05-24 20:52:41 +0300414
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000415 $this->qb_select[] = $sql;
Jamie Rumbelowd6ce1e92012-04-26 13:27:35 +0100416 $this->qb_no_escape[] = NULL;
Barry Mienydd671972010-10-04 16:33:58 +0200417
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000418 if ($this->qb_caching === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000419 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000420 $this->qb_cache_select[] = $sql;
421 $this->qb_cache_exists[] = 'select';
Derek Allard2067d1a2008-11-13 22:59:24 +0000422 }
Barry Mienydd671972010-10-04 16:33:58 +0200423
Derek Allard2067d1a2008-11-13 22:59:24 +0000424 return $this;
425 }
426
427 // --------------------------------------------------------------------
428
429 /**
430 * Determines the alias name based on the table
431 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200432 * @param string $item
Derek Allard2067d1a2008-11-13 22:59:24 +0000433 * @return string
434 */
Phil Sturgeon9789f322011-07-15 15:14:05 -0600435 protected function _create_alias_from_table($item)
Derek Allard2067d1a2008-11-13 22:59:24 +0000436 {
437 if (strpos($item, '.') !== FALSE)
438 {
Andrey Andreevdb0c0622012-02-29 19:02:46 +0200439 $item = explode('.', $item);
440 return end($item);
Derek Allard2067d1a2008-11-13 22:59:24 +0000441 }
Barry Mienydd671972010-10-04 16:33:58 +0200442
Derek Allard2067d1a2008-11-13 22:59:24 +0000443 return $item;
444 }
445
446 // --------------------------------------------------------------------
447
448 /**
449 * DISTINCT
450 *
451 * Sets a flag which tells the query string compiler to add DISTINCT
452 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200453 * @param bool $val
Andrew Podner4296a652012-12-17 07:51:15 -0500454 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000455 */
Phil Sturgeon9789f322011-07-15 15:14:05 -0600456 public function distinct($val = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000457 {
Andrey Andreev7b5eb732012-05-24 20:52:41 +0300458 $this->qb_distinct = is_bool($val) ? $val : TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000459 return $this;
460 }
Barry Mienydd671972010-10-04 16:33:58 +0200461
Derek Allard2067d1a2008-11-13 22:59:24 +0000462 // --------------------------------------------------------------------
463
464 /**
465 * From
466 *
467 * Generates the FROM portion of the query
468 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200469 * @param mixed $from can be a string or array
Andrew Podner4296a652012-12-17 07:51:15 -0500470 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000471 */
Phil Sturgeon9789f322011-07-15 15:14:05 -0600472 public function from($from)
Derek Allard2067d1a2008-11-13 22:59:24 +0000473 {
Andrey Andreev7b5eb732012-05-24 20:52:41 +0300474 foreach ((array) $from as $val)
Derek Allard2067d1a2008-11-13 22:59:24 +0000475 {
476 if (strpos($val, ',') !== FALSE)
477 {
478 foreach (explode(',', $val) as $v)
479 {
480 $v = trim($v);
481 $this->_track_aliases($v);
Barry Mienydd671972010-10-04 16:33:58 +0200482
George Petsagourakis193d4482012-04-28 11:16:18 +0300483 $this->qb_from[] = $v = $this->protect_identifiers($v, TRUE, NULL, FALSE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000484
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000485 if ($this->qb_caching === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000486 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000487 $this->qb_cache_from[] = $v;
488 $this->qb_cache_exists[] = 'from';
Barry Mienydd671972010-10-04 16:33:58 +0200489 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000490 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000491 }
492 else
493 {
494 $val = trim($val);
495
Andrey Andreev24276a32012-01-08 02:44:38 +0200496 // Extract any aliases that might exist. We use this information
Jamie Rumbelow0c092992012-03-06 22:05:16 +0000497 // in the protect_identifiers to know whether to add a table prefix
Derek Allard2067d1a2008-11-13 22:59:24 +0000498 $this->_track_aliases($val);
Barry Mienydd671972010-10-04 16:33:58 +0200499
Jamie Rumbelow0c092992012-03-06 22:05:16 +0000500 $this->qb_from[] = $val = $this->protect_identifiers($val, TRUE, NULL, FALSE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000501
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000502 if ($this->qb_caching === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000503 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000504 $this->qb_cache_from[] = $val;
505 $this->qb_cache_exists[] = 'from';
Derek Allard2067d1a2008-11-13 22:59:24 +0000506 }
507 }
508 }
509
510 return $this;
511 }
512
513 // --------------------------------------------------------------------
514
515 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +0200516 * JOIN
Derek Allard2067d1a2008-11-13 22:59:24 +0000517 *
518 * Generates the JOIN portion of the query
519 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000520 * @param string
521 * @param string the join condition
522 * @param string the type of join
Alex Bilbief512b732012-06-16 11:15:19 +0100523 * @param string whether not to try to escape identifiers
Andrew Podner4296a652012-12-17 07:51:15 -0500524 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000525 */
Andrey Andreevfe642da2012-06-16 03:47:33 +0300526 public function join($table, $cond, $type = '', $escape = NULL)
Barry Mienydd671972010-10-04 16:33:58 +0200527 {
Alex Bilbie48a2baf2012-06-02 11:09:54 +0100528 if ($type !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000529 {
530 $type = strtoupper(trim($type));
531
Andrey Andreev42870232012-06-12 01:30:20 +0300532 if ( ! in_array($type, array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER'), TRUE))
Derek Allard2067d1a2008-11-13 22:59:24 +0000533 {
534 $type = '';
535 }
536 else
537 {
538 $type .= ' ';
539 }
540 }
541
Andrey Andreev24276a32012-01-08 02:44:38 +0200542 // Extract any aliases that might exist. We use this information
Jamie Rumbelow0c092992012-03-06 22:05:16 +0000543 // in the protect_identifiers to know whether to add a table prefix
Derek Allard2067d1a2008-11-13 22:59:24 +0000544 $this->_track_aliases($table);
545
Andrey Andreevfe642da2012-06-16 03:47:33 +0300546 is_bool($escape) OR $escape = $this->_protect_identifiers;
547
Andrey Andreevc6011942016-02-11 23:49:37 +0200548 if ( ! $this->_has_operator($cond))
Andrey Andreev3751f932012-06-17 18:07:48 +0300549 {
550 $cond = ' USING ('.($escape ? $this->escape_identifiers($cond) : $cond).')';
551 }
Andrey Andreevc6011942016-02-11 23:49:37 +0200552 elseif ($escape === FALSE)
Andrey Andreev3751f932012-06-17 18:07:48 +0300553 {
554 $cond = ' ON '.$cond;
Derek Allard2067d1a2008-11-13 22:59:24 +0000555 }
Andrey Andreevc6011942016-02-11 23:49:37 +0200556 else
557 {
558 // Split multiple conditions
559 if (preg_match_all('/\sAND\s|\sOR\s/i', $cond, $joints, PREG_OFFSET_CAPTURE))
560 {
561 $conditions = array();
562 $joints = $joints[0];
563 array_unshift($joints, array('', 0));
564
565 for ($i = count($joints) - 1, $pos = strlen($cond); $i >= 0; $i--)
566 {
567 $joints[$i][1] += strlen($joints[$i][0]); // offset
568 $conditions[$i] = substr($cond, $joints[$i][1], $pos - $joints[$i][1]);
569 $pos = $joints[$i][1] - strlen($joints[$i][0]);
570 $joints[$i] = $joints[$i][0];
571 }
572 }
573 else
574 {
575 $conditions = array($cond);
576 $joints = array('');
577 }
578
579 $cond = ' ON ';
580 for ($i = 0, $c = count($conditions); $i < $c; $i++)
581 {
582 $operator = $this->_get_operator($conditions[$i]);
583 $cond .= $joints[$i];
584 $cond .= preg_match("/(\(*)?([\[\]\w\.'-]+)".preg_quote($operator)."(.*)/i", $conditions[$i], $match)
585 ? $match[1].$this->protect_identifiers($match[2]).$operator.$this->protect_identifiers($match[3])
586 : $conditions[$i];
587 }
588 }
Barry Mienydd671972010-10-04 16:33:58 +0200589
Andrey Andreev42870232012-06-12 01:30:20 +0300590 // Do we want to escape the table name?
591 if ($escape === TRUE)
592 {
593 $table = $this->protect_identifiers($table, TRUE, NULL, FALSE);
594 }
595
Derek Allard2067d1a2008-11-13 22:59:24 +0000596 // Assemble the JOIN statement
Andrey Andreev3751f932012-06-17 18:07:48 +0300597 $this->qb_join[] = $join = $type.'JOIN '.$table.$cond;
Derek Allard2067d1a2008-11-13 22:59:24 +0000598
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000599 if ($this->qb_caching === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000600 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000601 $this->qb_cache_join[] = $join;
602 $this->qb_cache_exists[] = 'join';
Derek Allard2067d1a2008-11-13 22:59:24 +0000603 }
604
605 return $this;
606 }
607
608 // --------------------------------------------------------------------
609
610 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +0200611 * WHERE
Derek Allard2067d1a2008-11-13 22:59:24 +0000612 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200613 * Generates the WHERE portion of the query.
614 * Separates multiple calls with 'AND'.
Derek Allard2067d1a2008-11-13 22:59:24 +0000615 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000616 * @param mixed
617 * @param mixed
Andrey Andreev42870232012-06-12 01:30:20 +0300618 * @param bool
Andrew Podner4296a652012-12-17 07:51:15 -0500619 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000620 */
Andrey Andreev498c1e02012-06-16 03:34:10 +0300621 public function where($key, $value = NULL, $escape = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000622 {
Andrey Andreevd40459d2012-07-18 16:46:39 +0300623 return $this->_wh('qb_where', $key, $value, 'AND ', $escape);
Derek Allard2067d1a2008-11-13 22:59:24 +0000624 }
Barry Mienydd671972010-10-04 16:33:58 +0200625
Derek Allard2067d1a2008-11-13 22:59:24 +0000626 // --------------------------------------------------------------------
627
628 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +0200629 * OR WHERE
Derek Allard2067d1a2008-11-13 22:59:24 +0000630 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200631 * Generates the WHERE portion of the query.
632 * Separates multiple calls with 'OR'.
Derek Allard2067d1a2008-11-13 22:59:24 +0000633 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000634 * @param mixed
635 * @param mixed
Andrey Andreev42870232012-06-12 01:30:20 +0300636 * @param bool
Andrew Podner4296a652012-12-17 07:51:15 -0500637 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000638 */
Andrey Andreev498c1e02012-06-16 03:34:10 +0300639 public function or_where($key, $value = NULL, $escape = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000640 {
Andrey Andreevd40459d2012-07-18 16:46:39 +0300641 return $this->_wh('qb_where', $key, $value, 'OR ', $escape);
Derek Allard2067d1a2008-11-13 22:59:24 +0000642 }
643
644 // --------------------------------------------------------------------
645
646 /**
Andrey Andreevd40459d2012-07-18 16:46:39 +0300647 * WHERE, HAVING
Derek Allard2067d1a2008-11-13 22:59:24 +0000648 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200649 * @used-by where()
650 * @used-by or_where()
651 * @used-by having()
652 * @used-by or_having()
Derek Allard2067d1a2008-11-13 22:59:24 +0000653 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200654 * @param string $qb_key 'qb_where' or 'qb_having'
655 * @param mixed $key
656 * @param mixed $value
657 * @param string $type
658 * @param bool $escape
Andrew Podner4296a652012-12-17 07:51:15 -0500659 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000660 */
Andrey Andreevd40459d2012-07-18 16:46:39 +0300661 protected function _wh($qb_key, $key, $value = NULL, $type = 'AND ', $escape = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000662 {
Andrey Andreevd40459d2012-07-18 16:46:39 +0300663 $qb_cache_key = ($qb_key === 'qb_having') ? 'qb_cache_having' : 'qb_cache_where';
664
Derek Allard2067d1a2008-11-13 22:59:24 +0000665 if ( ! is_array($key))
666 {
667 $key = array($key => $value);
668 }
Barry Mienydd671972010-10-04 16:33:58 +0200669
Rougin Royce Gutib191550a2014-08-24 16:19:08 +0800670 // If the escape value was not set will base it on the global setting
Andrey Andreeve10fb792012-06-15 12:07:04 +0300671 is_bool($escape) OR $escape = $this->_protect_identifiers;
Derek Allard2067d1a2008-11-13 22:59:24 +0000672
673 foreach ($key as $k => $v)
674 {
Andrey Andreevd40459d2012-07-18 16:46:39 +0300675 $prefix = (count($this->$qb_key) === 0 && count($this->$qb_cache_key) === 0)
Andrey Andreev58803fb2012-06-24 00:45:37 +0300676 ? $this->_group_get_type('')
677 : $this->_group_get_type($type);
Derek Allard2067d1a2008-11-13 22:59:24 +0000678
vlakoff1228fe22013-01-14 01:30:09 +0100679 if ($v !== NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000680 {
Andrey Andreevf7631f12015-07-27 21:54:41 +0300681 if ($escape === TRUE)
682 {
683 $v = ' '.$this->escape($v);
684 }
WanWizard7219c072011-12-28 14:09:05 +0100685
Derek Allard2067d1a2008-11-13 22:59:24 +0000686 if ( ! $this->_has_operator($k))
687 {
Greg Akere156c6e2011-04-20 16:03:04 -0500688 $k .= ' = ';
Derek Allard2067d1a2008-11-13 22:59:24 +0000689 }
690 }
Andrey Andreev3a5efc22012-11-20 21:18:08 +0200691 elseif ( ! $this->_has_operator($k))
692 {
693 // value appears not to have been set, assign the test to IS NULL
694 $k .= ' IS NULL';
695 }
Andrey Andreevbe4bab92016-10-28 12:50:03 +0300696 elseif (preg_match('/\s*(!?=|<>|\sIS(?:\s+NOT)?\s)\s*$/i', $k, $match, PREG_OFFSET_CAPTURE))
Andrey Andreev5bf4dcd2014-09-29 20:07:15 +0300697 {
698 $k = substr($k, 0, $match[0][1]).($match[1][0] === '=' ? ' IS NULL' : ' IS NOT NULL');
699 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000700
Andrey Andreevd40459d2012-07-18 16:46:39 +0300701 $this->{$qb_key}[] = array('condition' => $prefix.$k.$v, 'escape' => $escape);
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000702 if ($this->qb_caching === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000703 {
Andrey Andreevd40459d2012-07-18 16:46:39 +0300704 $this->{$qb_cache_key}[] = array('condition' => $prefix.$k.$v, 'escape' => $escape);
705 $this->qb_cache_exists[] = substr($qb_key, 3);
Derek Allard2067d1a2008-11-13 22:59:24 +0000706 }
Barry Mienydd671972010-10-04 16:33:58 +0200707
Derek Allard2067d1a2008-11-13 22:59:24 +0000708 }
Barry Mienydd671972010-10-04 16:33:58 +0200709
Derek Allard2067d1a2008-11-13 22:59:24 +0000710 return $this;
711 }
712
713 // --------------------------------------------------------------------
714
715 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +0200716 * WHERE IN
Derek Allard2067d1a2008-11-13 22:59:24 +0000717 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200718 * Generates a WHERE field IN('item', 'item') SQL query,
719 * joined with 'AND' if appropriate.
Derek Allard2067d1a2008-11-13 22:59:24 +0000720 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200721 * @param string $key The field to search
722 * @param array $values The values searched on
723 * @param bool $escape
Andrew Podner4296a652012-12-17 07:51:15 -0500724 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000725 */
Andrey Andreev498c1e02012-06-16 03:34:10 +0300726 public function where_in($key = NULL, $values = NULL, $escape = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000727 {
Andrey Andreev498c1e02012-06-16 03:34:10 +0300728 return $this->_where_in($key, $values, FALSE, 'AND ', $escape);
Derek Allard2067d1a2008-11-13 22:59:24 +0000729 }
Barry Mienydd671972010-10-04 16:33:58 +0200730
Derek Allard2067d1a2008-11-13 22:59:24 +0000731 // --------------------------------------------------------------------
732
733 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +0200734 * OR WHERE IN
Derek Allard2067d1a2008-11-13 22:59:24 +0000735 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200736 * Generates a WHERE field IN('item', 'item') SQL query,
737 * joined with 'OR' if appropriate.
Derek Allard2067d1a2008-11-13 22:59:24 +0000738 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200739 * @param string $key The field to search
740 * @param array $values The values searched on
741 * @param bool $escape
Andrew Podner4296a652012-12-17 07:51:15 -0500742 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000743 */
Andrey Andreev498c1e02012-06-16 03:34:10 +0300744 public function or_where_in($key = NULL, $values = NULL, $escape = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000745 {
Andrey Andreev498c1e02012-06-16 03:34:10 +0300746 return $this->_where_in($key, $values, FALSE, 'OR ', $escape);
Derek Allard2067d1a2008-11-13 22:59:24 +0000747 }
748
749 // --------------------------------------------------------------------
750
751 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +0200752 * WHERE NOT IN
Derek Allard2067d1a2008-11-13 22:59:24 +0000753 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200754 * Generates a WHERE field NOT IN('item', 'item') SQL query,
755 * joined with 'AND' if appropriate.
Derek Allard2067d1a2008-11-13 22:59:24 +0000756 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200757 * @param string $key The field to search
758 * @param array $values The values searched on
759 * @param bool $escape
Andrew Podner4296a652012-12-17 07:51:15 -0500760 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000761 */
Andrey Andreev498c1e02012-06-16 03:34:10 +0300762 public function where_not_in($key = NULL, $values = NULL, $escape = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000763 {
Andrey Andreev498c1e02012-06-16 03:34:10 +0300764 return $this->_where_in($key, $values, TRUE, 'AND ', $escape);
Derek Allard2067d1a2008-11-13 22:59:24 +0000765 }
Barry Mienydd671972010-10-04 16:33:58 +0200766
Derek Allard2067d1a2008-11-13 22:59:24 +0000767 // --------------------------------------------------------------------
768
769 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +0200770 * OR WHERE NOT IN
Derek Allard2067d1a2008-11-13 22:59:24 +0000771 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200772 * Generates a WHERE field NOT IN('item', 'item') SQL query,
773 * joined with 'OR' if appropriate.
Derek Allard2067d1a2008-11-13 22:59:24 +0000774 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200775 * @param string $key The field to search
776 * @param array $values The values searched on
777 * @param bool $escape
Andrew Podner4296a652012-12-17 07:51:15 -0500778 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000779 */
Andrey Andreev498c1e02012-06-16 03:34:10 +0300780 public function or_where_not_in($key = NULL, $values = NULL, $escape = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000781 {
Andrey Andreev498c1e02012-06-16 03:34:10 +0300782 return $this->_where_in($key, $values, TRUE, 'OR ', $escape);
Derek Allard2067d1a2008-11-13 22:59:24 +0000783 }
784
785 // --------------------------------------------------------------------
786
787 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +0200788 * Internal WHERE IN
Derek Allard2067d1a2008-11-13 22:59:24 +0000789 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200790 * @used-by where_in()
791 * @used-by or_where_in()
792 * @used-by where_not_in()
793 * @used-by or_where_not_in()
Derek Allard2067d1a2008-11-13 22:59:24 +0000794 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200795 * @param string $key The field to search
796 * @param array $values The values searched on
797 * @param bool $not If the statement would be IN or NOT IN
798 * @param string $type
799 * @param bool $escape
Andrew Podner4296a652012-12-17 07:51:15 -0500800 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000801 */
Andrey Andreev498c1e02012-06-16 03:34:10 +0300802 protected function _where_in($key = NULL, $values = NULL, $not = FALSE, $type = 'AND ', $escape = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000803 {
804 if ($key === NULL OR $values === NULL)
805 {
Rafael Queiroz6600b692012-06-08 14:34:20 -0300806 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000807 }
Barry Mienydd671972010-10-04 16:33:58 +0200808
Derek Allard2067d1a2008-11-13 22:59:24 +0000809 if ( ! is_array($values))
810 {
811 $values = array($values);
812 }
Barry Mienydd671972010-10-04 16:33:58 +0200813
Andrey Andreev498c1e02012-06-16 03:34:10 +0300814 is_bool($escape) OR $escape = $this->_protect_identifiers;
815
Derek Allard2067d1a2008-11-13 22:59:24 +0000816 $not = ($not) ? ' NOT' : '';
817
Andrey Andreevd738b6b2015-07-29 16:24:57 +0300818 if ($escape === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000819 {
Andrey Andreevd738b6b2015-07-29 16:24:57 +0300820 $where_in = array();
821 foreach ($values as $value)
822 {
823 $where_in[] = $this->escape($value);
824 }
825 }
826 else
827 {
828 $where_in = array_values($values);
Derek Allard2067d1a2008-11-13 22:59:24 +0000829 }
830
Andrey Andreev0d2d84f2015-07-31 13:48:59 +0300831 $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0)
832 ? $this->_group_get_type('')
833 : $this->_group_get_type($type);
834
Andrey Andreev6e704752012-07-18 00:46:33 +0300835 $where_in = array(
Andrey Andreev94611df2012-07-19 12:29:54 +0300836 'condition' => $prefix.$key.$not.' IN('.implode(', ', $where_in).')',
Andrey Andreev6e704752012-07-18 00:46:33 +0300837 'escape' => $escape
838 );
Barry Mienydd671972010-10-04 16:33:58 +0200839
Andrey Andreev6e704752012-07-18 00:46:33 +0300840 $this->qb_where[] = $where_in;
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000841 if ($this->qb_caching === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000842 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000843 $this->qb_cache_where[] = $where_in;
844 $this->qb_cache_exists[] = 'where';
Derek Allard2067d1a2008-11-13 22:59:24 +0000845 }
846
Derek Allard2067d1a2008-11-13 22:59:24 +0000847 return $this;
848 }
Barry Mienydd671972010-10-04 16:33:58 +0200849
Derek Allard2067d1a2008-11-13 22:59:24 +0000850 // --------------------------------------------------------------------
851
852 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +0200853 * LIKE
Derek Allard2067d1a2008-11-13 22:59:24 +0000854 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200855 * Generates a %LIKE% portion of the query.
856 * Separates multiple calls with 'AND'.
Derek Allard2067d1a2008-11-13 22:59:24 +0000857 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200858 * @param mixed $field
859 * @param string $match
860 * @param string $side
861 * @param bool $escape
Andrew Podner4296a652012-12-17 07:51:15 -0500862 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000863 */
Andrey Andreevb0478652012-07-18 15:34:46 +0300864 public function like($field, $match = '', $side = 'both', $escape = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000865 {
Andrey Andreevb0478652012-07-18 15:34:46 +0300866 return $this->_like($field, $match, 'AND ', $side, '', $escape);
Derek Allard2067d1a2008-11-13 22:59:24 +0000867 }
868
869 // --------------------------------------------------------------------
870
871 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +0200872 * NOT LIKE
Derek Allard2067d1a2008-11-13 22:59:24 +0000873 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200874 * Generates a NOT LIKE portion of the query.
875 * Separates multiple calls with 'AND'.
Derek Allard2067d1a2008-11-13 22:59:24 +0000876 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200877 * @param mixed $field
878 * @param string $match
879 * @param string $side
880 * @param bool $escape
Andrew Podner4296a652012-12-17 07:51:15 -0500881 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000882 */
Andrey Andreevb0478652012-07-18 15:34:46 +0300883 public function not_like($field, $match = '', $side = 'both', $escape = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000884 {
Andrey Andreevb0478652012-07-18 15:34:46 +0300885 return $this->_like($field, $match, 'AND ', $side, 'NOT', $escape);
Derek Allard2067d1a2008-11-13 22:59:24 +0000886 }
Barry Mienydd671972010-10-04 16:33:58 +0200887
Derek Allard2067d1a2008-11-13 22:59:24 +0000888 // --------------------------------------------------------------------
889
890 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +0200891 * OR LIKE
Derek Allard2067d1a2008-11-13 22:59:24 +0000892 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200893 * Generates a %LIKE% portion of the query.
894 * Separates multiple calls with 'OR'.
Derek Allard2067d1a2008-11-13 22:59:24 +0000895 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200896 * @param mixed $field
897 * @param string $match
898 * @param string $side
899 * @param bool $escape
Andrew Podner4296a652012-12-17 07:51:15 -0500900 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000901 */
Andrey Andreevb0478652012-07-18 15:34:46 +0300902 public function or_like($field, $match = '', $side = 'both', $escape = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000903 {
Andrey Andreevb0478652012-07-18 15:34:46 +0300904 return $this->_like($field, $match, 'OR ', $side, '', $escape);
Derek Allard2067d1a2008-11-13 22:59:24 +0000905 }
906
907 // --------------------------------------------------------------------
908
909 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +0200910 * OR NOT LIKE
Derek Allard2067d1a2008-11-13 22:59:24 +0000911 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200912 * Generates a NOT LIKE portion of the query.
913 * Separates multiple calls with 'OR'.
Derek Allard2067d1a2008-11-13 22:59:24 +0000914 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200915 * @param mixed $field
916 * @param string $match
917 * @param string $side
918 * @param bool $escape
Andrew Podner4296a652012-12-17 07:51:15 -0500919 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000920 */
Andrey Andreevb0478652012-07-18 15:34:46 +0300921 public function or_not_like($field, $match = '', $side = 'both', $escape = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000922 {
Andrey Andreevb0478652012-07-18 15:34:46 +0300923 return $this->_like($field, $match, 'OR ', $side, 'NOT', $escape);
Derek Allard2067d1a2008-11-13 22:59:24 +0000924 }
Barry Mienydd671972010-10-04 16:33:58 +0200925
Derek Allard2067d1a2008-11-13 22:59:24 +0000926 // --------------------------------------------------------------------
927
928 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +0200929 * Internal LIKE
Derek Allard2067d1a2008-11-13 22:59:24 +0000930 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200931 * @used-by like()
932 * @used-by or_like()
933 * @used-by not_like()
934 * @used-by or_not_like()
Derek Allard2067d1a2008-11-13 22:59:24 +0000935 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200936 * @param mixed $field
937 * @param string $match
938 * @param string $type
939 * @param string $side
940 * @param string $not
941 * @param bool $escape
Andrew Podner4296a652012-12-17 07:51:15 -0500942 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +0000943 */
Andrey Andreevb0478652012-07-18 15:34:46 +0300944 protected function _like($field, $match = '', $type = 'AND ', $side = 'both', $not = '', $escape = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000945 {
946 if ( ! is_array($field))
947 {
948 $field = array($field => $match);
949 }
Barry Mienydd671972010-10-04 16:33:58 +0200950
Andrey Andreevb0478652012-07-18 15:34:46 +0300951 is_bool($escape) OR $escape = $this->_protect_identifiers;
Andrey Andreev19311362015-04-07 00:02:14 +0300952 // lowercase $side in case somebody writes e.g. 'BEFORE' instead of 'before' (doh)
953 $side = strtolower($side);
Andrey Andreevb0478652012-07-18 15:34:46 +0300954
Derek Allard2067d1a2008-11-13 22:59:24 +0000955 foreach ($field as $k => $v)
956 {
Andrey Andreev41738232012-11-30 00:13:17 +0200957 $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0)
958 ? $this->_group_get_type('') : $this->_group_get_type($type);
959
Andrey Andreevd738b6b2015-07-29 16:24:57 +0300960 if ($escape === TRUE)
961 {
962 $v = $this->escape_like_str($v);
963 }
Andrey Andreevfc11dcc2012-06-04 16:39:19 +0300964
Andrey Andreev24276a32012-01-08 02:44:38 +0200965 if ($side === 'none')
Kyle Farris81ef70f2011-08-31 11:59:12 -0400966 {
Andrey Andreevb0478652012-07-18 15:34:46 +0300967 $like_statement = "{$prefix} {$k} {$not} LIKE '{$v}'";
Kyle Farris81ef70f2011-08-31 11:59:12 -0400968 }
Andrey Andreev24276a32012-01-08 02:44:38 +0200969 elseif ($side === 'before')
Derek Allard2067d1a2008-11-13 22:59:24 +0000970 {
Andrey Andreevb0478652012-07-18 15:34:46 +0300971 $like_statement = "{$prefix} {$k} {$not} LIKE '%{$v}'";
Derek Allard2067d1a2008-11-13 22:59:24 +0000972 }
Andrey Andreev24276a32012-01-08 02:44:38 +0200973 elseif ($side === 'after')
Derek Allard2067d1a2008-11-13 22:59:24 +0000974 {
Andrey Andreevb0478652012-07-18 15:34:46 +0300975 $like_statement = "{$prefix} {$k} {$not} LIKE '{$v}%'";
Derek Allard2067d1a2008-11-13 22:59:24 +0000976 }
977 else
978 {
Andrey Andreevb0478652012-07-18 15:34:46 +0300979 $like_statement = "{$prefix} {$k} {$not} LIKE '%{$v}%'";
Derek Allard2067d1a2008-11-13 22:59:24 +0000980 }
Derek Jonesd10e8962010-03-02 17:10:36 -0600981
Derek Jonese4ed5832009-02-20 21:44:59 +0000982 // some platforms require an escape sequence definition for LIKE wildcards
Andrey Andreevd738b6b2015-07-29 16:24:57 +0300983 if ($escape === TRUE && $this->_like_escape_str !== '')
Derek Jonese4ed5832009-02-20 21:44:59 +0000984 {
Andrey Andreevb0478652012-07-18 15:34:46 +0300985 $like_statement .= sprintf($this->_like_escape_str, $this->_like_escape_chr);
Derek Jonese4ed5832009-02-20 21:44:59 +0000986 }
Derek Jonesd10e8962010-03-02 17:10:36 -0600987
Andrey Andreevb0478652012-07-18 15:34:46 +0300988 $this->qb_where[] = array('condition' => $like_statement, 'escape' => $escape);
Jamie Rumbelow7efad202012-02-19 12:37:00 +0000989 if ($this->qb_caching === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000990 {
Andrey Andreev55bbd722013-01-28 19:02:13 +0200991 $this->qb_cache_where[] = array('condition' => $like_statement, 'escape' => $escape);
Andrey Andreevededc4a2012-07-18 01:16:15 +0300992 $this->qb_cache_exists[] = 'where';
Derek Allard2067d1a2008-11-13 22:59:24 +0000993 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000994 }
Andrey Andreev24276a32012-01-08 02:44:38 +0200995
Derek Allard2067d1a2008-11-13 22:59:24 +0000996 return $this;
997 }
Barry Mienydd671972010-10-04 16:33:58 +0200998
Derek Allard2067d1a2008-11-13 22:59:24 +0000999 // --------------------------------------------------------------------
1000
1001 /**
WanWizard7219c072011-12-28 14:09:05 +01001002 * Starts a query group.
1003 *
Andrey Andreevae85eb42012-11-02 01:42:31 +02001004 * @param string $not (Internal use only)
1005 * @param string $type (Internal use only)
Andrew Podner4296a652012-12-17 07:51:15 -05001006 * @return CI_DB_query_builder
WanWizard7219c072011-12-28 14:09:05 +01001007 */
1008 public function group_start($not = '', $type = 'AND ')
1009 {
1010 $type = $this->_group_get_type($type);
WanWizard7219c072011-12-28 14:09:05 +01001011
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001012 $this->qb_where_group_started = TRUE;
Jamie Rumbelowd6ce1e92012-04-26 13:27:35 +01001013 $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) ? '' : $type;
Andrey Andreev6e704752012-07-18 00:46:33 +03001014 $where = array(
1015 'condition' => $prefix.$not.str_repeat(' ', ++$this->qb_where_group_count).' (',
1016 'escape' => FALSE
1017 );
WanWizard7219c072011-12-28 14:09:05 +01001018
Andrey Andreev6e704752012-07-18 00:46:33 +03001019 $this->qb_where[] = $where;
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001020 if ($this->qb_caching)
WanWizard7219c072011-12-28 14:09:05 +01001021 {
Andrey Andreev6e704752012-07-18 00:46:33 +03001022 $this->qb_cache_where[] = $where;
WanWizard7219c072011-12-28 14:09:05 +01001023 }
1024
1025 return $this;
1026 }
1027
1028 // --------------------------------------------------------------------
1029
1030 /**
1031 * Starts a query group, but ORs the group
1032 *
Andrew Podner4296a652012-12-17 07:51:15 -05001033 * @return CI_DB_query_builder
WanWizard7219c072011-12-28 14:09:05 +01001034 */
1035 public function or_group_start()
1036 {
1037 return $this->group_start('', 'OR ');
1038 }
1039
1040 // --------------------------------------------------------------------
1041
1042 /**
1043 * Starts a query group, but NOTs the group
1044 *
Andrew Podner4296a652012-12-17 07:51:15 -05001045 * @return CI_DB_query_builder
WanWizard7219c072011-12-28 14:09:05 +01001046 */
1047 public function not_group_start()
1048 {
1049 return $this->group_start('NOT ', 'AND ');
1050 }
1051
1052 // --------------------------------------------------------------------
1053
1054 /**
1055 * Starts a query group, but OR NOTs the group
1056 *
Andrew Podner4296a652012-12-17 07:51:15 -05001057 * @return CI_DB_query_builder
WanWizard7219c072011-12-28 14:09:05 +01001058 */
1059 public function or_not_group_start()
1060 {
1061 return $this->group_start('NOT ', 'OR ');
1062 }
1063
1064 // --------------------------------------------------------------------
1065
1066 /**
1067 * Ends a query group
1068 *
Andrew Podner4296a652012-12-17 07:51:15 -05001069 * @return CI_DB_query_builder
WanWizard7219c072011-12-28 14:09:05 +01001070 */
1071 public function group_end()
1072 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001073 $this->qb_where_group_started = FALSE;
Andrey Andreev6e704752012-07-18 00:46:33 +03001074 $where = array(
1075 'condition' => str_repeat(' ', $this->qb_where_group_count--).')',
1076 'escape' => FALSE
1077 );
WanWizard7219c072011-12-28 14:09:05 +01001078
Andrey Andreev6e704752012-07-18 00:46:33 +03001079 $this->qb_where[] = $where;
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001080 if ($this->qb_caching)
WanWizard7219c072011-12-28 14:09:05 +01001081 {
Andrey Andreev6e704752012-07-18 00:46:33 +03001082 $this->qb_cache_where[] = $where;
WanWizard7219c072011-12-28 14:09:05 +01001083 }
1084
WanWizard7219c072011-12-28 14:09:05 +01001085 return $this;
1086 }
1087
1088 // --------------------------------------------------------------------
1089
1090 /**
1091 * Group_get_type
1092 *
Andrey Andreevae85eb42012-11-02 01:42:31 +02001093 * @used-by group_start()
1094 * @used-by _like()
1095 * @used-by _wh()
1096 * @used-by _where_in()
WanWizard7219c072011-12-28 14:09:05 +01001097 *
Andrey Andreevae85eb42012-11-02 01:42:31 +02001098 * @param string $type
WanWizard7219c072011-12-28 14:09:05 +01001099 * @return string
1100 */
1101 protected function _group_get_type($type)
1102 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001103 if ($this->qb_where_group_started)
WanWizard7219c072011-12-28 14:09:05 +01001104 {
1105 $type = '';
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001106 $this->qb_where_group_started = FALSE;
WanWizard7219c072011-12-28 14:09:05 +01001107 }
1108
1109 return $type;
1110 }
1111
1112 // --------------------------------------------------------------------
1113
1114 /**
Derek Allard2067d1a2008-11-13 22:59:24 +00001115 * GROUP BY
1116 *
Andrey Andreevae85eb42012-11-02 01:42:31 +02001117 * @param string $by
1118 * @param bool $escape
Andrew Podner4296a652012-12-17 07:51:15 -05001119 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +00001120 */
Andrey Andreevc9b924c2012-07-19 13:06:02 +03001121 public function group_by($by, $escape = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +00001122 {
Andrey Andreev96feb582012-07-19 13:12:34 +03001123 is_bool($escape) OR $escape = $this->_protect_identifiers;
1124
Derek Allard2067d1a2008-11-13 22:59:24 +00001125 if (is_string($by))
1126 {
Andrey Andreev96feb582012-07-19 13:12:34 +03001127 $by = ($escape === TRUE)
1128 ? explode(',', $by)
1129 : array($by);
Derek Allard2067d1a2008-11-13 22:59:24 +00001130 }
Barry Mienydd671972010-10-04 16:33:58 +02001131
Derek Allard2067d1a2008-11-13 22:59:24 +00001132 foreach ($by as $val)
1133 {
1134 $val = trim($val);
Barry Mienydd671972010-10-04 16:33:58 +02001135
Alex Bilbie48a2baf2012-06-02 11:09:54 +01001136 if ($val !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001137 {
Andrey Andreev96feb582012-07-19 13:12:34 +03001138 $val = array('field' => $val, 'escape' => $escape);
Barry Mienydd671972010-10-04 16:33:58 +02001139
Andrey Andreev96feb582012-07-19 13:12:34 +03001140 $this->qb_groupby[] = $val;
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001141 if ($this->qb_caching === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001142 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001143 $this->qb_cache_groupby[] = $val;
1144 $this->qb_cache_exists[] = 'groupby';
Derek Allard2067d1a2008-11-13 22:59:24 +00001145 }
1146 }
1147 }
Andrey Andreev24276a32012-01-08 02:44:38 +02001148
Derek Allard2067d1a2008-11-13 22:59:24 +00001149 return $this;
1150 }
1151
1152 // --------------------------------------------------------------------
1153
1154 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +02001155 * HAVING
Derek Allard2067d1a2008-11-13 22:59:24 +00001156 *
Andrey Andreevae85eb42012-11-02 01:42:31 +02001157 * Separates multiple calls with 'AND'.
Derek Allard2067d1a2008-11-13 22:59:24 +00001158 *
Andrey Andreevae85eb42012-11-02 01:42:31 +02001159 * @param string $key
1160 * @param string $value
1161 * @param bool $escape
Andrey Andreevaec51262016-02-09 21:11:07 +02001162 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +00001163 */
Andrey Andreev0bcf5902012-10-12 13:03:29 +03001164 public function having($key, $value = NULL, $escape = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +00001165 {
Andrey Andreevd40459d2012-07-18 16:46:39 +03001166 return $this->_wh('qb_having', $key, $value, 'AND ', $escape);
Derek Allard2067d1a2008-11-13 22:59:24 +00001167 }
Barry Mienydd671972010-10-04 16:33:58 +02001168
Derek Allard2067d1a2008-11-13 22:59:24 +00001169 // --------------------------------------------------------------------
1170
1171 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +02001172 * OR HAVING
Derek Allard2067d1a2008-11-13 22:59:24 +00001173 *
Andrey Andreevae85eb42012-11-02 01:42:31 +02001174 * Separates multiple calls with 'OR'.
Derek Allard2067d1a2008-11-13 22:59:24 +00001175 *
Andrey Andreevae85eb42012-11-02 01:42:31 +02001176 * @param string $key
1177 * @param string $value
1178 * @param bool $escape
Andrey Andreevaec51262016-02-09 21:11:07 +02001179 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +00001180 */
Andrey Andreev0bcf5902012-10-12 13:03:29 +03001181 public function or_having($key, $value = NULL, $escape = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +00001182 {
Andrey Andreevd40459d2012-07-18 16:46:39 +03001183 return $this->_wh('qb_having', $key, $value, 'OR ', $escape);
Derek Allard2067d1a2008-11-13 22:59:24 +00001184 }
Barry Mienydd671972010-10-04 16:33:58 +02001185
Derek Allard2067d1a2008-11-13 22:59:24 +00001186 // --------------------------------------------------------------------
1187
1188 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +02001189 * ORDER BY
Derek Allard2067d1a2008-11-13 22:59:24 +00001190 *
Andrey Andreevae85eb42012-11-02 01:42:31 +02001191 * @param string $orderby
vlakoff9f8e2992013-09-08 14:05:04 +02001192 * @param string $direction ASC, DESC or RANDOM
Andrey Andreevae85eb42012-11-02 01:42:31 +02001193 * @param bool $escape
Andrew Podner4296a652012-12-17 07:51:15 -05001194 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +00001195 */
Andrey Andreevd24160c2012-06-16 03:21:20 +03001196 public function order_by($orderby, $direction = '', $escape = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +00001197 {
Andrey Andreev98e46cf2012-11-13 03:01:42 +02001198 $direction = strtoupper(trim($direction));
Andrey Andreev2d486232012-07-19 14:46:51 +03001199
Andrey Andreev98e46cf2012-11-13 03:01:42 +02001200 if ($direction === 'RANDOM')
Derek Allard2067d1a2008-11-13 22:59:24 +00001201 {
Andrey Andreev2d486232012-07-19 14:46:51 +03001202 $direction = '';
Andrey Andreev98e46cf2012-11-13 03:01:42 +02001203
1204 // Do we have a seed value?
1205 $orderby = ctype_digit((string) $orderby)
vlakoffe6c4d5b2013-09-08 13:54:57 +02001206 ? sprintf($this->_random_keyword[1], $orderby)
Andrey Andreev98e46cf2012-11-13 03:01:42 +02001207 : $this->_random_keyword[0];
Derek Allard2067d1a2008-11-13 22:59:24 +00001208 }
Andrey Andreev2d486232012-07-19 14:46:51 +03001209 elseif (empty($orderby))
Derek Allard2067d1a2008-11-13 22:59:24 +00001210 {
Andrey Andreev2d486232012-07-19 14:46:51 +03001211 return $this;
1212 }
1213 elseif ($direction !== '')
1214 {
Andrey Andreev98e46cf2012-11-13 03:01:42 +02001215 $direction = in_array($direction, array('ASC', 'DESC'), TRUE) ? ' '.$direction : '';
Derek Allard2067d1a2008-11-13 22:59:24 +00001216 }
Barry Mienydd671972010-10-04 16:33:58 +02001217
Andrey Andreevd24160c2012-06-16 03:21:20 +03001218 is_bool($escape) OR $escape = $this->_protect_identifiers;
Barry Mienydd671972010-10-04 16:33:58 +02001219
Andrey Andreev2d486232012-07-19 14:46:51 +03001220 if ($escape === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001221 {
Andrey Andreev93dd2f22012-10-24 10:09:18 +03001222 $qb_orderby[] = array('field' => $orderby, 'direction' => $direction, 'escape' => FALSE);
Andrey Andreev2d486232012-07-19 14:46:51 +03001223 }
1224 else
1225 {
1226 $qb_orderby = array();
1227 foreach (explode(',', $orderby) as $field)
Derek Allard2067d1a2008-11-13 22:59:24 +00001228 {
Andrey Andreev2d486232012-07-19 14:46:51 +03001229 $qb_orderby[] = ($direction === '' && preg_match('/\s+(ASC|DESC)$/i', rtrim($field), $match, PREG_OFFSET_CAPTURE))
1230 ? array('field' => ltrim(substr($field, 0, $match[0][1])), 'direction' => ' '.$match[1][0], 'escape' => TRUE)
1231 : array('field' => trim($field), 'direction' => $direction, 'escape' => TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +00001232 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001233 }
Barry Mienydd671972010-10-04 16:33:58 +02001234
Andrey Andreev2d486232012-07-19 14:46:51 +03001235 $this->qb_orderby = array_merge($this->qb_orderby, $qb_orderby);
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001236 if ($this->qb_caching === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001237 {
Andrey Andreev2d486232012-07-19 14:46:51 +03001238 $this->qb_cache_orderby = array_merge($this->qb_cache_orderby, $qb_orderby);
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001239 $this->qb_cache_exists[] = 'orderby';
Derek Allard2067d1a2008-11-13 22:59:24 +00001240 }
1241
1242 return $this;
1243 }
Barry Mienydd671972010-10-04 16:33:58 +02001244
Derek Allard2067d1a2008-11-13 22:59:24 +00001245 // --------------------------------------------------------------------
1246
1247 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +02001248 * LIMIT
Derek Allard2067d1a2008-11-13 22:59:24 +00001249 *
Andrey Andreevae85eb42012-11-02 01:42:31 +02001250 * @param int $value LIMIT value
1251 * @param int $offset OFFSET value
Andrew Podner4296a652012-12-17 07:51:15 -05001252 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +00001253 */
Andrey Andreev4a587f52014-12-11 16:27:15 +02001254 public function limit($value, $offset = 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001255 {
vlakoff912f1bc2013-01-15 03:34:12 +01001256 is_null($value) OR $this->qb_limit = (int) $value;
Andrey Andreev777153d2012-06-18 13:30:45 +03001257 empty($offset) OR $this->qb_offset = (int) $offset;
Barry Mienydd671972010-10-04 16:33:58 +02001258
Derek Allard2067d1a2008-11-13 22:59:24 +00001259 return $this;
1260 }
Barry Mienydd671972010-10-04 16:33:58 +02001261
Derek Allard2067d1a2008-11-13 22:59:24 +00001262 // --------------------------------------------------------------------
1263
1264 /**
1265 * Sets the OFFSET value
1266 *
Andrey Andreevae85eb42012-11-02 01:42:31 +02001267 * @param int $offset OFFSET value
Andrew Podner4296a652012-12-17 07:51:15 -05001268 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +00001269 */
Phil Sturgeon9789f322011-07-15 15:14:05 -06001270 public function offset($offset)
Derek Allard2067d1a2008-11-13 22:59:24 +00001271 {
Andrey Andreev777153d2012-06-18 13:30:45 +03001272 empty($offset) OR $this->qb_offset = (int) $offset;
Derek Allard2067d1a2008-11-13 22:59:24 +00001273 return $this;
1274 }
Barry Mienydd671972010-10-04 16:33:58 +02001275
Derek Allard2067d1a2008-11-13 22:59:24 +00001276 // --------------------------------------------------------------------
1277
1278 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +02001279 * LIMIT string
Andrey Andreev2c35b642012-06-24 03:05:26 +03001280 *
Andrey Andreevae85eb42012-11-02 01:42:31 +02001281 * Generates a platform-specific LIMIT clause.
Andrey Andreev2c35b642012-06-24 03:05:26 +03001282 *
Andrey Andreevae85eb42012-11-02 01:42:31 +02001283 * @param string $sql SQL Query
Andrey Andreev2c35b642012-06-24 03:05:26 +03001284 * @return string
1285 */
Andrey Andreevc9b924c2012-07-19 13:06:02 +03001286 protected function _limit($sql)
Andrey Andreev2c35b642012-06-24 03:05:26 +03001287 {
Andrey Andreevacc64812016-07-29 11:42:28 +03001288 return $sql.' LIMIT '.($this->qb_offset ? $this->qb_offset.', ' : '').(int) $this->qb_limit;
Andrey Andreev2c35b642012-06-24 03:05:26 +03001289 }
1290
1291 // --------------------------------------------------------------------
1292
1293 /**
Andrey Andreevfe642da2012-06-16 03:47:33 +03001294 * The "set" function.
1295 *
1296 * Allows key/value pairs to be set for inserting or updating
Derek Allard2067d1a2008-11-13 22:59:24 +00001297 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001298 * @param mixed
1299 * @param string
Andrey Andreeva8bb4be2012-03-26 15:54:23 +03001300 * @param bool
Andrew Podner4296a652012-12-17 07:51:15 -05001301 * @return CI_DB_query_builder
Derek Allard2067d1a2008-11-13 22:59:24 +00001302 */
Andrey Andreevfe642da2012-06-16 03:47:33 +03001303 public function set($key, $value = '', $escape = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +00001304 {
1305 $key = $this->_object_to_array($key);
Barry Mienydd671972010-10-04 16:33:58 +02001306
Derek Allard2067d1a2008-11-13 22:59:24 +00001307 if ( ! is_array($key))
1308 {
1309 $key = array($key => $value);
Barry Mienydd671972010-10-04 16:33:58 +02001310 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001311
Andrey Andreevfe642da2012-06-16 03:47:33 +03001312 is_bool($escape) OR $escape = $this->_protect_identifiers;
1313
Derek Allard2067d1a2008-11-13 22:59:24 +00001314 foreach ($key as $k => $v)
1315 {
Andrey Andreev2dfbe992015-07-27 21:54:18 +03001316 $this->qb_set[$this->protect_identifiers($k, FALSE, $escape)] = ($escape)
1317 ? $this->escape($v) : $v;
Derek Allard2067d1a2008-11-13 22:59:24 +00001318 }
Barry Mienydd671972010-10-04 16:33:58 +02001319
Derek Allard2067d1a2008-11-13 22:59:24 +00001320 return $this;
1321 }
WanWizard7219c072011-12-28 14:09:05 +01001322
Kyle Farris0c147b32011-08-26 02:29:31 -04001323 // --------------------------------------------------------------------
1324
1325 /**
1326 * Get SELECT query string
1327 *
1328 * Compiles a SELECT query string and returns the sql.
1329 *
Kyle Farris0c147b32011-08-26 02:29:31 -04001330 * @param string the table name to select from (optional)
Calvin Tam55bc5052015-07-24 02:27:24 -07001331 * @param bool TRUE: resets QB values; FALSE: leave QB values alone
Kyle Farris0c147b32011-08-26 02:29:31 -04001332 * @return string
1333 */
WanWizard7219c072011-12-28 14:09:05 +01001334 public function get_compiled_select($table = '', $reset = TRUE)
Kyle Farris0c147b32011-08-26 02:29:31 -04001335 {
Alex Bilbie48a2baf2012-06-02 11:09:54 +01001336 if ($table !== '')
kylefarris0a3176b2011-08-26 02:37:52 -04001337 {
Kyle Farris0c147b32011-08-26 02:29:31 -04001338 $this->_track_aliases($table);
1339 $this->from($table);
1340 }
WanWizard7219c072011-12-28 14:09:05 +01001341
Andrey Andreev650b4c02012-06-11 12:07:15 +03001342 $select = $this->_compile_select();
WanWizard7219c072011-12-28 14:09:05 +01001343
Kyle Farris0c147b32011-08-26 02:29:31 -04001344 if ($reset === TRUE)
1345 {
1346 $this->_reset_select();
1347 }
WanWizard7219c072011-12-28 14:09:05 +01001348
Kyle Farris0c147b32011-08-26 02:29:31 -04001349 return $select;
1350 }
WanWizard7219c072011-12-28 14:09:05 +01001351
Derek Allard2067d1a2008-11-13 22:59:24 +00001352 // --------------------------------------------------------------------
1353
1354 /**
1355 * Get
1356 *
1357 * Compiles the select statement based on the other functions called
1358 * and runs the query
1359 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001360 * @param string the table
1361 * @param string the limit clause
1362 * @param string the offset clause
Andrey Andreevaec51262016-02-09 21:11:07 +02001363 * @return CI_DB_result
Derek Allard2067d1a2008-11-13 22:59:24 +00001364 */
Andrey Andreev650b4c02012-06-11 12:07:15 +03001365 public function get($table = '', $limit = NULL, $offset = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +00001366 {
Alex Bilbie48a2baf2012-06-02 11:09:54 +01001367 if ($table !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001368 {
1369 $this->_track_aliases($table);
1370 $this->from($table);
1371 }
Barry Mienydd671972010-10-04 16:33:58 +02001372
Andrey Andreev650b4c02012-06-11 12:07:15 +03001373 if ( ! empty($limit))
Derek Allard2067d1a2008-11-13 22:59:24 +00001374 {
1375 $this->limit($limit, $offset);
1376 }
Barry Mienydd671972010-10-04 16:33:58 +02001377
Andrey Andreev24276a32012-01-08 02:44:38 +02001378 $result = $this->query($this->_compile_select());
Derek Allard2067d1a2008-11-13 22:59:24 +00001379 $this->_reset_select();
1380 return $result;
1381 }
1382
Andrey Andreev7b5eb732012-05-24 20:52:41 +03001383 // --------------------------------------------------------------------
1384
Derek Allard2067d1a2008-11-13 22:59:24 +00001385 /**
1386 * "Count All Results" query
1387 *
Barry Mienydd671972010-10-04 16:33:58 +02001388 * Generates a platform-specific query string that counts all records
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001389 * returned by an Query Builder query.
Derek Allard2067d1a2008-11-13 22:59:24 +00001390 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001391 * @param string
yaoshanliang2f164052015-03-16 16:48:15 +08001392 * @param bool the reset clause
vlakoffc6ac7482013-11-17 00:50:06 +01001393 * @return int
Derek Allard2067d1a2008-11-13 22:59:24 +00001394 */
yaoshanliang19c28472015-03-15 10:42:18 +08001395 public function count_all_results($table = '', $reset = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001396 {
Alex Bilbie48a2baf2012-06-02 11:09:54 +01001397 if ($table !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001398 {
1399 $this->_track_aliases($table);
1400 $this->from($table);
1401 }
Barry Mienydd671972010-10-04 16:33:58 +02001402
Andrey Andreev075bdb42016-01-25 13:31:23 +02001403 // ORDER BY usage is often problematic here (most notably
1404 // on Microsoft SQL Server) and ultimately unnecessary
1405 // for selecting COUNT(*) ...
Andrey Andreev71a78c22017-07-10 14:51:08 +03001406 $qb_orderby = $this->qb_orderby;
Andrey Andreev59bae572017-07-03 14:13:08 +03001407 $qb_cache_orderby = $this->qb_cache_orderby;
pgee70cf3924e2017-10-03 10:09:04 +11001408 $this->qb_orderby = $this->qb_cache_orderby = array();
Andrey Andreev075bdb42016-01-25 13:31:23 +02001409
Andrey Andreev2c1b3d92017-06-15 14:22:49 +03001410 $result = ($this->qb_distinct === TRUE OR ! empty($this->qb_groupby) OR ! empty($this->qb_cache_groupby) OR $this->qb_limit OR $this->qb_offset)
Andrey Andreevb05f5062012-10-26 12:01:02 +03001411 ? $this->query($this->_count_string.$this->protect_identifiers('numrows')."\nFROM (\n".$this->_compile_select()."\n) CI_count_all_results")
1412 : $this->query($this->_compile_select($this->_count_string.$this->protect_identifiers('numrows')));
yaoshanliang9971e7b2015-03-14 13:09:16 +08001413
yaoshanliang2f164052015-03-16 16:48:15 +08001414 if ($reset === TRUE)
yaoshanliang19c28472015-03-15 10:42:18 +08001415 {
yaoshanliang2f164052015-03-16 16:48:15 +08001416 $this->_reset_select();
yaoshanliang19c28472015-03-15 10:42:18 +08001417 }
Andrey Andreev59bae572017-07-03 14:13:08 +03001418 else
Andrey Andreev075bdb42016-01-25 13:31:23 +02001419 {
Andrey Andreev59bae572017-07-03 14:13:08 +03001420 $this->qb_orderby = $qb_orderby;
1421 $this->qb_cache_orderby = $qb_cache_orderby;
Andrey Andreev075bdb42016-01-25 13:31:23 +02001422 }
Barry Mienydd671972010-10-04 16:33:58 +02001423
Purwandi1d160e72012-01-09 16:33:28 +07001424 if ($result->num_rows() === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001425 {
Phil Sturgeonaf6f3442011-03-22 19:12:23 +00001426 return 0;
Derek Allard2067d1a2008-11-13 22:59:24 +00001427 }
1428
Purwandi1d160e72012-01-09 16:33:28 +07001429 $row = $result->row();
Phil Sturgeonaf6f3442011-03-22 19:12:23 +00001430 return (int) $row->numrows;
Derek Allard2067d1a2008-11-13 22:59:24 +00001431 }
Andrey Andreev7b5eb732012-05-24 20:52:41 +03001432
Derek Allard2067d1a2008-11-13 22:59:24 +00001433 // --------------------------------------------------------------------
1434
1435 /**
1436 * Get_Where
1437 *
1438 * Allows the where clause, limit and offset to be added directly
1439 *
Andrey Andreevae85eb42012-11-02 01:42:31 +02001440 * @param string $table
1441 * @param string $where
1442 * @param int $limit
1443 * @param int $offset
Andrey Andreevaec51262016-02-09 21:11:07 +02001444 * @return CI_DB_result
Derek Allard2067d1a2008-11-13 22:59:24 +00001445 */
Andrey Andreeveb22d542012-06-26 23:16:35 +03001446 public function get_where($table = '', $where = NULL, $limit = NULL, $offset = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +00001447 {
Alex Bilbie48a2baf2012-06-02 11:09:54 +01001448 if ($table !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001449 {
1450 $this->from($table);
1451 }
1452
vlakoff1228fe22013-01-14 01:30:09 +01001453 if ($where !== NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +00001454 {
1455 $this->where($where);
1456 }
Barry Mienydd671972010-10-04 16:33:58 +02001457
Andrey Andreev650b4c02012-06-11 12:07:15 +03001458 if ( ! empty($limit))
Derek Allard2067d1a2008-11-13 22:59:24 +00001459 {
1460 $this->limit($limit, $offset);
1461 }
Barry Mienydd671972010-10-04 16:33:58 +02001462
Andrey Andreev24276a32012-01-08 02:44:38 +02001463 $result = $this->query($this->_compile_select());
Derek Allard2067d1a2008-11-13 22:59:24 +00001464 $this->_reset_select();
1465 return $result;
1466 }
1467
1468 // --------------------------------------------------------------------
1469
1470 /**
Derek Jonesd10e8962010-03-02 17:10:36 -06001471 * Insert_Batch
1472 *
1473 * Compiles batch insert strings and runs the queries
1474 *
Andrey Andreevae85eb42012-11-02 01:42:31 +02001475 * @param string $table Table to insert into
1476 * @param array $set An associative array of insert values
Andrey Andreevbdd9c112012-11-06 12:07:16 +02001477 * @param bool $escape Whether to escape values and identifiers
Andrey Andreevae85eb42012-11-02 01:42:31 +02001478 * @return int Number of rows inserted or FALSE on failure
Derek Jonesd10e8962010-03-02 17:10:36 -06001479 */
Andrey Andreev105a48b2016-02-04 15:45:10 +02001480 public function insert_batch($table, $set = NULL, $escape = NULL, $batch_size = 100)
Barry Mienydd671972010-10-04 16:33:58 +02001481 {
Andrey Andreev8ec82e22016-01-26 16:33:31 +02001482 if ($set === NULL)
Derek Jonesd10e8962010-03-02 17:10:36 -06001483 {
Andrey Andreev8ec82e22016-01-26 16:33:31 +02001484 if (empty($this->qb_set))
1485 {
1486 return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE;
1487 }
1488 }
1489 else
1490 {
1491 if (empty($set))
1492 {
1493 return ($this->db_debug) ? $this->display_error('insert_batch() called with no data') : FALSE;
1494 }
1495
Andrey Andreevbdd9c112012-11-06 12:07:16 +02001496 $this->set_insert_batch($set, '', $escape);
Derek Jonesd10e8962010-03-02 17:10:36 -06001497 }
Barry Mienydd671972010-10-04 16:33:58 +02001498
Andrey Andreev8ec82e22016-01-26 16:33:31 +02001499 if (strlen($table) === 0)
Derek Jonesd10e8962010-03-02 17:10:36 -06001500 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001501 if ( ! isset($this->qb_from[0]))
Derek Jonesd10e8962010-03-02 17:10:36 -06001502 {
Andrey Andreev24276a32012-01-08 02:44:38 +02001503 return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;
Derek Jonesd10e8962010-03-02 17:10:36 -06001504 }
Barry Mienydd671972010-10-04 16:33:58 +02001505
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001506 $table = $this->qb_from[0];
Derek Jonesd10e8962010-03-02 17:10:36 -06001507 }
1508
1509 // Batch this baby
Andrey Andreev9f808b02012-10-24 17:38:48 +03001510 $affected_rows = 0;
Andrey Andreev105a48b2016-02-04 15:45:10 +02001511 for ($i = 0, $total = count($this->qb_set); $i < $total; $i += $batch_size)
Derek Jonesd10e8962010-03-02 17:10:36 -06001512 {
Andrey Andreevd9a40632016-07-22 15:49:08 +03001513 if ($this->query($this->_insert_batch($this->protect_identifiers($table, TRUE, $escape, FALSE), $this->qb_keys, array_slice($this->qb_set, $i, $batch_size))))
1514 {
1515 $affected_rows += $this->affected_rows();
1516 }
Derek Jonesd10e8962010-03-02 17:10:36 -06001517 }
Barry Mienydd671972010-10-04 16:33:58 +02001518
Derek Jonesd10e8962010-03-02 17:10:36 -06001519 $this->_reset_write();
Andrey Andreev9f808b02012-10-24 17:38:48 +03001520 return $affected_rows;
Derek Jonesd10e8962010-03-02 17:10:36 -06001521 }
1522
1523 // --------------------------------------------------------------------
1524
1525 /**
Andrey Andreev083e3c82012-11-06 12:48:32 +02001526 * Insert batch statement
Andrey Andreev97f36972012-04-05 12:44:36 +03001527 *
1528 * Generates a platform-specific insert string from the supplied data.
1529 *
Andrey Andreev083e3c82012-11-06 12:48:32 +02001530 * @param string $table Table name
1531 * @param array $keys INSERT keys
1532 * @param array $values INSERT values
Andrey Andreeva3bca8f2012-04-05 15:17:25 +03001533 * @return string
Andrey Andreev97f36972012-04-05 12:44:36 +03001534 */
1535 protected function _insert_batch($table, $keys, $values)
1536 {
Andrey Andreev65d537c2012-04-05 14:11:41 +03001537 return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES '.implode(', ', $values);
Andrey Andreev97f36972012-04-05 12:44:36 +03001538 }
1539
1540 // --------------------------------------------------------------------
1541
1542 /**
Derek Jones37f4b9c2011-07-01 17:56:50 -05001543 * The "set_insert_batch" function. Allows key/value pairs to be set for batch inserts
Derek Jonesd10e8962010-03-02 17:10:36 -06001544 *
Derek Jonesd10e8962010-03-02 17:10:36 -06001545 * @param mixed
1546 * @param string
Andrey Andreeva8bb4be2012-03-26 15:54:23 +03001547 * @param bool
Andrew Podner4296a652012-12-17 07:51:15 -05001548 * @return CI_DB_query_builder
Derek Jonesd10e8962010-03-02 17:10:36 -06001549 */
Andrey Andreevfe642da2012-06-16 03:47:33 +03001550 public function set_insert_batch($key, $value = '', $escape = NULL)
Derek Jonesd10e8962010-03-02 17:10:36 -06001551 {
1552 $key = $this->_object_to_array_batch($key);
Barry Mienydd671972010-10-04 16:33:58 +02001553
Derek Jonesd10e8962010-03-02 17:10:36 -06001554 if ( ! is_array($key))
1555 {
1556 $key = array($key => $value);
Barry Mienydd671972010-10-04 16:33:58 +02001557 }
Derek Jonesd10e8962010-03-02 17:10:36 -06001558
Andrey Andreevfe642da2012-06-16 03:47:33 +03001559 is_bool($escape) OR $escape = $this->_protect_identifiers;
1560
Andrey Andreev51c84f32017-01-03 17:42:26 +02001561 $keys = array_keys($this->_object_to_array(reset($key)));
Derek Jonesd10e8962010-03-02 17:10:36 -06001562 sort($keys);
1563
1564 foreach ($key as $row)
1565 {
Iban Eguia3c0a4522012-04-15 13:30:44 +02001566 $row = $this->_object_to_array($row);
Barry Mienydd671972010-10-04 16:33:58 +02001567 if (count(array_diff($keys, array_keys($row))) > 0 OR count(array_diff(array_keys($row), $keys)) > 0)
1568 {
1569 // batch function above returns an error on an empty array
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001570 $this->qb_set[] = array();
Barry Mienydd671972010-10-04 16:33:58 +02001571 return;
1572 }
Phil Sturgeond0ac1a22011-02-15 22:54:08 +00001573
Barry Mienydd671972010-10-04 16:33:58 +02001574 ksort($row); // puts $row in the same order as our keys
1575
Andrey Andreev2dfbe992015-07-27 21:54:18 +03001576 if ($escape !== FALSE)
Derek Jonesd10e8962010-03-02 17:10:36 -06001577 {
Andrey Andreev2dfbe992015-07-27 21:54:18 +03001578 $clean = array();
1579 foreach ($row as $value)
1580 {
1581 $clean[] = $this->escape($value);
1582 }
1583
1584 $row = $clean;
Barry Mienydd671972010-10-04 16:33:58 +02001585 }
Andrey Andreev650b4c02012-06-11 12:07:15 +03001586
Andrey Andreev838a9d62012-12-03 14:37:47 +02001587 $this->qb_set[] = '('.implode(',', $row).')';
Derek Jonesd10e8962010-03-02 17:10:36 -06001588 }
1589
1590 foreach ($keys as $k)
1591 {
Andrey Andreevfe642da2012-06-16 03:47:33 +03001592 $this->qb_keys[] = $this->protect_identifiers($k, FALSE, $escape);
Derek Jonesd10e8962010-03-02 17:10:36 -06001593 }
Barry Mienydd671972010-10-04 16:33:58 +02001594
Derek Jonesd10e8962010-03-02 17:10:36 -06001595 return $this;
1596 }
WanWizard7219c072011-12-28 14:09:05 +01001597
Kyle Farris0c147b32011-08-26 02:29:31 -04001598 // --------------------------------------------------------------------
1599
1600 /**
1601 * Get INSERT query string
1602 *
1603 * Compiles an insert query and returns the sql
1604 *
Kyle Farris0c147b32011-08-26 02:29:31 -04001605 * @param string the table to insert into
Jamie Rumbelowd6ce1e92012-04-26 13:27:35 +01001606 * @param bool TRUE: reset QB values; FALSE: leave QB values alone
Kyle Farris0c147b32011-08-26 02:29:31 -04001607 * @return string
1608 */
1609 public function get_compiled_insert($table = '', $reset = TRUE)
WanWizard7219c072011-12-28 14:09:05 +01001610 {
Kyle Farris0c147b32011-08-26 02:29:31 -04001611 if ($this->_validate_insert($table) === FALSE)
1612 {
1613 return FALSE;
1614 }
WanWizard7219c072011-12-28 14:09:05 +01001615
Kyle Farris76116012011-08-31 11:17:48 -04001616 $sql = $this->_insert(
Jamie Rumbelow0c092992012-03-06 22:05:16 +00001617 $this->protect_identifiers(
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001618 $this->qb_from[0], TRUE, NULL, FALSE
Kyle Farris76116012011-08-31 11:17:48 -04001619 ),
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001620 array_keys($this->qb_set),
1621 array_values($this->qb_set)
Kyle Farris76116012011-08-31 11:17:48 -04001622 );
WanWizard7219c072011-12-28 14:09:05 +01001623
Kyle Farris0c147b32011-08-26 02:29:31 -04001624 if ($reset === TRUE)
1625 {
1626 $this->_reset_write();
1627 }
WanWizard7219c072011-12-28 14:09:05 +01001628
Kyle Farris0c147b32011-08-26 02:29:31 -04001629 return $sql;
1630 }
Derek Jonesd10e8962010-03-02 17:10:36 -06001631
Derek Allard2067d1a2008-11-13 22:59:24 +00001632 // --------------------------------------------------------------------
1633
1634 /**
1635 * Insert
1636 *
1637 * Compiles an insert string and runs the query
1638 *
Phil Sturgeon9789f322011-07-15 15:14:05 -06001639 * @param string the table to insert data into
Derek Allard2067d1a2008-11-13 22:59:24 +00001640 * @param array an associative array of insert values
Andrey Andreevbdd9c112012-11-06 12:07:16 +02001641 * @param bool $escape Whether to escape values and identifiers
Andrey Andreevaec51262016-02-09 21:11:07 +02001642 * @return bool TRUE on success, FALSE on failure
Derek Allard2067d1a2008-11-13 22:59:24 +00001643 */
Andrey Andreevbdd9c112012-11-06 12:07:16 +02001644 public function insert($table = '', $set = NULL, $escape = NULL)
Barry Mienydd671972010-10-04 16:33:58 +02001645 {
vlakoff1228fe22013-01-14 01:30:09 +01001646 if ($set !== NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +00001647 {
Andrey Andreevbdd9c112012-11-06 12:07:16 +02001648 $this->set($set, '', $escape);
Derek Allard2067d1a2008-11-13 22:59:24 +00001649 }
WanWizard7219c072011-12-28 14:09:05 +01001650
Kyle Farris0c147b32011-08-26 02:29:31 -04001651 if ($this->_validate_insert($table) === FALSE)
1652 {
1653 return FALSE;
1654 }
WanWizard7219c072011-12-28 14:09:05 +01001655
Kyle Farris76116012011-08-31 11:17:48 -04001656 $sql = $this->_insert(
Jamie Rumbelow0c092992012-03-06 22:05:16 +00001657 $this->protect_identifiers(
Andrey Andreevbdd9c112012-11-06 12:07:16 +02001658 $this->qb_from[0], TRUE, $escape, FALSE
WanWizard7219c072011-12-28 14:09:05 +01001659 ),
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001660 array_keys($this->qb_set),
1661 array_values($this->qb_set)
Kyle Farris76116012011-08-31 11:17:48 -04001662 );
Barry Mienydd671972010-10-04 16:33:58 +02001663
Kyle Farris0c147b32011-08-26 02:29:31 -04001664 $this->_reset_write();
1665 return $this->query($sql);
1666 }
WanWizard7219c072011-12-28 14:09:05 +01001667
Kyle Farris0c147b32011-08-26 02:29:31 -04001668 // --------------------------------------------------------------------
1669
1670 /**
1671 * Validate Insert
1672 *
1673 * This method is used by both insert() and get_compiled_insert() to
1674 * validate that the there data is actually being set and that table
1675 * has been chosen to be inserted into.
1676 *
Kyle Farris0c147b32011-08-26 02:29:31 -04001677 * @param string the table to insert data into
1678 * @return string
1679 */
WanWizard7219c072011-12-28 14:09:05 +01001680 protected function _validate_insert($table = '')
Kyle Farris0c147b32011-08-26 02:29:31 -04001681 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001682 if (count($this->qb_set) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001683 {
Andrey Andreev24276a32012-01-08 02:44:38 +02001684 return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +00001685 }
1686
Alex Bilbie48a2baf2012-06-02 11:09:54 +01001687 if ($table !== '')
Kyle Farris0c147b32011-08-26 02:29:31 -04001688 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001689 $this->qb_from[0] = $table;
Kyle Farris0c147b32011-08-26 02:29:31 -04001690 }
Andrey Andreev7b5eb732012-05-24 20:52:41 +03001691 elseif ( ! isset($this->qb_from[0]))
1692 {
1693 return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;
1694 }
WanWizard7219c072011-12-28 14:09:05 +01001695
Kyle Farris0c147b32011-08-26 02:29:31 -04001696 return TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +00001697 }
Barry Mienydd671972010-10-04 16:33:58 +02001698
Phil Sturgeon9789f322011-07-15 15:14:05 -06001699 // --------------------------------------------------------------------
1700
1701 /**
1702 * Replace
1703 *
1704 * Compiles an replace into string and runs the query
1705 *
1706 * @param string the table to replace data into
1707 * @param array an associative array of insert values
Andrey Andreevaec51262016-02-09 21:11:07 +02001708 * @return bool TRUE on success, FALSE on failure
Phil Sturgeon9789f322011-07-15 15:14:05 -06001709 */
1710 public function replace($table = '', $set = NULL)
Derek Jonesd10e8962010-03-02 17:10:36 -06001711 {
vlakoff1228fe22013-01-14 01:30:09 +01001712 if ($set !== NULL)
Derek Jonesd10e8962010-03-02 17:10:36 -06001713 {
1714 $this->set($set);
1715 }
Barry Mienydd671972010-10-04 16:33:58 +02001716
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001717 if (count($this->qb_set) === 0)
Derek Jonesd10e8962010-03-02 17:10:36 -06001718 {
Andrey Andreev24276a32012-01-08 02:44:38 +02001719 return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE;
Derek Jonesd10e8962010-03-02 17:10:36 -06001720 }
1721
Alex Bilbie48a2baf2012-06-02 11:09:54 +01001722 if ($table === '')
Derek Jonesd10e8962010-03-02 17:10:36 -06001723 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001724 if ( ! isset($this->qb_from[0]))
Derek Jonesd10e8962010-03-02 17:10:36 -06001725 {
Andrey Andreev24276a32012-01-08 02:44:38 +02001726 return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;
Derek Jonesd10e8962010-03-02 17:10:36 -06001727 }
Barry Mienydd671972010-10-04 16:33:58 +02001728
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001729 $table = $this->qb_from[0];
Derek Jonesd10e8962010-03-02 17:10:36 -06001730 }
1731
Jamie Rumbelow0c092992012-03-06 22:05:16 +00001732 $sql = $this->_replace($this->protect_identifiers($table, TRUE, NULL, FALSE), array_keys($this->qb_set), array_values($this->qb_set));
Jamie Rumbelow3b1355c2012-03-06 21:27:46 +00001733
Derek Jonesd10e8962010-03-02 17:10:36 -06001734 $this->_reset_write();
Barry Mienydd671972010-10-04 16:33:58 +02001735 return $this->query($sql);
Derek Jonesd10e8962010-03-02 17:10:36 -06001736 }
WanWizard7219c072011-12-28 14:09:05 +01001737
Kyle Farris0c147b32011-08-26 02:29:31 -04001738 // --------------------------------------------------------------------
Derek Jonesd10e8962010-03-02 17:10:36 -06001739
Kyle Farris0c147b32011-08-26 02:29:31 -04001740 /**
Andrey Andreeva3bca8f2012-04-05 15:17:25 +03001741 * Replace statement
1742 *
1743 * Generates a platform-specific replace string from the supplied data
1744 *
1745 * @param string the table name
1746 * @param array the insert keys
1747 * @param array the insert values
1748 * @return string
1749 */
1750 protected function _replace($table, $keys, $values)
1751 {
1752 return 'REPLACE INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
1753 }
1754
1755 // --------------------------------------------------------------------
1756
1757 /**
Andrey Andreev7eaa14f2012-10-09 11:34:01 +03001758 * FROM tables
Andrey Andreevc78e56a2012-06-08 02:12:07 +03001759 *
Andrey Andreev7eaa14f2012-10-09 11:34:01 +03001760 * Groups tables in FROM clauses if needed, so there is no confusion
1761 * about operator precedence.
Andrey Andreevc78e56a2012-06-08 02:12:07 +03001762 *
Claudio Galdiolo93e78132015-01-29 11:43:56 -05001763 * Note: This is only used (and overridden) by MySQL and CUBRID.
Andrey Andreev7eaa14f2012-10-09 11:34:01 +03001764 *
1765 * @return string
Andrey Andreevc78e56a2012-06-08 02:12:07 +03001766 */
Andrey Andreev7eaa14f2012-10-09 11:34:01 +03001767 protected function _from_tables()
Andrey Andreevc78e56a2012-06-08 02:12:07 +03001768 {
Andrey Andreev7eaa14f2012-10-09 11:34:01 +03001769 return implode(', ', $this->qb_from);
Andrey Andreevc78e56a2012-06-08 02:12:07 +03001770 }
1771
1772 // --------------------------------------------------------------------
1773
1774 /**
Kyle Farris0c147b32011-08-26 02:29:31 -04001775 * Get UPDATE query string
1776 *
1777 * Compiles an update query and returns the sql
1778 *
Kyle Farris0c147b32011-08-26 02:29:31 -04001779 * @param string the table to update
Jamie Rumbelowd6ce1e92012-04-26 13:27:35 +01001780 * @param bool TRUE: reset QB values; FALSE: leave QB values alone
Kyle Farris0c147b32011-08-26 02:29:31 -04001781 * @return string
1782 */
1783 public function get_compiled_update($table = '', $reset = TRUE)
1784 {
1785 // Combine any cached components with the current statements
1786 $this->_merge_cache();
WanWizard7219c072011-12-28 14:09:05 +01001787
Kyle Farris0c147b32011-08-26 02:29:31 -04001788 if ($this->_validate_update($table) === FALSE)
1789 {
1790 return FALSE;
1791 }
WanWizard7219c072011-12-28 14:09:05 +01001792
Andrey Andreev4b9fec62015-07-20 17:26:31 +03001793 $sql = $this->_update($this->qb_from[0], $this->qb_set);
WanWizard7219c072011-12-28 14:09:05 +01001794
Kyle Farris0c147b32011-08-26 02:29:31 -04001795 if ($reset === TRUE)
1796 {
1797 $this->_reset_write();
1798 }
WanWizard7219c072011-12-28 14:09:05 +01001799
Kyle Farris0c147b32011-08-26 02:29:31 -04001800 return $sql;
1801 }
WanWizard7219c072011-12-28 14:09:05 +01001802
Derek Allard2067d1a2008-11-13 22:59:24 +00001803 // --------------------------------------------------------------------
1804
1805 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +02001806 * UPDATE
Derek Allard2067d1a2008-11-13 22:59:24 +00001807 *
Andrey Andreevae85eb42012-11-02 01:42:31 +02001808 * Compiles an update string and runs the query.
Derek Allard2067d1a2008-11-13 22:59:24 +00001809 *
Andrey Andreevae85eb42012-11-02 01:42:31 +02001810 * @param string $table
1811 * @param array $set An associative array of update values
1812 * @param mixed $where
1813 * @param int $limit
Andrey Andreevaec51262016-02-09 21:11:07 +02001814 * @return bool TRUE on success, FALSE on failure
Derek Allard2067d1a2008-11-13 22:59:24 +00001815 */
Phil Sturgeon9789f322011-07-15 15:14:05 -06001816 public function update($table = '', $set = NULL, $where = NULL, $limit = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +00001817 {
1818 // Combine any cached components with the current statements
1819 $this->_merge_cache();
1820
vlakoff1228fe22013-01-14 01:30:09 +01001821 if ($set !== NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +00001822 {
1823 $this->set($set);
1824 }
Barry Mienydd671972010-10-04 16:33:58 +02001825
Kyle Farris0c147b32011-08-26 02:29:31 -04001826 if ($this->_validate_update($table) === FALSE)
1827 {
1828 return FALSE;
1829 }
1830
Alex Bilbie48a2baf2012-06-02 11:09:54 +01001831 if ($where !== NULL)
Kyle Farris0c147b32011-08-26 02:29:31 -04001832 {
1833 $this->where($where);
1834 }
1835
Andrey Andreev650b4c02012-06-11 12:07:15 +03001836 if ( ! empty($limit))
Kyle Farris0c147b32011-08-26 02:29:31 -04001837 {
1838 $this->limit($limit);
1839 }
1840
Andrey Andreev4b9fec62015-07-20 17:26:31 +03001841 $sql = $this->_update($this->qb_from[0], $this->qb_set);
Kyle Farris0c147b32011-08-26 02:29:31 -04001842 $this->_reset_write();
1843 return $this->query($sql);
1844 }
WanWizard7219c072011-12-28 14:09:05 +01001845
Kyle Farris0c147b32011-08-26 02:29:31 -04001846 // --------------------------------------------------------------------
1847
1848 /**
1849 * Validate Update
1850 *
1851 * This method is used by both update() and get_compiled_update() to
1852 * validate that data is actually being set and that a table has been
1853 * chosen to be update.
1854 *
Kyle Farris0c147b32011-08-26 02:29:31 -04001855 * @param string the table to update data on
Andrey Andreev24276a32012-01-08 02:44:38 +02001856 * @return bool
Kyle Farris0c147b32011-08-26 02:29:31 -04001857 */
Andrey Andreev4b9fec62015-07-20 17:26:31 +03001858 protected function _validate_update($table)
Kyle Farris0c147b32011-08-26 02:29:31 -04001859 {
Alex Bilbie48a2baf2012-06-02 11:09:54 +01001860 if (count($this->qb_set) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001861 {
Andrey Andreev24276a32012-01-08 02:44:38 +02001862 return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +00001863 }
1864
Alex Bilbie48a2baf2012-06-02 11:09:54 +01001865 if ($table !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001866 {
Andrey Andreev4b9fec62015-07-20 17:26:31 +03001867 $this->qb_from = array($this->protect_identifiers($table, TRUE, NULL, FALSE));
Derek Allard2067d1a2008-11-13 22:59:24 +00001868 }
Andrey Andreev7b5eb732012-05-24 20:52:41 +03001869 elseif ( ! isset($this->qb_from[0]))
1870 {
1871 return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;
1872 }
Andrey Andreev24276a32012-01-08 02:44:38 +02001873
1874 return TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +00001875 }
WanWizard7219c072011-12-28 14:09:05 +01001876
Derek Jonesd10e8962010-03-02 17:10:36 -06001877 // --------------------------------------------------------------------
1878
1879 /**
1880 * Update_Batch
1881 *
1882 * Compiles an update string and runs the query
1883 *
Derek Jonesd10e8962010-03-02 17:10:36 -06001884 * @param string the table to retrieve the results from
1885 * @param array an associative array of update values
1886 * @param string the where key
Andrey Andreev9f808b02012-10-24 17:38:48 +03001887 * @return int number of rows affected or FALSE on failure
Derek Jonesd10e8962010-03-02 17:10:36 -06001888 */
Andrey Andreev105a48b2016-02-04 15:45:10 +02001889 public function update_batch($table, $set = NULL, $index = NULL, $batch_size = 100)
Derek Jonesd10e8962010-03-02 17:10:36 -06001890 {
1891 // Combine any cached components with the current statements
1892 $this->_merge_cache();
Barry Mienydd671972010-10-04 16:33:58 +02001893
vlakoff1228fe22013-01-14 01:30:09 +01001894 if ($index === NULL)
Derek Jonesd10e8962010-03-02 17:10:36 -06001895 {
Andrey Andreev24276a32012-01-08 02:44:38 +02001896 return ($this->db_debug) ? $this->display_error('db_must_use_index') : FALSE;
Derek Jonesd10e8962010-03-02 17:10:36 -06001897 }
1898
Andrey Andreev8ec82e22016-01-26 16:33:31 +02001899 if ($set === NULL)
Derek Jonesd10e8962010-03-02 17:10:36 -06001900 {
Andrey Andreev8338bbb2016-12-12 14:17:52 +02001901 if (empty($this->qb_set_ub))
Andrey Andreev8ec82e22016-01-26 16:33:31 +02001902 {
1903 return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE;
1904 }
1905 }
1906 else
1907 {
1908 if (empty($set))
1909 {
1910 return ($this->db_debug) ? $this->display_error('update_batch() called with no data') : FALSE;
1911 }
1912
Derek Jonesd10e8962010-03-02 17:10:36 -06001913 $this->set_update_batch($set, $index);
1914 }
1915
Andrey Andreev8ec82e22016-01-26 16:33:31 +02001916 if (strlen($table) === 0)
Derek Jonesd10e8962010-03-02 17:10:36 -06001917 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001918 if ( ! isset($this->qb_from[0]))
Derek Jonesd10e8962010-03-02 17:10:36 -06001919 {
Andrey Andreev24276a32012-01-08 02:44:38 +02001920 return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;
Derek Jonesd10e8962010-03-02 17:10:36 -06001921 }
Barry Mienydd671972010-10-04 16:33:58 +02001922
Jamie Rumbelow7efad202012-02-19 12:37:00 +00001923 $table = $this->qb_from[0];
Derek Jonesd10e8962010-03-02 17:10:36 -06001924 }
Barry Mienydd671972010-10-04 16:33:58 +02001925
Derek Jonesd10e8962010-03-02 17:10:36 -06001926 // Batch this baby
Andrey Andreev9f808b02012-10-24 17:38:48 +03001927 $affected_rows = 0;
Andrey Andreev8338bbb2016-12-12 14:17:52 +02001928 for ($i = 0, $total = count($this->qb_set_ub); $i < $total; $i += $batch_size)
Derek Jonesd10e8962010-03-02 17:10:36 -06001929 {
Andrey Andreev8338bbb2016-12-12 14:17:52 +02001930 if ($this->query($this->_update_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->qb_set_ub, $i, $batch_size), $index)))
Andrey Andreevd9a40632016-07-22 15:49:08 +03001931 {
1932 $affected_rows += $this->affected_rows();
1933 }
1934
Andrey Andreev79f888b2013-08-06 13:59:23 +03001935 $this->qb_where = array();
Derek Jonesd10e8962010-03-02 17:10:36 -06001936 }
Barry Mienydd671972010-10-04 16:33:58 +02001937
Derek Jonesd10e8962010-03-02 17:10:36 -06001938 $this->_reset_write();
Andrey Andreev9f808b02012-10-24 17:38:48 +03001939 return $affected_rows;
Derek Jonesd10e8962010-03-02 17:10:36 -06001940 }
1941
1942 // --------------------------------------------------------------------
1943
1944 /**
Andrey Andreev219565d2013-03-12 20:00:08 +02001945 * Update_Batch statement
1946 *
1947 * Generates a platform-specific batch update string from the supplied data
1948 *
1949 * @param string $table Table name
1950 * @param array $values Update data
1951 * @param string $index WHERE key
1952 * @return string
1953 */
1954 protected function _update_batch($table, $values, $index)
1955 {
1956 $ids = array();
1957 foreach ($values as $key => $val)
1958 {
Andrey Andreev8338bbb2016-12-12 14:17:52 +02001959 $ids[] = $val[$index]['value'];
Andrey Andreev219565d2013-03-12 20:00:08 +02001960
1961 foreach (array_keys($val) as $field)
1962 {
1963 if ($field !== $index)
1964 {
Andrey Andreev8338bbb2016-12-12 14:17:52 +02001965 $final[$val[$field]['field']][] = 'WHEN '.$val[$index]['field'].' = '.$val[$index]['value'].' THEN '.$val[$field]['value'];
Andrey Andreev219565d2013-03-12 20:00:08 +02001966 }
1967 }
1968 }
1969
1970 $cases = '';
1971 foreach ($final as $k => $v)
1972 {
1973 $cases .= $k." = CASE \n"
1974 .implode("\n", $v)."\n"
1975 .'ELSE '.$k.' END, ';
1976 }
1977
Andrey Andreev8338bbb2016-12-12 14:17:52 +02001978 $this->where($val[$index]['field'].' IN('.implode(',', $ids).')', NULL, FALSE);
Andrey Andreev219565d2013-03-12 20:00:08 +02001979
1980 return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
1981 }
1982
1983 // --------------------------------------------------------------------
1984
1985 /**
Derek Jones37f4b9c2011-07-01 17:56:50 -05001986 * The "set_update_batch" function. Allows key/value pairs to be set for batch updating
Derek Jonesd10e8962010-03-02 17:10:36 -06001987 *
Derek Jonesd10e8962010-03-02 17:10:36 -06001988 * @param array
1989 * @param string
Andrey Andreeva8bb4be2012-03-26 15:54:23 +03001990 * @param bool
Andrew Podner4296a652012-12-17 07:51:15 -05001991 * @return CI_DB_query_builder
Derek Jonesd10e8962010-03-02 17:10:36 -06001992 */
Andrey Andreevfe642da2012-06-16 03:47:33 +03001993 public function set_update_batch($key, $index = '', $escape = NULL)
Derek Jonesd10e8962010-03-02 17:10:36 -06001994 {
1995 $key = $this->_object_to_array_batch($key);
Barry Mienydd671972010-10-04 16:33:58 +02001996
Derek Jonesd10e8962010-03-02 17:10:36 -06001997 if ( ! is_array($key))
1998 {
1999 // @todo error
Barry Mienydd671972010-10-04 16:33:58 +02002000 }
Derek Jonesd10e8962010-03-02 17:10:36 -06002001
Andrey Andreevfe642da2012-06-16 03:47:33 +03002002 is_bool($escape) OR $escape = $this->_protect_identifiers;
2003
Derek Jonesd10e8962010-03-02 17:10:36 -06002004 foreach ($key as $k => $v)
2005 {
2006 $index_set = FALSE;
2007 $clean = array();
Pascal Krietec3a4a8d2011-02-14 13:40:08 -05002008 foreach ($v as $k2 => $v2)
Derek Jonesd10e8962010-03-02 17:10:36 -06002009 {
Alex Bilbie48a2baf2012-06-02 11:09:54 +01002010 if ($k2 === $index)
Derek Jonesd10e8962010-03-02 17:10:36 -06002011 {
2012 $index_set = TRUE;
2013 }
Derek Jonesd10e8962010-03-02 17:10:36 -06002014
Andrey Andreev8338bbb2016-12-12 14:17:52 +02002015 $clean[$k2] = array(
2016 'field' => $this->protect_identifiers($k2, FALSE, $escape),
2017 'value' => ($escape === FALSE ? $v2 : $this->escape($v2))
2018 );
Derek Jonesd10e8962010-03-02 17:10:36 -06002019 }
2020
Andrey Andreev7b5eb732012-05-24 20:52:41 +03002021 if ($index_set === FALSE)
Derek Jonesd10e8962010-03-02 17:10:36 -06002022 {
2023 return $this->display_error('db_batch_missing_index');
2024 }
2025
Andrey Andreev8338bbb2016-12-12 14:17:52 +02002026 $this->qb_set_ub[] = $clean;
Derek Jonesd10e8962010-03-02 17:10:36 -06002027 }
Barry Mienydd671972010-10-04 16:33:58 +02002028
Derek Jonesd10e8962010-03-02 17:10:36 -06002029 return $this;
2030 }
2031
Derek Allard2067d1a2008-11-13 22:59:24 +00002032 // --------------------------------------------------------------------
2033
2034 /**
2035 * Empty Table
2036 *
2037 * Compiles a delete string and runs "DELETE FROM table"
2038 *
Derek Allard2067d1a2008-11-13 22:59:24 +00002039 * @param string the table to empty
Andrey Andreevaec51262016-02-09 21:11:07 +02002040 * @return bool TRUE on success, FALSE on failure
Derek Allard2067d1a2008-11-13 22:59:24 +00002041 */
Phil Sturgeon9789f322011-07-15 15:14:05 -06002042 public function empty_table($table = '')
Derek Allard2067d1a2008-11-13 22:59:24 +00002043 {
Alex Bilbie48a2baf2012-06-02 11:09:54 +01002044 if ($table === '')
Derek Allard2067d1a2008-11-13 22:59:24 +00002045 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002046 if ( ! isset($this->qb_from[0]))
Derek Allard2067d1a2008-11-13 22:59:24 +00002047 {
Andrey Andreev24276a32012-01-08 02:44:38 +02002048 return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +00002049 }
2050
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002051 $table = $this->qb_from[0];
Derek Allard2067d1a2008-11-13 22:59:24 +00002052 }
2053 else
2054 {
Andrey Andreev032e7ea2012-03-06 19:48:35 +02002055 $table = $this->protect_identifiers($table, TRUE, NULL, FALSE);
Derek Allard2067d1a2008-11-13 22:59:24 +00002056 }
2057
2058 $sql = $this->_delete($table);
Derek Allard2067d1a2008-11-13 22:59:24 +00002059 $this->_reset_write();
Derek Allard2067d1a2008-11-13 22:59:24 +00002060 return $this->query($sql);
2061 }
2062
2063 // --------------------------------------------------------------------
2064
2065 /**
2066 * Truncate
2067 *
2068 * Compiles a truncate string and runs the query
2069 * If the database does not support the truncate() command
2070 * This function maps to "DELETE FROM table"
2071 *
Derek Allard2067d1a2008-11-13 22:59:24 +00002072 * @param string the table to truncate
Andrey Andreevaec51262016-02-09 21:11:07 +02002073 * @return bool TRUE on success, FALSE on failure
Derek Allard2067d1a2008-11-13 22:59:24 +00002074 */
Phil Sturgeon9789f322011-07-15 15:14:05 -06002075 public function truncate($table = '')
Derek Allard2067d1a2008-11-13 22:59:24 +00002076 {
Alex Bilbie48a2baf2012-06-02 11:09:54 +01002077 if ($table === '')
Derek Allard2067d1a2008-11-13 22:59:24 +00002078 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002079 if ( ! isset($this->qb_from[0]))
Derek Allard2067d1a2008-11-13 22:59:24 +00002080 {
Andrey Andreev24276a32012-01-08 02:44:38 +02002081 return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +00002082 }
2083
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002084 $table = $this->qb_from[0];
Derek Allard2067d1a2008-11-13 22:59:24 +00002085 }
2086 else
2087 {
Andrey Andreev032e7ea2012-03-06 19:48:35 +02002088 $table = $this->protect_identifiers($table, TRUE, NULL, FALSE);
Derek Allard2067d1a2008-11-13 22:59:24 +00002089 }
2090
2091 $sql = $this->_truncate($table);
Derek Allard2067d1a2008-11-13 22:59:24 +00002092 $this->_reset_write();
Derek Allard2067d1a2008-11-13 22:59:24 +00002093 return $this->query($sql);
2094 }
WanWizard7219c072011-12-28 14:09:05 +01002095
Kyle Farris0c147b32011-08-26 02:29:31 -04002096 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02002097
Kyle Farris0c147b32011-08-26 02:29:31 -04002098 /**
Andrey Andreeva6fe36e2012-04-05 16:00:32 +03002099 * Truncate statement
2100 *
2101 * Generates a platform-specific truncate string from the supplied data
2102 *
2103 * If the database does not support the truncate() command,
2104 * then this method maps to 'DELETE FROM table'
2105 *
2106 * @param string the table name
2107 * @return string
2108 */
2109 protected function _truncate($table)
2110 {
2111 return 'TRUNCATE '.$table;
2112 }
2113
2114 // --------------------------------------------------------------------
2115
2116 /**
Kyle Farris0c147b32011-08-26 02:29:31 -04002117 * Get DELETE query string
2118 *
2119 * Compiles a delete query string and returns the sql
2120 *
Kyle Farris0c147b32011-08-26 02:29:31 -04002121 * @param string the table to delete from
Jamie Rumbelowd6ce1e92012-04-26 13:27:35 +01002122 * @param bool TRUE: reset QB values; FALSE: leave QB values alone
Kyle Farris0c147b32011-08-26 02:29:31 -04002123 * @return string
2124 */
2125 public function get_compiled_delete($table = '', $reset = TRUE)
2126 {
2127 $this->return_delete_sql = TRUE;
2128 $sql = $this->delete($table, '', NULL, $reset);
2129 $this->return_delete_sql = FALSE;
2130 return $sql;
2131 }
WanWizard7219c072011-12-28 14:09:05 +01002132
Derek Allard2067d1a2008-11-13 22:59:24 +00002133 // --------------------------------------------------------------------
2134
2135 /**
2136 * Delete
2137 *
2138 * Compiles a delete string and runs the query
2139 *
Derek Allard2067d1a2008-11-13 22:59:24 +00002140 * @param mixed the table(s) to delete from. String or array
2141 * @param mixed the where clause
2142 * @param mixed the limit clause
Andrey Andreeva8bb4be2012-03-26 15:54:23 +03002143 * @param bool
Andrey Andreev0bcf5902012-10-12 13:03:29 +03002144 * @return mixed
Derek Allard2067d1a2008-11-13 22:59:24 +00002145 */
Phil Sturgeon9789f322011-07-15 15:14:05 -06002146 public function delete($table = '', $where = '', $limit = NULL, $reset_data = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +00002147 {
2148 // Combine any cached components with the current statements
2149 $this->_merge_cache();
2150
Alex Bilbie48a2baf2012-06-02 11:09:54 +01002151 if ($table === '')
Derek Allard2067d1a2008-11-13 22:59:24 +00002152 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002153 if ( ! isset($this->qb_from[0]))
Derek Allard2067d1a2008-11-13 22:59:24 +00002154 {
Andrey Andreev24276a32012-01-08 02:44:38 +02002155 return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +00002156 }
2157
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002158 $table = $this->qb_from[0];
Derek Allard2067d1a2008-11-13 22:59:24 +00002159 }
2160 elseif (is_array($table))
2161 {
Andrey Andreeva1170af2015-07-02 11:46:56 +03002162 empty($where) && $reset_data = FALSE;
2163
Pascal Krietec3a4a8d2011-02-14 13:40:08 -05002164 foreach ($table as $single_table)
Derek Allard2067d1a2008-11-13 22:59:24 +00002165 {
Andrey Andreev13f50542012-10-12 12:31:02 +03002166 $this->delete($single_table, $where, $limit, $reset_data);
Derek Allard2067d1a2008-11-13 22:59:24 +00002167 }
Andrey Andreeva1170af2015-07-02 11:46:56 +03002168
Derek Allard2067d1a2008-11-13 22:59:24 +00002169 return;
2170 }
2171 else
2172 {
Andrey Andreev032e7ea2012-03-06 19:48:35 +02002173 $table = $this->protect_identifiers($table, TRUE, NULL, FALSE);
Derek Allard2067d1a2008-11-13 22:59:24 +00002174 }
2175
Alex Bilbie48a2baf2012-06-02 11:09:54 +01002176 if ($where !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +00002177 {
2178 $this->where($where);
2179 }
2180
Andrey Andreev650b4c02012-06-11 12:07:15 +03002181 if ( ! empty($limit))
Derek Allard2067d1a2008-11-13 22:59:24 +00002182 {
2183 $this->limit($limit);
2184 }
2185
Andrey Andreev94611df2012-07-19 12:29:54 +03002186 if (count($this->qb_where) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00002187 {
Andrey Andreev24276a32012-01-08 02:44:38 +02002188 return ($this->db_debug) ? $this->display_error('db_del_must_use_where') : FALSE;
Barry Mienydd671972010-10-04 16:33:58 +02002189 }
Derek Allard2067d1a2008-11-13 22:59:24 +00002190
Andrey Andreevb0478652012-07-18 15:34:46 +03002191 $sql = $this->_delete($table);
Derek Allard2067d1a2008-11-13 22:59:24 +00002192 if ($reset_data)
2193 {
2194 $this->_reset_write();
2195 }
WanWizard7219c072011-12-28 14:09:05 +01002196
Andrey Andreev24276a32012-01-08 02:44:38 +02002197 return ($this->return_delete_sql === TRUE) ? $sql : $this->query($sql);
Derek Allard2067d1a2008-11-13 22:59:24 +00002198 }
WanWizard7219c072011-12-28 14:09:05 +01002199
Derek Allard2067d1a2008-11-13 22:59:24 +00002200 // --------------------------------------------------------------------
2201
2202 /**
Andrey Andreevc01d3162012-04-09 12:55:11 +03002203 * Delete statement
2204 *
2205 * Generates a platform-specific delete string from the supplied data
2206 *
2207 * @param string the table name
Andrey Andreevc01d3162012-04-09 12:55:11 +03002208 * @return string
2209 */
Andrey Andreevb0478652012-07-18 15:34:46 +03002210 protected function _delete($table)
Andrey Andreevc01d3162012-04-09 12:55:11 +03002211 {
Andrey Andreevd40459d2012-07-18 16:46:39 +03002212 return 'DELETE FROM '.$table.$this->_compile_wh('qb_where')
Andrey Andreevc9b924c2012-07-19 13:06:02 +03002213 .($this->qb_limit ? ' LIMIT '.$this->qb_limit : '');
Andrey Andreevc01d3162012-04-09 12:55:11 +03002214 }
2215
2216 // --------------------------------------------------------------------
2217
2218 /**
Derek Allard2067d1a2008-11-13 22:59:24 +00002219 * DB Prefix
2220 *
2221 * Prepends a database prefix if one exists in configuration
2222 *
Derek Allard2067d1a2008-11-13 22:59:24 +00002223 * @param string the table
2224 * @return string
2225 */
Phil Sturgeon9789f322011-07-15 15:14:05 -06002226 public function dbprefix($table = '')
Derek Allard2067d1a2008-11-13 22:59:24 +00002227 {
Alex Bilbie48a2baf2012-06-02 11:09:54 +01002228 if ($table === '')
Derek Allard2067d1a2008-11-13 22:59:24 +00002229 {
2230 $this->display_error('db_table_name_required');
2231 }
2232
2233 return $this->dbprefix.$table;
2234 }
2235
2236 // --------------------------------------------------------------------
2237
2238 /**
Phil Sturgeon8a022472011-07-15 15:25:15 -06002239 * Set DB Prefix
2240 *
2241 * Set's the DB Prefix to something new without needing to reconnect
2242 *
2243 * @param string the prefix
2244 * @return string
2245 */
2246 public function set_dbprefix($prefix = '')
2247 {
2248 return $this->dbprefix = $prefix;
2249 }
2250
2251 // --------------------------------------------------------------------
2252
2253 /**
Derek Allard2067d1a2008-11-13 22:59:24 +00002254 * Track Aliases
2255 *
2256 * Used to track SQL statements written with aliased tables.
2257 *
Derek Allard2067d1a2008-11-13 22:59:24 +00002258 * @param string The table to inspect
2259 * @return string
Barry Mienydd671972010-10-04 16:33:58 +02002260 */
Phil Sturgeon9789f322011-07-15 15:14:05 -06002261 protected function _track_aliases($table)
Derek Allard2067d1a2008-11-13 22:59:24 +00002262 {
2263 if (is_array($table))
2264 {
2265 foreach ($table as $t)
2266 {
2267 $this->_track_aliases($t);
2268 }
2269 return;
2270 }
Barry Mienydd671972010-10-04 16:33:58 +02002271
Derek Jones37f4b9c2011-07-01 17:56:50 -05002272 // Does the string contain a comma? If so, we need to separate
Derek Allard2067d1a2008-11-13 22:59:24 +00002273 // the string into discreet statements
2274 if (strpos($table, ',') !== FALSE)
2275 {
2276 return $this->_track_aliases(explode(',', $table));
2277 }
Barry Mienydd671972010-10-04 16:33:58 +02002278
Derek Allard2067d1a2008-11-13 22:59:24 +00002279 // if a table alias is used we can recognize it by a space
Andrey Andreev24276a32012-01-08 02:44:38 +02002280 if (strpos($table, ' ') !== FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00002281 {
2282 // if the alias is written with the AS keyword, remove it
Andrey Andreev5a257182012-06-10 06:18:14 +03002283 $table = preg_replace('/\s+AS\s+/i', ' ', $table);
Barry Mienydd671972010-10-04 16:33:58 +02002284
Derek Allard2067d1a2008-11-13 22:59:24 +00002285 // Grab the alias
Andrey Andreev24276a32012-01-08 02:44:38 +02002286 $table = trim(strrchr($table, ' '));
Barry Mienydd671972010-10-04 16:33:58 +02002287
Derek Allard2067d1a2008-11-13 22:59:24 +00002288 // Store the alias, if it doesn't already exist
Andrey Andreev437ffe02017-01-17 12:44:19 +02002289 if ( ! in_array($table, $this->qb_aliased_tables, TRUE))
Derek Allard2067d1a2008-11-13 22:59:24 +00002290 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002291 $this->qb_aliased_tables[] = $table;
Andrey Andreev437ffe02017-01-17 12:44:19 +02002292 if ($this->qb_caching === TRUE && ! in_array($table, $this->qb_cache_aliased_tables, TRUE))
2293 {
2294 $this->qb_cache_aliased_tables[] = $table;
2295 $this->qb_cache_exists[] = 'aliased_tables';
2296 }
Derek Allard2067d1a2008-11-13 22:59:24 +00002297 }
2298 }
2299 }
WanWizard7219c072011-12-28 14:09:05 +01002300
Derek Allard2067d1a2008-11-13 22:59:24 +00002301 // --------------------------------------------------------------------
2302
2303 /**
2304 * Compile the SELECT statement
2305 *
2306 * Generates a query string based on which functions were used.
Andrey Andreev5fd3ae82012-10-24 14:55:35 +03002307 * Should not be called directly.
Derek Allard2067d1a2008-11-13 22:59:24 +00002308 *
Andrey Andreevae85eb42012-11-02 01:42:31 +02002309 * @param bool $select_override
Derek Allard2067d1a2008-11-13 22:59:24 +00002310 * @return string
2311 */
Phil Sturgeon9789f322011-07-15 15:14:05 -06002312 protected function _compile_select($select_override = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00002313 {
2314 // Combine any cached components with the current statements
2315 $this->_merge_cache();
2316
Derek Allard2067d1a2008-11-13 22:59:24 +00002317 // Write the "select" portion of the query
Derek Allard2067d1a2008-11-13 22:59:24 +00002318 if ($select_override !== FALSE)
2319 {
2320 $sql = $select_override;
2321 }
2322 else
2323 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002324 $sql = ( ! $this->qb_distinct) ? 'SELECT ' : 'SELECT DISTINCT ';
Barry Mienydd671972010-10-04 16:33:58 +02002325
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002326 if (count($this->qb_select) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00002327 {
Barry Mienydd671972010-10-04 16:33:58 +02002328 $sql .= '*';
Derek Allard2067d1a2008-11-13 22:59:24 +00002329 }
2330 else
Barry Mienydd671972010-10-04 16:33:58 +02002331 {
Derek Allard2067d1a2008-11-13 22:59:24 +00002332 // Cycle through the "select" portion of the query and prep each column name.
Andrey Andreev1924eb32015-04-08 17:19:24 +03002333 // The reason we protect identifiers here rather than in the select() function
Derek Allard2067d1a2008-11-13 22:59:24 +00002334 // is because until the user calls the from() function we don't know if there are aliases
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002335 foreach ($this->qb_select as $key => $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00002336 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002337 $no_escape = isset($this->qb_no_escape[$key]) ? $this->qb_no_escape[$key] : NULL;
Jamie Rumbelow0c092992012-03-06 22:05:16 +00002338 $this->qb_select[$key] = $this->protect_identifiers($val, FALSE, $no_escape);
Derek Allard2067d1a2008-11-13 22:59:24 +00002339 }
Barry Mienydd671972010-10-04 16:33:58 +02002340
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002341 $sql .= implode(', ', $this->qb_select);
Derek Allard2067d1a2008-11-13 22:59:24 +00002342 }
2343 }
2344
Derek Allard2067d1a2008-11-13 22:59:24 +00002345 // Write the "FROM" portion of the query
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002346 if (count($this->qb_from) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00002347 {
Andrey Andreeve78f8152012-10-09 11:38:38 +03002348 $sql .= "\nFROM ".$this->_from_tables();
Derek Allard2067d1a2008-11-13 22:59:24 +00002349 }
2350
Derek Allard2067d1a2008-11-13 22:59:24 +00002351 // Write the "JOIN" portion of the query
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002352 if (count($this->qb_join) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00002353 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002354 $sql .= "\n".implode("\n", $this->qb_join);
Derek Allard2067d1a2008-11-13 22:59:24 +00002355 }
2356
Andrey Andreev2d486232012-07-19 14:46:51 +03002357 $sql .= $this->_compile_wh('qb_where')
2358 .$this->_compile_group_by()
2359 .$this->_compile_wh('qb_having')
2360 .$this->_compile_order_by(); // ORDER BY
Andrey Andreevb0478652012-07-18 15:34:46 +03002361
Andrey Andreevd40459d2012-07-18 16:46:39 +03002362 // LIMIT
Andrey Andreevacc64812016-07-29 11:42:28 +03002363 if ($this->qb_limit OR $this->qb_offset)
Derek Allard2067d1a2008-11-13 22:59:24 +00002364 {
Andrey Andreevc9b924c2012-07-19 13:06:02 +03002365 return $this->_limit($sql."\n");
Derek Allard2067d1a2008-11-13 22:59:24 +00002366 }
2367
2368 return $sql;
2369 }
2370
2371 // --------------------------------------------------------------------
2372
2373 /**
Andrey Andreevd40459d2012-07-18 16:46:39 +03002374 * Compile WHERE, HAVING statements
Andrey Andreev6e704752012-07-18 00:46:33 +03002375 *
Andrey Andreevd40459d2012-07-18 16:46:39 +03002376 * Escapes identifiers in WHERE and HAVING statements at execution time.
2377 *
Andrey Andreev99c17e52016-02-29 16:53:45 +02002378 * Required so that aliases are tracked properly, regardless of whether
Andrey Andreevd40459d2012-07-18 16:46:39 +03002379 * where(), or_where(), having(), or_having are called prior to from(),
2380 * join() and dbprefix is added only if needed.
Andrey Andreev6e704752012-07-18 00:46:33 +03002381 *
Andrey Andreevae85eb42012-11-02 01:42:31 +02002382 * @param string $qb_key 'qb_where' or 'qb_having'
Andrey Andreevd40459d2012-07-18 16:46:39 +03002383 * @return string SQL statement
Andrey Andreev6e704752012-07-18 00:46:33 +03002384 */
Andrey Andreevd40459d2012-07-18 16:46:39 +03002385 protected function _compile_wh($qb_key)
Andrey Andreev6e704752012-07-18 00:46:33 +03002386 {
Andrey Andreevd40459d2012-07-18 16:46:39 +03002387 if (count($this->$qb_key) > 0)
Andrey Andreev6e704752012-07-18 00:46:33 +03002388 {
Andrey Andreevd40459d2012-07-18 16:46:39 +03002389 for ($i = 0, $c = count($this->$qb_key); $i < $c; $i++)
Andrey Andreev6e704752012-07-18 00:46:33 +03002390 {
Andrey Andreev5e3d48c2013-10-29 14:36:18 +02002391 // Is this condition already compiled?
2392 if (is_string($this->{$qb_key}[$i]))
2393 {
2394 continue;
2395 }
2396 elseif ($this->{$qb_key}[$i]['escape'] === FALSE)
Andrey Andreev6e704752012-07-18 00:46:33 +03002397 {
Andrey Andreevd40459d2012-07-18 16:46:39 +03002398 $this->{$qb_key}[$i] = $this->{$qb_key}[$i]['condition'];
Andrey Andreev6e704752012-07-18 00:46:33 +03002399 continue;
2400 }
2401
Andrey Andreevf2ec8b82012-10-12 14:01:13 +03002402 // Split multiple conditions
2403 $conditions = preg_split(
Andrey Andreev554b4522015-09-01 13:51:26 +03002404 '/((?:^|\s+)AND\s+|(?:^|\s+)OR\s+)/i',
Andrey Andreevf2ec8b82012-10-12 14:01:13 +03002405 $this->{$qb_key}[$i]['condition'],
2406 -1,
2407 PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY
2408 );
2409
2410 for ($ci = 0, $cc = count($conditions); $ci < $cc; $ci++)
Andrey Andreev6e704752012-07-18 00:46:33 +03002411 {
Andrey Andreevf2ec8b82012-10-12 14:01:13 +03002412 if (($op = $this->_get_operator($conditions[$ci])) === FALSE
Andrey Andreeve4742582012-10-25 13:25:13 +03002413 OR ! preg_match('/^(\(?)(.*)('.preg_quote($op, '/').')\s*(.*(?<!\)))?(\)?)$/i', $conditions[$ci], $matches))
Andrey Andreevf2ec8b82012-10-12 14:01:13 +03002414 {
2415 continue;
2416 }
2417
2418 // $matches = array(
2419 // 0 => '(test <= foo)', /* the whole thing */
2420 // 1 => '(', /* optional */
2421 // 2 => 'test', /* the field name */
2422 // 3 => ' <= ', /* $op */
2423 // 4 => 'foo', /* optional, if $op is e.g. 'IS NULL' */
2424 // 5 => ')' /* optional */
2425 // );
Andrey Andreev082aa402012-10-22 19:41:55 +03002426
2427 if ( ! empty($matches[4]))
2428 {
2429 $this->_is_literal($matches[4]) OR $matches[4] = $this->protect_identifiers(trim($matches[4]));
2430 $matches[4] = ' '.$matches[4];
2431 }
2432
Andrey Andreevf2ec8b82012-10-12 14:01:13 +03002433 $conditions[$ci] = $matches[1].$this->protect_identifiers(trim($matches[2]))
2434 .' '.trim($matches[3]).$matches[4].$matches[5];
Andrey Andreev6e704752012-07-18 00:46:33 +03002435 }
2436
Andrey Andreevf2ec8b82012-10-12 14:01:13 +03002437 $this->{$qb_key}[$i] = implode('', $conditions);
Andrey Andreev6e704752012-07-18 00:46:33 +03002438 }
2439
Andrey Andreev9d3aa1b2012-10-12 12:14:09 +03002440 return ($qb_key === 'qb_having' ? "\nHAVING " : "\nWHERE ")
2441 .implode("\n", $this->$qb_key);
Andrey Andreev6e704752012-07-18 00:46:33 +03002442 }
2443
Andrey Andreevb0478652012-07-18 15:34:46 +03002444 return '';
Andrey Andreev6e704752012-07-18 00:46:33 +03002445 }
2446
2447 // --------------------------------------------------------------------
2448
2449 /**
Andrey Andreevc9b924c2012-07-19 13:06:02 +03002450 * Compile GROUP BY
2451 *
2452 * Escapes identifiers in GROUP BY statements at execution time.
2453 *
Andrey Andreev71d8f722017-01-17 12:01:00 +02002454 * Required so that aliases are tracked properly, regardless of whether
Andrey Andreevc9b924c2012-07-19 13:06:02 +03002455 * group_by() is called prior to from(), join() and dbprefix is added
2456 * only if needed.
2457 *
2458 * @return string SQL statement
2459 */
2460 protected function _compile_group_by()
2461 {
2462 if (count($this->qb_groupby) > 0)
2463 {
Andrey Andreev96feb582012-07-19 13:12:34 +03002464 for ($i = 0, $c = count($this->qb_groupby); $i < $c; $i++)
2465 {
Andrey Andreev5e3d48c2013-10-29 14:36:18 +02002466 // Is it already compiled?
Andrey Andreev18eba242014-01-23 22:52:31 +02002467 if (is_string($this->qb_groupby[$i]))
Andrey Andreev5e3d48c2013-10-29 14:36:18 +02002468 {
2469 continue;
2470 }
2471
Andrey Andreev082aa402012-10-22 19:41:55 +03002472 $this->qb_groupby[$i] = ($this->qb_groupby[$i]['escape'] === FALSE OR $this->_is_literal($this->qb_groupby[$i]['field']))
Andrey Andreev96feb582012-07-19 13:12:34 +03002473 ? $this->qb_groupby[$i]['field']
Andrey Andreev13f50542012-10-12 12:31:02 +03002474 : $this->protect_identifiers($this->qb_groupby[$i]['field']);
Andrey Andreev96feb582012-07-19 13:12:34 +03002475 }
2476
Andrey Andreev0bcf5902012-10-12 13:03:29 +03002477 return "\nGROUP BY ".implode(', ', $this->qb_groupby);
Andrey Andreevc9b924c2012-07-19 13:06:02 +03002478 }
2479
2480 return '';
2481 }
2482
2483 // --------------------------------------------------------------------
2484
2485 /**
Andrey Andreev2d486232012-07-19 14:46:51 +03002486 * Compile ORDER BY
2487 *
2488 * Escapes identifiers in ORDER BY statements at execution time.
2489 *
Andrey Andreev71d8f722017-01-17 12:01:00 +02002490 * Required so that aliases are tracked properly, regardless of whether
Andrey Andreev2d486232012-07-19 14:46:51 +03002491 * order_by() is called prior to from(), join() and dbprefix is added
2492 * only if needed.
2493 *
2494 * @return string SQL statement
2495 */
2496 protected function _compile_order_by()
2497 {
Andrey Andreev33cc3e12017-01-16 16:01:58 +02002498 if (empty($this->qb_orderby))
Andrey Andreev2d486232012-07-19 14:46:51 +03002499 {
Andrey Andreev33cc3e12017-01-16 16:01:58 +02002500 return '';
2501 }
Andrey Andreev2d486232012-07-19 14:46:51 +03002502
Andrey Andreev33cc3e12017-01-16 16:01:58 +02002503 for ($i = 0, $c = count($this->qb_orderby); $i < $c; $i++)
2504 {
2505 if (is_string($this->qb_orderby[$i]))
2506 {
2507 continue;
Andrey Andreev2d486232012-07-19 14:46:51 +03002508 }
2509
Andrey Andreev33cc3e12017-01-16 16:01:58 +02002510 if ($this->qb_orderby[$i]['escape'] !== FALSE && ! $this->_is_literal($this->qb_orderby[$i]['field']))
2511 {
2512 $this->qb_orderby[$i]['field'] = $this->protect_identifiers($this->qb_orderby[$i]['field']);
2513 }
2514
2515 $this->qb_orderby[$i] = $this->qb_orderby[$i]['field'].$this->qb_orderby[$i]['direction'];
Andrey Andreev2d486232012-07-19 14:46:51 +03002516 }
2517
Andrey Andreev33cc3e12017-01-16 16:01:58 +02002518 return "\nORDER BY ".implode(', ', $this->qb_orderby);
Andrey Andreev2d486232012-07-19 14:46:51 +03002519 }
2520
2521 // --------------------------------------------------------------------
2522
2523 /**
Derek Allard2067d1a2008-11-13 22:59:24 +00002524 * Object to Array
2525 *
2526 * Takes an object as input and converts the class variables to array key/vals
2527 *
Derek Allard2067d1a2008-11-13 22:59:24 +00002528 * @param object
2529 * @return array
2530 */
Andrey Andreev7b5eb732012-05-24 20:52:41 +03002531 protected function _object_to_array($object)
Derek Allard2067d1a2008-11-13 22:59:24 +00002532 {
2533 if ( ! is_object($object))
2534 {
2535 return $object;
2536 }
Barry Mienydd671972010-10-04 16:33:58 +02002537
Derek Allard2067d1a2008-11-13 22:59:24 +00002538 $array = array();
2539 foreach (get_object_vars($object) as $key => $val)
2540 {
2541 // There are some built in keys we need to ignore for this conversion
Alex Bilbie48a2baf2012-06-02 11:09:54 +01002542 if ( ! is_object($val) && ! is_array($val) && $key !== '_parent_name')
Derek Allard2067d1a2008-11-13 22:59:24 +00002543 {
2544 $array[$key] = $val;
2545 }
2546 }
Derek Jonesd10e8962010-03-02 17:10:36 -06002547
2548 return $array;
2549 }
Barry Mienydd671972010-10-04 16:33:58 +02002550
Derek Jonesd10e8962010-03-02 17:10:36 -06002551 // --------------------------------------------------------------------
2552
2553 /**
2554 * Object to Array
2555 *
2556 * Takes an object as input and converts the class variables to array key/vals
2557 *
Derek Jonesd10e8962010-03-02 17:10:36 -06002558 * @param object
2559 * @return array
2560 */
Andrey Andreev7b5eb732012-05-24 20:52:41 +03002561 protected function _object_to_array_batch($object)
Derek Jonesd10e8962010-03-02 17:10:36 -06002562 {
2563 if ( ! is_object($object))
2564 {
2565 return $object;
2566 }
Barry Mienydd671972010-10-04 16:33:58 +02002567
Derek Jonesd10e8962010-03-02 17:10:36 -06002568 $array = array();
2569 $out = get_object_vars($object);
2570 $fields = array_keys($out);
2571
2572 foreach ($fields as $val)
2573 {
2574 // There are some built in keys we need to ignore for this conversion
Andrey Andreev24276a32012-01-08 02:44:38 +02002575 if ($val !== '_parent_name')
Derek Jonesd10e8962010-03-02 17:10:36 -06002576 {
Derek Jonesd10e8962010-03-02 17:10:36 -06002577 $i = 0;
2578 foreach ($out[$val] as $data)
2579 {
Andrey Andreev24276a32012-01-08 02:44:38 +02002580 $array[$i++][$val] = $data;
Derek Jonesd10e8962010-03-02 17:10:36 -06002581 }
2582 }
2583 }
2584
Derek Allard2067d1a2008-11-13 22:59:24 +00002585 return $array;
2586 }
Barry Mienydd671972010-10-04 16:33:58 +02002587
Derek Allard2067d1a2008-11-13 22:59:24 +00002588 // --------------------------------------------------------------------
2589
2590 /**
2591 * Start Cache
2592 *
Jamie Rumbelow17c1bed2012-03-06 21:30:38 +00002593 * Starts QB caching
Derek Allard2067d1a2008-11-13 22:59:24 +00002594 *
Andrey Andreev4a587f52014-12-11 16:27:15 +02002595 * @return CI_DB_query_builder
Barry Mienydd671972010-10-04 16:33:58 +02002596 */
Phil Sturgeon9789f322011-07-15 15:14:05 -06002597 public function start_cache()
Derek Allard2067d1a2008-11-13 22:59:24 +00002598 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002599 $this->qb_caching = TRUE;
Andrey Andreev4a587f52014-12-11 16:27:15 +02002600 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +00002601 }
2602
2603 // --------------------------------------------------------------------
2604
2605 /**
2606 * Stop Cache
2607 *
Jamie Rumbelow17c1bed2012-03-06 21:30:38 +00002608 * Stops QB caching
Derek Allard2067d1a2008-11-13 22:59:24 +00002609 *
Andrey Andreev4a587f52014-12-11 16:27:15 +02002610 * @return CI_DB_query_builder
Barry Mienydd671972010-10-04 16:33:58 +02002611 */
Phil Sturgeon9789f322011-07-15 15:14:05 -06002612 public function stop_cache()
Derek Allard2067d1a2008-11-13 22:59:24 +00002613 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002614 $this->qb_caching = FALSE;
Andrey Andreev4a587f52014-12-11 16:27:15 +02002615 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +00002616 }
2617
2618 // --------------------------------------------------------------------
2619
2620 /**
2621 * Flush Cache
2622 *
Jamie Rumbelow17c1bed2012-03-06 21:30:38 +00002623 * Empties the QB cache
Derek Allard2067d1a2008-11-13 22:59:24 +00002624 *
Andrey Andreev4a587f52014-12-11 16:27:15 +02002625 * @return CI_DB_query_builder
Barry Mienydd671972010-10-04 16:33:58 +02002626 */
Phil Sturgeon9789f322011-07-15 15:14:05 -06002627 public function flush_cache()
Barry Mienydd671972010-10-04 16:33:58 +02002628 {
Phil Sturgeon9789f322011-07-15 15:14:05 -06002629 $this->_reset_run(array(
Jamie Rumbelow17c1bed2012-03-06 21:30:38 +00002630 'qb_cache_select' => array(),
2631 'qb_cache_from' => array(),
2632 'qb_cache_join' => array(),
2633 'qb_cache_where' => array(),
Jamie Rumbelow17c1bed2012-03-06 21:30:38 +00002634 'qb_cache_groupby' => array(),
2635 'qb_cache_having' => array(),
2636 'qb_cache_orderby' => array(),
2637 'qb_cache_set' => array(),
2638 'qb_cache_exists' => array(),
Andrey Andreev437ffe02017-01-17 12:44:19 +02002639 'qb_cache_no_escape' => array(),
2640 'qb_cache_aliased_tables' => array()
Phil Sturgeon9789f322011-07-15 15:14:05 -06002641 ));
Andrey Andreev4a587f52014-12-11 16:27:15 +02002642
2643 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +00002644 }
2645
2646 // --------------------------------------------------------------------
2647
2648 /**
2649 * Merge Cache
2650 *
Jamie Rumbelow17c1bed2012-03-06 21:30:38 +00002651 * When called, this function merges any cached QB arrays with
Derek Allard2067d1a2008-11-13 22:59:24 +00002652 * locally called ones.
2653 *
Derek Allard2067d1a2008-11-13 22:59:24 +00002654 * @return void
2655 */
Phil Sturgeon9789f322011-07-15 15:14:05 -06002656 protected function _merge_cache()
Derek Allard2067d1a2008-11-13 22:59:24 +00002657 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002658 if (count($this->qb_cache_exists) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00002659 {
2660 return;
2661 }
Andrey Andreev1720a6a2014-01-06 13:50:05 +02002662 elseif (in_array('select', $this->qb_cache_exists, TRUE))
2663 {
2664 $qb_no_escape = $this->qb_cache_no_escape;
2665 }
Derek Allard2067d1a2008-11-13 22:59:24 +00002666
GDmac17a05282013-11-11 13:18:09 +01002667 foreach (array_unique($this->qb_cache_exists) as $val) // select, from, etc.
Derek Allard2067d1a2008-11-13 22:59:24 +00002668 {
Jamie Rumbelowae123e02012-02-21 16:39:56 +00002669 $qb_variable = 'qb_'.$val;
2670 $qb_cache_var = 'qb_cache_'.$val;
Andrey Andreev35e3b0b2013-11-12 16:07:08 +02002671 $qb_new = $this->$qb_cache_var;
GDmace1b86832013-11-08 16:52:54 +01002672
Andrey Andreev1720a6a2014-01-06 13:50:05 +02002673 for ($i = 0, $c = count($this->$qb_variable); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +00002674 {
Andrey Andreev1720a6a2014-01-06 13:50:05 +02002675 if ( ! in_array($this->{$qb_variable}[$i], $qb_new, TRUE))
2676 {
2677 $qb_new[] = $this->{$qb_variable}[$i];
2678 if ($val === 'select')
2679 {
2680 $qb_no_escape[] = $this->qb_no_escape[$i];
2681 }
2682 }
Derek Allard2067d1a2008-11-13 22:59:24 +00002683 }
Andrey Andreev35e3b0b2013-11-12 16:07:08 +02002684
GDmace1b86832013-11-08 16:52:54 +01002685 $this->$qb_variable = $qb_new;
Andrey Andreev1720a6a2014-01-06 13:50:05 +02002686 if ($val === 'select')
2687 {
2688 $this->qb_no_escape = $qb_no_escape;
2689 }
Derek Allard2067d1a2008-11-13 22:59:24 +00002690 }
Derek Allard2067d1a2008-11-13 22:59:24 +00002691 }
WanWizard7219c072011-12-28 14:09:05 +01002692
Kyle Farris0c147b32011-08-26 02:29:31 -04002693 // --------------------------------------------------------------------
2694
2695 /**
Andrey Andreev082aa402012-10-22 19:41:55 +03002696 * Is literal
2697 *
2698 * Determines if a string represents a literal value or a field name
2699 *
Andrey Andreev02e4cd72012-11-13 11:50:47 +02002700 * @param string $str
Andrey Andreev082aa402012-10-22 19:41:55 +03002701 * @return bool
2702 */
2703 protected function _is_literal($str)
2704 {
2705 $str = trim($str);
2706
Andrey Andreev3a5efc22012-11-20 21:18:08 +02002707 if (empty($str) OR ctype_digit($str) OR (string) (float) $str === $str OR in_array(strtoupper($str), array('TRUE', 'FALSE'), TRUE))
Andrey Andreev082aa402012-10-22 19:41:55 +03002708 {
2709 return TRUE;
2710 }
2711
2712 static $_str;
2713
2714 if (empty($_str))
2715 {
2716 $_str = ($this->_escape_char !== '"')
2717 ? array('"', "'") : array("'");
2718 }
2719
Andrey Andreev3a5efc22012-11-20 21:18:08 +02002720 return in_array($str[0], $_str, TRUE);
Andrey Andreev082aa402012-10-22 19:41:55 +03002721 }
2722
2723 // --------------------------------------------------------------------
2724
2725 /**
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002726 * Reset Query Builder values.
WanWizard7219c072011-12-28 14:09:05 +01002727 *
Jamie Rumbelow17c1bed2012-03-06 21:30:38 +00002728 * Publicly-visible method to reset the QB values.
Kyle Farris0c147b32011-08-26 02:29:31 -04002729 *
Andrey Andreev435e0c22014-12-11 16:30:13 +02002730 * @return CI_DB_query_builder
Kyle Farris0c147b32011-08-26 02:29:31 -04002731 */
2732 public function reset_query()
2733 {
2734 $this->_reset_select();
2735 $this->_reset_write();
Andrey Andreev435e0c22014-12-11 16:30:13 +02002736 return $this;
Kyle Farris0c147b32011-08-26 02:29:31 -04002737 }
Derek Allard2067d1a2008-11-13 22:59:24 +00002738
2739 // --------------------------------------------------------------------
2740
2741 /**
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002742 * Resets the query builder values. Called by the get() function
Derek Allard2067d1a2008-11-13 22:59:24 +00002743 *
Derek Allard2067d1a2008-11-13 22:59:24 +00002744 * @param array An array of fields to reset
2745 * @return void
2746 */
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002747 protected function _reset_run($qb_reset_items)
Derek Allard2067d1a2008-11-13 22:59:24 +00002748 {
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002749 foreach ($qb_reset_items as $item => $default_value)
Derek Allard2067d1a2008-11-13 22:59:24 +00002750 {
Andrey Andreevae85eb42012-11-02 01:42:31 +02002751 $this->$item = $default_value;
Derek Allard2067d1a2008-11-13 22:59:24 +00002752 }
2753 }
2754
2755 // --------------------------------------------------------------------
2756
2757 /**
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002758 * Resets the query builder values. Called by the get() function
Derek Allard2067d1a2008-11-13 22:59:24 +00002759 *
Derek Allard2067d1a2008-11-13 22:59:24 +00002760 * @return void
2761 */
Phil Sturgeon9789f322011-07-15 15:14:05 -06002762 protected function _reset_select()
Derek Allard2067d1a2008-11-13 22:59:24 +00002763 {
Andrey Andreev24276a32012-01-08 02:44:38 +02002764 $this->_reset_run(array(
Andrey Andreev4a587f52014-12-11 16:27:15 +02002765 'qb_select' => array(),
2766 'qb_from' => array(),
2767 'qb_join' => array(),
2768 'qb_where' => array(),
2769 'qb_groupby' => array(),
2770 'qb_having' => array(),
2771 'qb_orderby' => array(),
2772 'qb_aliased_tables' => array(),
2773 'qb_no_escape' => array(),
2774 'qb_distinct' => FALSE,
2775 'qb_limit' => FALSE,
2776 'qb_offset' => FALSE
2777 ));
Derek Allard2067d1a2008-11-13 22:59:24 +00002778 }
Barry Mienydd671972010-10-04 16:33:58 +02002779
Derek Allard2067d1a2008-11-13 22:59:24 +00002780 // --------------------------------------------------------------------
2781
2782 /**
Jamie Rumbelow7efad202012-02-19 12:37:00 +00002783 * Resets the query builder "write" values.
Derek Allard2067d1a2008-11-13 22:59:24 +00002784 *
Robin Sowell43753fd2010-09-16 12:52:07 -04002785 * Called by the insert() update() insert_batch() update_batch() and delete() functions
Derek Allard2067d1a2008-11-13 22:59:24 +00002786 *
Derek Allard2067d1a2008-11-13 22:59:24 +00002787 * @return void
2788 */
Phil Sturgeon9789f322011-07-15 15:14:05 -06002789 protected function _reset_write()
Barry Mienydd671972010-10-04 16:33:58 +02002790 {
Andrey Andreev24276a32012-01-08 02:44:38 +02002791 $this->_reset_run(array(
Jamie Rumbelowd6ce1e92012-04-26 13:27:35 +01002792 'qb_set' => array(),
Andrey Andreev8338bbb2016-12-12 14:17:52 +02002793 'qb_set_ub' => array(),
Jamie Rumbelowd6ce1e92012-04-26 13:27:35 +01002794 'qb_from' => array(),
Andrey Andreev3e014372013-02-21 15:59:34 +02002795 'qb_join' => array(),
Jamie Rumbelowd6ce1e92012-04-26 13:27:35 +01002796 'qb_where' => array(),
Jamie Rumbelowd6ce1e92012-04-26 13:27:35 +01002797 'qb_orderby' => array(),
2798 'qb_keys' => array(),
Andrey Andreev650b4c02012-06-11 12:07:15 +03002799 'qb_limit' => FALSE
Andrey Andreev4a587f52014-12-11 16:27:15 +02002800 ));
Derek Allard2067d1a2008-11-13 22:59:24 +00002801 }
Andrey Andreev24276a32012-01-08 02:44:38 +02002802
Derek Allard2067d1a2008-11-13 22:59:24 +00002803}