blob: 116ed7027c30995d9f3b843ac92d47f1c42e75b2 [file] [log] [blame]
<?php
/**
* File containing the ezcQueryExpression 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
*/
/**
* The ezcQueryExpression class is used to create database independent SQL expression.
*
* The QueryExpression class is usually used through the 'expr' variable in
* one of the Select, Insert, Update or Delete classes.
*
* Note that the methods for logical or and and are
* named lOr and lAnd respectively. This is because and and or are reserved names
* in PHP and can not be used in method names.
*
* @package Database
* @version //autogentag//
* @mainclass
*/
class ezcQueryExpression
{
/**
* A pointer to the database handler to use for this query.
*
* @var PDO
*/
protected $db;
/**
* The column and table name aliases.
*
* Format: array('alias' => 'realName')
* @var array(string=>string)
*/
private $aliases = null;
/**
* The flag that switch quoting mode for
* values provided by user in miscelaneous SQL functions.
*
* @var boolean
*/
protected $quoteValues = true;
/**
* Contains an interval map from generic intervals to MySQL native intervals.
*
* @var array(string=>string)
*/
protected $intervalMap = array(
'SECOND' => 'SECOND',
'MINUTE' => 'MINUTE',
'HOUR' => 'HOUR',
'DAY' => 'DAY',
'MONTH' => 'MONTH',
'YEAR' => 'YEAR',
);
/**
* Constructs an empty ezcQueryExpression
*
* @param PDO $db
* @param array(string=>string) $aliases
*/
public function __construct( PDO $db, array $aliases = array() )
{
$this->db = $db;
if ( !empty( $aliases ) )
{
$this->aliases = $aliases;
}
}
/**
* Sets the aliases $aliases for this object.
*
* The aliases can be used to substitute the column and table names with more
* friendly names. E.g PersistentObject uses it to allow using property and class
* names instead of column and table names.
*
* @param array(string=>string) $aliases
* @return void
*/
public function setAliases( array $aliases )
{
$this->aliases = $aliases;
}
/**
* Returns true if this object has aliases.
*
* @return bool
*/
public function hasAliases()
{
return $this->aliases !== null ? true : false;
}
/**
* Returns the correct identifier for the alias $alias.
*
* If the alias does not exists in the list of aliases
* it is returned unchanged.
*
* @param string $alias
* @return string
*/
protected function getIdentifier( $alias )
{
$aliasParts = explode( '.', $alias );
$identifiers = array();
// If the alias consists of one part, then we just look it up in the
// array. If we find it, we use it, otherwise we return the name as-is
// and assume it's just a column name. The alias target can be a fully
// qualified name (table.column).
if ( count( $aliasParts ) == 1 )
{
if ( $this->aliases !== null &&
array_key_exists( $alias, $this->aliases ) )
{
$alias = $this->aliases[$alias];
}
return $alias;
}
// If the passed name consist of two parts, we need to check all parts
// of the passed-in name for aliases, because an alias can be made for
// both a table name and a column name. For each element we try to find
// whether we have an alias mapping. Unlike the above case, the alias
// target can in this case *not* consist of a fully qualified name as
// this would introduce another part of the name (with two dots).
for ( $i = 0; $i < count( $aliasParts ); $i++ )
{
if ( $this->aliases !== null &&
array_key_exists( $aliasParts[$i], $this->aliases ) )
{
// We only use the found alias if the alias target is not a fully
// qualified name (table.column).
$tmpAlias = $this->aliases[$aliasParts[$i]];
if ( count( explode( '.', $tmpAlias ) ) === 1 )
{
$aliasParts[$i] = $this->aliases[$aliasParts[$i]];
}
}
}
$alias = join( '.', $aliasParts );
return $alias;
}
/**
* Returns the correct identifiers for the aliases found in $aliases.
*
* This method is similar to getIdentifier except that it works on an array.
*
* @param array(string) $aliasList
* @return array(string)
*/
protected function getIdentifiers( array $aliasList )
{
if ( $this->aliases !== null )
{
foreach ( $aliasList as $key => $alias )
{
$aliasList[$key] = $this->getIdentifier( $alias );
}
}
return $aliasList;
}
/**
* Sets the mode of quoting for parameters passed
* to SQL functions and operators.
*
* Quoting mode is set to ON by default.
* $q->expr->in( 'column1', 'Hello', 'world' ) will
* produce SQL "column1 IN ( 'Hello', 'world' )"
* ( note quotes in SQL ).
*
* User must execute setValuesQuoting( false ) before call
* to function where quoting of parameters is not desirable.
* Example:
* <code>
* $q->expr->setValuesQuoting( false );
* $q->expr->in( 'column1', 'SELECT * FROM table' )
* </code>
* This will produce SQL "column1 IN ( SELECT * FROM table )".
*
* Quoting mode will remain unchanged until next call
* to setValuesQuoting().
*
* @param boolean $doQuoting - flag that switch quoting.
* @return void
*/
public function setValuesQuoting( $doQuoting )
{
$this->quoteValues = $doQuoting;
}
/**
* Returns the SQL to bind logical expressions together using a logical or.
*
* lOr() accepts an arbitrary number of parameters. Each parameter
* must contain a logical expression or an array with logical expressions.
*
* Example:
* <code>
* $q = ezcDbInstance::get()->createSelectQuery();
* $e = $q->expr;
* $q->select( '*' )->from( 'table' )
* ->where( $e->lOr( $e->eq( 'id', $q->bindValue( 1 ) ),
* $e->eq( 'id', $q->bindValue( 2 ) ) ) );
* </code>
*
* @throws ezcDbAbstractionException if called with no parameters.
* @return string a logical expression
*/
public function lOr()
{
$args = func_get_args();
if ( count( $args ) < 1 )
{
throw new ezcQueryVariableParameterException( 'lOr', count( $args ), 1 );
}
$elements = ezcQuerySelect::arrayFlatten( $args );
if ( count( $elements ) == 1 )
{
return $elements[0];
}
else
{
return '( ' . join( ' OR ', $elements ) . ' )';
}
}
/**
* Returns the SQL to bind logical expressions together using a logical and.
*
* lAnd() accepts an arbitrary number of parameters. Each parameter
* must contain a logical expression or an array with logical expressions.
*
* Example:
* <code>
* $q = ezcDbInstance::get()->createSelectQuery();
* $e = $q->expr;
* $q->select( '*' )->from( 'table' )
* ->where( $e->lAnd( $e->eq( 'id', $q->bindValue( 1 ) ),
* $e->eq( 'id', $q->bindValue( 2 ) ) ) );
* </code>
*
* @throws ezcDbAbstractionException if called with no parameters.
* @return string a logical expression
*/
public function lAnd()
{
$args = func_get_args();
if ( count( $args ) < 1 )
{
throw new ezcQueryVariableParameterException( 'lAnd', count( $args ), 1 );
}
$elements = ezcQuerySelect::arrayFlatten( $args );
if ( count( $elements ) == 1 )
{
return $elements[0];
}
else
{
return '( ' . join( ' AND ', $elements ) . ' )';
}
}
/**
* Returns the SQL for a logical not, negating the $expression.
*
* Example:
* <code>
* $q = ezcDbInstance::get()->createSelectQuery();
* $e = $q->expr;
* $q->select( '*' )->from( 'table' )
* ->where( $e->eq( 'id', $e->not( 'null' ) ) );
* </code>
*
* @param string $expression
* @return string a logical expression
*/
public function not( $expression )
{
$expression = $this->getIdentifier( $expression );
return "NOT ( {$expression} )";
}
// math
/**
* Returns the SQL to perform the same mathematical operation over an array
* of values or expressions.
*
* basicMath() accepts an arbitrary number of parameters. Each parameter
* must contain a value or an expression or an array with values or
* expressions.
*
* @throws ezcDbAbstractionException if called with no parameters.
* @param string $type the type of operation, can be '+', '-', '*' or '/'.
* @param string|array(string) $...
* @return string an expression
*/
private function basicMath( $type )
{
$args = func_get_args();
$elements = ezcQuerySelect::arrayFlatten( array_slice( $args, 1 ) );
$elements = $this->getIdentifiers( $elements );
if ( count( $elements ) < 1 )
{
throw new ezcQueryVariableParameterException( $type, count( $args ), 1 );
}
if ( count( $elements ) == 1 )
{
return $elements[0];
}
else
{
return '( ' . join( " $type ", $elements ) . ' )';
}
}
/**
* Returns the SQL to add values or expressions together.
*
* add() accepts an arbitrary number of parameters. Each parameter
* must contain a value or an expression or an array with values or
* expressions.
*
* Example:
* <code>
* $q = ezcDbInstance::get()->createSelectQuery();
* $q->select( '*' )->from( 'table' )
* ->where( $q->expr->add( 'id', 2 ) );
* </code>
*
* @throws ezcDbAbstractionException if called with no parameters.
* @param string|array(string) $...
* @return string an expression
*/
public function add()
{
$args = func_get_args();
return $this->basicMath( '+', $args );
}
/**
* Returns the SQL to subtract values or expressions from eachother.
*
* subtract() accepts an arbitrary number of parameters. Each parameter
* must contain a value or an expression or an array with values or
* expressions.
*
* Example:
* <code>
* $q = ezcDbInstance::get()->createSelectQuery();
* $q->select( '*' )->from( 'table' )
* ->where( $q->expr->subtract( 'id', 2 ) );
* </code>
*
* @throws ezcDbAbstractionException if called with no parameters.
* @param string|array(string) $...
* @return string an expression
*/
public function sub()
{
$args = func_get_args();
return $this->basicMath( '-', $args );
}
/**
* Returns the SQL to multiply values or expressions by eachother.
*
* multiply() accepts an arbitrary number of parameters. Each parameter
* must contain a value or an expression or an array with values or
* expressions.
*
* Example:
* <code>
* $q = ezcDbInstance::get()->createSelectQuery();
* $q->select( '*' )->from( 'table' )
* ->where( $q->expr->multiply( 'id', 2 ) );
* </code>
*
* @throws ezcDbAbstractionException if called with no parameters.
* @param string|array(string) $...
* @return string an expression
*/
public function mul()
{
$args = func_get_args();
return $this->basicMath( '*', $args );
}
/**
* Returns the SQL to divide values or expressions by eachother.
*
* divide() accepts an arbitrary number of parameters. Each parameter
* must contain a value or an expression or an array with values or
* expressions.
*
* Example:
* <code>
* $q = ezcDbInstance::get()->createSelectQuery();
* $q->select( '*' )->from( 'table' )
* ->where( $q->expr->divide( 'id', 2 ) );
* </code>
*
* @throws ezcDbAbstractionException if called with no parameters.
* @param string|array(string) $...
* @return string an expression
*/
public function div()
{
$args = func_get_args();
return $this->basicMath( '/', $args );
}
/**
* Returns the SQL to check if two values are equal.
*
* Example:
* <code>
* $q = ezcDbInstance::get()->createSelectQuery();
* $q->select( '*' )->from( 'table' )
* ->where( $q->expr->eq( 'id', $q->bindValue( 1 ) ) );
* </code>
*
* @param string $value1 logical expression to compare
* @param string $value2 logical expression to compare with
* @return string logical expression
*/
public function eq( $value1, $value2 )
{
$value1 = $this->getIdentifier( $value1 );
$value2 = $this->getIdentifier( $value2 );
return "{$value1} = {$value2}";
}
/**
* Returns the SQL to check if two values are unequal.
*
* Example:
* <code>
* $q = ezcDbInstance::get()->createSelectQuery();
* $q->select( '*' )->from( 'table' )
* ->where( $q->expr->neq( 'id', $q->bindValue( 1 ) ) );
* </code>
*
* @param string $value1 logical expression to compare
* @param string $value2 logical expression to compare with
* @return string logical expression
*/
public function neq( $value1, $value2 )
{
$value1 = $this->getIdentifier( $value1 );
$value2 = $this->getIdentifier( $value2 );
return "{$value1} <> {$value2}";
}
/**
* Returns the SQL to check if one value is greater than another value.
*
* Example:
* <code>
* $q = ezcDbInstance::get()->createSelectQuery();
* $q->select( '*' )->from( 'table' )
* ->where( $q->expr->gt( 'id', $q->bindValue( 1 ) ) );
* </code>
*
* @param string $value1 logical expression to compare
* @param string $value2 logical expression to compare with
* @return string logical expression
*/
public function gt( $value1, $value2 )
{
$value1 = $this->getIdentifier( $value1 );
$value2 = $this->getIdentifier( $value2 );
return "{$value1} > {$value2}";
}
/**
* Returns the SQL to check if one value is greater than or equal to
* another value.
*
* Example:
* <code>
* $q = ezcDbInstance::get()->createSelectQuery();
* $q->select( '*' )->from( 'table' )
* ->where( $q->expr->gte( 'id', $q->bindValue( 1 ) ) );
* </code>
*
* @param string $value1 logical expression to compare
* @param string $value2 logical expression to compare with
* @return string logical expression
*/
public function gte( $value1, $value2 )
{
$value1 = $this->getIdentifier( $value1 );
$value2 = $this->getIdentifier( $value2 );
return "{$value1} >= {$value2}";
}
/**
* Returns the SQL to check if one value is less than another value.
*
* Example:
* <code>
* $q = ezcDbInstance::get()->createSelectQuery();
* $q->select( '*' )->from( 'table' )
* ->where( $q->expr->lt( 'id', $q->bindValue( 1 ) ) );
* </code>
*
* @param string $value1 logical expression to compare
* @param string $value2 logical expression to compare with
* @return string logical expression
*/
public function lt( $value1, $value2 )
{
$value1 = $this->getIdentifier( $value1 );
$value2 = $this->getIdentifier( $value2 );
return "{$value1} < {$value2}";
}
/**
* Returns the SQL to check if one value is less than or equal to
* another value.
*
* Example:
* <code>
* $q = ezcDbInstance::get()->createSelectQuery();
* $q->select( '*' )->from( 'table' )
* ->where( $q->expr->lte( 'id', $q->bindValue( 1 ) ) );
* </code>
*
* @param string $value1 logical expression to compare
* @param string $value2 logical expression to compare with
* @return string logical expression
*/
public function lte( $value1, $value2 )
{
$value1 = $this->getIdentifier( $value1 );
$value2 = $this->getIdentifier( $value2 );
return "{$value1} <= {$value2}";
}
/**
* Returns the SQL to check if a value is one in a set of
* given values..
*
* in() accepts an arbitrary number of parameters. The first parameter
* must always specify the value that should be matched against. Successive
* parameters must contain a logical expression or an array with logical
* expressions. These expressions will be matched against the first
* parameter.
*
* Example:
* <code>
* $q->select( '*' )->from( 'table' )
* ->where( $q->expr->in( 'id', 1, 2, 3 ) );
* </code>
*
* Optimization note: Call setQuotingValues( false ) before using in() with
* big lists of numeric parameters. This avoid redundant quoting of numbers
* in resulting SQL query and saves time of converting strings to
* numbers inside RDBMS.
*
* @throws ezcQueryVariableParameterException if called with less than two
* parameters.
* @throws ezcQueryInvalidParameterException if the 2nd parameter is an
* empty array.
* @param string $column the value that should be matched against
* @param string|array(string) $... values that will be matched against $column
* @return string logical expression
*/
public function in( $column )
{
$args = func_get_args();
if ( count( $args ) < 2 )
{
throw new ezcQueryVariableParameterException( 'in', count( $args ), 2 );
}
if ( is_array( $args[1] ) && count( $args[1] ) == 0 )
{
throw new ezcQueryInvalidParameterException( 'in', 2, 'an empty array', 'a non-empty array' );
}
$values = ezcQuerySelect::arrayFlatten( array_slice( $args, 1 ) );
$column = $this->getIdentifier( $column );
// Special handling of sub selects to avoid double braces
if ( count( $values ) === 1 && $values[0] instanceof ezcQuerySubSelect )
{
return "{$column} IN " . $values[0]->getQuery();
}
$values = $this->getIdentifiers( $values );
if ( count( $values ) == 0 )
{
throw new ezcQueryVariableParameterException( 'in', count( $args ), 2 );
}
if ( $this->quoteValues )
{
foreach ( $values as $key => $value )
{
switch ( true )
{
case $value instanceof ezcQuerySubSelect:
$values[$key] = $value->getQuery(); // fix for PHP 5.1.6 because typecasting to string not working there.
break;
case is_int( $value ):
case is_float( $value ):
$values[$key] = (string) $value;
break;
default:
$values[$key] = $this->db->quote( $value );
}
}
}
return "{$column} IN ( " . join( ', ', $values ) . ' )';
}
/**
* Returns SQL that checks if a expression is null.
*
* Example:
* <code>
* $q = ezcDbInstance::get()->createSelectQuery();
* $q->select( '*' )->from( 'table' )
* ->where( $q->expr->isNull( 'id' ) );
* </code>
*
* @param string $expression the expression that should be compared to null
* @return string logical expression
*/
public function isNull( $expression )
{
$expression = $this->getIdentifier( $expression );
return "{$expression} IS NULL";
}
/**
* Returns SQL that checks if an expression evaluates to a value between
* two values.
*
* The parameter $expression is checked if it is between $value1 and $value2.
*
* Note: There is a slight difference in the way BETWEEN works on some databases.
* http://www.w3schools.com/sql/sql_between.asp. If you want complete database
* independence you should avoid using between().
*
* Example:
* <code>
* $q = ezcDbInstance::get()->createSelectQuery();
* $q->select( '*' )->from( 'table' )
* ->where( $q->expr->between( 'id', $q->bindValue( 1 ), $q->bindValue( 5 ) ) );
* </code>
*
* @param string $expression the value to compare to
* @param string $value1 the lower value to compare with
* @param string $value2 the higher value to compare with
* @return string logical expression
*/
public function between( $expression, $value1, $value2 )
{
$expression = $this->getIdentifier( $expression );
$value1 = $this->getIdentifier( $value1 );
$value2 = $this->getIdentifier( $value2 );
return "{$expression} BETWEEN {$value1} AND {$value2}";
}
/**
* Match a partial string in a column.
*
* Like will look for the pattern in the column given. Like accepts
* the wildcards '_' matching a single character and '%' matching
* any number of characters.
*
* @param string $expression the name of the expression to match on
* @param string $pattern the pattern to match with.
*/
public function like( $expression, $pattern )
{
$expression = $this->getIdentifier( $expression );
return "{$expression} LIKE {$pattern}";
}
// aggregate functions
/**
* Returns the average value of a column
*
* @param string $column the column to use
* @return string
*/
public function avg( $column )
{
$column = $this->getIdentifier( $column );
return "AVG( {$column} )";
}
/**
* Returns the number of rows (without a NULL value) of a column
*
* If a '*' is used instead of a column the number of selected rows
* is returned.
*
* @param string $column the column to use
* @return string
*/
public function count( $column )
{
$column = $this->getIdentifier( $column );
return "COUNT( {$column} )";
}
/**
* Returns the highest value of a column
*
* @param string $column the column to use
* @return string
*/
public function max( $column )
{
$column = $this->getIdentifier( $column );
return "MAX( {$column} )";
}
/**
* Returns the lowest value of a column
*
* @param string $column the column to use
* @return string
*/
public function min( $column )
{
$column = $this->getIdentifier( $column );
return "MIN( {$column} )";
}
/**
* Returns the total sum of a column
*
* @param string $column the column to use
* @return string
*/
public function sum( $column )
{
$column = $this->getIdentifier( $column );
return "SUM( {$column} )";
}
// scalar functions
/**
* Returns the md5 sum of $column.
*
* Note: Not SQL92, but common functionality
*
* @param string $column
* @return string
*/
public function md5( $column )
{
$column = $this->getIdentifier( $column );
return "MD5( {$column} )";
}
/**
* Returns the length of text field $column
*
* @param string $column
* @return string
*/
public function length( $column )
{
$column = $this->getIdentifier( $column );
return "LENGTH( {$column} )";
}
/**
* Rounds a numeric field to the number of decimals specified.
*
* @param string $column
* @param int $decimals
* @return string
*/
public function round( $column, $decimals )
{
$column = $this->getIdentifier( $column );
return "ROUND( {$column}, {$decimals} )";
}
/**
* Returns the remainder of the division operation
* $expression1 / $expression2.
*
* @param string $expression1
* @param string $expression2
* @return string
*/
public function mod( $expression1, $expression2 )
{
$expression1 = $this->getIdentifier( $expression1 );
$expression2 = $this->getIdentifier( $expression2 );
return "MOD( {$expression1}, {$expression2} )";
}
/**
* Returns the current system date and time in the database internal
* format.
*
* @return string
*/
public function now()
{
return "NOW()";
}
// string functions
/**
* Returns part of a string.
*
* Note: Not SQL92, but common functionality.
*
* @param string $value the target $value the string or the string column.
* @param int $from extract from this characeter.
* @param int $len extract this amount of characters.
* @return string sql that extracts part of a string.
*/
public function subString( $value, $from, $len = null )
{
$value = $this->getIdentifier( $value );
if ( $len === null )
{
return "substring( {$value} from {$from} )";
}
else
{
$len = $this->getIdentifier( $len );
return "substring( {$value} from {$from} for {$len} )";
}
}
/**
* Returns a series of strings concatinated
*
* concat() accepts an arbitrary number of parameters. Each parameter
* must contain an expression or an array with expressions.
*
* @param string|array(string) $... strings that will be concatinated.
*/
public function concat()
{
$args = func_get_args();
$cols = ezcQuerySelect::arrayFlatten( $args );
if ( count( $cols ) < 1 )
{
throw new ezcQueryVariableParameterException( 'concat', count( $args ), 1 );
}
$cols = $this->getIdentifiers( $cols );
return "CONCAT( " . join( ', ', $cols ) . ' )';
}
/**
* Returns the SQL to locate the position of the first occurrence of a substring
*
* @param string $substr
* @param string $value
* @return string
*/
public function position( $substr, $value )
{
$value = $this->getIdentifier( $value );
return "LOCATE( '{$substr}', {$value} )";
}
/**
* Returns the SQL to change all characters to lowercase
*
* @param string $value
* @return string
*/
public function lower( $value )
{
$value = $this->getIdentifier( $value );
return "LOWER( {$value} )";
}
/**
* Returns the SQL to change all characters to uppercase
*
* @param string $value
* @return string
*/
public function upper( $value )
{
$value = $this->getIdentifier( $value );
return "UPPER( {$value} )";
}
/**
* Returns the SQL to calculate the next lowest integer value from the number.
*
* @param string $number
* @return string
*/
public function floor( $number )
{
$number = $this->getIdentifier( $number );
return " FLOOR( {$number} ) ";
}
/**
* Returns the SQL to calculate the next highest integer value from the number.
*
* @param string $number
* @return string
*/
public function ceil( $number )
{
$number = $this->getIdentifier( $number );
return " CEIL( {$number} ) ";
}
/**
* Returns the SQL that performs the bitwise AND on two values.
*
* @param string $value1
* @param string $value2
* @return string
*/
public function bitAnd( $value1, $value2 )
{
$value1 = $this->getIdentifier( $value1 );
$value2 = $this->getIdentifier( $value2 );
return "( {$value1} & {$value2} )";
}
/**
* Returns the SQL that performs the bitwise OR on two values.
*
* @param string $value1
* @param string $value2
* @return string
*/
public function bitOr( $value1, $value2 )
{
$value1 = $this->getIdentifier( $value1 );
$value2 = $this->getIdentifier( $value2 );
return "( {$value1} | {$value2} )";
}
/**
* Returns the SQL that performs the bitwise XOR on two values.
*
* @param string $value1
* @param string $value2
* @return string
*/
public function bitXor( $value1, $value2 )
{
$value1 = $this->getIdentifier( $value1 );
$value2 = $this->getIdentifier( $value2 );
return "( {$value1} ^ {$value2} )";
}
/**
* Returns the SQL that converts a timestamp value to a unix timestamp.
*
* @param string $column
* @return string
*/
public function unixTimestamp( $column )
{
$column = $this->getIdentifier( $column );
return " UNIX_TIMESTAMP( {$column} ) ";
}
/**
* Returns the SQL that subtracts an interval from a timestamp value.
*
* @param string $column
* @param numeric $expr
* @param string $type one of SECOND, MINUTE, HOUR, DAY, MONTH, or YEAR
* @return string
*/
public function dateSub( $column, $expr, $type )
{
$type = $this->intervalMap[$type];
$column = $this->getIdentifier( $column );
return " {$column} - INTERVAL {$expr} {$type} ";
}
/**
* Returns the SQL that adds an interval to a timestamp value.
*
* @param string $column
* @param numeric $expr
* @param string $type one of SECOND, MINUTE, HOUR, DAY, MONTH, or YEAR
* @return string
*/
public function dateAdd( $column, $expr, $type )
{
$type = $this->intervalMap[$type];
$column = $this->getIdentifier( $column );
return " {$column} + INTERVAL {$expr} {$type} ";
}
/**
* Returns the SQL that extracts parts from a timestamp value.
*
* @param string $column The column to operate on
* @param string $type one of SECOND, MINUTE, HOUR, DAY, MONTH, or YEAR
* @return string
*/
public function dateExtract( $column, $type )
{
$type = $this->intervalMap[$type];
$column = $this->getIdentifier( $column );
return " EXTRACT( {$type} FROM {$column} ) ";
}
/**
* Returns a searched CASE statement.
*
* Accepts an arbitrary number of parameters.
* The first parameter (array) must always be specified, the last
* parameter (string) specifies the ELSE result.
*
* Example:
* <code>
* $q = ezcDbInstance::get()->createSelectQuery();
* $q->select(
* $q->expr->searchedCase(
* array( $q->expr->gte( 'column1', 20 ), 'column1' )
* , array( $q->expr->gte( 'column2', 50 ), 'column2' )
* , 'column3'
* )
* )
* ->from( 'table' );
* </code>
*
* @throws ezcQueryVariableParameterException
* @return string
*/
public function searchedCase()
{
$args = func_get_args();
if ( count( $args ) === 0 )
{
throw new ezcQueryVariableParameterException( 'searchedCase', count( $args ), 1 );
}
$expr = ' CASE';
foreach ( $args as $arg )
{
if ( is_array( $arg ) && count( $arg ) == 2 )
{
$column1 = $this->getIdentifier( $arg[0] );
$column2 = $this->getIdentifier( $arg[1] );
$expr .= " WHEN {$column1} THEN {$column2}";
}
else if ( is_scalar( $arg ) )
{
$column = $this->getIdentifier( $arg );
$expr .= " ELSE {$column}";
}
}
$expr .= ' END ';
return $expr;
}
}
?>