Author: Sergey Alexeev
Date: 2007-05-03 22:15:43 +0200 (Thu, 03 May 2007)
New Revision: 5029

Log:
- Added feature #9960 [Database] sql abstraction.
                Based on contributions by Joel Arvidsson and Friedel Hill.
 

Modified:
   trunk/Database/ChangeLog
   trunk/Database/src/handlers/sqlite.php
   trunk/Database/src/sqlabstraction/expression.php
   trunk/Database/src/sqlabstraction/implementations/expression_mssql.php
   trunk/Database/src/sqlabstraction/implementations/expression_oracle.php
   trunk/Database/src/sqlabstraction/implementations/expression_pgsql.php
   trunk/Database/src/sqlabstraction/implementations/expression_sqlite.php
   
trunk/Database/src/sqlabstraction/implementations/query_sqlite_function_implementations.php
   trunk/Database/tests/sqlabstraction/expression_test.php

Modified: trunk/Database/ChangeLog
===================================================================
--- trunk/Database/ChangeLog    2007-05-03 19:19:57 UTC (rev 5028)
+++ trunk/Database/ChangeLog    2007-05-03 20:15:43 UTC (rev 5029)
@@ -11,7 +11,9 @@
 - Fixed issue #10529: Tests for quoting of strings in query expressions.
 - Added feature #8448: Select Distinct not supported
 - Added feature #7772: SQL Server implementation for the Database package. 
-                       Based on contributions by Friedel Hill.
+                Based on contributions by Joel Arvidsson and Friedel Hill.
+- Added feature #9960 [Database] sql abstraction.
+                Based on contributions by Joel Arvidsson and Friedel Hill.
 
 1.2 - Monday 18 December 2006
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Modified: trunk/Database/src/handlers/sqlite.php
===================================================================
--- trunk/Database/src/handlers/sqlite.php      2007-05-03 19:19:57 UTC (rev 
5028)
+++ trunk/Database/src/handlers/sqlite.php      2007-05-03 20:15:43 UTC (rev 
5029)
@@ -68,6 +68,9 @@
         /* Register PHP implementations of missing functions in SQLite */
         $this->sqliteCreateFunction( 'md5', array( 'ezcQuerySqliteFunctions', 
'md5Impl'), 1 );
         $this->sqliteCreateFunction( 'mod', array( 'ezcQuerySqliteFunctions', 
'modImpl'), 2 );
+        $this->sqliteCreateFunction( 'locate', array( 
'ezcQuerySqliteFunctions', 'positionImpl'), 2 );
+        $this->sqliteCreateFunction( 'floor', array( 
'ezcQuerySqliteFunctions', 'floorImpl'), 1 );
+        $this->sqliteCreateFunction( 'ceil', array( 'ezcQuerySqliteFunctions', 
'ceilImpl'), 1 );        
         $this->sqliteCreateFunction( 'concat', array( 
'ezcQuerySqliteFunctions', 'concatImpl') );
         $this->sqliteCreateFunction( 'now', 'time', 0 );
     }

Modified: trunk/Database/src/sqlabstraction/expression.php
===================================================================
--- trunk/Database/src/sqlabstraction/expression.php    2007-05-03 19:19:57 UTC 
(rev 5028)
+++ trunk/Database/src/sqlabstraction/expression.php    2007-05-03 20:15:43 UTC 
(rev 5029)
@@ -47,6 +47,20 @@
     private $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     
@@ -809,5 +823,218 @@
         $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 $date
+     * @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;
+    }
 }
 ?>

Modified: trunk/Database/src/sqlabstraction/implementations/expression_mssql.php
===================================================================
--- trunk/Database/src/sqlabstraction/implementations/expression_mssql.php      
2007-05-03 19:19:57 UTC (rev 5028)
+++ trunk/Database/src/sqlabstraction/implementations/expression_mssql.php      
2007-05-03 20:15:43 UTC (rev 5029)
@@ -17,6 +17,19 @@
  */
 class ezcQueryExpressionMssql extends ezcQueryExpression
 {
+    /**
+     * Contains an interval map from generic intervals to MS SQL native 
intervals.
+     *
+     * @var array(string=>string)
+     */
+    protected $intervalMap = array(
+        'SECOND' => 'second',
+        'MINUTE' => 'minute',
+        'HOUR' => 'Hour',
+        'DAY' => 'Day',
+        'MONTH' => 'Month',
+        'YEAR' => 'Year',
+    );
 
     /**
      * Returns the remainder of the division operation
@@ -35,7 +48,7 @@
 
     /**
      * Returns the md5 sum of a field. 
-     * There is two variants of implementation for this feature.
+     * There are two variants of implementation for this feature.
      * Both not ideal though.
      * First don't require additional setup of MS SQL Server
      * and uses undocumented function master.dbo.fn_varbintohexstr()
@@ -43,7 +56,7 @@
      *
      * Second one requires the stored procedure
      * from http://www.thecodeproject.com/database/xp_md5.asp to 
-     * be installed and wrapped by the user defined function fn_md5
+     * be installed and wrapped by the user defined function fn_md5.
      *
      * @return string
      */
@@ -124,5 +137,89 @@
         $cols = $this->getIdentifiers( $cols );
         return 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 "CHARINDEX( '{$substr}', {$value} )";
+    }
+
+    /**
+     * 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 " CEILING( {$number} ) ";
+    }
+
+    /**
+     * Returns the SQL that converts a timestamp value to number of seconds 
since 1970-01-01 00:00:00-00.
+     *
+     * @param string $column
+     * @return string
+     */
+    public function unixTimestamp( $column )
+    {
+        $column = $this->getIdentifier( $column );
+        return " DATEDIFF(s, '19700101', {$column} ) - ".date('Z')." ";
+    }
+
+    /**
+     * 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 " CONVERT( varchar( 19 ), DATEADD( {$type}, -{$expr}, {$column} 
), 120 ) ";
+    }
+
+    /**
+     * 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 " CONVERT( varchar( 19 ), DATEADD( {$type}, +{$expr}, {$column} 
), 120 ) ";
+    }
+
+    /**
+     * Returns the SQL that extracts parts from a timestamp value.
+     *
+     * @param string $date
+     * @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 " DATEPART( {$type}, {$column} ) ";
+    }
 }
 ?>

Modified: 
trunk/Database/src/sqlabstraction/implementations/expression_oracle.php
===================================================================
--- trunk/Database/src/sqlabstraction/implementations/expression_oracle.php     
2007-05-03 19:19:57 UTC (rev 5028)
+++ trunk/Database/src/sqlabstraction/implementations/expression_oracle.php     
2007-05-03 20:15:43 UTC (rev 5029)
@@ -86,5 +86,153 @@
     {
         return "LOCALTIMESTAMP";
     }
+
+    /**
+     * 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 "INSTR( {$value}, '{$substr}' )";
+    }
+
+    /**
+     * 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 "bitand( {$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} - bitand( {$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} - bitand( {$value1}, {$value2} ) * 2 
)";
+    }
+
+    /**
+     * 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 );
+
+        if( $column != 'NOW()' )
+        {
+            $column = "CAST( {$column} AS TIMESTAMP )";
+//            // alternative
+//            if( preg_match( '/[0-9]{4}-[0-9]{2}-[0-9]{2} 
[0-9]{2}:[0-9]{2}:[0-9]{2}/', $column ) ) {
+//                $column = "TO_TIMESTAMP( {$column}, 'YYYY-MM-DD HH24:MI:SS' 
)";
+//            }
+        }
+
+        $date1 = "CAST( SYS_EXTRACT_UTC( {$column} ) AS DATE )";
+        $date2 = "TO_DATE( '19700101000000', 'YYYYMMDDHH24MISS' )";
+        return " ROUND( ( {$date1} - {$date2} ) / ( 1 / 86400 ) ) ";
+    }
+
+    /**
+     * 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 );
+
+        if( $column != 'NOW()' )
+        {
+            $column = "CAST( {$column} AS TIMESTAMP )";
+        }
+
+        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 );
+
+        if( $column != 'NOW()' )
+        {
+            $column = "CAST( {$column} AS TIMESTAMP )";
+        }
+
+        return " {$column} + INTERVAL '{$expr}' {$type} ";
+    }
+
+    /**
+     * Returns the SQL that extracts parts from a timestamp value.
+     *
+     * @param string $date
+     * @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 );
+
+        if( $column != 'NOW()' )
+        {
+            $column = "CAST( {$column} AS TIMESTAMP )";
+        }
+
+        if( $type == 'SECOND' )
+        {
+            return " FLOOR( EXTRACT( {$type} FROM {$column} ) ) ";
+        }
+        else
+        {
+            return " EXTRACT( {$type} FROM {$column} ) ";
+        }
+    }
 }
 ?>

Modified: trunk/Database/src/sqlabstraction/implementations/expression_pgsql.php
===================================================================
--- trunk/Database/src/sqlabstraction/implementations/expression_pgsql.php      
2007-05-03 19:19:57 UTC (rev 5028)
+++ trunk/Database/src/sqlabstraction/implementations/expression_pgsql.php      
2007-05-03 20:15:43 UTC (rev 5029)
@@ -124,5 +124,106 @@
     {
         return "LOCALTIMESTAMP(0)";
     }
+
+    /**
+     * 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 "POSITION( '{$substr}' IN {$value} )";
+    }
+
+    /**
+     * 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 " EXTRACT( EPOCH FROM CAST( {$column} AS TIMESTAMP ) ) ";
+    }
+
+    /**
+     * 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];
+
+        if( $column != 'NOW()' )
+        {
+            $column = $this->getIdentifier( $column );
+            $column = "CAST( {$column} AS TIMESTAMP )";
+        }
+
+        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];
+
+        if( $column != 'NOW()' )
+        {
+            $column = $this->getIdentifier( $column );
+            $column = "CAST( {$column} AS TIMESTAMP )";
+        }
+
+        return " {$column} + INTERVAL '{$expr} {$type}' ";
+    }
+
+    /**
+     * Returns the SQL that extracts parts from a timestamp value.
+     *
+     * @param string $date
+     * @param string $type one of SECOND, MINUTE, HOUR, DAY, MONTH, or YEAR
+     * @return string
+     */
+    public function dateExtract( $column, $type )
+    {
+        $type = $this->intervalMap[$type];
+
+        if( $column != 'NOW()' )
+        {
+            $column = $this->getIdentifier( $column );
+            $column = "CAST( {$column} AS TIMESTAMP )";
+        }
+
+        return " EXTRACT( {$type} FROM {$column} ) ";
+    }
 }
 ?>

Modified: 
trunk/Database/src/sqlabstraction/implementations/expression_sqlite.php
===================================================================
--- trunk/Database/src/sqlabstraction/implementations/expression_sqlite.php     
2007-05-03 19:19:57 UTC (rev 5028)
+++ trunk/Database/src/sqlabstraction/implementations/expression_sqlite.php     
2007-05-03 20:15:43 UTC (rev 5029)
@@ -21,6 +21,20 @@
 class ezcQueryExpressionSqlite extends ezcQueryExpression
 {
     /**
+     * Contains an interval map from generic intervals to SQLite native 
intervals.
+     * 
+     * @var array(string=>string)
+     */
+    protected $intervalMap = array(
+        'SECOND' => 'seconds',
+        'MINUTE' => 'minutes',
+        'HOUR' => 'hours',
+        'DAY' => 'days',
+        'MONTH' => 'months',
+        'YEAR' => 'years',
+    );
+
+    /**
      * Returns part of a string.
      *
      * Note: Not SQL92, but common functionality. SQLite only supports the 3
@@ -55,5 +69,110 @@
     {
         return '"' . date( 'Y-m-d H:i:s' ) . '"';
     }
+
+    /**
+     * 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} ) - ( {$value1} & {$value2} ) )";
+    }
+
+    /**
+     * Returns the SQL that converts a timestamp value to a unix timestamp.
+     *
+     * @param string $column
+     * @return string
+     */
+    public function unixTimestamp( $column )
+    {
+        if( $column == 'NOW()' )
+        {
+            return " strftime( '%s', 'now' ) ";
+        }
+        else
+        {
+            $column = $this->getIdentifier( $column );
+            return " strftime( '%s', {$column} ) - ".date('Z')." ";
+        }
+    }
+
+    /**
+     * 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 " datetime( {$column} , '-{$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 " datetime( {$column} , '+{$expr} {$type}' ) ";
+    }
+
+    /**
+     * Returns the SQL that extracts parts from a timestamp value.
+     *
+     * @param string $date
+     * @param string $type one of SECOND, MINUTE, HOUR, DAY, MONTH, or YEAR
+     * @return string
+     */
+    public function dateExtract( $column, $type )
+    {
+        switch ( $type )
+        {
+            case 'SECOND':
+                $type = '%S';
+                break;
+            case 'MINUTE':
+                $type = '%M';
+                break;
+            case 'HOUR':
+                $type = '%H';
+                break;
+            case 'DAY':
+                $type = '%d';
+                break;
+            case 'MONTH':
+                $type = '%m';
+                break;
+            case 'YEAR':
+                $type = '%Y';
+                break;
+        }
+
+        if( $column == 'NOW()' )
+        {
+            $column = "'now'";
+        }
+
+        $column = $this->getIdentifier( $column );
+        return " strftime( '{$type}', {$column} ) ";
+    }
 }
 ?>

Modified: 
trunk/Database/src/sqlabstraction/implementations/query_sqlite_function_implementations.php
===================================================================
--- 
trunk/Database/src/sqlabstraction/implementations/query_sqlite_function_implementations.php
 2007-05-03 19:19:57 UTC (rev 5028)
+++ 
trunk/Database/src/sqlabstraction/implementations/query_sqlite_function_implementations.php
 2007-05-03 20:15:43 UTC (rev 5029)
@@ -50,5 +50,39 @@
         $args = func_get_args();
         return join( '', $args );
     }
+
+    /**
+     * Returns the SQL to locate the position of the first occurrence of a 
substring
+     * 
+     * @param string $substr
+     * @param string $value
+     * @return integer
+     */
+     static public function positionImpl( $substr, $value )
+     {
+         return strpos( $value, $substr ) + 1;
+     }
+
+    /**
+     * Returns the next lowest integer value from the number
+     * 
+     * @param numeric $number
+     * @return integer
+     */
+     static public function floorImpl( $number )
+     {
+         return (int) floor( $number );
+     }
+
+     /**
+      * Returns the next highest integer value from the number
+      * 
+      * @param numeric $number
+      * @return integer
+      */
+     static public function ceilImpl( $number )
+     {
+         return (int) ceil( $number );
+     }
 }
 ?>

Modified: trunk/Database/tests/sqlabstraction/expression_test.php
===================================================================
--- trunk/Database/tests/sqlabstraction/expression_test.php     2007-05-03 
19:19:57 UTC (rev 5028)
+++ trunk/Database/tests/sqlabstraction/expression_test.php     2007-05-03 
20:15:43 UTC (rev 5029)
@@ -26,6 +26,7 @@
 
     protected function setUp()
     {
+        
         try {
             $this->db = ezcDbInstance::get();
         }
@@ -45,11 +46,24 @@
         catch ( Exception $e ) {} // eat
 
         // insert some data
-        $this->db->exec( 'CREATE TABLE query_test ( id int, company 
VARCHAR(255), section VARCHAR(255), employees int NULL)' );
-        $this->db->exec( "INSERT INTO query_test VALUES ( 1, 'eZ systems', 
'Norway', 20 )" );
-        $this->db->exec( "INSERT INTO query_test VALUES ( 2, 'IBM', 'Norway', 
500 )" );
-        $this->db->exec( "INSERT INTO query_test VALUES ( 3, 'eZ systems', 
'Ukraine', 10 )" );
-        $this->db->exec( "INSERT INTO query_test VALUES ( 4, 'IBM', 'Germany', 
null )" );
+        if ( $this->db->getName() === 'mssql' )
+        {
+            $this->db->exec( 'CREATE TABLE query_test ( id int, company 
VARCHAR(255), section VARCHAR(255), employees int NULL, somedate DATETIME NULL 
)' );
+        }
+        else
+        {
+            $this->db->exec( 'CREATE TABLE query_test ( id int, company 
VARCHAR(255), section VARCHAR(255), employees int NULL, somedate TIMESTAMP )' );
+        }
+
+        if( $this->db->getName() === 'oracle' )
+        {
+            $this->db->exec( "ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 
'YYYY-MM-DD HH24:MI:SS'" ); // set the timestamp format
+        }
+       
+        $this->db->exec( "INSERT INTO query_test VALUES ( 1, 'eZ systems', 
'Norway', 20, '2007-05-03 11:54:17' )" );
+        $this->db->exec( "INSERT INTO query_test VALUES ( 2, 'IBM', 'Norway', 
500, null )" );
+        $this->db->exec( "INSERT INTO query_test VALUES ( 3, 'eZ systems', 
'Ukraine', 10, null )" );
+        $this->db->exec( "INSERT INTO query_test VALUES ( 4, 'IBM', 'Germany', 
null, null )" );
     }
 
     protected function tearDown()
@@ -437,10 +451,31 @@
         catch ( ezcQueryVariableParameterException $e ) {}
     }
 
+    public function testSearchedCaseNone()
+    {
+        try
+        {
+            $this->e->searchedCase();
+            $this->fail( "Expected exception" );
+        }
+        catch ( ezcQueryVariableParameterException $e ) {}
+    }
+
+    public function testSearchedCase()
+    {
+        $reference = ' CASE WHEN 10 >= 20 THEN 1 WHEN 20 >= 20 THEN 2 ELSE 3 
END ';
+        $result = $this->e->searchedCase(
+            array( $this->e->gte( 10, 20 ), 1 ),
+            array( $this->e->gte( 20, 20 ), 2 ),
+            3
+        );
+        $this->assertSame( $reference, $result );
+    }
+
     /**
-     * Implementation tests, these are run on a selectQuery object so we know
-     * we have the correct expression type.
-     */
+    * Implementation tests, these are run on a selectQuery object so we know
+    * we have the correct expression type.
+    */
     public function testlOrSingleImpl()
     {
         $this->q->select( '*' )->from( 'query_test' )
@@ -670,8 +705,8 @@
 
     public function testInAlreadyQuotedImpl()
     {
-        $this->db->exec( "INSERT INTO query_test VALUES ( 5, 'ACME Inc.', 
'''test-only''', null )" );
-        $this->db->exec( "INSERT INTO query_test VALUES ( 6, 'ACME Inc.', 
'\"test-only\"', null )" );
+        $this->db->exec( "INSERT INTO query_test VALUES ( 5, 'ACME Inc.', 
'''test-only''', null, null )" );
+        $this->db->exec( "INSERT INTO query_test VALUES ( 6, 'ACME Inc.', 
'\"test-only\"', null, null )" );
 
         $this->q->select( '*' )->from( 'query_test' )
             ->where( $this->e->in( 'section', "'Norway'", "'Ukraine'", 
"'test-only'", "\"test-only\"" ) );
@@ -889,7 +924,237 @@
         $this->assertEquals( 'eZ systems rocks!', $stmt->fetchColumn( 0 ) );
     }
 
-    /**
+    public function testPositionImpl()
+    {
+        $this->q->select( $this->e->position( 's', "'eZ systems'" ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( 4, (int)$stmt->fetchColumn( 0 ) );
+    }
+
+    public function testLowerImpl()
+    {
+        $this->q->select( $this->e->lower( "'eZ systems'" ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( 'ez systems', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testUpperImpl()
+    {
+        $this->q->select( $this->e->upper( "'eZ systems'" ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( 'EZ SYSTEMS', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testFloorImpl()
+    {
+        $this->q->select( $this->e->floor( 3.33 ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( 3, (int)$stmt->fetchColumn( 0 ) );
+    }
+
+    public function testCeilImpl()
+    {
+        $this->q->select( $this->e->ceil( 3.33 ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( 4, (int)$stmt->fetchColumn( 0 ) );
+    }
+
+    public function testUnixTimestampImpl()
+    {
+        $this->q->select( $this->e->unixTimestamp( "'2007-05-03 11:54:17'" ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( strtotime( '2007-05-03 11:54:17' ), 
(int)$stmt->fetchColumn( 0 ) );
+    }
+
+    public function testDateSubSecondImpl()
+    {
+        $this->q->select( $this->e->dateSub( "'2007-05-03 11:54:17'", 1, 
'SECOND' ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( '2007-05-03 11:54:16', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testDateSubMinuteImpl()
+    {
+        $this->q->select( $this->e->dateSub( "'2007-05-03 11:54:17'", 1, 
'MINUTE' ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( '2007-05-03 11:53:17', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testDateSubHourImpl()
+    {
+        $this->q->select( $this->e->dateSub( "'2007-05-03 11:54:17'", 1, 
'HOUR' ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( '2007-05-03 10:54:17', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testDateSubDayImpl()
+    {
+        $this->q->select( $this->e->dateSub( "'2007-05-03 11:54:17'", 1, 'DAY' 
) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( '2007-05-02 11:54:17', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testDateSubMonthImpl()
+    {
+        $this->q->select( $this->e->dateSub( "'2007-05-03 11:54:17'", 1, 
'MONTH' ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( '2007-04-03 11:54:17', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testDateSubYearImpl()
+    {
+        $this->q->select( $this->e->dateSub( "'2007-05-03 11:54:17'", 1, 
'YEAR' ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( '2006-05-03 11:54:17', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testDateAddSecondImpl()
+    {
+        $this->q->select( $this->e->dateAdd( "'2007-05-03 11:54:17'", 1, 
'SECOND' ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( '2007-05-03 11:54:18', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testDateAddMinuteImpl()
+    {
+        $this->q->select( $this->e->dateAdd( "'2007-05-03 11:54:17'", 1, 
'MINUTE' ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( '2007-05-03 11:55:17', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testDateAddHourImpl()
+    {
+        $this->q->select( $this->e->dateAdd( "'2007-05-03 11:54:17'", 1, 
'HOUR' ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( '2007-05-03 12:54:17', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testDateAddDayImpl()
+    {
+        $this->q->select( $this->e->dateAdd( "'2007-05-03 11:54:17'", 1, 'DAY' 
) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( '2007-05-04 11:54:17', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testDateAddMonthImpl()
+    {
+        $this->q->select( $this->e->dateAdd( "'2007-05-03 11:54:17'", 1, 
'MONTH' ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( '2007-06-03 11:54:17', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testDateAddYearImpl()
+    {
+        $this->q->select( $this->e->dateAdd( "'2007-05-03 11:54:17'", 1, 
'YEAR' ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( '2008-05-03 11:54:17', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testDateExtractSecondImpl()
+    {
+        $this->q->select( $this->e->dateExtract( "'2007-05-03 11:54:17'", 
'SECOND' ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( '17', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testDateExtractMinuteImpl()
+    {
+        $this->q->select( $this->e->dateExtract( "'2007-05-03 11:54:17'", 
'MINUTE' ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( '54', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testDateExtractHourImpl()
+    {
+        $this->q->select( $this->e->dateExtract( "'2007-05-03 11:54:17'", 
'HOUR' ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( '11', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testDateExtractDayImpl()
+    {
+        $this->q->select( $this->e->dateExtract( "'2006-11-16 11:54:17'", 
'DAY' ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( '16', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testDateExtractMonthImpl()
+    {
+        $this->q->select( $this->e->dateExtract( "'2006-11-16 11:54:17'", 
'MONTH' ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( '11', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testDateExtractYearImpl()
+    {
+        $this->q->select( $this->e->dateExtract( "'2006-11-16 11:54:17'", 
'YEAR' ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( '2006', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testSearchedCaseImpl()
+    {
+        $this->q->select(
+            $this->q->expr->searchedCase(
+                array( $this->e->gte( 10, 20 ), 1 ),
+                array( $this->e->gte( 20, 20 ), 2 ),
+                3
+            )
+        );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( 2, (int)$stmt->fetchColumn( 0 ) );
+    }
+
+    public function testBitAndImpl()
+    {
+        $this->q->select( $this->e->bitAnd( 3, 10 ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( 2, (int)$stmt->fetchColumn( 0 ) );
+    }
+
+    public function testBitOrImpl()
+    {
+        $this->q->select( $this->e->bitOr( 3, 10 ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( 11, (int)$stmt->fetchColumn( 0 ) );
+    }
+
+    public function testBitXorImpl()
+    {
+        $this->q->select( $this->e->bitXor( 3, 10 ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+       $this->assertSame( 9, (int)$stmt->fetchColumn( 0 ) );
+    }
+   
+     /**
      * Repeat of the implementation tests, but now testing with alias 
functionality.
      */
 // Not tested since it requires boolean field
@@ -1274,5 +1539,190 @@
         $this->assertEquals( $reference, $this->q->getQuery() );
     }
 
+    public function testPositionImplWithAlias()
+    {
+        $this->q->setAliases( array( 'text' => 'company' ) );
+        $this->q->select( $this->q->expr->position( 's', 'text' ) )
+            ->from( 'query_test' );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( 4, (int)$stmt->fetchColumn( 0 ) );
+    }
+
+    public function testLowerImplWithAlias()
+    {
+        $this->q->setAliases( array( 'text' => 'company' ) );
+        $this->q->select( $this->q->expr->lower( 'text' ) )
+            ->from( 'query_test' );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( 'ez systems', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testUpperImplWithAlias()
+    {
+        $this->q->setAliases( array( 'text' => 'company' ) );
+        $this->q->select( $this->q->expr->upper( 'text' ) )
+            ->from( 'query_test' );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( 'EZ SYSTEMS', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testFloorImplWithAlias()
+    {
+        $this->q->setAliases( array( 'empl' => 'employees' ) );
+        $this->q->select( $this->q->expr->floor( 'empl' ) )
+            ->from( 'query_test' )
+            ->where( $this->q->expr->eq( 'id', 1 ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( 20, (int)$stmt->fetchColumn( 0 ) );
+    }
+
+    public function testCeilImplWithAlias()
+    {
+        $this->q->setAliases( array( 'empl' => 'employees' ) );
+        $this->q->select( $this->q->expr->ceil( 'empl' ) )
+            ->from( 'query_test' )
+            ->where( $this->q->expr->eq( 'id', 1 ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( 20, (int)$stmt->fetchColumn( 0 ) );
+    }
+
+    public function testUnixTimestampImplWithAlias()
+    {
+        $this->q->setAliases( array( 'mydate' => 'somedate' ) );
+        $this->q->select( $this->q->expr->unixTimestamp( 'mydate' ) )
+            ->from( 'query_test' )
+            ->where( $this->q->expr->eq( 'id', 1 ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( strtotime( '2007-05-03 11:54:17' ), 
(int)$stmt->fetchColumn( 0 ) );
+    }
+
+    public function testDateSubImplWithAlias()
+    {
+        $this->q->setAliases( array( 'mydate' => 'somedate' ) );
+        $this->q->select( $this->q->expr->dateSub( 'mydate', 1, 'SECOND' ) )
+            ->from( 'query_test' )
+            ->where( $this->q->expr->eq( 'id', 1 ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( '2007-05-03 11:54:16', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testDateAddImplWithAlias()
+    {
+        $this->q->setAliases( array( 'mydate' => 'somedate' ) );
+        $this->q->select( $this->q->expr->dateAdd( 'mydate', 1, 'SECOND' ) )
+            ->from( 'query_test' )
+            ->where( $this->q->expr->eq( 'id', 1 ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( '2007-05-03 11:54:18', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testDateExtractImplWithAlias()
+    {
+        $this->q->setAliases( array( 'mydate' => 'somedate' ) );
+        $this->q->select( $this->q->expr->dateExtract( 'mydate', 'SECOND' ) )
+            ->from( 'query_test' )
+            ->where( $this->q->expr->eq( 'id', 1 ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( '17', $stmt->fetchColumn( 0 ) );
+    }
+
+    public function testSearchedCaseImplWithAlias()
+    {
+        $this->q->setAliases( array( 'identifier' => 'id', 'empl' => 
'employees' ) );
+        $this->q->select(
+            $this->q->expr->searchedCase(
+                  array( $this->q->expr->gte( 'empl', 20 ), 'empl' )
+                , 'identifier'
+            )
+        )
+            ->from( 'query_test' )
+            ->orderBy( 'query_test.id' );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $result = $stmt->fetchAll( PDO::FETCH_NUM );
+        $this->assertSame( 20, (int)$result[0][0] );
+        $this->assertSame( 500, (int)$result[1][0] );
+        $this->assertSame( 3, (int)$result[2][0] );
+        $this->assertSame( 4, (int)$result[3][0] );
+    }
+
+    public function testBitAndImplWithAlias()
+    {
+        $this->q->setAliases( array( 'empl' => 'employees' ) );
+        $this->q->select( $this->q->expr->bitAnd( 3, 'empl' ) )
+            ->from( 'query_test' )
+            ->where( $this->q->expr->eq( 'id', 3 ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( 2, (int)$stmt->fetchColumn( 0 ) );
+    }
+
+    public function testBitOrImplWithAlias()
+    {
+        $this->q->setAliases( array( 'empl' => 'employees' ) );
+        $this->q->select( $this->q->expr->bitOr( 3, 'empl' ) )
+            ->from( 'query_test' )
+            ->where( $this->q->expr->eq( 'id', 3 ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( 11, (int)$stmt->fetchColumn( 0 ) );
+    }
+
+    public function testBitXorImplWithAlias()
+    {
+        $this->q->setAliases( array( 'empl' => 'employees' ) );
+        $this->q->select( $this->q->expr->bitXor( 3, 'empl' ) )
+            ->from( 'query_test' )
+            ->where( $this->q->expr->eq( 'id', 3 ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertSame( 9, (int)$stmt->fetchColumn( 0 ) );
+    }
+
+    /**
+     * Repeat of relevant implementation tests, but now testing with 
ezcQueryExpression::now().
+     */
+    public function testUnixTimestampImplNow()
+    {
+        $this->q->select( $this->e->unixTimestamp( $this->q->expr->now() ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertEquals( time(), $stmt->fetchColumn( 0 ), '', 1 ); // with 
delta 1
+    }
+
+    public function testDateSubImplNow()
+    {
+        $this->q->select( $this->e->dateSub( $this->q->expr->now(), 1, 
'MINUTE' ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertEquals( time() - 60, strtotime( $stmt->fetchColumn( 0 ) 
), '', 1 ); // with delta 1
+    }
+
+    public function testDateAddImplNow()
+    {
+        $this->q->select( $this->e->dateAdd( $this->q->expr->now(), 1, 
'MINUTE' ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $this->assertEquals( time() + 60, strtotime( $stmt->fetchColumn( 0 ) 
), '', 1 ); // with delta 1
+    }
+
+    public function testDateExtractImplNow()
+    {
+        $this->q->select( $this->e->dateExtract( $this->q->expr->now(), 
'SECOND' ) );
+        $stmt = $this->q->prepare();
+        $stmt->execute();
+        $result = $stmt->fetchColumn( 0 );
+        $this->assertSame( (double)$result, floor( (double)$result ) );
+        $this->assertEquals( (int)date( 's' ), (int)$result, '', 1 ); // with 
delta 1
+    }
 }
 ?>

-- 
svn-components mailing list
[email protected]
http://lists.ez.no/mailman/listinfo/svn-components

Reply via email to