Source for file query.php

Documentation is available at query.php

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

Documentation generated on Tue, 19 Nov 2013 15:11:32 +0100 by phpDocumentor 1.4.3