blob: d75273f897c6c1a66532ad321eeba57e9c121014 [file] [log] [blame]
<?php
/**
* File containing the ezcQueryOracle 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
*/
/**
* Oracle specific implementation of ezcQuery.
*
* This class reimplements methods where Oracle differs from
* the standard implementation in ezcQuery.Most notably LIMIT
* which is not supported directly in oracle.
*
* @see ezcQuery
* @package Database
* @version //autogentag//
*/
class ezcQuerySelectOracle extends ezcQuerySelect
{
/**
* If a limit and/or offset has been set for this query.
*/
private $hasLimit = false;
/**
* The limit set.
*
* @var int
*/
private $limit = 0;
/**
* The offset set.
*
* @var int
*/
private $offset = 0;
/**
* Constructs a new ezcQueryOracle object working on the database $db.
*
* @param PDO $db
*/
public function __construct( PDO $db )
{
parent::__construct( $db );
}
/**
* Resets the query object for reuse.
*
* @return void
*/
public function reset()
{
$this->hasLimit = false;
$this->limit = 0;
$this->offset = 0;
parent::reset();
}
/**
* 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 Old name
* @param string $alias Alias
* @return string the query string "columnname as targetname
*/
public function alias( $name, $alias )
{
$name = $this->getIdentifier( $name );
return "{$name} {$alias}";
}
/**
* 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>
*
* Oracle does not support the LIMIT keyword. A complete rewrite of the
* query is neccessary. Queries will be rewritten like this:
* <code>
* Original query in MySQL syntax:
* SELECT * FROM table LIMIT 10, 5
* The corresponding Oracle query:
* SELECT * FROM (SELECT a.*, ROWNUM rn FROM (SELECT * FROM table) a WHERE rownum <= 15) WHERE rn >= 6;
* </code>
* Even though the Oracle query is three times as long it performs about the same
* as mysql on small result sets and a bit better on large result sets.
*
* Note that you will not get a result if you call buildLimit() when using the oracle database.
*
* @param string $limit integer expression
* @param string $offset integer expression
* @return ezcQuerySelect
*/
public function limit( $limit, $offset = 0 )
{
$this->hasLimit = true;
$this->limit = $limit;
$this->offset = $offset;
return $this;
}
/**
* Returns dummy table name 'dual'.
*
* @return string
*/
static public function getDummyTableName()
{
return 'dual';
}
/**
* Transforms the query from the parent to provide LIMIT functionality.
*/
public function getQuery()
{
$query = parent::getQuery();
if ( $this->hasLimit )
{
$max = $this->offset + $this->limit;
if ( $this->offset > 0 )
{
$min = $this->offset + 1;
$query = "SELECT * FROM (SELECT a.*, ROWNUM rn FROM ( {$query} ) a WHERE rownum <= {$max} ) WHERE rn >= {$min}";
}
else
{
$query = "SELECT a.* FROM ( {$query} ) a WHERE ROWNUM <= {$max}";
}
}
return $query;
}
/**
* Handles preparing query.
*
* Overrides ezcQuery->prepare()
*
* Adds "FROM dual" to the select if no FROM clause specified
* i.e. fixes queries like "SELECT 1+1" to work in Oracle.
*
* @return PDOStatement
*/
public function prepare()
{
if ( $this->fromString == null || $this->fromString == '' )
{
$this->from( $this->getDummyTableName() );
}
return parent::prepare();
}
}
?>