composer package updates
[openemr.git] / vendor / doctrine / dbal / lib / Doctrine / DBAL / Query / QueryBuilder.php
blob1e18f9dc2859e9ae135db96b34a8e4127c8cbfa1
1 <?php
2 /*
3 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15 * This software consists of voluntary contributions made by many individuals
16 * and is licensed under the MIT license. For more information, see
17 * <http://www.doctrine-project.org>.
20 namespace Doctrine\DBAL\Query;
22 use Doctrine\DBAL\Query\Expression\CompositeExpression;
23 use Doctrine\DBAL\Connection;
25 /**
26 * QueryBuilder class is responsible to dynamically create SQL queries.
28 * Important: Verify that every feature you use will work with your database vendor.
29 * SQL Query Builder does not attempt to validate the generated SQL at all.
31 * The query builder does no validation whatsoever if certain features even work with the
32 * underlying database vendor. Limit queries and joins are NOT applied to UPDATE and DELETE statements
33 * even if some vendors such as MySQL support it.
35 * @link www.doctrine-project.org
36 * @since 2.1
37 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
38 * @author Benjamin Eberlei <kontakt@beberlei.de>
40 class QueryBuilder
43 * The query types.
45 const SELECT = 0;
46 const DELETE = 1;
47 const UPDATE = 2;
48 const INSERT = 3;
51 * The builder states.
53 const STATE_DIRTY = 0;
54 const STATE_CLEAN = 1;
56 /**
57 * The DBAL Connection.
59 * @var \Doctrine\DBAL\Connection
61 private $connection;
63 /**
64 * @var array The array of SQL parts collected.
66 private $sqlParts = array(
67 'select' => array(),
68 'from' => array(),
69 'join' => array(),
70 'set' => array(),
71 'where' => null,
72 'groupBy' => array(),
73 'having' => null,
74 'orderBy' => array(),
75 'values' => array(),
78 /**
79 * The complete SQL string for this query.
81 * @var string
83 private $sql;
85 /**
86 * The query parameters.
88 * @var array
90 private $params = array();
92 /**
93 * The parameter type map of this query.
95 * @var array
97 private $paramTypes = array();
99 /**
100 * The type of query this is. Can be select, update or delete.
102 * @var integer
104 private $type = self::SELECT;
107 * The state of the query object. Can be dirty or clean.
109 * @var integer
111 private $state = self::STATE_CLEAN;
114 * The index of the first result to retrieve.
116 * @var integer
118 private $firstResult = null;
121 * The maximum number of results to retrieve.
123 * @var integer
125 private $maxResults = null;
128 * The counter of bound parameters used with {@see bindValue).
130 * @var integer
132 private $boundCounter = 0;
135 * Initializes a new <tt>QueryBuilder</tt>.
137 * @param \Doctrine\DBAL\Connection $connection The DBAL Connection.
139 public function __construct(Connection $connection)
141 $this->connection = $connection;
145 * Gets an ExpressionBuilder used for object-oriented construction of query expressions.
146 * This producer method is intended for convenient inline usage. Example:
148 * <code>
149 * $qb = $conn->createQueryBuilder()
150 * ->select('u')
151 * ->from('users', 'u')
152 * ->where($qb->expr()->eq('u.id', 1));
153 * </code>
155 * For more complex expression construction, consider storing the expression
156 * builder object in a local variable.
158 * @return \Doctrine\DBAL\Query\Expression\ExpressionBuilder
160 public function expr()
162 return $this->connection->getExpressionBuilder();
166 * Gets the type of the currently built query.
168 * @return integer
170 public function getType()
172 return $this->type;
176 * Gets the associated DBAL Connection for this query builder.
178 * @return \Doctrine\DBAL\Connection
180 public function getConnection()
182 return $this->connection;
186 * Gets the state of this query builder instance.
188 * @return integer Either QueryBuilder::STATE_DIRTY or QueryBuilder::STATE_CLEAN.
190 public function getState()
192 return $this->state;
196 * Executes this query using the bound parameters and their types.
198 * Uses {@see Connection::executeQuery} for select statements and {@see Connection::executeUpdate}
199 * for insert, update and delete statements.
201 * @return \Doctrine\DBAL\Driver\Statement|int
203 public function execute()
205 if ($this->type == self::SELECT) {
206 return $this->connection->executeQuery($this->getSQL(), $this->params, $this->paramTypes);
207 } else {
208 return $this->connection->executeUpdate($this->getSQL(), $this->params, $this->paramTypes);
213 * Gets the complete SQL string formed by the current specifications of this QueryBuilder.
215 * <code>
216 * $qb = $em->createQueryBuilder()
217 * ->select('u')
218 * ->from('User', 'u')
219 * echo $qb->getSQL(); // SELECT u FROM User u
220 * </code>
222 * @return string The SQL query string.
224 public function getSQL()
226 if ($this->sql !== null && $this->state === self::STATE_CLEAN) {
227 return $this->sql;
230 switch ($this->type) {
231 case self::INSERT:
232 $sql = $this->getSQLForInsert();
233 break;
234 case self::DELETE:
235 $sql = $this->getSQLForDelete();
236 break;
238 case self::UPDATE:
239 $sql = $this->getSQLForUpdate();
240 break;
242 case self::SELECT:
243 default:
244 $sql = $this->getSQLForSelect();
245 break;
248 $this->state = self::STATE_CLEAN;
249 $this->sql = $sql;
251 return $sql;
255 * Sets a query parameter for the query being constructed.
257 * <code>
258 * $qb = $conn->createQueryBuilder()
259 * ->select('u')
260 * ->from('users', 'u')
261 * ->where('u.id = :user_id')
262 * ->setParameter(':user_id', 1);
263 * </code>
265 * @param string|integer $key The parameter position or name.
266 * @param mixed $value The parameter value.
267 * @param string|null $type One of the PDO::PARAM_* constants.
269 * @return $this This QueryBuilder instance.
271 public function setParameter($key, $value, $type = null)
273 if ($type !== null) {
274 $this->paramTypes[$key] = $type;
277 $this->params[$key] = $value;
279 return $this;
283 * Sets a collection of query parameters for the query being constructed.
285 * <code>
286 * $qb = $conn->createQueryBuilder()
287 * ->select('u')
288 * ->from('users', 'u')
289 * ->where('u.id = :user_id1 OR u.id = :user_id2')
290 * ->setParameters(array(
291 * ':user_id1' => 1,
292 * ':user_id2' => 2
293 * ));
294 * </code>
296 * @param array $params The query parameters to set.
297 * @param array $types The query parameters types to set.
299 * @return $this This QueryBuilder instance.
301 public function setParameters(array $params, array $types = array())
303 $this->paramTypes = $types;
304 $this->params = $params;
306 return $this;
310 * Gets all defined query parameters for the query being constructed indexed by parameter index or name.
312 * @return array The currently defined query parameters indexed by parameter index or name.
314 public function getParameters()
316 return $this->params;
320 * Gets a (previously set) query parameter of the query being constructed.
322 * @param mixed $key The key (index or name) of the bound parameter.
324 * @return mixed The value of the bound parameter.
326 public function getParameter($key)
328 return isset($this->params[$key]) ? $this->params[$key] : null;
332 * Gets all defined query parameter types for the query being constructed indexed by parameter index or name.
334 * @return array The currently defined query parameter types indexed by parameter index or name.
336 public function getParameterTypes()
338 return $this->paramTypes;
342 * Gets a (previously set) query parameter type of the query being constructed.
344 * @param mixed $key The key (index or name) of the bound parameter type.
346 * @return mixed The value of the bound parameter type.
348 public function getParameterType($key)
350 return isset($this->paramTypes[$key]) ? $this->paramTypes[$key] : null;
354 * Sets the position of the first result to retrieve (the "offset").
356 * @param integer $firstResult The first result to return.
358 * @return $this This QueryBuilder instance.
360 public function setFirstResult($firstResult)
362 $this->state = self::STATE_DIRTY;
363 $this->firstResult = $firstResult;
365 return $this;
369 * Gets the position of the first result the query object was set to retrieve (the "offset").
370 * Returns NULL if {@link setFirstResult} was not applied to this QueryBuilder.
372 * @return integer The position of the first result.
374 public function getFirstResult()
376 return $this->firstResult;
380 * Sets the maximum number of results to retrieve (the "limit").
382 * @param integer $maxResults The maximum number of results to retrieve.
384 * @return $this This QueryBuilder instance.
386 public function setMaxResults($maxResults)
388 $this->state = self::STATE_DIRTY;
389 $this->maxResults = $maxResults;
391 return $this;
395 * Gets the maximum number of results the query object was set to retrieve (the "limit").
396 * Returns NULL if {@link setMaxResults} was not applied to this query builder.
398 * @return integer The maximum number of results.
400 public function getMaxResults()
402 return $this->maxResults;
406 * Either appends to or replaces a single, generic query part.
408 * The available parts are: 'select', 'from', 'set', 'where',
409 * 'groupBy', 'having' and 'orderBy'.
411 * @param string $sqlPartName
412 * @param string $sqlPart
413 * @param boolean $append
415 * @return $this This QueryBuilder instance.
417 public function add($sqlPartName, $sqlPart, $append = false)
419 $isArray = is_array($sqlPart);
420 $isMultiple = is_array($this->sqlParts[$sqlPartName]);
422 if ($isMultiple && !$isArray) {
423 $sqlPart = array($sqlPart);
426 $this->state = self::STATE_DIRTY;
428 if ($append) {
429 if ($sqlPartName == "orderBy" || $sqlPartName == "groupBy" || $sqlPartName == "select" || $sqlPartName == "set") {
430 foreach ($sqlPart as $part) {
431 $this->sqlParts[$sqlPartName][] = $part;
433 } elseif ($isArray && is_array($sqlPart[key($sqlPart)])) {
434 $key = key($sqlPart);
435 $this->sqlParts[$sqlPartName][$key][] = $sqlPart[$key];
436 } elseif ($isMultiple) {
437 $this->sqlParts[$sqlPartName][] = $sqlPart;
438 } else {
439 $this->sqlParts[$sqlPartName] = $sqlPart;
442 return $this;
445 $this->sqlParts[$sqlPartName] = $sqlPart;
447 return $this;
451 * Specifies an item that is to be returned in the query result.
452 * Replaces any previously specified selections, if any.
454 * <code>
455 * $qb = $conn->createQueryBuilder()
456 * ->select('u.id', 'p.id')
457 * ->from('users', 'u')
458 * ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id');
459 * </code>
461 * @param mixed $select The selection expressions.
463 * @return $this This QueryBuilder instance.
465 public function select($select = null)
467 $this->type = self::SELECT;
469 if (empty($select)) {
470 return $this;
473 $selects = is_array($select) ? $select : func_get_args();
475 return $this->add('select', $selects, false);
479 * Adds an item that is to be returned in the query result.
481 * <code>
482 * $qb = $conn->createQueryBuilder()
483 * ->select('u.id')
484 * ->addSelect('p.id')
485 * ->from('users', 'u')
486 * ->leftJoin('u', 'phonenumbers', 'u.id = p.user_id');
487 * </code>
489 * @param mixed $select The selection expression.
491 * @return $this This QueryBuilder instance.
493 public function addSelect($select = null)
495 $this->type = self::SELECT;
497 if (empty($select)) {
498 return $this;
501 $selects = is_array($select) ? $select : func_get_args();
503 return $this->add('select', $selects, true);
507 * Turns the query being built into a bulk delete query that ranges over
508 * a certain table.
510 * <code>
511 * $qb = $conn->createQueryBuilder()
512 * ->delete('users', 'u')
513 * ->where('u.id = :user_id');
514 * ->setParameter(':user_id', 1);
515 * </code>
517 * @param string $delete The table whose rows are subject to the deletion.
518 * @param string $alias The table alias used in the constructed query.
520 * @return $this This QueryBuilder instance.
522 public function delete($delete = null, $alias = null)
524 $this->type = self::DELETE;
526 if ( ! $delete) {
527 return $this;
530 return $this->add('from', array(
531 'table' => $delete,
532 'alias' => $alias
537 * Turns the query being built into a bulk update query that ranges over
538 * a certain table
540 * <code>
541 * $qb = $conn->createQueryBuilder()
542 * ->update('users', 'u')
543 * ->set('u.password', md5('password'))
544 * ->where('u.id = ?');
545 * </code>
547 * @param string $update The table whose rows are subject to the update.
548 * @param string $alias The table alias used in the constructed query.
550 * @return $this This QueryBuilder instance.
552 public function update($update = null, $alias = null)
554 $this->type = self::UPDATE;
556 if ( ! $update) {
557 return $this;
560 return $this->add('from', array(
561 'table' => $update,
562 'alias' => $alias
567 * Turns the query being built into an insert query that inserts into
568 * a certain table
570 * <code>
571 * $qb = $conn->createQueryBuilder()
572 * ->insert('users')
573 * ->values(
574 * array(
575 * 'name' => '?',
576 * 'password' => '?'
578 * );
579 * </code>
581 * @param string $insert The table into which the rows should be inserted.
583 * @return $this This QueryBuilder instance.
585 public function insert($insert = null)
587 $this->type = self::INSERT;
589 if ( ! $insert) {
590 return $this;
593 return $this->add('from', array(
594 'table' => $insert
599 * Creates and adds a query root corresponding to the table identified by the
600 * given alias, forming a cartesian product with any existing query roots.
602 * <code>
603 * $qb = $conn->createQueryBuilder()
604 * ->select('u.id')
605 * ->from('users', 'u')
606 * </code>
608 * @param string $from The table.
609 * @param string|null $alias The alias of the table.
611 * @return $this This QueryBuilder instance.
613 public function from($from, $alias = null)
615 return $this->add('from', array(
616 'table' => $from,
617 'alias' => $alias
618 ), true);
622 * Creates and adds a join to the query.
624 * <code>
625 * $qb = $conn->createQueryBuilder()
626 * ->select('u.name')
627 * ->from('users', 'u')
628 * ->join('u', 'phonenumbers', 'p', 'p.is_primary = 1');
629 * </code>
631 * @param string $fromAlias The alias that points to a from clause.
632 * @param string $join The table name to join.
633 * @param string $alias The alias of the join table.
634 * @param string $condition The condition for the join.
636 * @return $this This QueryBuilder instance.
638 public function join($fromAlias, $join, $alias, $condition = null)
640 return $this->innerJoin($fromAlias, $join, $alias, $condition);
644 * Creates and adds a join to the query.
646 * <code>
647 * $qb = $conn->createQueryBuilder()
648 * ->select('u.name')
649 * ->from('users', 'u')
650 * ->innerJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
651 * </code>
653 * @param string $fromAlias The alias that points to a from clause.
654 * @param string $join The table name to join.
655 * @param string $alias The alias of the join table.
656 * @param string $condition The condition for the join.
658 * @return $this This QueryBuilder instance.
660 public function innerJoin($fromAlias, $join, $alias, $condition = null)
662 return $this->add('join', array(
663 $fromAlias => array(
664 'joinType' => 'inner',
665 'joinTable' => $join,
666 'joinAlias' => $alias,
667 'joinCondition' => $condition
669 ), true);
673 * Creates and adds a left join to the query.
675 * <code>
676 * $qb = $conn->createQueryBuilder()
677 * ->select('u.name')
678 * ->from('users', 'u')
679 * ->leftJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
680 * </code>
682 * @param string $fromAlias The alias that points to a from clause.
683 * @param string $join The table name to join.
684 * @param string $alias The alias of the join table.
685 * @param string $condition The condition for the join.
687 * @return $this This QueryBuilder instance.
689 public function leftJoin($fromAlias, $join, $alias, $condition = null)
691 return $this->add('join', array(
692 $fromAlias => array(
693 'joinType' => 'left',
694 'joinTable' => $join,
695 'joinAlias' => $alias,
696 'joinCondition' => $condition
698 ), true);
702 * Creates and adds a right join to the query.
704 * <code>
705 * $qb = $conn->createQueryBuilder()
706 * ->select('u.name')
707 * ->from('users', 'u')
708 * ->rightJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
709 * </code>
711 * @param string $fromAlias The alias that points to a from clause.
712 * @param string $join The table name to join.
713 * @param string $alias The alias of the join table.
714 * @param string $condition The condition for the join.
716 * @return $this This QueryBuilder instance.
718 public function rightJoin($fromAlias, $join, $alias, $condition = null)
720 return $this->add('join', array(
721 $fromAlias => array(
722 'joinType' => 'right',
723 'joinTable' => $join,
724 'joinAlias' => $alias,
725 'joinCondition' => $condition
727 ), true);
731 * Sets a new value for a column in a bulk update query.
733 * <code>
734 * $qb = $conn->createQueryBuilder()
735 * ->update('users', 'u')
736 * ->set('u.password', md5('password'))
737 * ->where('u.id = ?');
738 * </code>
740 * @param string $key The column to set.
741 * @param string $value The value, expression, placeholder, etc.
743 * @return $this This QueryBuilder instance.
745 public function set($key, $value)
747 return $this->add('set', $key .' = ' . $value, true);
751 * Specifies one or more restrictions to the query result.
752 * Replaces any previously specified restrictions, if any.
754 * <code>
755 * $qb = $conn->createQueryBuilder()
756 * ->select('u.name')
757 * ->from('users', 'u')
758 * ->where('u.id = ?');
760 * // You can optionally programatically build and/or expressions
761 * $qb = $conn->createQueryBuilder();
763 * $or = $qb->expr()->orx();
764 * $or->add($qb->expr()->eq('u.id', 1));
765 * $or->add($qb->expr()->eq('u.id', 2));
767 * $qb->update('users', 'u')
768 * ->set('u.password', md5('password'))
769 * ->where($or);
770 * </code>
772 * @param mixed $predicates The restriction predicates.
774 * @return $this This QueryBuilder instance.
776 public function where($predicates)
778 if ( ! (func_num_args() == 1 && $predicates instanceof CompositeExpression)) {
779 $predicates = new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args());
782 return $this->add('where', $predicates);
786 * Adds one or more restrictions to the query results, forming a logical
787 * conjunction with any previously specified restrictions.
789 * <code>
790 * $qb = $conn->createQueryBuilder()
791 * ->select('u')
792 * ->from('users', 'u')
793 * ->where('u.username LIKE ?')
794 * ->andWhere('u.is_active = 1');
795 * </code>
797 * @param mixed $where The query restrictions.
799 * @return $this This QueryBuilder instance.
801 * @see where()
803 public function andWhere($where)
805 $args = func_get_args();
806 $where = $this->getQueryPart('where');
808 if ($where instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_AND) {
809 $where->addMultiple($args);
810 } else {
811 array_unshift($args, $where);
812 $where = new CompositeExpression(CompositeExpression::TYPE_AND, $args);
815 return $this->add('where', $where, true);
819 * Adds one or more restrictions to the query results, forming a logical
820 * disjunction with any previously specified restrictions.
822 * <code>
823 * $qb = $em->createQueryBuilder()
824 * ->select('u.name')
825 * ->from('users', 'u')
826 * ->where('u.id = 1')
827 * ->orWhere('u.id = 2');
828 * </code>
830 * @param mixed $where The WHERE statement.
832 * @return $this This QueryBuilder instance.
834 * @see where()
836 public function orWhere($where)
838 $args = func_get_args();
839 $where = $this->getQueryPart('where');
841 if ($where instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_OR) {
842 $where->addMultiple($args);
843 } else {
844 array_unshift($args, $where);
845 $where = new CompositeExpression(CompositeExpression::TYPE_OR, $args);
848 return $this->add('where', $where, true);
852 * Specifies a grouping over the results of the query.
853 * Replaces any previously specified groupings, if any.
855 * <code>
856 * $qb = $conn->createQueryBuilder()
857 * ->select('u.name')
858 * ->from('users', 'u')
859 * ->groupBy('u.id');
860 * </code>
862 * @param mixed $groupBy The grouping expression.
864 * @return $this This QueryBuilder instance.
866 public function groupBy($groupBy)
868 if (empty($groupBy)) {
869 return $this;
872 $groupBy = is_array($groupBy) ? $groupBy : func_get_args();
874 return $this->add('groupBy', $groupBy, false);
879 * Adds a grouping expression to the query.
881 * <code>
882 * $qb = $conn->createQueryBuilder()
883 * ->select('u.name')
884 * ->from('users', 'u')
885 * ->groupBy('u.lastLogin');
886 * ->addGroupBy('u.createdAt')
887 * </code>
889 * @param mixed $groupBy The grouping expression.
891 * @return $this This QueryBuilder instance.
893 public function addGroupBy($groupBy)
895 if (empty($groupBy)) {
896 return $this;
899 $groupBy = is_array($groupBy) ? $groupBy : func_get_args();
901 return $this->add('groupBy', $groupBy, true);
905 * Sets a value for a column in an insert query.
907 * <code>
908 * $qb = $conn->createQueryBuilder()
909 * ->insert('users')
910 * ->values(
911 * array(
912 * 'name' => '?'
915 * ->setValue('password', '?');
916 * </code>
918 * @param string $column The column into which the value should be inserted.
919 * @param string $value The value that should be inserted into the column.
921 * @return $this This QueryBuilder instance.
923 public function setValue($column, $value)
925 $this->sqlParts['values'][$column] = $value;
927 return $this;
931 * Specifies values for an insert query indexed by column names.
932 * Replaces any previous values, if any.
934 * <code>
935 * $qb = $conn->createQueryBuilder()
936 * ->insert('users')
937 * ->values(
938 * array(
939 * 'name' => '?',
940 * 'password' => '?'
942 * );
943 * </code>
945 * @param array $values The values to specify for the insert query indexed by column names.
947 * @return $this This QueryBuilder instance.
949 public function values(array $values)
951 return $this->add('values', $values);
955 * Specifies a restriction over the groups of the query.
956 * Replaces any previous having restrictions, if any.
958 * @param mixed $having The restriction over the groups.
960 * @return $this This QueryBuilder instance.
962 public function having($having)
964 if ( ! (func_num_args() == 1 && $having instanceof CompositeExpression)) {
965 $having = new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args());
968 return $this->add('having', $having);
972 * Adds a restriction over the groups of the query, forming a logical
973 * conjunction with any existing having restrictions.
975 * @param mixed $having The restriction to append.
977 * @return $this This QueryBuilder instance.
979 public function andHaving($having)
981 $args = func_get_args();
982 $having = $this->getQueryPart('having');
984 if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_AND) {
985 $having->addMultiple($args);
986 } else {
987 array_unshift($args, $having);
988 $having = new CompositeExpression(CompositeExpression::TYPE_AND, $args);
991 return $this->add('having', $having);
995 * Adds a restriction over the groups of the query, forming a logical
996 * disjunction with any existing having restrictions.
998 * @param mixed $having The restriction to add.
1000 * @return $this This QueryBuilder instance.
1002 public function orHaving($having)
1004 $args = func_get_args();
1005 $having = $this->getQueryPart('having');
1007 if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_OR) {
1008 $having->addMultiple($args);
1009 } else {
1010 array_unshift($args, $having);
1011 $having = new CompositeExpression(CompositeExpression::TYPE_OR, $args);
1014 return $this->add('having', $having);
1018 * Specifies an ordering for the query results.
1019 * Replaces any previously specified orderings, if any.
1021 * @param string $sort The ordering expression.
1022 * @param string $order The ordering direction.
1024 * @return $this This QueryBuilder instance.
1026 public function orderBy($sort, $order = null)
1028 return $this->add('orderBy', $sort . ' ' . (! $order ? 'ASC' : $order), false);
1032 * Adds an ordering to the query results.
1034 * @param string $sort The ordering expression.
1035 * @param string $order The ordering direction.
1037 * @return $this This QueryBuilder instance.
1039 public function addOrderBy($sort, $order = null)
1041 return $this->add('orderBy', $sort . ' ' . (! $order ? 'ASC' : $order), true);
1045 * Gets a query part by its name.
1047 * @param string $queryPartName
1049 * @return mixed
1051 public function getQueryPart($queryPartName)
1053 return $this->sqlParts[$queryPartName];
1057 * Gets all query parts.
1059 * @return array
1061 public function getQueryParts()
1063 return $this->sqlParts;
1067 * Resets SQL parts.
1069 * @param array|null $queryPartNames
1071 * @return $this This QueryBuilder instance.
1073 public function resetQueryParts($queryPartNames = null)
1075 if (is_null($queryPartNames)) {
1076 $queryPartNames = array_keys($this->sqlParts);
1079 foreach ($queryPartNames as $queryPartName) {
1080 $this->resetQueryPart($queryPartName);
1083 return $this;
1087 * Resets a single SQL part.
1089 * @param string $queryPartName
1091 * @return $this This QueryBuilder instance.
1093 public function resetQueryPart($queryPartName)
1095 $this->sqlParts[$queryPartName] = is_array($this->sqlParts[$queryPartName])
1096 ? array() : null;
1098 $this->state = self::STATE_DIRTY;
1100 return $this;
1104 * @return string
1106 * @throws \Doctrine\DBAL\Query\QueryException
1108 private function getSQLForSelect()
1110 $query = 'SELECT ' . implode(', ', $this->sqlParts['select']);
1112 $query .= ($this->sqlParts['from'] ? ' FROM ' . implode(', ', $this->getFromClauses()) : '')
1113 . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : '')
1114 . ($this->sqlParts['groupBy'] ? ' GROUP BY ' . implode(', ', $this->sqlParts['groupBy']) : '')
1115 . ($this->sqlParts['having'] !== null ? ' HAVING ' . ((string) $this->sqlParts['having']) : '')
1116 . ($this->sqlParts['orderBy'] ? ' ORDER BY ' . implode(', ', $this->sqlParts['orderBy']) : '');
1118 if ($this->isLimitQuery()) {
1119 return $this->connection->getDatabasePlatform()->modifyLimitQuery(
1120 $query,
1121 $this->maxResults,
1122 $this->firstResult
1126 return $query;
1130 * @return string[]
1132 private function getFromClauses()
1134 $fromClauses = array();
1135 $knownAliases = array();
1137 // Loop through all FROM clauses
1138 foreach ($this->sqlParts['from'] as $from) {
1139 if ($from['alias'] === null) {
1140 $tableSql = $from['table'];
1141 $tableReference = $from['table'];
1142 } else {
1143 $tableSql = $from['table'] . ' ' . $from['alias'];
1144 $tableReference = $from['alias'];
1147 $knownAliases[$tableReference] = true;
1149 $fromClauses[$tableReference] = $tableSql . $this->getSQLForJoins($tableReference, $knownAliases);
1152 $this->verifyAllAliasesAreKnown($knownAliases);
1154 return $fromClauses;
1158 * @param array $knownAliases
1160 * @throws QueryException
1162 private function verifyAllAliasesAreKnown(array $knownAliases)
1164 foreach ($this->sqlParts['join'] as $fromAlias => $joins) {
1165 if ( ! isset($knownAliases[$fromAlias])) {
1166 throw QueryException::unknownAlias($fromAlias, array_keys($knownAliases));
1172 * @return bool
1174 private function isLimitQuery()
1176 return $this->maxResults !== null || $this->firstResult !== null;
1180 * Converts this instance into an INSERT string in SQL.
1182 * @return string
1184 private function getSQLForInsert()
1186 return 'INSERT INTO ' . $this->sqlParts['from']['table'] .
1187 ' (' . implode(', ', array_keys($this->sqlParts['values'])) . ')' .
1188 ' VALUES(' . implode(', ', $this->sqlParts['values']) . ')';
1192 * Converts this instance into an UPDATE string in SQL.
1194 * @return string
1196 private function getSQLForUpdate()
1198 $table = $this->sqlParts['from']['table'] . ($this->sqlParts['from']['alias'] ? ' ' . $this->sqlParts['from']['alias'] : '');
1199 $query = 'UPDATE ' . $table
1200 . ' SET ' . implode(", ", $this->sqlParts['set'])
1201 . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : '');
1203 return $query;
1207 * Converts this instance into a DELETE string in SQL.
1209 * @return string
1211 private function getSQLForDelete()
1213 $table = $this->sqlParts['from']['table'] . ($this->sqlParts['from']['alias'] ? ' ' . $this->sqlParts['from']['alias'] : '');
1214 $query = 'DELETE FROM ' . $table . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : '');
1216 return $query;
1220 * Gets a string representation of this QueryBuilder which corresponds to
1221 * the final SQL query being constructed.
1223 * @return string The string representation of this QueryBuilder.
1225 public function __toString()
1227 return $this->getSQL();
1231 * Creates a new named parameter and bind the value $value to it.
1233 * This method provides a shortcut for PDOStatement::bindValue
1234 * when using prepared statements.
1236 * The parameter $value specifies the value that you want to bind. If
1237 * $placeholder is not provided bindValue() will automatically create a
1238 * placeholder for you. An automatic placeholder will be of the name
1239 * ':dcValue1', ':dcValue2' etc.
1241 * For more information see {@link http://php.net/pdostatement-bindparam}
1243 * Example:
1244 * <code>
1245 * $value = 2;
1246 * $q->eq( 'id', $q->bindValue( $value ) );
1247 * $stmt = $q->executeQuery(); // executed with 'id = 2'
1248 * </code>
1250 * @license New BSD License
1251 * @link http://www.zetacomponents.org
1253 * @param mixed $value
1254 * @param mixed $type
1255 * @param string $placeHolder The name to bind with. The string must start with a colon ':'.
1257 * @return string the placeholder name used.
1259 public function createNamedParameter($value, $type = \PDO::PARAM_STR, $placeHolder = null)
1261 if ($placeHolder === null) {
1262 $this->boundCounter++;
1263 $placeHolder = ":dcValue" . $this->boundCounter;
1265 $this->setParameter(substr($placeHolder, 1), $value, $type);
1267 return $placeHolder;
1271 * Creates a new positional parameter and bind the given value to it.
1273 * Attention: If you are using positional parameters with the query builder you have
1274 * to be very careful to bind all parameters in the order they appear in the SQL
1275 * statement , otherwise they get bound in the wrong order which can lead to serious
1276 * bugs in your code.
1278 * Example:
1279 * <code>
1280 * $qb = $conn->createQueryBuilder();
1281 * $qb->select('u.*')
1282 * ->from('users', 'u')
1283 * ->where('u.username = ' . $qb->createPositionalParameter('Foo', PDO::PARAM_STR))
1284 * ->orWhere('u.username = ' . $qb->createPositionalParameter('Bar', PDO::PARAM_STR))
1285 * </code>
1287 * @param mixed $value
1288 * @param integer $type
1290 * @return string
1292 public function createPositionalParameter($value, $type = \PDO::PARAM_STR)
1294 $this->boundCounter++;
1295 $this->setParameter($this->boundCounter, $value, $type);
1297 return "?";
1301 * @param string $fromAlias
1302 * @param array $knownAliases
1304 * @return string
1306 private function getSQLForJoins($fromAlias, array &$knownAliases)
1308 $sql = '';
1310 if (isset($this->sqlParts['join'][$fromAlias])) {
1311 foreach ($this->sqlParts['join'][$fromAlias] as $join) {
1312 if (array_key_exists($join['joinAlias'], $knownAliases)) {
1313 throw QueryException::nonUniqueAlias($join['joinAlias'], array_keys($knownAliases));
1315 $sql .= ' ' . strtoupper($join['joinType'])
1316 . ' JOIN ' . $join['joinTable'] . ' ' . $join['joinAlias']
1317 . ' ON ' . ((string) $join['joinCondition']);
1318 $knownAliases[$join['joinAlias']] = true;
1321 foreach ($this->sqlParts['join'][$fromAlias] as $join) {
1322 $sql .= $this->getSQLForJoins($join['joinAlias'], $knownAliases);
1326 return $sql;
1330 * Deep clone of all expression objects in the SQL parts.
1332 * @return void
1334 public function __clone()
1336 foreach ($this->sqlParts as $part => $elements) {
1337 if (is_array($this->sqlParts[$part])) {
1338 foreach ($this->sqlParts[$part] as $idx => $element) {
1339 if (is_object($element)) {
1340 $this->sqlParts[$part][$idx] = clone $element;
1343 } elseif (is_object($elements)) {
1344 $this->sqlParts[$part] = clone $elements;
1348 foreach ($this->params as $name => $param) {
1349 if (is_object($param)) {
1350 $this->params[$name] = clone $param;