| <?php |
| /** |
| * File containing the ezcQuerySelect class. |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| * @package Database |
| * @version //autogentag// |
| * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 |
| */ |
| |
| /** |
| * Class to create select database independent SELECT queries. |
| * |
| * Note that this class creates queries that are syntactically independent |
| * of database. Semantically the queries still differ and so the same |
| * query may produce different results on different databases. Such |
| * differences are noted throughout the documentation of this class. |
| * |
| * This class implements SQL92. If your database differs from the SQL92 |
| * implementation extend this class and reimplement the methods that produce |
| * different results. Some methods implemented in ezcQuery are not defined by SQL92. |
| * These methods are marked and ezcQuery will return MySQL syntax for these cases. |
| * |
| * The examples show the SQL generated by this class. |
| * Database specific implementations may produce different results. |
| * |
| * Example: |
| * <code> |
| * $q = ezcDbInstance::get()->createSelectQuery(); |
| * $q->select( '*' )->from( 'Greetings' ) |
| * ->where( $q->expr->gt( 'age', 10 ), |
| * $q->expr->eq( 'greeting', $q->bindValue( 'Hello world' ) ) ) |
| * ->orderBy( 'owner' ) |
| * ->limit( 10 ); |
| * $stmt = $q->prepare(); // $stmt is a normal PDOStatement |
| * $stmt->execute(); |
| * </code> |
| * |
| * Database independence: |
| * TRUE/FALSE, MySQL accepts 0 and 1 as boolean values. PostgreSQL does not, but accepts TRUE/FALSE. |
| * @todo introduction needs examples with clone(), reusing a query and advanced binding. |
| * @package Database |
| * @version //autogentag// |
| * @mainclass |
| */ |
| class ezcQuerySelect extends ezcQuery |
| { |
| /** |
| * Sort the result ascending. |
| */ |
| const ASC = 'ASC'; |
| |
| /** |
| * Sort the result descending. |
| */ |
| const DESC = 'DESC'; |
| |
| /** |
| * Stores the SELECT part of the SQL. |
| * |
| * Everything from 'SELECT' until 'FROM' is stored. |
| * @var string |
| */ |
| protected $selectString = null; |
| |
| /** |
| * Stores the FROM part of the SQL. |
| * |
| * Everything from 'FROM' until 'WHERE' is stored. |
| * @var string |
| */ |
| protected $fromString = null; |
| |
| /** |
| * Stores the WHERE part of the SQL. |
| * |
| * Everything from 'WHERE' until 'GROUP', 'LIMIT', 'ORDER' or 'SORT' is stored. |
| * @var string |
| */ |
| protected $whereString = null; |
| |
| /** |
| * Stores the GROUP BY part of the SQL. |
| * |
| * @var string |
| */ |
| protected $groupString = null; |
| |
| /** |
| * Stores the HAVING part of SQL |
| * |
| * @var string |
| */ |
| protected $havingString = null; |
| |
| /** |
| * Stores the ORDER BY part of the SQL. |
| * |
| * @var string |
| */ |
| protected $orderString = null; |
| |
| /** |
| * Stores the LIMIT part of the SQL. |
| * |
| * @var string |
| */ |
| protected $limitString = null; |
| |
| /** |
| * Stores the name of last invoked SQL clause method. |
| * |
| * Could be 'select', 'from', 'where', 'group', 'having', 'order', 'limit' |
| * @var string |
| */ |
| protected $lastInvokedMethod = null; |
| |
| /** |
| * Constructs a new ezcQuery object. |
| * |
| * For an introduction to aliases see {@link ezcQuery::__construct()}. |
| * |
| * @param PDO $db a pointer to the database object. |
| * @param array(string=>string) $aliases |
| */ |
| public function __construct( PDO $db, array $aliases = array() ) |
| { |
| parent::__construct( $db, $aliases ); |
| } |
| |
| /** |
| * Resets the query object for reuse. |
| * |
| * @return void |
| */ |
| public function reset() |
| { |
| $this->selectString = null; |
| $this->fromString = null; |
| $this->whereString = null; |
| $this->groupString = null; |
| $this->havingString = null; |
| $this->orderString = null; |
| $this->limitString = null; |
| $this->lastInvokedClauseMethod = null; |
| |
| $this->boundCounter = 0; |
| $this->boundValues = array(); |
| } |
| |
| /** |
| * Opens the query and selects which columns you want to return with |
| * the query. |
| * |
| * select() accepts an arbitrary number of parameters. Each parameter |
| * must contain either the name of a column or an array containing |
| * the names of the columns. |
| * Each call to select() appends columns to the list of columns that will be |
| * used in the query. |
| * |
| * Example: |
| * <code> |
| * $q->select( 'column1', 'column2' ); |
| * </code> |
| * The same could also be written |
| * <code> |
| * $columns[] = 'column1'; |
| * $columns[] = 'column2; |
| * $q->select( $columns ); |
| * </code> |
| * or using several calls |
| * <code> |
| * $q->select( 'column1' )->select( 'column2' ); |
| * </code> |
| * |
| * Each of above code produce SQL clause 'SELECT column1, column2' for the query. |
| * |
| * @throws ezcQueryVariableParameterException if called with no parameters.. |
| * @param string|array(string) $... Either a string with a column name or an array of column names. |
| * @return ezcQuery returns a pointer to $this. |
| */ |
| public function select() |
| { |
| if ( $this->selectString == null ) |
| { |
| $this->selectString = 'SELECT '; |
| } |
| |
| $args = func_get_args(); |
| $cols = self::arrayFlatten( $args ); |
| |
| if ( count( $cols ) < 1 ) |
| { |
| throw new ezcQueryVariableParameterException( 'select', count( $args ), 1 ); |
| } |
| $this->lastInvokedMethod = 'select'; |
| $cols = $this->getIdentifiers( $cols ); |
| |
| // glue string should be inserted each time but not before first entry |
| if ( ( $this->selectString !== 'SELECT ' ) && |
| ( $this->selectString !== 'SELECT DISTINCT ' ) ) |
| { |
| $this->selectString .= ', '; |
| } |
| |
| $this->selectString .= join( ', ', $cols ); |
| return $this; |
| } |
| |
| /** |
| * Returns SQL to create an alias |
| * |
| * This method can be used to create an alias for either a |
| * table or a column. |
| * Example: |
| * <code> |
| * // this will make the table users have the alias employees |
| * // and the column user_id the alias employee_id |
| * $q->select( $q->alias( 'user_id', 'employee_id' ) |
| * ->from( $q->alias( 'users', 'employees' ) ); |
| * </code> |
| * |
| * @param string $name |
| * @param string $alias |
| * @return string the query string "columnname as targetname" |
| */ |
| public function alias( $name, $alias ) |
| { |
| $name = $this->getIdentifier( $name ); |
| return "{$name} AS {$alias}"; |
| } |
| |
| /** |
| * Opens the query and uses a distinct select on the columns you want to |
| * return with the query. |
| * |
| * selectDistinct() accepts an arbitrary number of parameters. Each |
| * parameter must contain either the name of a column or an array |
| * containing the names of the columns. |
| * Each call to selectDistinct() appends columns to the list of columns |
| * that will be used in the query. |
| * |
| * Example: |
| * <code> |
| * $q->selectDistinct( 'column1', 'column2' ); |
| * </code> |
| * The same could also be written |
| * <code> |
| * $columns[] = 'column1'; |
| * $columns[] = 'column2; |
| * $q->selectDistinct( $columns ); |
| * </code> |
| * or using several calls |
| * <code> |
| * $q->selectDistinct( 'column1' )->select( 'column2' ); |
| * </code> |
| * |
| * Each of above code produce SQL clause 'SELECT DISTINCT column1, column2' |
| * for the query. |
| * |
| * You may call select() after calling selectDistinct() which will result |
| * in the additional columns beein added. A call of selectDistinct() after |
| * select() will result in an ezcQueryInvalidException. |
| * |
| * @throws ezcQueryVariableParameterException if called with no parameters.. |
| * @throws ezcQueryInvalidException if called after select() |
| * @param string|array(string) $... Either a string with a column name or an array of column names. |
| * @return ezcQuery returns a pointer to $this. |
| */ |
| public function selectDistinct() |
| { |
| if ( $this->selectString == null ) |
| { |
| $this->selectString = 'SELECT DISTINCT '; |
| } |
| elseif ( strpos ( $this->selectString, 'DISTINCT' ) === false ) |
| { |
| throw new ezcQueryInvalidException( |
| 'SELECT', |
| 'You can\'t use selectDistinct() after using select() in the same query.' |
| ); |
| } |
| |
| // Call ezcQuerySelect::select() to do the parameter processing |
| $args = func_get_args(); |
| return call_user_func_array( |
| array( $this, 'select' ), |
| $args |
| ); |
| } |
| |
| /** |
| * Select which tables you want to select from. |
| * |
| * from() accepts an arbitrary number of parameters. Each parameter |
| * must contain either the name of a table or an array containing |
| * the names of tables.. |
| * Each call to from() appends tables to the list of tables that will be |
| * used in the query. |
| * |
| * Example: |
| * <code> |
| * // the following code will produce the SQL |
| * // SELECT id FROM table_name |
| * $q->select( 'id' )->from( 'table_name' ); |
| * </code> |
| * |
| * @throws ezcQueryVariableParameterException if called with no parameters. |
| * @param string|array(string) $... Either a string with a table name or an array of table names. |
| * @return ezcQuery a pointer to $this |
| */ |
| public function from() |
| { |
| if ( $this->fromString == '' ) |
| { |
| $this->fromString = 'FROM '; |
| } |
| |
| $args = func_get_args(); |
| $tables = self::arrayFlatten( $args ); |
| if ( count( $tables ) < 1 ) |
| { |
| throw new ezcQueryVariableParameterException( 'from', count( $args ), 1 ); |
| } |
| $this->lastInvokedMethod = 'from'; |
| $tables = $this->getIdentifiers( $tables ); |
| |
| // glue string should be inserted each time but not before first entry |
| if ( $this->fromString != 'FROM ' ) |
| { |
| $this->fromString .= ', '; |
| } |
| |
| $this->fromString .= join( ', ', $tables ); |
| return $this; |
| } |
| |
| /** |
| * Returns the SQL for a join or prepares $fromString for a join. |
| * |
| * This method could be used in two forms: |
| * |
| * <b>doJoin( $joinType, 't2', $joinCondition )</b> |
| * |
| * Takes the join type and two string arguments and returns ezcQuery. |
| * |
| * The second parameter is the name of the table to join with. The table to |
| * which is joined should have been previously set with the from() method. |
| * |
| * The third parameter should be a string containing a join condition that |
| * is returned by an ezcQueryExpression. |
| * |
| * <b>doJoin( $joinType, 't2', 't1.id', 't2.id' )</b> |
| * |
| * Takes the join type and three string arguments and returns ezcQuery. |
| * This is a simplified form of the three parameter version. doJoin( |
| * 'inner', 't2', 't1.id', 't2.id' ) is equal to doJoin( 'inner', 't2', |
| * $this->expr->eq('t1.id', 't2.id' ) ); |
| * |
| * The second parameter is the name of the table to join with. The table to |
| * which is joined should have been previously set with the from() method. |
| * |
| * The third parameter is the name of the column on the table set |
| * previously with the from() method and the fourth parameter the name of |
| * the column to join with on the table that was specified in the first |
| * parameter. |
| * |
| * @apichange Remove "5" argument version. |
| * |
| * @throws ezcQueryInvalidException if called with inconsistent parameters or if |
| * invoked without preceding call to from(). |
| * |
| * @param string $type The join type: inner, right or left. |
| * @param string $table2,... The table to join with, followed by either the |
| * two join columns, or a join condition. |
| * @return ezcQuery |
| */ |
| protected function doJoin( $type ) |
| { |
| $args = func_get_args(); |
| // Remove the first one, as that's the $type of join. |
| array_shift( $args ); |
| |
| $sqlType = strtoupper( $type ); |
| |
| $passedArgsCount = func_num_args() - 1; |
| if ( $passedArgsCount < 2 || $passedArgsCount > 4 ) |
| { |
| throw new ezcQueryInvalidException( 'SELECT', "Wrong argument count passed to {$type}Join(): {$passedArgsCount}" ); |
| } |
| |
| // deprecated syntax |
| if ( $passedArgsCount == 4 ) |
| { |
| if ( is_string( $args[0] ) && is_string( $args[1] ) && |
| is_string( $args[2] ) && is_string( $args[3] ) |
| ) |
| { |
| $table1 = $this->getIdentifier( $args[0] ); |
| $table2 = $this->getIdentifier( $args[1] ); |
| $column1 = $this->getIdentifier( $args[2] ); |
| $column2 = $this->getIdentifier( $args[3] ); |
| |
| return "{$table1} {$sqlType} JOIN {$table2} ON {$column1} = {$column2}"; |
| } |
| else |
| { |
| throw new ezcQueryInvalidException( 'SELECT', "Inconsistent types of arguments passed to {$type}Join()." ); |
| } |
| } |
| |
| // using from()->*Join() syntax assumed, so check if last call was to from() |
| if ( $this->lastInvokedMethod != 'from' ) |
| { |
| throw new ezcQueryInvalidException( 'SELECT', "Invoking {$type}Join() not immediately after from()." ); |
| } |
| |
| $table = ''; |
| if ( !is_string( $args[0] ) ) |
| { |
| throw new ezcQueryInvalidException( 'SELECT', |
| "Inconsistent type of first argument passed to {$type}Join(). Should be string with name of table." ); |
| } |
| $table = $this->getIdentifier( $args[0] ); |
| |
| $condition = ''; |
| if ( $passedArgsCount == 2 && is_string( $args[1] ) ) |
| { |
| $condition = $args[1]; |
| } |
| else if ( $passedArgsCount == 3 && is_string( $args[1] ) && is_string( $args[2] ) ) |
| { |
| $arg1 = $this->getIdentifier( $args[1] ); |
| $arg2 = $this->getIdentifier( $args[2] ); |
| |
| $condition = "{$arg1} = {$arg2}"; |
| } |
| |
| $this->fromString .= " {$sqlType} JOIN {$table} ON {$condition}"; |
| return $this; |
| } |
| |
| /** |
| * Returns the SQL for an inner join or prepares $fromString for an inner join. |
| * |
| * This method could be used in two forms: |
| * |
| * <b>innerJoin( 't2', $joinCondition )</b> |
| * |
| * Takes 2 string arguments and returns ezcQuery. |
| * |
| * The first parameter is the name of the table to join with. The table to |
| * which is joined should have been previously set with the from() method. |
| * |
| * The second parameter should be a string containing a join condition that |
| * is returned by an ezcQueryExpression. |
| * |
| * Example: |
| * <code> |
| * // the following code will produce the SQL |
| * // SELECT id FROM t1 INNER JOIN t2 ON t1.id = t2.id |
| * $q->select( 'id' )->from( 't1' )->innerJoin( 't2', $q->expr->eq('t1.id', 't2.id' ) ); |
| * </code> |
| * |
| * <b>innerJoin( 't2', 't1.id', 't2.id' )</b> |
| * |
| * Takes 3 string arguments and returns ezcQuery. This is a simplified form |
| * of the 2 parameter version. innerJoin( 't2', 't1.id', 't2.id' ) is |
| * equal to innerJoin( 't2', $this->expr->eq('t1.id', 't2.id' ) ); |
| * |
| * The first parameter is the name of the table to join with. The table to |
| * which is joined should have been previously set with the from() method. |
| * |
| * The second parameter is the name of the column on the table set |
| * previously with the from() method and the third parameter the name of |
| * the column to join with on the table that was specified in the first |
| * parameter. |
| * |
| * Example: |
| * <code> |
| * // the following code will produce the SQL |
| * // SELECT id FROM t1 INNER JOIN t2 ON t1.id = t2.id |
| * $q->select( 'id' )->from( 't1' )->innerJoin( 't2', 't1.id', 't2.id' ); |
| * </code> |
| * |
| * @apichange Remove 4 argument version. |
| * |
| * @throws ezcQueryInvalidException if called with inconsistent parameters or if |
| * invoked without preceding call to from(). |
| * |
| * @param string $table2,... The table to join with, followed by either the |
| * two join columns, or a join condition. |
| * @return ezcQuery |
| */ |
| public function innerJoin() |
| { |
| $args = func_get_args(); |
| array_unshift( $args, 'inner' ); |
| return call_user_func_array( array( $this, 'doJoin' ), $args ); |
| } |
| |
| /** |
| * Returns the SQL for a left join or prepares $fromString for a left join. |
| * |
| * This method could be used in two forms: |
| * |
| * <b>leftJoin( 't2', $joinCondition )</b> |
| * |
| * Takes 2 string arguments and returns ezcQuery. |
| * |
| * The first parameter is the name of the table to join with. The table to |
| * which is joined should have been previously set with the from() method. |
| * |
| * The second parameter should be a string containing a join condition that |
| * is returned by an ezcQueryExpression. |
| * |
| * Example: |
| * <code> |
| * // the following code will produce the SQL |
| * // SELECT id FROM t1 LEFT JOIN t2 ON t1.id = t2.id |
| * $q->select( 'id' )->from( 't1' )->leftJoin( 't2', $q->expr->eq('t1.id', 't2.id' ) ); |
| * </code> |
| * |
| * <b>leftJoin( 't2', 't1.id', 't2.id' )</b> |
| * |
| * Takes 3 string arguments and returns ezcQuery. This is a simplified form |
| * of the 2 parameter version. leftJoin( 't2', 't1.id', 't2.id' ) is |
| * equal to leftJoin( 't2', $this->expr->eq('t1.id', 't2.id' ) ); |
| * |
| * The first parameter is the name of the table to join with. The table to |
| * which is joined should have been previously set with the from() method. |
| * |
| * The second parameter is the name of the column on the table set |
| * previously with the from() method and the third parameter the name of |
| * the column to join with on the table that was specified in the first |
| * parameter. |
| * |
| * Example: |
| * <code> |
| * // the following code will produce the SQL |
| * // SELECT id FROM t1 LEFT JOIN t2 ON t1.id = t2.id |
| * $q->select( 'id' )->from( 't1' )->leftJoin( 't2', 't1.id', 't2.id' ); |
| * </code> |
| * |
| * @apichange Remove 4 argument version. |
| * |
| * @throws ezcQueryInvalidException if called with inconsistent parameters or if |
| * invoked without preceding call to from(). |
| * |
| * @param string $table2,... The table to join with, followed by either the |
| * two join columns, or a join condition. |
| * @return ezcQuery |
| */ |
| public function leftJoin() |
| { |
| $args = func_get_args(); |
| array_unshift( $args, 'left' ); |
| return call_user_func_array( array( $this, 'doJoin' ), $args ); |
| } |
| |
| /** |
| * Returns the SQL for a right join or prepares $fromString for a right join. |
| * |
| * This method could be used in two forms: |
| * |
| * <b>rightJoin( 't2', $joinCondition )</b> |
| * |
| * Takes 2 string arguments and returns ezcQuery. |
| * |
| * The first parameter is the name of the table to join with. The table to |
| * which is joined should have been previously set with the from() method. |
| * |
| * The second parameter should be a string containing a join condition that |
| * is returned by an ezcQueryExpression. |
| * |
| * Example: |
| * <code> |
| * // the following code will produce the SQL |
| * // SELECT id FROM t1 LEFT JOIN t2 ON t1.id = t2.id |
| * $q->select( 'id' )->from( 't1' )->rightJoin( 't2', $q->expr->eq('t1.id', 't2.id' ) ); |
| * </code> |
| * |
| * <b>rightJoin( 't2', 't1.id', 't2.id' )</b> |
| * |
| * Takes 3 string arguments and returns ezcQuery. This is a simplified form |
| * of the 2 parameter version. rightJoin( 't2', 't1.id', 't2.id' ) is |
| * equal to rightJoin( 't2', $this->expr->eq('t1.id', 't2.id' ) ); |
| * |
| * The first parameter is the name of the table to join with. The table to |
| * which is joined should have been previously set with the from() method. |
| * |
| * The second parameter is the name of the column on the table set |
| * previously with the from() method and the third parameter the name of |
| * the column to join with on the table that was specified in the first |
| * parameter. |
| * |
| * Example: |
| * <code> |
| * // the following code will produce the SQL |
| * // SELECT id FROM t1 LEFT JOIN t2 ON t1.id = t2.id |
| * $q->select( 'id' )->from( 't1' )->rightJoin( 't2', 't1.id', 't2.id' ); |
| * </code> |
| * |
| * @apichange Remove 4 argument version. |
| * |
| * @throws ezcQueryInvalidException if called with inconsistent parameters or if |
| * invoked without preceding call to from(). |
| * |
| * @param string $table2,... The table to join with, followed by either the |
| * two join columns, or a join condition. |
| * @return ezcQuery |
| */ |
| public function rightJoin() |
| { |
| $args = func_get_args(); |
| array_unshift( $args, 'right' ); |
| return call_user_func_array( array( $this, 'doJoin' ), $args ); |
| } |
| |
| /** |
| * Adds a where clause with logical expressions to the query. |
| * |
| * where() accepts an arbitrary number of parameters. Each parameter |
| * must contain a logical expression or an array with logical expressions. |
| * If you specify multiple logical expression they are connected using |
| * a logical and. |
| * |
| * Multiple calls to where() will join the expressions using a logical and. |
| * |
| * Example: |
| * <code> |
| * $q->select( '*' )->from( 'table' )->where( $q->expr->eq( 'id', 1 ) ); |
| * </code> |
| * |
| * @throws ezcQueryVariableParameterException if called with no parameters. |
| * @param string|array(string) $... Either a string with a logical expression name |
| * or an array with logical expressions. |
| * @return ezcQuerySelect |
| */ |
| public function where() |
| { |
| if ( $this->whereString == null ) |
| { |
| $this->whereString = 'WHERE '; |
| } |
| |
| $args = func_get_args(); |
| $expressions = self::arrayFlatten( $args ); |
| if ( count( $expressions ) < 1 ) |
| { |
| throw new ezcQueryVariableParameterException( 'where', count( $args ), 1 ); |
| } |
| |
| $this->lastInvokedMethod = 'where'; |
| |
| // glue string should be inserted each time but not before first entry |
| if ( $this->whereString != 'WHERE ' ) |
| { |
| $this->whereString .= ' AND '; |
| } |
| |
| $this->whereString .= join( ' AND ', $expressions ); |
| return $this; |
| } |
| |
| |
| // limit, order and group |
| |
| /** |
| * Returns SQL that limits the result set. |
| * |
| * $limit controls the maximum number of rows that will be returned. |
| * $offset controls which row that will be the first in the result |
| * set from the total amount of matching rows. |
| * |
| * Example: |
| * <code> |
| * $q->select( '*' )->from( 'table' ) |
| * ->limit( 10, 0 ); |
| * </code> |
| * |
| * LIMIT is not part of SQL92. It is implemented here anyway since all |
| * databases support it one way or the other and because it is |
| * essential. |
| * |
| * @param string $limit integer expression |
| * @param string $offset integer expression |
| * @return ezcQuerySelect |
| */ |
| public function limit( $limit, $offset = '' ) |
| { |
| if ( $offset === '' ) |
| { |
| $this->limitString = "LIMIT {$limit}"; |
| } |
| else |
| { |
| $this->limitString = "LIMIT {$limit} OFFSET {$offset}"; |
| } |
| $this->lastInvokedMethod = 'limit'; |
| |
| return $this; |
| } |
| |
| /** |
| * Returns SQL that orders the result set by a given column. |
| * |
| * You can call orderBy multiple times. Each call will add a |
| * column to order by. |
| * |
| * Example: |
| * <code> |
| * $q->select( '*' )->from( 'table' ) |
| * ->orderBy( 'id' ); |
| * </code> |
| * |
| * @param string $column a column name in the result set |
| * @param string $type if the column should be sorted ascending or descending. |
| * you can specify this using ezcQuerySelect::ASC or ezcQuerySelect::DESC |
| * @return ezcQuery a pointer to $this |
| */ |
| public function orderBy( $column, $type = self::ASC ) |
| { |
| $string = $this->getIdentifier( $column ); |
| if ( $type == self::DESC ) |
| { |
| $string .= ' DESC'; |
| } |
| if ( $this->orderString == '' ) |
| { |
| $this->orderString = "ORDER BY {$string}"; |
| } |
| else |
| { |
| $this->orderString .= ", {$string}"; |
| } |
| $this->lastInvokedMethod = 'order'; |
| |
| return $this; |
| } |
| |
| /** |
| * Returns SQL that groups the result set by a given column. |
| * |
| * You can call groupBy multiple times. Each call will add a |
| * column to group by. |
| * |
| * Example: |
| * <code> |
| * $q->select( '*' )->from( 'table' ) |
| * ->groupBy( 'id' ); |
| * </code> |
| * |
| * @throws ezcQueryVariableParameterException if called with no parameters. |
| * @param string $column a column name in the result set |
| * @return ezcQuery a pointer to $this |
| */ |
| public function groupBy() |
| { |
| $args = func_get_args(); |
| $columns = self::arrayFlatten( $args ); |
| if ( count( $columns ) < 1 ) |
| { |
| throw new ezcQueryVariableParameterException( 'groupBy', count( $args ), 1 ); |
| } |
| $columns = $this->getIdentifiers( $columns ); |
| |
| $string = join( ', ', $columns ); |
| if ( $this->groupString == '' ) |
| { |
| $this->groupString = "GROUP BY {$string}" ; |
| } |
| else |
| { |
| $this->groupString .= ", {$string}"; |
| } |
| |
| $this->lastInvokedMethod = 'group'; |
| |
| return $this; |
| } |
| |
| /** |
| * Returns SQL that set having by a given expression. |
| * |
| * You can call having multiple times. Each call will add an |
| * expression with a logical and. |
| * |
| * Example: |
| * <code> |
| * $q->select( '*' )->from( 'table' )->groupBy( 'id' ) |
| * ->having( $q->expr->eq('id',1) ); |
| * </code> |
| * |
| * @throws ezcQueryInvalidException |
| * if invoked without preceding call to groupBy(). |
| * @throws ezcQueryVariableParameterException |
| * if called with no parameters. |
| * @param string|array(string) $... Either a string with a logical expression name |
| * or an array with logical expressions. |
| * @return ezcQuery a pointer to $this |
| */ |
| public function having() |
| { |
| // using groupBy()->having() syntax assumed, so check if last call was to groupBy() |
| if ( $this->lastInvokedMethod != 'group' && $this->lastInvokedMethod != 'having' ) |
| { |
| throw new ezcQueryInvalidException( 'SELECT', 'Invoking having() not immediately after groupBy().' ); |
| } |
| |
| $args = func_get_args(); |
| $expressions = self::arrayFlatten( $args ); |
| if ( count( $expressions ) < 1 ) |
| { |
| throw new ezcQueryVariableParameterException( 'having', count( $args ), 1 ); |
| } |
| |
| if ( $this->havingString == null ) |
| { |
| $this->havingString = 'HAVING '; |
| } |
| |
| // will add "AND expression" in subsequent calls to having() |
| if ( $this->havingString != 'HAVING ' ) |
| { |
| $this->havingString .= ' AND '; |
| } |
| |
| $this->havingString .= join( ' AND ', $expressions ); |
| $this->lastInvokedMethod = 'having'; |
| return $this; |
| } |
| |
| /** |
| * Returns dummy table name. |
| * |
| * If your select query just evaluates an expression |
| * without fetching table data (e.g. 'SELECT 1+1') |
| * some databases require you to specify a dummy table in FROM clause. |
| * (Oracle: 'SELECT 1+1 FROM dual'). |
| * |
| * This methods returns name of such a dummy table. |
| * For DBMSs that don't require that, the method returns false. |
| * Otherwise the dummy table name is returned. |
| * |
| * @return bool|string a dummy table name or false if not needed |
| */ |
| static public function getDummyTableName() |
| { |
| return false; |
| } |
| |
| /** |
| * Returns the complete select query string. |
| * |
| * This method uses the build methods to build the |
| * various parts of the select query. |
| * |
| * @todo add newlines? easier for debugging |
| * @throws ezcQueryInvalidException if it was not possible to build a valid query. |
| * @return string |
| */ |
| public function getQuery() |
| { |
| if ( $this->selectString == null ) |
| { |
| throw new ezcQueryInvalidException( "SELECT", "select() was not called before getQuery()." ); |
| } |
| |
| $query = "{$this->selectString}"; |
| if ( $this->fromString != null ) |
| { |
| $query = "{$query} {$this->fromString}"; |
| } |
| if ( $this->whereString != null ) |
| { |
| $query = "{$query} {$this->whereString}"; |
| } |
| if ( $this->groupString != null ) |
| { |
| $query = "{$query} {$this->groupString}"; |
| } |
| if ( $this->havingString != null ) |
| { |
| $query = "{$query} {$this->havingString}"; |
| } |
| if ( $this->orderString != null ) |
| { |
| $query = "{$query} {$this->orderString}"; |
| } |
| if ( $this->limitString != null ) |
| { |
| $query = "{$query} {$this->limitString}"; |
| } |
| return $query; |
| } |
| |
| } |
| |
| ?> |