blob: 7e43749932cd17c32bb1465d6bee1abafc12f2c7 [file] [log] [blame]
<?php
/**
* File containing the ezcDbHandler 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
*/
/**
* Defines interface for all the database drivers implementations.
*
* ezcDbHandler provides some functionality that is not present in PDO.
* - handling of offset/limit in a datbase independent way
* - correct recursive handling of transactions
*
* @version //autogentag//
* @package Database
* @mainclass
*/
abstract class ezcDbHandler extends PDO
{
/**
* Stores the transaction nesting level.
*
* @var int
*/
protected $transactionNestingLevel = 0;
/**
* This flag is set to true when an SQL query has failed.
* In this case the transaction should be rolled back.
*
* @var bool
*/
protected $transactionErrorFlag = false;
/**
* Characters to quote identifiers with. Should be overwritten in handler
* implementation, if different for a specific handler. In some cases the
* quoting start and end characters differ (e.g. ODBC), but mostly they are
* the same.
*
* @var string
*/
protected $identifierQuoteChars = array(
"start" => '"',
"end" => '"',
);
/**
* Constructs a handler object.
*
* note: Remember to always call this constructor from constructor of a derived class!
*
* @see PDO::__construct()
* @param array $dbParams Misc database connection parameters.
* @param string $dsn Data Source Name, generated by constructor
* of a derived class.
*/
public function __construct( $dbParams, $dsn )
{
$user = null;
$pass = null;
$driverOptions = null;
foreach ( $dbParams as $key => $val )
{
switch ( $key )
{
case 'user':
case 'username':
$user = $val;
break;
case 'pass':
case 'password':
$pass = $val;
break;
case 'driver-opts':
$driverOptions = $val;
break;
}
}
parent::__construct( $dsn, $user, $pass, $driverOptions );
$this->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$this->setAttribute( PDO::ATTR_CASE, PDO::CASE_LOWER );
}
/**
* Returns the name of the handler.
*
* Returns handler name
* (e.g. 'mysql', 'pgsql', 'oracle', etc.)
*
* This method can be used to choose more optimal query
* for the given Database.
*
* note This is commented out because it breaks with PHP 5.2.
*
* @return string
*/
// abstract static public function getName();
/**
* Returns true if the given $feature is supported by the handler.
*
* Derived classes should override this method to report
* the features they support.
*
* @apichange Never implemented properly, no good use (See #10937)
* @ignore
* @param string $feature
* @return bool
*/
static public function hasFeature( $feature )
{
return false;
}
/**
* Begins a transaction.
*
* This method executes a begin transaction query unless a
* transaction has already been started (transaction nesting level > 0 )
*
* Each call to beginTransaction() must have a corresponding commit() or
* rollback() call.
*
* @see commit()
* @see rollback()
* @return bool
*/
public function beginTransaction()
{
$retval = true;
if ( $this->transactionNestingLevel == 0 )
{
$retval = parent::beginTransaction();
}
// else NOP
$this->transactionNestingLevel++;
return $retval;
}
/**
* Commits a transaction.
*
* If this this call to commit corresponds to the outermost call to
* beginTransaction() and all queries within this transaction were
* successful, a commit query is executed. If one of the queries returned
* with an error, a rollback query is executed instead.
*
* This method returns true if the transaction was successful. If the
* transaction failed and rollback was called, false is returned.
*
* @see beginTransaction()
* @see rollback()
* @return bool
*/
public function commit()
{
if ( $this->transactionNestingLevel <= 0 )
{
$this->transactionNestingLevel = 0;
throw new ezcDbTransactionException( "commit() called before beginTransaction()." );
}
$retval = true;
if ( $this->transactionNestingLevel == 1 )
{
if ( $this->transactionErrorFlag )
{
parent::rollback();
$this->transactionErrorFlag = false; // reset error flag
$retval = false;
}
else
{
parent::commit();
}
}
// else NOP
$this->transactionNestingLevel--;
return $retval;
}
/**
* Rollback a transaction.
*
* If this this call to rollback corresponds to the outermost call to
* beginTransaction(), a rollback query is executed. If this is an inner
* transaction (nesting level > 1) the error flag is set, leaving the
* rollback to the outermost transaction.
*
* This method always returns true.
*
* @see beginTransaction()
* @see commit()
* @return bool
*/
public function rollback()
{
if ( $this->transactionNestingLevel <= 0 )
{
$this->transactionNestingLevel = 0;
throw new ezcDbTransactionException( "rollback() called without previous beginTransaction()." );
}
if ( $this->transactionNestingLevel == 1 )
{
parent::rollback();
$this->transactionErrorFlag = false; // reset error flag
}
else
{
// set the error flag, so that if there is outermost commit
// then ROLLBACK will be done instead of COMMIT
$this->transactionErrorFlag = true;
}
$this->transactionNestingLevel--;
return true;
}
/**
* Returns a new ezcQuerySelect derived object for the correct database type.
*
* @return ezcQuerySelect
*/
public function createSelectQuery()
{
return new ezcQuerySelect( $this );
}
/**
* Returns a new ezcQueryUpdate derived object for the correct database type.
*
* @return ezcQueryUpdate
*/
public function createUpdateQuery()
{
return new ezcQueryUpdate( $this );
}
/**
* Returns a new ezcQueryInsert derived object for the correct database type.
*
* @return ezcQueryInsert
*/
public function createInsertQuery()
{
return new ezcQueryInsert( $this );
}
/**
* Returns a new ezcQueryDelete derived object for the correct database type.
*
* @return ezcQueryDelete
*/
public function createDeleteQuery()
{
return new ezcQueryDelete( $this );
}
/**
* Returns a new ezcQueryExpression derived object for the correct database type.
*
* @return ezcQueryExpression
*/
public function createExpression()
{
return new ezcQueryExpression( $this );
}
/**
* Returns a new ezcUtilities derived object for the correct database type.
*
* @return ezcDbUtilities
*/
public function createUtilities()
{
return new ezcDbUtilities( $this );
}
/**
* Returns the quoted version of an identifier to be used in an SQL query.
* This method takes a given identifier and quotes it, so it can safely be
* used in SQL queries.
*
* @param string $identifier The identifier to quote.
* @return string The quoted identifier.
*/
public function quoteIdentifier( $identifier )
{
if ( sizeof( $this->identifierQuoteChars ) === 2 )
{
$identifier =
$this->identifierQuoteChars["start"]
. str_replace(
$this->identifierQuoteChars["end"],
$this->identifierQuoteChars["end"].$this->identifierQuoteChars["end"],
$identifier
)
. $this->identifierQuoteChars["end"];
}
return $identifier;
}
}
?>