DB_active_rec.php 42 KB

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