PageRenderTime 67ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 1ms

/libraries/joomla/database/query.php

https://bitbucket.org/biojazzard/joomla-eboracast
PHP | 1841 lines | 767 code | 202 blank | 872 comment | 60 complexity | bcb47ac1675c2f8d410a9e63aeb0cf29 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0, MIT, BSD-3-Clause
  1. <?php
  2. /**
  3. * @package Joomla.Platform
  4. * @subpackage Database
  5. *
  6. * @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE
  8. */
  9. defined('JPATH_PLATFORM') or die;
  10. /**
  11. * Query Element Class.
  12. *
  13. * @property-read string $name The name of the element.
  14. * @property-read array $elements An array of elements.
  15. * @property-read string $glue Glue piece.
  16. *
  17. * @package Joomla.Platform
  18. * @subpackage Database
  19. * @since 11.1
  20. */
  21. class JDatabaseQueryElement
  22. {
  23. /**
  24. * @var string The name of the element.
  25. * @since 11.1
  26. */
  27. protected $name = null;
  28. /**
  29. * @var array An array of elements.
  30. * @since 11.1
  31. */
  32. protected $elements = null;
  33. /**
  34. * @var string Glue piece.
  35. * @since 11.1
  36. */
  37. protected $glue = null;
  38. /**
  39. * Constructor.
  40. *
  41. * @param string $name The name of the element.
  42. * @param mixed $elements String or array.
  43. * @param string $glue The glue for elements.
  44. *
  45. * @since 11.1
  46. */
  47. public function __construct($name, $elements, $glue = ',')
  48. {
  49. $this->elements = array();
  50. $this->name = $name;
  51. $this->glue = $glue;
  52. $this->append($elements);
  53. }
  54. /**
  55. * Magic function to convert the query element to a string.
  56. *
  57. * @return string
  58. *
  59. * @since 11.1
  60. */
  61. public function __toString()
  62. {
  63. if (substr($this->name, -2) == '()')
  64. {
  65. return PHP_EOL . substr($this->name, 0, -2) . '(' . implode($this->glue, $this->elements) . ')';
  66. }
  67. else
  68. {
  69. return PHP_EOL . $this->name . ' ' . implode($this->glue, $this->elements);
  70. }
  71. }
  72. /**
  73. * Appends element parts to the internal list.
  74. *
  75. * @param mixed $elements String or array.
  76. *
  77. * @return void
  78. *
  79. * @since 11.1
  80. */
  81. public function append($elements)
  82. {
  83. if (is_array($elements))
  84. {
  85. $this->elements = array_merge($this->elements, $elements);
  86. }
  87. else
  88. {
  89. $this->elements = array_merge($this->elements, array($elements));
  90. }
  91. }
  92. /**
  93. * Gets the elements of this element.
  94. *
  95. * @return array
  96. *
  97. * @since 11.1
  98. */
  99. public function getElements()
  100. {
  101. return $this->elements;
  102. }
  103. /**
  104. * Method to provide deep copy support to nested objects and arrays
  105. * when cloning.
  106. *
  107. * @return void
  108. *
  109. * @since 11.3
  110. */
  111. public function __clone()
  112. {
  113. foreach ($this as $k => $v)
  114. {
  115. if (is_object($v) || is_array($v))
  116. {
  117. $this->{$k} = unserialize(serialize($v));
  118. }
  119. }
  120. }
  121. }
  122. /**
  123. * Query Building Class.
  124. *
  125. * @package Joomla.Platform
  126. * @subpackage Database
  127. * @since 11.1
  128. *
  129. * @method string q() q($text, $escape = true) Alias for quote method
  130. * @method string qn() qs($name, $as = null) Alias for quoteName method
  131. * @method string e() e($text, $extra = false) Alias for escape method
  132. * @property-read JDatabaseQueryElement $type
  133. * @property-read JDatabaseQueryElement $select
  134. * @property-read JDatabaseQueryElement $group
  135. * @property-read JDatabaseQueryElement $having
  136. */
  137. abstract class JDatabaseQuery
  138. {
  139. /**
  140. * @var JDatabaseDriver The database driver.
  141. * @since 11.1
  142. */
  143. protected $db = null;
  144. /**
  145. * @var string The SQL query (if a direct query string was provided).
  146. * @since 12.1
  147. */
  148. protected $sql = null;
  149. /**
  150. * @var string The query type.
  151. * @since 11.1
  152. */
  153. protected $type = '';
  154. /**
  155. * @var JDatabaseQueryElement The query element for a generic query (type = null).
  156. * @since 11.1
  157. */
  158. protected $element = null;
  159. /**
  160. * @var JDatabaseQueryElement The select element.
  161. * @since 11.1
  162. */
  163. protected $select = null;
  164. /**
  165. * @var JDatabaseQueryElement The delete element.
  166. * @since 11.1
  167. */
  168. protected $delete = null;
  169. /**
  170. * @var JDatabaseQueryElement The update element.
  171. * @since 11.1
  172. */
  173. protected $update = null;
  174. /**
  175. * @var JDatabaseQueryElement The insert element.
  176. * @since 11.1
  177. */
  178. protected $insert = null;
  179. /**
  180. * @var JDatabaseQueryElement The from element.
  181. * @since 11.1
  182. */
  183. protected $from = null;
  184. /**
  185. * @var JDatabaseQueryElement The join element.
  186. * @since 11.1
  187. */
  188. protected $join = null;
  189. /**
  190. * @var JDatabaseQueryElement The set element.
  191. * @since 11.1
  192. */
  193. protected $set = null;
  194. /**
  195. * @var JDatabaseQueryElement The where element.
  196. * @since 11.1
  197. */
  198. protected $where = null;
  199. /**
  200. * @var JDatabaseQueryElement The group by element.
  201. * @since 11.1
  202. */
  203. protected $group = null;
  204. /**
  205. * @var JDatabaseQueryElement The having element.
  206. * @since 11.1
  207. */
  208. protected $having = null;
  209. /**
  210. * @var JDatabaseQueryElement The column list for an INSERT statement.
  211. * @since 11.1
  212. */
  213. protected $columns = null;
  214. /**
  215. * @var JDatabaseQueryElement The values list for an INSERT statement.
  216. * @since 11.1
  217. */
  218. protected $values = null;
  219. /**
  220. * @var JDatabaseQueryElement The order element.
  221. * @since 11.1
  222. */
  223. protected $order = null;
  224. /**
  225. * @var object The auto increment insert field element.
  226. * @since 11.1
  227. */
  228. protected $autoIncrementField = null;
  229. /**
  230. * @var JDatabaseQueryElement The call element.
  231. * @since 12.1
  232. */
  233. protected $call = null;
  234. /**
  235. * @var JDatabaseQueryElement The exec element.
  236. * @since 12.1
  237. */
  238. protected $exec = null;
  239. /**
  240. * @var JDatabaseQueryElement The union element.
  241. * @since 12.1
  242. */
  243. protected $union = null;
  244. /**
  245. * @var JDatabaseQueryElement The unionAll element.
  246. * @since 13.1
  247. */
  248. protected $unionAll = null;
  249. /**
  250. * Magic method to provide method alias support for quote() and quoteName().
  251. *
  252. * @param string $method The called method.
  253. * @param array $args The array of arguments passed to the method.
  254. *
  255. * @return string The aliased method's return value or null.
  256. *
  257. * @since 11.1
  258. */
  259. public function __call($method, $args)
  260. {
  261. if (empty($args))
  262. {
  263. return;
  264. }
  265. switch ($method)
  266. {
  267. case 'q':
  268. return $this->quote($args[0], isset($args[1]) ? $args[1] : true);
  269. break;
  270. case 'qn':
  271. return $this->quoteName($args[0], isset($args[1]) ? $args[1] : null);
  272. break;
  273. case 'e':
  274. return $this->escape($args[0], isset($args[1]) ? $args[1] : false);
  275. break;
  276. }
  277. }
  278. /**
  279. * Class constructor.
  280. *
  281. * @param JDatabaseDriver $db The database driver.
  282. *
  283. * @since 11.1
  284. */
  285. public function __construct(JDatabaseDriver $db = null)
  286. {
  287. $this->db = $db;
  288. }
  289. /**
  290. * Magic function to convert the query to a string.
  291. *
  292. * @return string The completed query.
  293. *
  294. * @since 11.1
  295. */
  296. public function __toString()
  297. {
  298. $query = '';
  299. if ($this->sql)
  300. {
  301. return $this->sql;
  302. }
  303. switch ($this->type)
  304. {
  305. case 'element':
  306. $query .= (string) $this->element;
  307. break;
  308. case 'select':
  309. $query .= (string) $this->select;
  310. $query .= (string) $this->from;
  311. if ($this->join)
  312. {
  313. // Special case for joins
  314. foreach ($this->join as $join)
  315. {
  316. $query .= (string) $join;
  317. }
  318. }
  319. if ($this->where)
  320. {
  321. $query .= (string) $this->where;
  322. }
  323. if ($this->group)
  324. {
  325. $query .= (string) $this->group;
  326. }
  327. if ($this->having)
  328. {
  329. $query .= (string) $this->having;
  330. }
  331. if ($this->order)
  332. {
  333. $query .= (string) $this->order;
  334. }
  335. break;
  336. case 'union':
  337. $query .= (string) $this->union;
  338. break;
  339. case 'unionAll':
  340. $query .= (string) $this->unionAll;
  341. break;
  342. case 'delete':
  343. $query .= (string) $this->delete;
  344. $query .= (string) $this->from;
  345. if ($this->join)
  346. {
  347. // Special case for joins
  348. foreach ($this->join as $join)
  349. {
  350. $query .= (string) $join;
  351. }
  352. }
  353. if ($this->where)
  354. {
  355. $query .= (string) $this->where;
  356. }
  357. break;
  358. case 'update':
  359. $query .= (string) $this->update;
  360. if ($this->join)
  361. {
  362. // Special case for joins
  363. foreach ($this->join as $join)
  364. {
  365. $query .= (string) $join;
  366. }
  367. }
  368. $query .= (string) $this->set;
  369. if ($this->where)
  370. {
  371. $query .= (string) $this->where;
  372. }
  373. break;
  374. case 'insert':
  375. $query .= (string) $this->insert;
  376. // Set method
  377. if ($this->set)
  378. {
  379. $query .= (string) $this->set;
  380. }
  381. // Columns-Values method
  382. elseif ($this->values)
  383. {
  384. if ($this->columns)
  385. {
  386. $query .= (string) $this->columns;
  387. }
  388. $elements = $this->values->getElements();
  389. if (!($elements[0] instanceof $this))
  390. {
  391. $query .= ' VALUES ';
  392. }
  393. $query .= (string) $this->values;
  394. }
  395. break;
  396. case 'call':
  397. $query .= (string) $this->call;
  398. break;
  399. case 'exec':
  400. $query .= (string) $this->exec;
  401. break;
  402. }
  403. if ($this instanceof JDatabaseQueryLimitable)
  404. {
  405. $query = $this->processLimit($query, $this->limit, $this->offset);
  406. }
  407. return $query;
  408. }
  409. /**
  410. * Magic function to get protected variable value
  411. *
  412. * @param string $name The name of the variable.
  413. *
  414. * @return mixed
  415. *
  416. * @since 11.1
  417. */
  418. public function __get($name)
  419. {
  420. return isset($this->$name) ? $this->$name : null;
  421. }
  422. /**
  423. * Add a single column, or array of columns to the CALL clause of the query.
  424. *
  425. * Note that you must not mix insert, update, delete and select method calls when building a query.
  426. * The call method can, however, be called multiple times in the same query.
  427. *
  428. * Usage:
  429. * $query->call('a.*')->call('b.id');
  430. * $query->call(array('a.*', 'b.id'));
  431. *
  432. * @param mixed $columns A string or an array of field names.
  433. *
  434. * @return JDatabaseQuery Returns this object to allow chaining.
  435. *
  436. * @since 12.1
  437. */
  438. public function call($columns)
  439. {
  440. $this->type = 'call';
  441. if (is_null($this->call))
  442. {
  443. $this->call = new JDatabaseQueryElement('CALL', $columns);
  444. }
  445. else
  446. {
  447. $this->call->append($columns);
  448. }
  449. return $this;
  450. }
  451. /**
  452. * Casts a value to a char.
  453. *
  454. * Ensure that the value is properly quoted before passing to the method.
  455. *
  456. * Usage:
  457. * $query->select($query->castAsChar('a'));
  458. *
  459. * @param string $value The value to cast as a char.
  460. *
  461. * @return string Returns the cast value.
  462. *
  463. * @since 11.1
  464. */
  465. public function castAsChar($value)
  466. {
  467. return $value;
  468. }
  469. /**
  470. * Gets the number of characters in a string.
  471. *
  472. * Note, use 'length' to find the number of bytes in a string.
  473. *
  474. * Usage:
  475. * $query->select($query->charLength('a'));
  476. *
  477. * @param string $field A value.
  478. * @param string $operator Comparison operator between charLength integer value and $condition
  479. * @param string $condition Integer value to compare charLength with.
  480. *
  481. * @return string The required char length call.
  482. *
  483. * @since 11.1
  484. */
  485. public function charLength($field, $operator = null, $condition = null)
  486. {
  487. return 'CHAR_LENGTH(' . $field . ')' . (isset($operator) && isset($condition) ? ' ' . $operator . ' ' . $condition : '');
  488. }
  489. /**
  490. * Clear data from the query or a specific clause of the query.
  491. *
  492. * @param string $clause Optionally, the name of the clause to clear, or nothing to clear the whole query.
  493. *
  494. * @return JDatabaseQuery Returns this object to allow chaining.
  495. *
  496. * @since 11.1
  497. */
  498. public function clear($clause = null)
  499. {
  500. $this->sql = null;
  501. switch ($clause)
  502. {
  503. case 'select':
  504. $this->select = null;
  505. $this->type = null;
  506. break;
  507. case 'delete':
  508. $this->delete = null;
  509. $this->type = null;
  510. break;
  511. case 'update':
  512. $this->update = null;
  513. $this->type = null;
  514. break;
  515. case 'insert':
  516. $this->insert = null;
  517. $this->type = null;
  518. $this->autoIncrementField = null;
  519. break;
  520. case 'from':
  521. $this->from = null;
  522. break;
  523. case 'join':
  524. $this->join = null;
  525. break;
  526. case 'set':
  527. $this->set = null;
  528. break;
  529. case 'where':
  530. $this->where = null;
  531. break;
  532. case 'group':
  533. $this->group = null;
  534. break;
  535. case 'having':
  536. $this->having = null;
  537. break;
  538. case 'order':
  539. $this->order = null;
  540. break;
  541. case 'columns':
  542. $this->columns = null;
  543. break;
  544. case 'values':
  545. $this->values = null;
  546. break;
  547. case 'exec':
  548. $this->exec = null;
  549. $this->type = null;
  550. break;
  551. case 'call':
  552. $this->call = null;
  553. $this->type = null;
  554. break;
  555. case 'limit':
  556. $this->offset = 0;
  557. $this->limit = 0;
  558. break;
  559. case 'union':
  560. $this->union = null;
  561. break;
  562. case 'unionAll':
  563. $this->unionAll = null;
  564. break;
  565. default:
  566. $this->type = null;
  567. $this->select = null;
  568. $this->delete = null;
  569. $this->update = null;
  570. $this->insert = null;
  571. $this->from = null;
  572. $this->join = null;
  573. $this->set = null;
  574. $this->where = null;
  575. $this->group = null;
  576. $this->having = null;
  577. $this->order = null;
  578. $this->columns = null;
  579. $this->values = null;
  580. $this->autoIncrementField = null;
  581. $this->exec = null;
  582. $this->call = null;
  583. $this->union = null;
  584. $this->unionAll = null;
  585. $this->offset = 0;
  586. $this->limit = 0;
  587. break;
  588. }
  589. return $this;
  590. }
  591. /**
  592. * Adds a column, or array of column names that would be used for an INSERT INTO statement.
  593. *
  594. * @param mixed $columns A column name, or array of column names.
  595. *
  596. * @return JDatabaseQuery Returns this object to allow chaining.
  597. *
  598. * @since 11.1
  599. */
  600. public function columns($columns)
  601. {
  602. if (is_null($this->columns))
  603. {
  604. $this->columns = new JDatabaseQueryElement('()', $columns);
  605. }
  606. else
  607. {
  608. $this->columns->append($columns);
  609. }
  610. return $this;
  611. }
  612. /**
  613. * Concatenates an array of column names or values.
  614. *
  615. * Usage:
  616. * $query->select($query->concatenate(array('a', 'b')));
  617. *
  618. * @param array $values An array of values to concatenate.
  619. * @param string $separator As separator to place between each value.
  620. *
  621. * @return string The concatenated values.
  622. *
  623. * @since 11.1
  624. */
  625. public function concatenate($values, $separator = null)
  626. {
  627. if ($separator)
  628. {
  629. return 'CONCATENATE(' . implode(' || ' . $this->quote($separator) . ' || ', $values) . ')';
  630. }
  631. else
  632. {
  633. return 'CONCATENATE(' . implode(' || ', $values) . ')';
  634. }
  635. }
  636. /**
  637. * Gets the current date and time.
  638. *
  639. * Usage:
  640. * $query->where('published_up < '.$query->currentTimestamp());
  641. *
  642. * @return string
  643. *
  644. * @since 11.1
  645. */
  646. public function currentTimestamp()
  647. {
  648. return 'CURRENT_TIMESTAMP()';
  649. }
  650. /**
  651. * Returns a PHP date() function compliant date format for the database driver.
  652. *
  653. * This method is provided for use where the query object is passed to a function for modification.
  654. * If you have direct access to the database object, it is recommended you use the getDateFormat method directly.
  655. *
  656. * @return string The format string.
  657. *
  658. * @since 11.1
  659. */
  660. public function dateFormat()
  661. {
  662. if (!($this->db instanceof JDatabaseDriver))
  663. {
  664. throw new RuntimeException('JLIB_DATABASE_ERROR_INVALID_DB_OBJECT');
  665. }
  666. return $this->db->getDateFormat();
  667. }
  668. /**
  669. * Creates a formatted dump of the query for debugging purposes.
  670. *
  671. * Usage:
  672. * echo $query->dump();
  673. *
  674. * @return string
  675. *
  676. * @since 11.3
  677. */
  678. public function dump()
  679. {
  680. return '<pre class="jdatabasequery">' . str_replace('#__', $this->db->getPrefix(), $this) . '</pre>';
  681. }
  682. /**
  683. * Add a table name to the DELETE clause of the query.
  684. *
  685. * Note that you must not mix insert, update, delete and select method calls when building a query.
  686. *
  687. * Usage:
  688. * $query->delete('#__a')->where('id = 1');
  689. *
  690. * @param string $table The name of the table to delete from.
  691. *
  692. * @return JDatabaseQuery Returns this object to allow chaining.
  693. *
  694. * @since 11.1
  695. */
  696. public function delete($table = null)
  697. {
  698. $this->type = 'delete';
  699. $this->delete = new JDatabaseQueryElement('DELETE', null);
  700. if (!empty($table))
  701. {
  702. $this->from($table);
  703. }
  704. return $this;
  705. }
  706. /**
  707. * Method to escape a string for usage in an SQL statement.
  708. *
  709. * This method is provided for use where the query object is passed to a function for modification.
  710. * If you have direct access to the database object, it is recommended you use the escape method directly.
  711. *
  712. * Note that 'e' is an alias for this method as it is in JDatabaseDriver.
  713. *
  714. * @param string $text The string to be escaped.
  715. * @param boolean $extra Optional parameter to provide extra escaping.
  716. *
  717. * @return string The escaped string.
  718. *
  719. * @since 11.1
  720. * @throws RuntimeException if the internal db property is not a valid object.
  721. */
  722. public function escape($text, $extra = false)
  723. {
  724. if (!($this->db instanceof JDatabaseDriver))
  725. {
  726. throw new RuntimeException('JLIB_DATABASE_ERROR_INVALID_DB_OBJECT');
  727. }
  728. return $this->db->escape($text, $extra);
  729. }
  730. /**
  731. * Add a single column, or array of columns to the EXEC clause of the query.
  732. *
  733. * Note that you must not mix insert, update, delete and select method calls when building a query.
  734. * The exec method can, however, be called multiple times in the same query.
  735. *
  736. * Usage:
  737. * $query->exec('a.*')->exec('b.id');
  738. * $query->exec(array('a.*', 'b.id'));
  739. *
  740. * @param mixed $columns A string or an array of field names.
  741. *
  742. * @return JDatabaseQuery Returns this object to allow chaining.
  743. *
  744. * @since 12.1
  745. */
  746. public function exec($columns)
  747. {
  748. $this->type = 'exec';
  749. if (is_null($this->exec))
  750. {
  751. $this->exec = new JDatabaseQueryElement('EXEC', $columns);
  752. }
  753. else
  754. {
  755. $this->exec->append($columns);
  756. }
  757. return $this;
  758. }
  759. /**
  760. * Add a table to the FROM clause of the query.
  761. *
  762. * Note that while an array of tables can be provided, it is recommended you use explicit joins.
  763. *
  764. * Usage:
  765. * $query->select('*')->from('#__a');
  766. *
  767. * @param mixed $tables A string or array of table names.
  768. * This can be a JDatabaseQuery object (or a child of it) when used
  769. * as a subquery in FROM clause along with a value for $subQueryAlias.
  770. * @param string $subQueryAlias Alias used when $tables is a JDatabaseQuery.
  771. *
  772. * @return JDatabaseQuery Returns this object to allow chaining.
  773. *
  774. * @throws RuntimeException
  775. *
  776. * @since 11.1
  777. */
  778. public function from($tables, $subQueryAlias = null)
  779. {
  780. if (is_null($this->from))
  781. {
  782. if ($tables instanceof $this)
  783. {
  784. if (is_null($subQueryAlias))
  785. {
  786. throw new RuntimeException('JLIB_DATABASE_ERROR_NULL_SUBQUERY_ALIAS');
  787. }
  788. $tables = '( ' . (string) $tables . ' ) AS ' . $this->quoteName($subQueryAlias);
  789. }
  790. $this->from = new JDatabaseQueryElement('FROM', $tables);
  791. }
  792. else
  793. {
  794. $this->from->append($tables);
  795. }
  796. return $this;
  797. }
  798. /**
  799. * Used to get a string to extract year from date column.
  800. *
  801. * Usage:
  802. * $query->select($query->year($query->quoteName('dateColumn')));
  803. *
  804. * @param string $date Date column containing year to be extracted.
  805. *
  806. * @return string Returns string to extract year from a date.
  807. *
  808. * @since 12.1
  809. */
  810. public function year($date)
  811. {
  812. return 'YEAR(' . $date . ')';
  813. }
  814. /**
  815. * Used to get a string to extract month from date column.
  816. *
  817. * Usage:
  818. * $query->select($query->month($query->quoteName('dateColumn')));
  819. *
  820. * @param string $date Date column containing month to be extracted.
  821. *
  822. * @return string Returns string to extract month from a date.
  823. *
  824. * @since 12.1
  825. */
  826. public function month($date)
  827. {
  828. return 'MONTH(' . $date . ')';
  829. }
  830. /**
  831. * Used to get a string to extract day from date column.
  832. *
  833. * Usage:
  834. * $query->select($query->day($query->quoteName('dateColumn')));
  835. *
  836. * @param string $date Date column containing day to be extracted.
  837. *
  838. * @return string Returns string to extract day from a date.
  839. *
  840. * @since 12.1
  841. */
  842. public function day($date)
  843. {
  844. return 'DAY(' . $date . ')';
  845. }
  846. /**
  847. * Used to get a string to extract hour from date column.
  848. *
  849. * Usage:
  850. * $query->select($query->hour($query->quoteName('dateColumn')));
  851. *
  852. * @param string $date Date column containing hour to be extracted.
  853. *
  854. * @return string Returns string to extract hour from a date.
  855. *
  856. * @since 12.1
  857. */
  858. public function hour($date)
  859. {
  860. return 'HOUR(' . $date . ')';
  861. }
  862. /**
  863. * Used to get a string to extract minute from date column.
  864. *
  865. * Usage:
  866. * $query->select($query->minute($query->quoteName('dateColumn')));
  867. *
  868. * @param string $date Date column containing minute to be extracted.
  869. *
  870. * @return string Returns string to extract minute from a date.
  871. *
  872. * @since 12.1
  873. */
  874. public function minute($date)
  875. {
  876. return 'MINUTE(' . $date . ')';
  877. }
  878. /**
  879. * Used to get a string to extract seconds from date column.
  880. *
  881. * Usage:
  882. * $query->select($query->second($query->quoteName('dateColumn')));
  883. *
  884. * @param string $date Date column containing second to be extracted.
  885. *
  886. * @return string Returns string to extract second from a date.
  887. *
  888. * @since 12.1
  889. */
  890. public function second($date)
  891. {
  892. return 'SECOND(' . $date . ')';
  893. }
  894. /**
  895. * Add a grouping column to the GROUP clause of the query.
  896. *
  897. * Usage:
  898. * $query->group('id');
  899. *
  900. * @param mixed $columns A string or array of ordering columns.
  901. *
  902. * @return JDatabaseQuery Returns this object to allow chaining.
  903. *
  904. * @since 11.1
  905. */
  906. public function group($columns)
  907. {
  908. if (is_null($this->group))
  909. {
  910. $this->group = new JDatabaseQueryElement('GROUP BY', $columns);
  911. }
  912. else
  913. {
  914. $this->group->append($columns);
  915. }
  916. return $this;
  917. }
  918. /**
  919. * A conditions to the HAVING clause of the query.
  920. *
  921. * Usage:
  922. * $query->group('id')->having('COUNT(id) > 5');
  923. *
  924. * @param mixed $conditions A string or array of columns.
  925. * @param string $glue The glue by which to join the conditions. Defaults to AND.
  926. *
  927. * @return JDatabaseQuery Returns this object to allow chaining.
  928. *
  929. * @since 11.1
  930. */
  931. public function having($conditions, $glue = 'AND')
  932. {
  933. if (is_null($this->having))
  934. {
  935. $glue = strtoupper($glue);
  936. $this->having = new JDatabaseQueryElement('HAVING', $conditions, " $glue ");
  937. }
  938. else
  939. {
  940. $this->having->append($conditions);
  941. }
  942. return $this;
  943. }
  944. /**
  945. * Add an INNER JOIN clause to the query.
  946. *
  947. * Usage:
  948. * $query->innerJoin('b ON b.id = a.id')->innerJoin('c ON c.id = b.id');
  949. *
  950. * @param string $condition The join condition.
  951. *
  952. * @return JDatabaseQuery Returns this object to allow chaining.
  953. *
  954. * @since 11.1
  955. */
  956. public function innerJoin($condition)
  957. {
  958. $this->join('INNER', $condition);
  959. return $this;
  960. }
  961. /**
  962. * Add a table name to the INSERT clause of the query.
  963. *
  964. * Note that you must not mix insert, update, delete and select method calls when building a query.
  965. *
  966. * Usage:
  967. * $query->insert('#__a')->set('id = 1');
  968. * $query->insert('#__a')->columns('id, title')->values('1,2')->values('3,4');
  969. * $query->insert('#__a')->columns('id, title')->values(array('1,2', '3,4'));
  970. *
  971. * @param mixed $table The name of the table to insert data into.
  972. * @param boolean $incrementField The name of the field to auto increment.
  973. *
  974. * @return JDatabaseQuery Returns this object to allow chaining.
  975. *
  976. * @since 11.1
  977. */
  978. public function insert($table, $incrementField=false)
  979. {
  980. $this->type = 'insert';
  981. $this->insert = new JDatabaseQueryElement('INSERT INTO', $table);
  982. $this->autoIncrementField = $incrementField;
  983. return $this;
  984. }
  985. /**
  986. * Add a JOIN clause to the query.
  987. *
  988. * Usage:
  989. * $query->join('INNER', 'b ON b.id = a.id);
  990. *
  991. * @param string $type The type of join. This string is prepended to the JOIN keyword.
  992. * @param string $conditions A string or array of conditions.
  993. *
  994. * @return JDatabaseQuery Returns this object to allow chaining.
  995. *
  996. * @since 11.1
  997. */
  998. public function join($type, $conditions)
  999. {
  1000. if (is_null($this->join))
  1001. {
  1002. $this->join = array();
  1003. }
  1004. $this->join[] = new JDatabaseQueryElement(strtoupper($type) . ' JOIN', $conditions);
  1005. return $this;
  1006. }
  1007. /**
  1008. * Add a LEFT JOIN clause to the query.
  1009. *
  1010. * Usage:
  1011. * $query->leftJoin('b ON b.id = a.id')->leftJoin('c ON c.id = b.id');
  1012. *
  1013. * @param string $condition The join condition.
  1014. *
  1015. * @return JDatabaseQuery Returns this object to allow chaining.
  1016. *
  1017. * @since 11.1
  1018. */
  1019. public function leftJoin($condition)
  1020. {
  1021. $this->join('LEFT', $condition);
  1022. return $this;
  1023. }
  1024. /**
  1025. * Get the length of a string in bytes.
  1026. *
  1027. * Note, use 'charLength' to find the number of characters in a string.
  1028. *
  1029. * Usage:
  1030. * query->where($query->length('a').' > 3');
  1031. *
  1032. * @param string $value The string to measure.
  1033. *
  1034. * @return int
  1035. *
  1036. * @since 11.1
  1037. */
  1038. public function length($value)
  1039. {
  1040. return 'LENGTH(' . $value . ')';
  1041. }
  1042. /**
  1043. * Get the null or zero representation of a timestamp for the database driver.
  1044. *
  1045. * This method is provided for use where the query object is passed to a function for modification.
  1046. * If you have direct access to the database object, it is recommended you use the nullDate method directly.
  1047. *
  1048. * Usage:
  1049. * $query->where('modified_date <> '.$query->nullDate());
  1050. *
  1051. * @param boolean $quoted Optionally wraps the null date in database quotes (true by default).
  1052. *
  1053. * @return string Null or zero representation of a timestamp.
  1054. *
  1055. * @since 11.1
  1056. */
  1057. public function nullDate($quoted = true)
  1058. {
  1059. if (!($this->db instanceof JDatabaseDriver))
  1060. {
  1061. throw new RuntimeException('JLIB_DATABASE_ERROR_INVALID_DB_OBJECT');
  1062. }
  1063. $result = $this->db->getNullDate($quoted);
  1064. if ($quoted)
  1065. {
  1066. return $this->db->quote($result);
  1067. }
  1068. return $result;
  1069. }
  1070. /**
  1071. * Add a ordering column to the ORDER clause of the query.
  1072. *
  1073. * Usage:
  1074. * $query->order('foo')->order('bar');
  1075. * $query->order(array('foo','bar'));
  1076. *
  1077. * @param mixed $columns A string or array of ordering columns.
  1078. *
  1079. * @return JDatabaseQuery Returns this object to allow chaining.
  1080. *
  1081. * @since 11.1
  1082. */
  1083. public function order($columns)
  1084. {
  1085. if (is_null($this->order))
  1086. {
  1087. $this->order = new JDatabaseQueryElement('ORDER BY', $columns);
  1088. }
  1089. else
  1090. {
  1091. $this->order->append($columns);
  1092. }
  1093. return $this;
  1094. }
  1095. /**
  1096. * Add an OUTER JOIN clause to the query.
  1097. *
  1098. * Usage:
  1099. * $query->outerJoin('b ON b.id = a.id')->outerJoin('c ON c.id = b.id');
  1100. *
  1101. * @param string $condition The join condition.
  1102. *
  1103. * @return JDatabaseQuery Returns this object to allow chaining.
  1104. *
  1105. * @since 11.1
  1106. */
  1107. public function outerJoin($condition)
  1108. {
  1109. $this->join('OUTER', $condition);
  1110. return $this;
  1111. }
  1112. /**
  1113. * Method to quote and optionally escape a string to database requirements for insertion into the database.
  1114. *
  1115. * This method is provided for use where the query object is passed to a function for modification.
  1116. * If you have direct access to the database object, it is recommended you use the quote method directly.
  1117. *
  1118. * Note that 'q' is an alias for this method as it is in JDatabaseDriver.
  1119. *
  1120. * Usage:
  1121. * $query->quote('fulltext');
  1122. * $query->q('fulltext');
  1123. * $query->q(array('option', 'fulltext'));
  1124. *
  1125. * @param mixed $text A string or an array of strings to quote.
  1126. * @param boolean $escape True to escape the string, false to leave it unchanged.
  1127. *
  1128. * @return string The quoted input string.
  1129. *
  1130. * @since 11.1
  1131. * @throws RuntimeException if the internal db property is not a valid object.
  1132. */
  1133. public function quote($text, $escape = true)
  1134. {
  1135. if (!($this->db instanceof JDatabaseDriver))
  1136. {
  1137. throw new RuntimeException('JLIB_DATABASE_ERROR_INVALID_DB_OBJECT');
  1138. }
  1139. return $this->db->quote($text, $escape);
  1140. }
  1141. /**
  1142. * Wrap an SQL statement identifier name such as column, table or database names in quotes to prevent injection
  1143. * risks and reserved word conflicts.
  1144. *
  1145. * This method is provided for use where the query object is passed to a function for modification.
  1146. * If you have direct access to the database object, it is recommended you use the quoteName method directly.
  1147. *
  1148. * Note that 'qn' is an alias for this method as it is in JDatabaseDriver.
  1149. *
  1150. * Usage:
  1151. * $query->quoteName('#__a');
  1152. * $query->qn('#__a');
  1153. *
  1154. * @param mixed $name The identifier name to wrap in quotes, or an array of identifier names to wrap in quotes.
  1155. * Each type supports dot-notation name.
  1156. * @param mixed $as The AS query part associated to $name. It can be string or array, in latter case it has to be
  1157. * same length of $name; if is null there will not be any AS part for string or array element.
  1158. *
  1159. * @return mixed The quote wrapped name, same type of $name.
  1160. *
  1161. * @since 11.1
  1162. * @throws RuntimeException if the internal db property is not a valid object.
  1163. */
  1164. public function quoteName($name, $as = null)
  1165. {
  1166. if (!($this->db instanceof JDatabaseDriver))
  1167. {
  1168. throw new RuntimeException('JLIB_DATABASE_ERROR_INVALID_DB_OBJECT');
  1169. }
  1170. return $this->db->quoteName($name, $as);
  1171. }
  1172. /**
  1173. * Add a RIGHT JOIN clause to the query.
  1174. *
  1175. * Usage:
  1176. * $query->rightJoin('b ON b.id = a.id')->rightJoin('c ON c.id = b.id');
  1177. *
  1178. * @param string $condition The join condition.
  1179. *
  1180. * @return JDatabaseQuery Returns this object to allow chaining.
  1181. *
  1182. * @since 11.1
  1183. */
  1184. public function rightJoin($condition)
  1185. {
  1186. $this->join('RIGHT', $condition);
  1187. return $this;
  1188. }
  1189. /**
  1190. * Add a single column, or array of columns to the SELECT clause of the query.
  1191. *
  1192. * Note that you must not mix insert, update, delete and select method calls when building a query.
  1193. * The select method can, however, be called multiple times in the same query.
  1194. *
  1195. * Usage:
  1196. * $query->select('a.*')->select('b.id');
  1197. * $query->select(array('a.*', 'b.id'));
  1198. *
  1199. * @param mixed $columns A string or an array of field names.
  1200. *
  1201. * @return JDatabaseQuery Returns this object to allow chaining.
  1202. *
  1203. * @since 11.1
  1204. */
  1205. public function select($columns)
  1206. {
  1207. $this->type = 'select';
  1208. if (is_null($this->select))
  1209. {
  1210. $this->select = new JDatabaseQueryElement('SELECT', $columns);
  1211. }
  1212. else
  1213. {
  1214. $this->select->append($columns);
  1215. }
  1216. return $this;
  1217. }
  1218. /**
  1219. * Add a single condition string, or an array of strings to the SET clause of the query.
  1220. *
  1221. * Usage:
  1222. * $query->set('a = 1')->set('b = 2');
  1223. * $query->set(array('a = 1', 'b = 2');
  1224. *
  1225. * @param mixed $conditions A string or array of string conditions.
  1226. * @param string $glue The glue by which to join the condition strings. Defaults to ,.
  1227. * Note that the glue is set on first use and cannot be changed.
  1228. *
  1229. * @return JDatabaseQuery Returns this object to allow chaining.
  1230. *
  1231. * @since 11.1
  1232. */
  1233. public function set($conditions, $glue = ',')
  1234. {
  1235. if (is_null($this->set))
  1236. {
  1237. $glue = strtoupper($glue);
  1238. $this->set = new JDatabaseQueryElement('SET', $conditions, "\n\t$glue ");
  1239. }
  1240. else
  1241. {
  1242. $this->set->append($conditions);
  1243. }
  1244. return $this;
  1245. }
  1246. /**
  1247. * Allows a direct query to be provided to the database
  1248. * driver's setQuery() method, but still allow queries
  1249. * to have bounded variables.
  1250. *
  1251. * Usage:
  1252. * $query->setQuery('select * from #__users');
  1253. *
  1254. * @param mixed $sql An SQL Query
  1255. *
  1256. * @return JDatabaseQuery Returns this object to allow chaining.
  1257. *
  1258. * @since 12.1
  1259. */
  1260. public function setQuery($sql)
  1261. {
  1262. $this->sql = $sql;
  1263. return $this;
  1264. }
  1265. /**
  1266. * Add a table name to the UPDATE clause of the query.
  1267. *
  1268. * Note that you must not mix insert, update, delete and select method calls when building a query.
  1269. *
  1270. * Usage:
  1271. * $query->update('#__foo')->set(...);
  1272. *
  1273. * @param string $table A table to update.
  1274. *
  1275. * @return JDatabaseQuery Returns this object to allow chaining.
  1276. *
  1277. * @since 11.1
  1278. */
  1279. public function update($table)
  1280. {
  1281. $this->type = 'update';
  1282. $this->update = new JDatabaseQueryElement('UPDATE', $table);
  1283. return $this;
  1284. }
  1285. /**
  1286. * Adds a tuple, or array of tuples that would be used as values for an INSERT INTO statement.
  1287. *
  1288. * Usage:
  1289. * $query->values('1,2,3')->values('4,5,6');
  1290. * $query->values(array('1,2,3', '4,5,6'));
  1291. *
  1292. * @param string $values A single tuple, or array of tuples.
  1293. *
  1294. * @return JDatabaseQuery Returns this object to allow chaining.
  1295. *
  1296. * @since 11.1
  1297. */
  1298. public function values($values)
  1299. {
  1300. if (is_null($this->values))
  1301. {
  1302. $this->values = new JDatabaseQueryElement('()', $values, '),(');
  1303. }
  1304. else
  1305. {
  1306. $this->values->append($values);
  1307. }
  1308. return $this;
  1309. }
  1310. /**
  1311. * Add a single condition, or an array of conditions to the WHERE clause of the query.
  1312. *
  1313. * Usage:
  1314. * $query->where('a = 1')->where('b = 2');
  1315. * $query->where(array('a = 1', 'b = 2'));
  1316. *
  1317. * @param mixed $conditions A string or array of where conditions.
  1318. * @param string $glue The glue by which to join the conditions. Defaults to AND.
  1319. * Note that the glue is set on first use and cannot be changed.
  1320. *
  1321. * @return JDatabaseQuery Returns this object to allow chaining.
  1322. *
  1323. * @since 11.1
  1324. */
  1325. public function where($conditions, $glue = 'AND')
  1326. {
  1327. if (is_null($this->where))
  1328. {
  1329. $glue = strtoupper($glue);
  1330. $this->where = new JDatabaseQueryElement('WHERE', $conditions, " $glue ");
  1331. }
  1332. else
  1333. {
  1334. $this->where->append($conditions);
  1335. }
  1336. return $this;
  1337. }
  1338. /**
  1339. * Method to provide deep copy support to nested objects and
  1340. * arrays when cloning.
  1341. *
  1342. * @return void
  1343. *
  1344. * @since 11.3
  1345. */
  1346. public function __clone()
  1347. {
  1348. foreach ($this as $k => $v)
  1349. {
  1350. if ($k === 'db')
  1351. {
  1352. continue;
  1353. }
  1354. if (is_object($v) || is_array($v))
  1355. {
  1356. $this->{$k} = unserialize(serialize($v));
  1357. }
  1358. }
  1359. }
  1360. /**
  1361. * Add a query to UNION with the current query.
  1362. * Multiple unions each require separate statements and create an array of unions.
  1363. *
  1364. * Usage:
  1365. * $query->union('SELECT name FROM #__foo')
  1366. * $query->union('SELECT name FROM #__foo','distinct')
  1367. * $query->union(array('SELECT name FROM #__foo','SELECT name FROM #__bar'))
  1368. *
  1369. * @param mixed $query The JDatabaseQuery object or string to union.
  1370. * @param boolean $distinct True to only return distinct rows from the union.
  1371. * @param string $glue The glue by which to join the conditions.
  1372. *
  1373. * @return mixed The JDatabaseQuery object on success or boolean false on failure.
  1374. *
  1375. * @since 12.1
  1376. */
  1377. public function union($query, $distinct = false, $glue = '')
  1378. {
  1379. // Clear any ORDER BY clause in UNION query
  1380. // See http://dev.mysql.com/doc/refman/5.0/en/union.html
  1381. if (!is_null($this->order))
  1382. {
  1383. $this->clear('order');
  1384. }
  1385. // Set up the DISTINCT flag, the name with parentheses, and the glue.
  1386. if ($distinct)
  1387. {
  1388. $name = 'UNION DISTINCT ()';
  1389. $glue = ')' . PHP_EOL . 'UNION DISTINCT (';
  1390. }
  1391. else
  1392. {
  1393. $glue = ')' . PHP_EOL . 'UNION (';
  1394. $name = 'UNION ()';
  1395. }
  1396. // Get the JDatabaseQueryElement if it does not exist
  1397. if (is_null($this->union))
  1398. {
  1399. $this->union = new JDatabaseQueryElement($name, $query, "$glue");
  1400. }
  1401. // Otherwise append the second UNION.
  1402. else
  1403. {
  1404. $this->union->append($query);
  1405. }
  1406. return $this;
  1407. }
  1408. /**
  1409. * Add a query to UNION DISTINCT with the current query. Simply a proxy to Union with the Distinct clause.
  1410. *
  1411. * Usage:
  1412. * $query->unionDistinct('SELECT name FROM #__foo')
  1413. *
  1414. * @param mixed $query The JDatabaseQuery object or string to union.
  1415. * @param string $glue The glue by which to join the conditions.
  1416. *
  1417. * @return mixed The JDatabaseQuery object on success or boolean false on failure.
  1418. *
  1419. * @since 12.1
  1420. */
  1421. public function unionDistinct($query, $glue = '')
  1422. {
  1423. $distinct = true;
  1424. // Apply the distinct flag to the union.
  1425. return $this->union($query, $distinct, $glue);
  1426. }
  1427. /**
  1428. * Find and replace sprintf-like tokens in a format string.
  1429. * Each token takes one of the following forms:
  1430. * %% - A literal percent character.
  1431. * %[t] - Where [t] is a type specifier.
  1432. * %[n]$[x] - Where [n] is an argument specifier and [t] is a type specifier.
  1433. *
  1434. * Types:
  1435. * a - Numeric: Replacement text is coerced to a numeric type but not quoted or escaped.
  1436. * e - Escape: Replacement text is passed to $this->escape().
  1437. * E - Escape (extra): Replacement text is passed to $this->escape() with true as the second argument.
  1438. * n - Name Quote: Replacement text is passed to $this->quoteName().
  1439. * q - Quote: Replacement text is passed to $this->quote().
  1440. * Q - Quote (no escape): Replacement text is passed to $this->quote() with false as the second argument.
  1441. * r - Raw: Replacement text is used as-is. (Be careful)
  1442. *
  1443. * Date Types:
  1444. * - Replacement text automatically quoted (use uppercase for Name Quote).
  1445. * - Replacement text should be a string in date format or name of a date column.
  1446. * y/Y - Year
  1447. * m/M - Month
  1448. * d/D - Day
  1449. * h/H - Hour
  1450. * i/I - Minute
  1451. * s/S - Second
  1452. *
  1453. * Invariable Types:
  1454. * - Takes no argument.
  1455. * - Argument index not incremented.
  1456. * t - Replacement text is the result of $this->currentTimestamp().
  1457. * z - Replacement text is the result of $this->nullDate(false).
  1458. * Z - Replacement text is the result of $this->nullDate(true).
  1459. *
  1460. * Usage:
  1461. * $query->format('SELECT %1$n FROM %2$n WHERE %3$n = %4$a', 'foo', '#__foo', 'bar', 1);
  1462. * Returns: SELECT `foo` FROM `#__foo` WHERE `bar` = 1
  1463. *
  1464. * Notes:
  1465. * The argument specifier is optional but recommended for clarity.
  1466. * The argument index used for unspecified tokens is incremented only when used.
  1467. *
  1468. * @param string $format The formatting string.
  1469. *
  1470. * @return string Returns a string produced according to the formatting string.
  1471. *
  1472. * @since 12.3
  1473. */
  1474. public function format($format)
  1475. {
  1476. $query = $this;
  1477. $args = array_slice(func_get_args(), 1);
  1478. array_unshift($args, null);
  1479. $i = 1;
  1480. $func = function ($match) use ($query, $args, &$i)
  1481. {
  1482. if (isset($match[6]) && $match[6] == '%')
  1483. {
  1484. return '%';
  1485. }
  1486. // No argument required, do not increment the argument index.
  1487. switch ($match[5])
  1488. {
  1489. case 't':
  1490. return $query->currentTimestamp();
  1491. break;
  1492. case 'z':
  1493. return $query->nullDate(false);
  1494. break;
  1495. case 'Z':
  1496. return $query->nullDate(true);
  1497. break;
  1498. }
  1499. // Increment the argument index only if argument specifier not provided.
  1500. $index = is_numeric($match[4]) ? (int) $match[4] : $i++;
  1501. if (!$index || !isset($args[$index]))
  1502. {
  1503. // TODO - What to do? sprintf() throws a Warning in these cases.
  1504. $replacement = '';
  1505. }
  1506. else
  1507. {
  1508. $replacement = $args[$index];
  1509. }
  1510. switch ($match[5])
  1511. {
  1512. case 'a':
  1513. return 0 + $replacement;
  1514. break;
  1515. case 'e':
  1516. return $query->escape($replacement);
  1517. break;
  1518. case 'E':
  1519. return $query->escape($replacement, true);
  1520. break;
  1521. case 'n':
  1522. return $query->quoteName($replacement);
  1523. break;
  1524. case 'q':
  1525. return $query->quote($replacement);
  1526. break;
  1527. case 'Q':
  1528. return $query->quote($replacement, false);
  1529. break;
  1530. case 'r':
  1531. return $replacement;
  1532. break;
  1533. // Dates
  1534. case 'y':
  1535. return $query->year($query->quote($replacement));
  1536. break;
  1537. case 'Y':
  1538. return $query->year($query->quoteName($replacement));
  1539. break;
  1540. case 'm':
  1541. return $query->month($query->quote($replacement));
  1542. break;
  1543. case 'M':
  1544. return $query->month($query->quoteName($replacement));
  1545. break;
  1546. case 'd':
  1547. return $query->day($query->quote($replacement));
  1548. break;
  1549. case 'D':
  1550. return $query->day($query->quoteName($replacement));
  1551. break;
  1552. case 'h':
  1553. return $query->hour($query->quote($replacement));
  1554. break;
  1555. case 'H':
  1556. return $query->hour($query->quoteName($replacement));
  1557. break;
  1558. case 'i':
  1559. return $query->minute($query->quote($replacement));
  1560. break;
  1561. case 'I':
  1562. return $query->minute($query->quoteName($replacement));
  1563. break;
  1564. case 's':
  1565. return $query->second($query->quote($replacement));
  1566. break;
  1567. case 'S':
  1568. return $query->second($query->quoteName($replacement));
  1569. break;
  1570. }
  1571. return '';
  1572. };
  1573. /**
  1574. * Regexp to find an replace all tokens.
  1575. * Matched fields:
  1576. * 0: Full token
  1577. * 1: Everything following '%'
  1578. * 2: Everything following '%' unless '%'
  1579. * 3: Argument specifier and '$'
  1580. * 4: Argument specifier
  1581. * 5: Type specifier
  1582. * 6: '%' if full token is '%%'
  1583. */
  1584. return preg_replace_callback('#%(((([\d]+)\$)?([aeEnqQryYmMdDhHiIsStzZ]))|(%))#', $func, $format);
  1585. }
  1586. /**
  1587. * Add to the current date and time.
  1588. * Usage:
  1589. * $query->select($query->dateAdd());
  1590. * Prefixing the interval with a - (negative sign) will cause subtraction to be used.
  1591. * Note: Not all drivers support all units.
  1592. *
  1593. * @param datetime $date The date to add to. May be date or datetime
  1594. * @param string $interval The string representation of the appropriate number of units
  1595. * @param string $datePart The part of the date to perform the addition on
  1596. *
  1597. * @return string The string with the appropriate sql for addition of dates
  1598. *
  1599. * @see http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_date-add
  1600. * @since 13.1
  1601. */
  1602. public function dateAdd($date, $interval, $datePart)
  1603. {
  1604. return trim("DATE_ADD('" . $date . "', INTERVAL " . $interval . ' ' . $datePart . ')');
  1605. }
  1606. /**
  1607. * Add a query to UNION ALL with the current query.
  1608. * Multiple unions each require separate statements and create an array of unions.
  1609. *
  1610. * Usage:
  1611. * $query->union('SELECT name FROM #__foo')
  1612. * $query->union('SELECT name FROM #__foo','distinct')
  1613. * $query->union(array('SELECT name FROM #__foo','SELECT name FROM #__bar'))
  1614. *
  1615. * @param mixed $query The JDatabaseQuery object or string to union.
  1616. * @param boolean $distinct True to only return distinct rows from the union.
  1617. * @param string $glue The glue by which to join the conditions.
  1618. *
  1619. * @return mixed The JDatabaseQuery object on success or boolean false on failure.
  1620. *
  1621. * @since 13.1
  1622. */
  1623. public function unionAll($query, $distinct = false, $glue = '')
  1624. {
  1625. $glue = ')' . PHP_EOL . 'UNION ALL (';
  1626. $name = 'UNION ALL ()';
  1627. // Get the JDatabaseQueryElement if it does not exist
  1628. if (is_null($this->unionAll))
  1629. {
  1630. $this->unionAll = new JDatabaseQueryElement($name, $query, "$glue");
  1631. }
  1632. // Otherwise append the second UNION.
  1633. else
  1634. {
  1635. $this->unionAll->append($query);
  1636. }
  1637. return $this;
  1638. }
  1639. }