DB_active_rec.php 42 KB

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