Added the zend framework 2 library, the path is specified in line no.26 in zend_modul...
[openemr.git] / interface / modules / zend_modules / library / Zend / Db / Sql / Select.php
blobdea84756c0996851a2caa1c0301b766643abc0f9
1 <?php
2 /**
3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
8 */
10 namespace Zend\Db\Sql;
12 use Zend\Db\Adapter\AdapterInterface;
13 use Zend\Db\Adapter\Driver\DriverInterface;
14 use Zend\Db\Adapter\StatementContainerInterface;
15 use Zend\Db\Adapter\ParameterContainer;
16 use Zend\Db\Adapter\Platform\PlatformInterface;
17 use Zend\Db\Adapter\Platform\Sql92 as AdapterSql92Platform;
19 /**
21 * @property Where $where
22 * @property Having $having
24 class Select extends AbstractSql implements SqlInterface, PreparableSqlInterface
26 /**#@+
27 * Constant
28 * @const
30 const SELECT = 'select';
31 const QUANTIFIER = 'quantifier';
32 const COLUMNS = 'columns';
33 const TABLE = 'table';
34 const JOINS = 'joins';
35 const WHERE = 'where';
36 const GROUP = 'group';
37 const HAVING = 'having';
38 const ORDER = 'order';
39 const LIMIT = 'limit';
40 const OFFSET = 'offset';
41 const QUANTIFIER_DISTINCT = 'DISTINCT';
42 const QUANTIFIER_ALL = 'ALL';
43 const JOIN_INNER = 'inner';
44 const JOIN_OUTER = 'outer';
45 const JOIN_LEFT = 'left';
46 const JOIN_RIGHT = 'right';
47 const SQL_STAR = '*';
48 const ORDER_ASCENDING = 'ASC';
49 const ORDER_DESCENDING = 'DESC';
50 const COMBINE = 'combine';
51 const COMBINE_UNION = 'union';
52 const COMBINE_EXCEPT = 'except';
53 const COMBINE_INTERSECT = 'intersect';
54 /**#@-*/
56 /**
57 * @var array Specifications
59 protected $specifications = array(
60 'statementStart' => '%1$s',
61 self::SELECT => array(
62 'SELECT %1$s FROM %2$s' => array(
63 array(1 => '%1$s', 2 => '%1$s AS %2$s', 'combinedby' => ', '),
64 null
66 'SELECT %1$s %2$s FROM %3$s' => array(
67 null,
68 array(1 => '%1$s', 2 => '%1$s AS %2$s', 'combinedby' => ', '),
69 null
72 self::JOINS => array(
73 '%1$s' => array(
74 array(3 => '%1$s JOIN %2$s ON %3$s', 'combinedby' => ' ')
77 self::WHERE => 'WHERE %1$s',
78 self::GROUP => array(
79 'GROUP BY %1$s' => array(
80 array(1 => '%1$s', 'combinedby' => ', ')
83 self::HAVING => 'HAVING %1$s',
84 self::ORDER => array(
85 'ORDER BY %1$s' => array(
86 array(1 => '%1$s', 2 => '%1$s %2$s', 'combinedby' => ', ')
89 self::LIMIT => 'LIMIT %1$s',
90 self::OFFSET => 'OFFSET %1$s',
91 'statementEnd' => '%1$s',
92 self::COMBINE => '%1$s ( %2$s )',
95 /**
96 * @var bool
98 protected $tableReadOnly = false;
101 * @var bool
103 protected $prefixColumnsWithTable = true;
106 * @var string|array|TableIdentifier
108 protected $table = null;
111 * @var null|string|Expression
113 protected $quantifier = null;
116 * @var array
118 protected $columns = array(self::SQL_STAR);
121 * @var array
123 protected $joins = array();
126 * @var Where
128 protected $where = null;
131 * @var null|string
133 protected $order = array();
136 * @var null|array
138 protected $group = null;
141 * @var null|string|array
143 protected $having = null;
146 * @var int|null
148 protected $limit = null;
151 * @var int|null
153 protected $offset = null;
156 * @var array
158 protected $combine = array();
161 * Constructor
163 * @param null|string|array|TableIdentifier $table
165 public function __construct($table = null)
167 if ($table) {
168 $this->from($table);
169 $this->tableReadOnly = true;
172 $this->where = new Where;
173 $this->having = new Having;
177 * Create from clause
179 * @param string|array|TableIdentifier $table
180 * @throws Exception\InvalidArgumentException
181 * @return Select
183 public function from($table)
185 if ($this->tableReadOnly) {
186 throw new Exception\InvalidArgumentException('Since this object was created with a table and/or schema in the constructor, it is read only.');
189 if (!is_string($table) && !is_array($table) && !$table instanceof TableIdentifier) {
190 throw new Exception\InvalidArgumentException('$table must be a string, array, or an instance of TableIdentifier');
193 if (is_array($table) && (!is_string(key($table)) || count($table) !== 1)) {
194 throw new Exception\InvalidArgumentException('from() expects $table as an array is a single element associative array');
197 $this->table = $table;
198 return $this;
202 * @param string|Expression $quantifier DISTINCT|ALL
203 * @return Select
205 public function quantifier($quantifier)
207 if (!is_string($quantifier) && !$quantifier instanceof Expression) {
208 throw new Exception\InvalidArgumentException(
209 'Quantifier must be one of DISTINCT, ALL, or some platform specific Expression object'
212 $this->quantifier = $quantifier;
213 return $this;
217 * Specify columns from which to select
219 * Possible valid states:
221 * array(*)
223 * array(value, ...)
224 * value can be strings or Expression objects
226 * array(string => value, ...)
227 * key string will be use as alias,
228 * value can be string or Expression objects
230 * @param array $columns
231 * @param bool $prefixColumnsWithTable
232 * @return Select
234 public function columns(array $columns, $prefixColumnsWithTable = true)
236 $this->columns = $columns;
237 $this->prefixColumnsWithTable = (bool) $prefixColumnsWithTable;
238 return $this;
242 * Create join clause
244 * @param string|array $name
245 * @param string $on
246 * @param string|array $columns
247 * @param string $type one of the JOIN_* constants
248 * @throws Exception\InvalidArgumentException
249 * @return Select
251 public function join($name, $on, $columns = self::SQL_STAR, $type = self::JOIN_INNER)
253 if (is_array($name) && (!is_string(key($name)) || count($name) !== 1)) {
254 throw new Exception\InvalidArgumentException(
255 sprintf("join() expects '%s' as an array is a single element associative array", array_shift($name))
258 if (!is_array($columns)) {
259 $columns = array($columns);
261 $this->joins[] = array(
262 'name' => $name,
263 'on' => $on,
264 'columns' => $columns,
265 'type' => $type
267 return $this;
271 * Create where clause
273 * @param Where|\Closure|string|array|Predicate\PredicateInterface $predicate
274 * @param string $combination One of the OP_* constants from Predicate\PredicateSet
275 * @throws Exception\InvalidArgumentException
276 * @return Select
278 public function where($predicate, $combination = Predicate\PredicateSet::OP_AND)
280 if ($predicate instanceof Where) {
281 $this->where = $predicate;
282 } elseif ($predicate instanceof Predicate\PredicateInterface) {
283 $this->where->addPredicate($predicate, $combination);
284 } elseif ($predicate instanceof \Closure) {
285 $predicate($this->where);
286 } else {
287 if (is_string($predicate)) {
288 // String $predicate should be passed as an expression
289 $predicate = (strpos($predicate, Expression::PLACEHOLDER) !== false)
290 ? new Predicate\Expression($predicate) : new Predicate\Literal($predicate);
291 $this->where->addPredicate($predicate, $combination);
292 } elseif (is_array($predicate)) {
294 foreach ($predicate as $pkey => $pvalue) {
295 // loop through predicates
297 if (is_string($pkey) && strpos($pkey, '?') !== false) {
298 // First, process strings that the abstraction replacement character ?
299 // as an Expression predicate
300 $predicate = new Predicate\Expression($pkey, $pvalue);
302 } elseif (is_string($pkey)) {
303 // Otherwise, if still a string, do something intelligent with the PHP type provided
305 if ($pvalue === null) {
306 // map PHP null to SQL IS NULL expression
307 $predicate = new Predicate\IsNull($pkey, $pvalue);
308 } elseif (is_array($pvalue)) {
309 // if the value is an array, assume IN() is desired
310 $predicate = new Predicate\In($pkey, $pvalue);
311 } elseif ($pvalue instanceof Predicate\PredicateInterface) {
313 throw new Exception\InvalidArgumentException(
314 'Using Predicate must not use string keys'
316 } else {
317 // otherwise assume that array('foo' => 'bar') means "foo" = 'bar'
318 $predicate = new Predicate\Operator($pkey, Predicate\Operator::OP_EQ, $pvalue);
320 } elseif ($pvalue instanceof Predicate\PredicateInterface) {
321 // Predicate type is ok
322 $predicate = $pvalue;
323 } else {
324 // must be an array of expressions (with int-indexed array)
325 $predicate = (strpos($pvalue, Expression::PLACEHOLDER) !== false)
326 ? new Predicate\Expression($pvalue) : new Predicate\Literal($pvalue);
328 $this->where->addPredicate($predicate, $combination);
332 return $this;
335 public function group($group)
337 if (is_array($group)) {
338 foreach ($group as $o) {
339 $this->group[] = $o;
341 } else {
342 $this->group[] = $group;
344 return $this;
348 * Create where clause
350 * @param Where|\Closure|string|array $predicate
351 * @param string $combination One of the OP_* constants from Predicate\PredicateSet
352 * @return Select
354 public function having($predicate, $combination = Predicate\PredicateSet::OP_AND)
356 if ($predicate instanceof Having) {
357 $this->having = $predicate;
358 } elseif ($predicate instanceof \Closure) {
359 $predicate($this->having);
360 } else {
361 if (is_string($predicate)) {
362 $predicate = new Predicate\Expression($predicate);
363 $this->having->addPredicate($predicate, $combination);
364 } elseif (is_array($predicate)) {
365 foreach ($predicate as $pkey => $pvalue) {
366 if (is_string($pkey) && strpos($pkey, '?') !== false) {
367 $predicate = new Predicate\Expression($pkey, $pvalue);
368 } elseif (is_string($pkey)) {
369 $predicate = new Predicate\Operator($pkey, Predicate\Operator::OP_EQ, $pvalue);
370 } else {
371 $predicate = new Predicate\Expression($pvalue);
373 $this->having->addPredicate($predicate, $combination);
377 return $this;
381 * @param string|array $order
382 * @return Select
384 public function order($order)
386 if (is_string($order)) {
387 if (strpos($order, ',') !== false) {
388 $order = preg_split('#,\s+#', $order);
389 } else {
390 $order = (array) $order;
392 } elseif (!is_array($order)) {
393 $order = array($order);
395 foreach ($order as $k => $v) {
396 if (is_string($k)) {
397 $this->order[$k] = $v;
398 } else {
399 $this->order[] = $v;
402 return $this;
406 * @param int $limit
407 * @return Select
409 public function limit($limit)
411 if (!is_numeric($limit)) {
412 throw new Exception\InvalidArgumentException(sprintf(
413 '%s expects parameter to be numeric, "%s" given',
414 __METHOD__,
415 (is_object($limit) ? get_class($limit) : gettype($limit))
419 $this->limit = $limit;
420 return $this;
424 * @param int $offset
425 * @return Select
427 public function offset($offset)
429 if (!is_numeric($offset)) {
430 throw new Exception\InvalidArgumentException(sprintf(
431 '%s expects parameter to be numeric, "%s" given',
432 __METHOD__,
433 (is_object($offset) ? get_class($offset) : gettype($offset))
437 $this->offset = $offset;
438 return $this;
442 * @param Select $select
443 * @param string $type
444 * @param string $modifier
445 * @return Select
446 * @throws Exception\InvalidArgumentException
448 public function combine(Select $select, $type = self::COMBINE_UNION, $modifier = '')
450 if ($this->combine !== array()) {
451 throw new Exception\InvalidArgumentException('This Select object is already combined and cannot be combined with multiple Selects objects');
453 $this->combine = array(
454 'select' => $select,
455 'type' => $type,
456 'modifier' => $modifier
458 return $this;
462 * @param string $part
463 * @return Select
464 * @throws Exception\InvalidArgumentException
466 public function reset($part)
468 switch ($part) {
469 case self::TABLE:
470 if ($this->tableReadOnly) {
471 throw new Exception\InvalidArgumentException(
472 'Since this object was created with a table and/or schema in the constructor, it is read only.'
475 $this->table = null;
476 break;
477 case self::QUANTIFIER:
478 $this->quantifier = null;
479 break;
480 case self::COLUMNS:
481 $this->columns = array();
482 break;
483 case self::JOINS:
484 $this->joins = array();
485 break;
486 case self::WHERE:
487 $this->where = new Where;
488 break;
489 case self::GROUP:
490 $this->group = null;
491 break;
492 case self::HAVING:
493 $this->having = new Having;
494 break;
495 case self::LIMIT:
496 $this->limit = null;
497 break;
498 case self::OFFSET:
499 $this->offset = null;
500 break;
501 case self::ORDER:
502 $this->order = null;
503 break;
504 case self::COMBINE:
505 $this->combine = array();
506 break;
508 return $this;
511 public function setSpecification($index, $specification)
513 if (!method_exists($this, 'process' . $index)) {
514 throw new Exception\InvalidArgumentException('Not a valid specification name.');
516 $this->specifications[$index] = $specification;
517 return $this;
520 public function getRawState($key = null)
522 $rawState = array(
523 self::TABLE => $this->table,
524 self::QUANTIFIER => $this->quantifier,
525 self::COLUMNS => $this->columns,
526 self::JOINS => $this->joins,
527 self::WHERE => $this->where,
528 self::ORDER => $this->order,
529 self::GROUP => $this->group,
530 self::HAVING => $this->having,
531 self::LIMIT => $this->limit,
532 self::OFFSET => $this->offset,
533 self::COMBINE => $this->combine
535 return (isset($key) && array_key_exists($key, $rawState)) ? $rawState[$key] : $rawState;
539 * Prepare statement
541 * @param AdapterInterface $adapter
542 * @param StatementContainerInterface $statementContainer
543 * @return void
545 public function prepareStatement(AdapterInterface $adapter, StatementContainerInterface $statementContainer)
547 // ensure statement has a ParameterContainer
548 $parameterContainer = $statementContainer->getParameterContainer();
549 if (!$parameterContainer instanceof ParameterContainer) {
550 $parameterContainer = new ParameterContainer();
551 $statementContainer->setParameterContainer($parameterContainer);
554 $sqls = array();
555 $parameters = array();
556 $platform = $adapter->getPlatform();
557 $driver = $adapter->getDriver();
559 foreach ($this->specifications as $name => $specification) {
560 $parameters[$name] = $this->{'process' . $name}($platform, $driver, $parameterContainer, $sqls, $parameters);
561 if ($specification && is_array($parameters[$name])) {
562 $sqls[$name] = $this->createSqlFromSpecificationAndParameters($specification, $parameters[$name]);
566 $sql = implode(' ', $sqls);
568 $statementContainer->setSql($sql);
569 return;
573 * Get SQL string for statement
575 * @param null|PlatformInterface $adapterPlatform If null, defaults to Sql92
576 * @return string
578 public function getSqlString(PlatformInterface $adapterPlatform = null)
580 // get platform, or create default
581 $adapterPlatform = ($adapterPlatform) ?: new AdapterSql92Platform;
583 $sqls = array();
584 $parameters = array();
586 foreach ($this->specifications as $name => $specification) {
587 $parameters[$name] = $this->{'process' . $name}($adapterPlatform, null, null, $sqls, $parameters);
588 if ($specification && is_array($parameters[$name])) {
589 $sqls[$name] = $this->createSqlFromSpecificationAndParameters($specification, $parameters[$name]);
593 $sql = implode(' ', $sqls);
594 return $sql;
598 * Returns whether the table is read only or not.
600 * @return bool
602 public function isTableReadOnly()
604 return $this->tableReadOnly;
608 * Render table with alias in from/join parts
610 * @todo move TableIdentifier concatination here
611 * @param string $table
612 * @param string $alias
613 * @return string
615 protected function renderTable($table, $alias = null)
617 $sql = $table;
618 if ($alias) {
619 $sql .= ' AS ' . $alias;
621 return $sql;
624 protected function processStatementStart(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null)
626 if ($this->combine !== array()) {
627 return array('(');
631 protected function processStatementEnd(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null)
633 if ($this->combine !== array()) {
634 return array(')');
639 * Process the select part
641 * @param PlatformInterface $platform
642 * @param DriverInterface $driver
643 * @param ParameterContainer $parameterContainer
644 * @return null|array
646 protected function processSelect(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null)
648 $expr = 1;
650 if (!$this->table) {
651 return null;
654 $table = $this->table;
655 $schema = $alias = null;
657 if (is_array($table)) {
658 $alias = key($this->table);
659 $table = current($this->table);
662 // create quoted table name to use in columns processing
663 if ($table instanceof TableIdentifier) {
664 list($table, $schema) = $table->getTableAndSchema();
667 if ($table instanceof Select) {
668 $table = '(' . $this->processSubselect($table, $platform, $driver, $parameterContainer) . ')';
669 } else {
670 $table = $platform->quoteIdentifier($table);
673 if ($schema) {
674 $table = $platform->quoteIdentifier($schema) . $platform->getIdentifierSeparator() . $table;
677 if ($alias) {
678 $fromTable = $platform->quoteIdentifier($alias);
679 $table = $this->renderTable($table, $fromTable);
680 } else {
681 $fromTable = $table;
684 if ($this->prefixColumnsWithTable) {
685 $fromTable .= $platform->getIdentifierSeparator();
686 } else {
687 $fromTable = '';
690 // process table columns
691 $columns = array();
692 foreach ($this->columns as $columnIndexOrAs => $column) {
694 $columnName = '';
695 if ($column === self::SQL_STAR) {
696 $columns[] = array($fromTable . self::SQL_STAR);
697 continue;
700 if ($column instanceof Expression) {
701 $columnParts = $this->processExpression(
702 $column,
703 $platform,
704 $driver,
705 $this->processInfo['paramPrefix'] . ((is_string($columnIndexOrAs)) ? $columnIndexOrAs : 'column')
707 if ($parameterContainer) {
708 $parameterContainer->merge($columnParts->getParameterContainer());
710 $columnName .= $columnParts->getSql();
711 } else {
712 $columnName .= $fromTable . $platform->quoteIdentifier($column);
715 // process As portion
716 if (is_string($columnIndexOrAs)) {
717 $columnAs = $platform->quoteIdentifier($columnIndexOrAs);
718 } elseif (stripos($columnName, ' as ') === false) {
719 $columnAs = (is_string($column)) ? $platform->quoteIdentifier($column) : 'Expression' . $expr++;
721 $columns[] = (isset($columnAs)) ? array($columnName, $columnAs) : array($columnName);
724 $separator = $platform->getIdentifierSeparator();
726 // process join columns
727 foreach ($this->joins as $join) {
728 foreach ($join['columns'] as $jKey => $jColumn) {
729 $jColumns = array();
730 if ($jColumn instanceof ExpressionInterface) {
731 $jColumnParts = $this->processExpression(
732 $jColumn,
733 $platform,
734 $driver,
735 $this->processInfo['paramPrefix'] . ((is_string($jKey)) ? $jKey : 'column')
737 if ($parameterContainer) {
738 $parameterContainer->merge($jColumnParts->getParameterContainer());
740 $jColumns[] = $jColumnParts->getSql();
741 } else {
742 $name = (is_array($join['name'])) ? key($join['name']) : $name = $join['name'];
743 if ($name instanceof TableIdentifier) {
744 $name = $platform->quoteIdentifier($name->getSchema()) . $separator . $platform->quoteIdentifier($name->getTable());
745 } else {
746 $name = $platform->quoteIdentifier($name);
748 $jColumns[] = $name . $separator . $platform->quoteIdentifierInFragment($jColumn);
750 if (is_string($jKey)) {
751 $jColumns[] = $platform->quoteIdentifier($jKey);
752 } elseif ($jColumn !== self::SQL_STAR) {
753 $jColumns[] = $platform->quoteIdentifier($jColumn);
755 $columns[] = $jColumns;
759 if ($this->quantifier) {
760 if ($this->quantifier instanceof Expression) {
761 $quantifierParts = $this->processExpression($this->quantifier, $platform, $driver, 'quantifier');
762 if ($parameterContainer) {
763 $parameterContainer->merge($quantifierParts->getParameterContainer());
765 $quantifier = $quantifierParts->getSql();
766 } else {
767 $quantifier = $this->quantifier;
771 if (isset($quantifier)) {
772 return array($quantifier, $columns, $table);
773 } else {
774 return array($columns, $table);
778 protected function processJoins(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null)
780 if (!$this->joins) {
781 return null;
784 // process joins
785 $joinSpecArgArray = array();
786 foreach ($this->joins as $j => $join) {
787 $joinSpecArgArray[$j] = array();
788 $joinName = null;
789 $joinAs = null;
791 // type
792 $joinSpecArgArray[$j][] = strtoupper($join['type']);
794 // table name
795 if (is_array($join['name'])) {
796 $joinName = current($join['name']);
797 $joinAs = $platform->quoteIdentifier(key($join['name']));
798 } else {
799 $joinName = $join['name'];
801 if ($joinName instanceof TableIdentifier) {
802 $joinName = $joinName->getTableAndSchema();
803 $joinName = $platform->quoteIdentifier($joinName[1]) . $platform->getIdentifierSeparator() . $platform->quoteIdentifier($joinName[0]);
804 } else {
805 if ($joinName instanceof Select) {
806 $joinName = '(' . $joinName->processSubSelect($joinName, $platform, $driver, $parameterContainer) . ')';
807 } else {
808 $joinName = $platform->quoteIdentifier($joinName);
811 $joinSpecArgArray[$j][] = (isset($joinAs)) ? $joinName . ' AS ' . $joinAs : $joinName;
813 // on expression
814 // note: for Expression objects, pass them to processExpression with a prefix specific to each join (used for named parameters)
815 $joinSpecArgArray[$j][] = ($join['on'] instanceof ExpressionInterface)
816 ? $this->processExpression($join['on'], $platform, $driver, $this->processInfo['paramPrefix'] . 'join' . ($j+1) . 'part')
817 : $platform->quoteIdentifierInFragment($join['on'], array('=', 'AND', 'OR', '(', ')', 'BETWEEN', '<', '>')); // on
818 if ($joinSpecArgArray[$j][2] instanceof StatementContainerInterface) {
819 if ($parameterContainer) {
820 $parameterContainer->merge($joinSpecArgArray[$j][2]->getParameterContainer());
822 $joinSpecArgArray[$j][2] = $joinSpecArgArray[$j][2]->getSql();
826 return array($joinSpecArgArray);
829 protected function processWhere(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null)
831 if ($this->where->count() == 0) {
832 return null;
834 $whereParts = $this->processExpression($this->where, $platform, $driver, $this->processInfo['paramPrefix'] . 'where');
835 if ($parameterContainer) {
836 $parameterContainer->merge($whereParts->getParameterContainer());
838 return array($whereParts->getSql());
841 protected function processGroup(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null)
843 if ($this->group === null) {
844 return null;
846 // process table columns
847 $groups = array();
848 foreach ($this->group as $column) {
849 $columnSql = '';
850 if ($column instanceof Expression) {
851 $columnParts = $this->processExpression($column, $platform, $driver, $this->processInfo['paramPrefix'] . 'group');
852 if ($parameterContainer) {
853 $parameterContainer->merge($columnParts->getParameterContainer());
855 $columnSql .= $columnParts->getSql();
856 } else {
857 $columnSql .= $platform->quoteIdentifierInFragment($column);
859 $groups[] = $columnSql;
861 return array($groups);
864 protected function processHaving(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null)
866 if ($this->having->count() == 0) {
867 return null;
869 $whereParts = $this->processExpression($this->having, $platform, $driver, $this->processInfo['paramPrefix'] . 'having');
870 if ($parameterContainer) {
871 $parameterContainer->merge($whereParts->getParameterContainer());
873 return array($whereParts->getSql());
876 protected function processOrder(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null)
878 if (empty($this->order)) {
879 return null;
881 $orders = array();
882 foreach ($this->order as $k => $v) {
883 if ($v instanceof Expression) {
884 /** @var $orderParts \Zend\Db\Adapter\StatementContainer */
885 $orderParts = $this->processExpression($v, $platform, $driver);
886 if ($parameterContainer) {
887 $parameterContainer->merge($orderParts->getParameterContainer());
889 $orders[] = array($orderParts->getSql());
890 continue;
892 if (is_int($k)) {
893 if (strpos($v, ' ') !== false) {
894 list($k, $v) = preg_split('# #', $v, 2);
895 } else {
896 $k = $v;
897 $v = self::ORDER_ASCENDING;
900 if (strtoupper($v) == self::ORDER_DESCENDING) {
901 $orders[] = array($platform->quoteIdentifierInFragment($k), self::ORDER_DESCENDING);
902 } else {
903 $orders[] = array($platform->quoteIdentifierInFragment($k), self::ORDER_ASCENDING);
906 return array($orders);
909 protected function processLimit(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null)
911 if ($this->limit === null) {
912 return null;
915 $limit = (int) $this->limit;
917 if ($driver) {
918 $sql = $driver->formatParameterName('limit');
919 $parameterContainer->offsetSet('limit', $limit, ParameterContainer::TYPE_INTEGER);
920 } else {
921 $sql = $platform->quoteValue($limit);
924 return array($sql);
927 protected function processOffset(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null)
929 if ($this->offset === null) {
930 return null;
933 $offset = (int) $this->offset;
935 if ($driver) {
936 $parameterContainer->offsetSet('offset', $offset, ParameterContainer::TYPE_INTEGER);
937 return array($driver->formatParameterName('offset'));
940 return array($platform->quoteValue($offset));
943 protected function processCombine(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null)
945 if ($this->combine == array()) {
946 return null;
949 $type = $this->combine['type'];
950 if ($this->combine['modifier']) {
951 $type .= ' ' . $this->combine['modifier'];
953 $type = strtoupper($type);
955 if ($driver) {
956 $sql = $this->processSubSelect($this->combine['select'], $platform, $driver, $parameterContainer);
957 return array($type, $sql);
959 return array(
960 $type,
961 $this->processSubSelect($this->combine['select'], $platform)
966 * Variable overloading
968 * @param string $name
969 * @throws Exception\InvalidArgumentException
970 * @return mixed
972 public function __get($name)
974 switch (strtolower($name)) {
975 case 'where':
976 return $this->where;
977 case 'having':
978 return $this->having;
979 default:
980 throw new Exception\InvalidArgumentException('Not a valid magic property for this object');
985 * __clone
987 * Resets the where object each time the Select is cloned.
989 * @return void
991 public function __clone()
993 $this->where = clone $this->where;
994 $this->having = clone $this->having;