Initial commit with Symfony 2.1+Vendors

Signed-off-by: Gergely POLONKAI (W00d5t0ck) <polesz@w00d5t0ck.info>
This commit is contained in:
Polonkai Gergely
2012-07-01 09:52:20 +02:00
commit 082a0130c2
5381 changed files with 416709 additions and 0 deletions

View File

@@ -0,0 +1,98 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Cache;
use Doctrine\DBAL\Driver\ResultStatement;
use PDO;
class ArrayStatement implements \IteratorAggregate, ResultStatement
{
private $data;
private $columnCount = 0;
private $num = 0;
private $defaultFetchStyle = PDO::FETCH_BOTH;
public function __construct(array $data)
{
$this->data = $data;
if (count($data)) {
$this->columnCount = count($data[0]);
}
}
public function closeCursor()
{
unset ($this->data);
}
public function columnCount()
{
return $this->columnCount;
}
public function setFetchMode($fetchStyle, $arg2 = null, $arg3 = null)
{
if ($arg2 !== null || $arg3 !== null) {
throw new \InvalidArgumentException("Caching layer does not support 2nd/3rd argument to setFetchMode()");
}
$this->defaultFetchStyle = $fetchStyle;
}
public function getIterator()
{
$data = $this->fetchAll($this->defaultFetchStyle);
return new \ArrayIterator($data);
}
public function fetch($fetchStyle = PDO::FETCH_BOTH)
{
if (isset($this->data[$this->num])) {
$row = $this->data[$this->num++];
if ($fetchStyle === PDO::FETCH_ASSOC) {
return $row;
} else if ($fetchStyle === PDO::FETCH_NUM) {
return array_values($row);
} else if ($fetchStyle === PDO::FETCH_BOTH) {
return array_merge($row, array_values($row));
}
}
return false;
}
public function fetchAll($fetchStyle = PDO::FETCH_BOTH)
{
$rows = array();
while ($row = $this->fetch($fetchStyle)) {
$rows[] = $row;
}
return $rows;
}
public function fetchColumn($columnIndex = 0)
{
$row = $this->fetch(PDO::FETCH_NUM);
if (!isset($row[$columnIndex])) {
// TODO: verify this is correct behavior
return false;
}
return $row[$columnIndex];
}
}

View File

@@ -0,0 +1,37 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Cache;
/**
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @since 2.2
*/
class CacheException extends \Doctrine\DBAL\DBALException
{
static public function noCacheKey()
{
return new self("No cache key was set.");
}
static public function noResultDriverConfigured()
{
return new self("Trying to cache a query but no result driver is configured.");
}
}

View File

@@ -0,0 +1,131 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Cache;
use Doctrine\Common\Cache\Cache;
/**
* Query Cache Profile handles the data relevant for query caching.
*
* It is a value object, setter methods return NEW instances.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class QueryCacheProfile
{
/**
* @var Cache
*/
private $resultCacheDriver;
/**
* @var int
*/
private $lifetime = 0;
/**
* @var string
*/
private $cacheKey;
/**
* @param int $lifetime
* @param string $cacheKey
* @param Cache $resultCache
*/
public function __construct($lifetime = 0, $cacheKey = null, Cache $resultCache = null)
{
$this->lifetime = $lifetime;
$this->cacheKey = $cacheKey;
$this->resultCacheDriver = $resultCache;
}
/**
* @return Cache
*/
public function getResultCacheDriver()
{
return $this->resultCacheDriver;
}
/**
* @return int
*/
public function getLifetime()
{
return $this->lifetime;
}
/**
* @return string
*/
public function getCacheKey()
{
if ($this->cacheKey === null) {
throw CacheException::noCacheKey();
}
return $this->cacheKey;
}
/**
* Generate the real cache key from query, params and types.
*
* @param string $query
* @param array $params
* @param array $types
* @return array
*/
public function generateCacheKeys($query, $params, $types)
{
$realCacheKey = $query . "-" . serialize($params) . "-" . serialize($types);
// should the key be automatically generated using the inputs or is the cache key set?
if ($this->cacheKey === null) {
$cacheKey = sha1($realCacheKey);
} else {
$cacheKey = $this->cacheKey;
}
return array($cacheKey, $realCacheKey);
}
/**
* @param Cache $cache
* @return QueryCacheProfile
*/
public function setResultCacheDriver(Cache $cache)
{
return new QueryCacheProfile($this->lifetime, $this->cacheKey, $cache);
}
/**
* @param string|null $cacheKey
* @return QueryCacheProfile
*/
public function setCacheKey($cacheKey)
{
return new QueryCacheProfile($this->lifetime, $cacheKey, $this->resultCacheDriver);
}
/**
* @param int $lifetime
* @return QueryCacheProfile
*/
public function setLifetime($lifetime)
{
return new QueryCacheProfile($lifetime, $this->cacheKey, $this->resultCacheDriver);
}
}

View File

@@ -0,0 +1,255 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Cache;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\ResultStatement;
use Doctrine\DBAL\Connection;
use Doctrine\Common\Cache\Cache;
use PDO;
/**
* Cache statement for SQL results.
*
* A result is saved in multiple cache keys, there is the originally specified
* cache key which is just pointing to result rows by key. The following things
* have to be ensured:
*
* 1. lifetime of the original key has to be longer than that of all the individual rows keys
* 2. if any one row key is missing the query has to be re-executed.
*
* Also you have to realize that the cache will load the whole result into memory at once to ensure 2.
* This means that the memory usage for cached results might increase by using this feature.
*/
class ResultCacheStatement implements \IteratorAggregate, ResultStatement
{
/**
* @var \Doctrine\Common\Cache\Cache
*/
private $resultCache;
/**
*
* @var string
*/
private $cacheKey;
/**
* @var string
*/
private $realKey;
/**
* @var int
*/
private $lifetime;
/**
* @var Doctrine\DBAL\Driver\Statement
*/
private $statement;
/**
* Did we reach the end of the statement?
*
* @var bool
*/
private $emptied = false;
/**
* @var array
*/
private $data;
/**
* @var int
*/
private $defaultFetchStyle = PDO::FETCH_BOTH;
/**
* @param Statement $stmt
* @param Cache $resultCache
* @param string $cacheKey
* @param string $realKey
* @param int $lifetime
*/
public function __construct(Statement $stmt, Cache $resultCache, $cacheKey, $realKey, $lifetime)
{
$this->statement = $stmt;
$this->resultCache = $resultCache;
$this->cacheKey = $cacheKey;
$this->realKey = $realKey;
$this->lifetime = $lifetime;
}
/**
* Closes the cursor, enabling the statement to be executed again.
*
* @return boolean Returns TRUE on success or FALSE on failure.
*/
public function closeCursor()
{
$this->statement->closeCursor();
if ($this->emptied && $this->data !== null) {
$data = $this->resultCache->fetch($this->cacheKey);
if (!$data) {
$data = array();
}
$data[$this->realKey] = $this->data;
$this->resultCache->save($this->cacheKey, $data, $this->lifetime);
unset($this->data);
}
}
/**
* columnCount
* Returns the number of columns in the result set
*
* @return integer Returns the number of columns in the result set represented
* by the PDOStatement object. If there is no result set,
* this method should return 0.
*/
public function columnCount()
{
return $this->statement->columnCount();
}
public function setFetchMode($fetchStyle, $arg2 = null, $arg3 = null)
{
$this->defaultFetchStyle = $fetchStyle;
}
public function getIterator()
{
$data = $this->fetchAll($this->defaultFetchStyle);
return new \ArrayIterator($data);
}
/**
* fetch
*
* @see Query::HYDRATE_* constants
* @param integer $fetchStyle Controls how the next row will be returned to the caller.
* This value must be one of the Query::HYDRATE_* constants,
* defaulting to Query::HYDRATE_BOTH
*
* @param integer $cursorOrientation For a PDOStatement object representing a scrollable cursor,
* this value determines which row will be returned to the caller.
* This value must be one of the Query::HYDRATE_ORI_* constants, defaulting to
* Query::HYDRATE_ORI_NEXT. To request a scrollable cursor for your
* PDOStatement object,
* you must set the PDO::ATTR_CURSOR attribute to Doctrine::CURSOR_SCROLL when you
* prepare the SQL statement with Doctrine_Adapter_Interface->prepare().
*
* @param integer $cursorOffset For a PDOStatement object representing a scrollable cursor for which the
* $cursorOrientation parameter is set to Query::HYDRATE_ORI_ABS, this value specifies
* the absolute number of the row in the result set that shall be fetched.
*
* For a PDOStatement object representing a scrollable cursor for
* which the $cursorOrientation parameter is set to Query::HYDRATE_ORI_REL, this value
* specifies the row to fetch relative to the cursor position before
* PDOStatement->fetch() was called.
*
* @return mixed
*/
public function fetch($fetchStyle = PDO::FETCH_BOTH)
{
if ($this->data === null) {
$this->data = array();
}
$row = $this->statement->fetch(PDO::FETCH_ASSOC);
if ($row) {
$this->data[] = $row;
if ($fetchStyle == PDO::FETCH_ASSOC) {
return $row;
} else if ($fetchStyle == PDO::FETCH_NUM) {
return array_values($row);
} else if ($fetchStyle == PDO::FETCH_BOTH) {
return array_merge($row, array_values($row));
} else {
throw new \InvalidArgumentException("Invalid fetch-style given for caching result.");
}
}
$this->emptied = true;
return false;
}
/**
* Returns an array containing all of the result set rows
*
* @param integer $fetchStyle Controls how the next row will be returned to the caller.
* This value must be one of the Query::HYDRATE_* constants,
* defaulting to Query::HYDRATE_BOTH
*
* @param integer $columnIndex Returns the indicated 0-indexed column when the value of $fetchStyle is
* Query::HYDRATE_COLUMN. Defaults to 0.
*
* @return array
*/
public function fetchAll($fetchStyle = PDO::FETCH_BOTH)
{
$rows = array();
while ($row = $this->fetch($fetchStyle)) {
$rows[] = $row;
}
return $rows;
}
/**
* fetchColumn
* Returns a single column from the next row of a
* result set or FALSE if there are no more rows.
*
* @param integer $columnIndex 0-indexed number of the column you wish to retrieve from the row. If no
* value is supplied, PDOStatement->fetchColumn()
* fetches the first column.
*
* @return string returns a single column in the next row of a result set.
*/
public function fetchColumn($columnIndex = 0)
{
$row = $this->fetch(PDO::FETCH_NUM);
if (!isset($row[$columnIndex])) {
// TODO: verify this is correct behavior
return false;
}
return $row[$columnIndex];
}
/**
* rowCount
* rowCount() returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement
* executed by the corresponding object.
*
* If the last SQL statement executed by the associated Statement object was a SELECT statement,
* some databases may return the number of rows returned by that statement. However,
* this behaviour is not guaranteed for all databases and should not be
* relied on for portable applications.
*
* @return integer Returns the number of rows.
*/
public function rowCount()
{
return $this->statement->rowCount();
}
}

View File

@@ -0,0 +1,113 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL;
use Doctrine\DBAL\Logging\SQLLogger;
use Doctrine\Common\Cache\Cache;
/**
* Configuration container for the Doctrine DBAL.
*
* @since 2.0
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @internal When adding a new configuration option just write a getter/setter
* pair and add the option to the _attributes array with a proper default value.
*/
class Configuration
{
/**
* The attributes that are contained in the configuration.
* Values are default values.
*
* @var array
*/
protected $_attributes = array();
/**
* Sets the SQL logger to use. Defaults to NULL which means SQL logging is disabled.
*
* @param SQLLogger $logger
*/
public function setSQLLogger(SQLLogger $logger = null)
{
$this->_attributes['sqlLogger'] = $logger;
}
/**
* Gets the SQL logger that is used.
*
* @return SQLLogger
*/
public function getSQLLogger()
{
return isset($this->_attributes['sqlLogger']) ?
$this->_attributes['sqlLogger'] : null;
}
/**
* Gets the cache driver implementation that is used for query result caching.
*
* @return \Doctrine\Common\Cache\Cache
*/
public function getResultCacheImpl()
{
return isset($this->_attributes['resultCacheImpl']) ?
$this->_attributes['resultCacheImpl'] : null;
}
/**
* Sets the cache driver implementation that is used for query result caching.
*
* @param \Doctrine\Common\Cache\Cache $cacheImpl
*/
public function setResultCacheImpl(Cache $cacheImpl)
{
$this->_attributes['resultCacheImpl'] = $cacheImpl;
}
/**
* Filter schema assets expression.
*
* Only include tables/sequences matching the filter expression regexp in
* schema instances generated for the active connection when calling
* {AbstractSchemaManager#createSchema()}.
*
* @param string $filterExpression
*/
public function setFilterSchemaAssetsExpression($filterExpression)
{
$this->_attributes['filterSchemaAssetsExpression'] = $filterExpression;
}
/**
* Return filter schema assets expression.
*
* @return string|null
*/
public function getFilterSchemaAssetsExpression()
{
if (isset($this->_attributes['filterSchemaAssetsExpression'])) {
return $this->_attributes['filterSchemaAssetsExpression'];
}
return null;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,54 @@
<?php
/*
* $Id: Exception.php 4628 2008-07-04 16:32:19Z romanb $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL;
/**
* Doctrine\DBAL\ConnectionException
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 4628 $
* @author Jonathan H. Wage <jonwage@gmail.com
*/
class ConnectionException extends DBALException
{
public static function commitFailedRollbackOnly()
{
return new self("Transaction commit failed because the transaction has been marked for rollback only.");
}
public static function noActiveTransaction()
{
return new self("There is no active transaction.");
}
public static function savepointsNotSupported()
{
return new self("Savepoints are not supported by this driver.");
}
public static function mayNotAlterNestedTransactionWithSavepointsInTransaction()
{
return new self("May not alter the nested transaction with savepoints behavior while a transaction is open.");
}
}

View File

@@ -0,0 +1,329 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Connections;
use Doctrine\DBAL\Connection,
Doctrine\DBAL\Driver,
Doctrine\DBAL\Configuration,
Doctrine\Common\EventManager,
Doctrine\DBAL\Event\ConnectionEventArgs,
Doctrine\DBAL\Events;
/**
* Master-Slave Connection
*
* Connection can be used with master-slave setups.
*
* Important for the understanding of this connection should be how and when
* it picks the slave or master.
*
* 1. Slave if master was never picked before and ONLY if 'getWrappedConnection'
* or 'executeQuery' is used.
* 2. Master picked when 'exec', 'executeUpdate', 'insert', 'delete', 'update', 'createSavepoint',
* 'releaseSavepoint', 'beginTransaction', 'rollback', 'commit', 'query' or
* 'prepare' is called.
* 3. If master was picked once during the lifetime of the connection it will always get picked afterwards.
* 4. One slave connection is randomly picked ONCE during a request.
*
* ATTENTION: You can write to the slave with this connection if you execute a write query without
* opening up a transaction. For example:
*
* $conn = DriverManager::getConnection(...);
* $conn->executeQuery("DELETE FROM table");
*
* Be aware that Connection#executeQuery is a method specifically for READ
* operations only.
*
* This connection is limited to slave operations using the
* Connection#executeQuery operation only, because it wouldn't be compatible
* with the ORM or SchemaManager code otherwise. Both use all the other
* operations in a context where writes could happen to a slave, which makes
* this restricted approach necessary.
*
* You can manually connect to the master at any time by calling:
*
* $conn->connect('master');
*
* Instantiation through the DriverManager looks like:
*
* @example
*
* $conn = DriverManager::getConnection(array(
* 'wrapperClass' => 'Doctrine\DBAL\Connections\MasterSlaveConnection',
* 'driver' => 'pdo_mysql',
* 'master' => array('user' => '', 'password' => '', 'host' => '', 'dbname' => ''),
* 'slaves' => array(
* array('user' => 'slave1', 'password', 'host' => '', 'dbname' => ''),
* array('user' => 'slave2', 'password', 'host' => '', 'dbname' => ''),
* )
* ));
*
* You can also pass 'driverOptions' and any other documented option to each of this drivers to pass additional information.
*
* @author Lars Strojny <lstrojny@php.net>
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class MasterSlaveConnection extends Connection
{
/**
* Master and slave connection (one of the randomly picked slaves)
*
* @var Doctrine\DBAL\Driver\Connection[]
*/
protected $connections = array('master' => null, 'slave' => null);
/**
* Create Master Slave Connection
*
* @param array $params
* @param Driver $driver
* @param Configuration $config
* @param EventManager $eventManager
*/
public function __construct(array $params, Driver $driver, Configuration $config = null, EventManager $eventManager = null)
{
if ( !isset($params['slaves']) || !isset($params['master']) ) {
throw new \InvalidArgumentException('master or slaves configuration missing');
}
if ( count($params['slaves']) == 0 ) {
throw new \InvalidArgumentException('You have to configure at least one slaves.');
}
$params['master']['driver'] = $params['driver'];
foreach ($params['slaves'] as $slaveKey => $slave) {
$params['slaves'][$slaveKey]['driver'] = $params['driver'];
}
parent::__construct($params, $driver, $config, $eventManager);
}
/**
* Check if the connection is currently towards the master or not.
*
* @return bool
*/
public function isConnectedToMaster()
{
return $this->_conn !== null && $this->_conn === $this->connections['master'];
}
/**
* {@inheritDoc}
*/
public function connect($connectionName = 'slave')
{
if ( $connectionName !== 'slave' && $connectionName !== 'master' ) {
throw new \InvalidArgumentException("Invalid option to connect(), only master or slave allowed.");
}
$forceMasterAsSlave = false;
if ($this->getTransactionNestingLevel() > 0) {
$connectionName = 'master';
$forceMasterAsSlave = true;
}
if ($this->connections[$connectionName]) {
if ($forceMasterAsSlave) {
$this->connections['slave'] = $this->_conn = $this->connections['master'];
} else {
$this->_conn = $this->connections[$connectionName];
}
return false;
}
if ($connectionName === 'master') {
/** Set slave connection to master to avoid invalid reads */
if ($this->connections['slave']) {
unset($this->connections['slave']);
}
$this->connections['master'] = $this->connections['slave'] = $this->_conn = $this->connectTo($connectionName);
} else {
$this->connections['slave'] = $this->_conn = $this->connectTo($connectionName);
}
if ($this->_eventManager->hasListeners(Events::postConnect)) {
$eventArgs = new ConnectionEventArgs($this);
$this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs);
}
return true;
}
/**
* Connect to a specific connection
*
* @param string $connectionName
* @return Driver
*/
protected function connectTo($connectionName)
{
$params = $this->getParams();
$driverOptions = isset($params['driverOptions']) ? $params['driverOptions'] : array();
$connectionParams = $this->chooseConnectionConfiguration($connectionName, $params);
$user = isset($connectionParams['user']) ? $connectionParams['user'] : null;
$password = isset($connectionParams['password']) ? $connectionParams['password'] : null;
return $this->_driver->connect($connectionParams, $user, $password, $driverOptions);
}
protected function chooseConnectionConfiguration($connectionName, $params)
{
if ($connectionName === 'master') {
return $params['master'];
}
return $params['slaves'][array_rand($params['slaves'])];
}
/**
* {@inheritDoc}
*/
public function executeUpdate($query, array $params = array(), array $types = array())
{
$this->connect('master');
return parent::executeUpdate($query, $params, $types);
}
/**
* {@inheritDoc}
*/
public function beginTransaction()
{
$this->connect('master');
return parent::beginTransaction();
}
/**
* {@inheritDoc}
*/
public function commit()
{
$this->connect('master');
return parent::commit();
}
/**
* {@inheritDoc}
*/
public function rollback()
{
$this->connect('master');
return parent::rollback();
}
/**
* {@inheritDoc}
*/
public function delete($tableName, array $identifier)
{
$this->connect('master');
return parent::delete($tableName, $identifier);
}
/**
* {@inheritDoc}
*/
public function update($tableName, array $data, array $identifier, array $types = array())
{
$this->connect('master');
return parent::update($tableName, $data, $identifier, $types);
}
/**
* {@inheritDoc}
*/
public function insert($tableName, array $data, array $types = array())
{
$this->connect('master');
return parent::insert($tableName, $data, $types);
}
/**
* {@inheritDoc}
*/
public function exec($statement)
{
$this->connect('master');
return parent::exec($statement);
}
/**
* {@inheritDoc}
*/
public function createSavepoint($savepoint)
{
$this->connect('master');
return parent::createSavepoint($savepoint);
}
/**
* {@inheritDoc}
*/
public function releaseSavepoint($savepoint)
{
$this->connect('master');
return parent::releaseSavepoint($savepoint);
}
/**
* {@inheritDoc}
*/
public function rollbackSavepoint($savepoint)
{
$this->connect('master');
return parent::rollbackSavepoint($savepoint);
}
public function query()
{
$this->connect('master');
$args = func_get_args();
$logger = $this->getConfiguration()->getSQLLogger();
if ($logger) {
$logger->startQuery($args[0]);
}
$statement = call_user_func_array(array($this->_conn, 'query'), $args);
if ($logger) {
$logger->stopQuery();
}
return $statement;
}
public function prepare($statement)
{
$this->connect('master');
return parent::prepare($statement);
}
}

View File

@@ -0,0 +1,88 @@
<?php
namespace Doctrine\DBAL;
class DBALException extends \Exception
{
public static function notSupported($method)
{
return new self("Operation '$method' is not supported by platform.");
}
public static function invalidPlatformSpecified()
{
return new self(
"Invalid 'platform' option specified, need to give an instance of ".
"\Doctrine\DBAL\Platforms\AbstractPlatform.");
}
public static function invalidPdoInstance()
{
return new self(
"The 'pdo' option was used in DriverManager::getConnection() but no ".
"instance of PDO was given."
);
}
public static function driverRequired()
{
return new self("The options 'driver' or 'driverClass' are mandatory if no PDO ".
"instance is given to DriverManager::getConnection().");
}
public static function unknownDriver($unknownDriverName, array $knownDrivers)
{
return new self("The given 'driver' ".$unknownDriverName." is unknown, ".
"Doctrine currently supports only the following drivers: ".implode(", ", $knownDrivers));
}
public static function invalidWrapperClass($wrapperClass)
{
return new self("The given 'wrapperClass' ".$wrapperClass." has to be a ".
"subtype of \Doctrine\DBAL\Connection.");
}
public static function invalidDriverClass($driverClass)
{
return new self("The given 'driverClass' ".$driverClass." has to implement the ".
"\Doctrine\DBAL\Driver interface.");
}
/**
* @param string $tableName
* @return DBALException
*/
public static function invalidTableName($tableName)
{
return new self("Invalid table name specified: ".$tableName);
}
/**
* @param string $tableName
* @return DBALException
*/
public static function noColumnsSpecifiedForTable($tableName)
{
return new self("No columns specified for table ".$tableName);
}
public static function limitOffsetInvalid()
{
return new self("Invalid Offset in Limit Query, it has to be larger or equal to 0.");
}
public static function typeExists($name)
{
return new self('Type '.$name.' already exists.');
}
public static function unknownColumnType($name)
{
return new self('Unknown column type '.$name.' requested.');
}
public static function typeNotFound($name)
{
return new self('Type to be overwritten '.$name.' does not exist.');
}
}

View File

@@ -0,0 +1,72 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL;
/**
* Driver interface.
* Interface that all DBAL drivers must implement.
*
* @since 2.0
*/
interface Driver
{
/**
* Attempts to create a connection with the database.
*
* @param array $params All connection parameters passed by the user.
* @param string $username The username to use when connecting.
* @param string $password The password to use when connecting.
* @param array $driverOptions The driver options to use when connecting.
* @return Doctrine\DBAL\Driver\Connection The database connection.
*/
public function connect(array $params, $username = null, $password = null, array $driverOptions = array());
/**
* Gets the DatabasePlatform instance that provides all the metadata about
* the platform this driver connects to.
*
* @return Doctrine\DBAL\Platforms\AbstractPlatform The database platform.
*/
public function getDatabasePlatform();
/**
* Gets the SchemaManager that can be used to inspect and change the underlying
* database schema of the platform this driver connects to.
*
* @param Doctrine\DBAL\Connection $conn
* @return Doctrine\DBAL\SchemaManager
*/
public function getSchemaManager(Connection $conn);
/**
* Gets the name of the driver.
*
* @return string The name of the driver.
*/
public function getName();
/**
* Get the name of the database connected to for this driver.
*
* @param Doctrine\DBAL\Connection $conn
* @return string $database
*/
public function getDatabase(Connection $conn);
}

View File

@@ -0,0 +1,42 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver;
/**
* Connection interface.
* Driver connections must implement this interface.
*
* This resembles (a subset of) the PDO interface.
*
* @since 2.0
*/
interface Connection
{
function prepare($prepareString);
function query();
function quote($input, $type=\PDO::PARAM_STR);
function exec($statement);
function lastInsertId($name = null);
function beginTransaction();
function commit();
function rollBack();
function errorCode();
function errorInfo();
}

View File

@@ -0,0 +1,115 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\IBMDB2;
class DB2Connection implements \Doctrine\DBAL\Driver\Connection
{
private $_conn = null;
public function __construct(array $params, $username, $password, $driverOptions = array())
{
$isPersistant = (isset($params['persistent']) && $params['persistent'] == true);
if ($isPersistant) {
$this->_conn = db2_pconnect($params['dbname'], $username, $password, $driverOptions);
} else {
$this->_conn = db2_connect($params['dbname'], $username, $password, $driverOptions);
}
if (!$this->_conn) {
throw new DB2Exception(db2_conn_errormsg());
}
}
public function prepare($sql)
{
$stmt = @db2_prepare($this->_conn, $sql);
if (!$stmt) {
throw new DB2Exception(db2_stmt_errormsg());
}
return new DB2Statement($stmt);
}
public function query()
{
$args = func_get_args();
$sql = $args[0];
$stmt = $this->prepare($sql);
$stmt->execute();
return $stmt;
}
public function quote($input, $type=\PDO::PARAM_STR)
{
$input = db2_escape_string($input);
if ($type == \PDO::PARAM_INT ) {
return $input;
} else {
return "'".$input."'";
}
}
public function exec($statement)
{
$stmt = $this->prepare($statement);
$stmt->execute();
return $stmt->rowCount();
}
public function lastInsertId($name = null)
{
return db2_last_insert_id($this->_conn);
}
public function beginTransaction()
{
db2_autocommit($this->_conn, DB2_AUTOCOMMIT_OFF);
}
public function commit()
{
if (!db2_commit($this->_conn)) {
throw new DB2Exception(db2_conn_errormsg($this->_conn));
}
db2_autocommit($this->_conn, DB2_AUTOCOMMIT_ON);
}
public function rollBack()
{
if (!db2_rollback($this->_conn)) {
throw new DB2Exception(db2_conn_errormsg($this->_conn));
}
db2_autocommit($this->_conn, DB2_AUTOCOMMIT_ON);
}
public function errorCode()
{
return db2_conn_error($this->_conn);
}
public function errorInfo()
{
return array(
0 => db2_conn_errormsg($this->_conn),
1 => $this->errorCode(),
);
}
}

View File

@@ -0,0 +1,111 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\IBMDB2;
use Doctrine\DBAL\Driver,
Doctrine\DBAL\Connection;
/**
* IBM DB2 Driver
*
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class DB2Driver implements Driver
{
/**
* Attempts to create a connection with the database.
*
* @param array $params All connection parameters passed by the user.
* @param string $username The username to use when connecting.
* @param string $password The password to use when connecting.
* @param array $driverOptions The driver options to use when connecting.
* @return Doctrine\DBAL\Driver\Connection The database connection.
*/
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
{
if ( ! isset($params['protocol'])) {
$params['protocol'] = 'TCPIP';
}
if ($params['host'] !== 'localhost' && $params['host'] != '127.0.0.1') {
// if the host isn't localhost, use extended connection params
$params['dbname'] = 'DRIVER={IBM DB2 ODBC DRIVER}' .
';DATABASE=' . $params['dbname'] .
';HOSTNAME=' . $params['host'] .
';PROTOCOL=' . $params['protocol'] .
';UID=' . $username .
';PWD=' . $password .';';
if (isset($params['port'])) {
$params['dbname'] .= 'PORT=' . $params['port'];
}
$username = null;
$password = null;
}
return new DB2Connection($params, $username, $password, $driverOptions);
}
/**
* Gets the DatabasePlatform instance that provides all the metadata about
* the platform this driver connects to.
*
* @return Doctrine\DBAL\Platforms\AbstractPlatform The database platform.
*/
public function getDatabasePlatform()
{
return new \Doctrine\DBAL\Platforms\DB2Platform;
}
/**
* Gets the SchemaManager that can be used to inspect and change the underlying
* database schema of the platform this driver connects to.
*
* @param Doctrine\DBAL\Connection $conn
* @return Doctrine\DBAL\SchemaManager
*/
public function getSchemaManager(Connection $conn)
{
return new \Doctrine\DBAL\Schema\DB2SchemaManager($conn);
}
/**
* Gets the name of the driver.
*
* @return string The name of the driver.
*/
public function getName()
{
return 'ibm_db2';
}
/**
* Get the name of the database connected to for this driver.
*
* @param Doctrine\DBAL\Connection $conn
* @return string $database
*/
public function getDatabase(\Doctrine\DBAL\Connection $conn)
{
$params = $conn->getParams();
return $params['dbname'];
}
}

View File

@@ -0,0 +1,27 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\IBMDB2;
class DB2Exception extends \Exception
{
}

View File

@@ -0,0 +1,215 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\IBMDB2;
use \Doctrine\DBAL\Driver\Statement;
class DB2Statement implements \IteratorAggregate, Statement
{
private $_stmt = null;
private $_bindParam = array();
private $_defaultFetchStyle = \PDO::FETCH_BOTH;
/**
* DB2_BINARY, DB2_CHAR, DB2_DOUBLE, or DB2_LONG
* @var array
*/
static private $_typeMap = array(
\PDO::PARAM_INT => DB2_LONG,
\PDO::PARAM_STR => DB2_CHAR,
);
public function __construct($stmt)
{
$this->_stmt = $stmt;
}
/**
* {@inheritdoc}
*/
public function bindValue($param, $value, $type = null)
{
return $this->bindParam($param, $value, $type);
}
/**
* {@inheritdoc}
*/
public function bindParam($column, &$variable, $type = null)
{
$this->_bindParam[$column] =& $variable;
if ($type && isset(self::$_typeMap[$type])) {
$type = self::$_typeMap[$type];
} else {
$type = DB2_CHAR;
}
if (!db2_bind_param($this->_stmt, $column, "variable", DB2_PARAM_IN, $type)) {
throw new DB2Exception(db2_stmt_errormsg());
}
return true;
}
/**
* {@inheritdoc}
*/
public function closeCursor()
{
if (!$this->_stmt) {
return false;
}
$this->_bindParam = array();
db2_free_result($this->_stmt);
$ret = db2_free_stmt($this->_stmt);
$this->_stmt = false;
return $ret;
}
/**
* {@inheritdoc}
*/
public function columnCount()
{
if (!$this->_stmt) {
return false;
}
return db2_num_fields($this->_stmt);
}
/**
* {@inheritdoc}
*/
public function errorCode()
{
return db2_stmt_error();
}
/**
* {@inheritdoc}
*/
public function errorInfo()
{
return array(
0 => db2_stmt_errormsg(),
1 => db2_stmt_error(),
);
}
/**
* {@inheritdoc}
*/
public function execute($params = null)
{
if (!$this->_stmt) {
return false;
}
/*$retval = true;
if ($params !== null) {
$retval = @db2_execute($this->_stmt, $params);
} else {
$retval = @db2_execute($this->_stmt);
}*/
if ($params === null) {
ksort($this->_bindParam);
$params = array_values($this->_bindParam);
}
$retval = @db2_execute($this->_stmt, $params);
if ($retval === false) {
throw new DB2Exception(db2_stmt_errormsg());
}
return $retval;
}
/**
* {@inheritdoc}
*/
public function setFetchMode($fetchStyle = \PDO::FETCH_BOTH, $arg2 = null, $arg3 = null)
{
$this->_defaultFetchStyle = $fetchStyle;
}
/**
* {@inheritdoc}
*/
public function getIterator()
{
$data = $this->fetchAll($this->_defaultFetchStyle);
return new \ArrayIterator($data);
}
/**
* {@inheritdoc}
*/
public function fetch($fetchStyle = null)
{
$fetchStyle = $fetchStyle ?: $this->_defaultFetchStyle;
switch ($fetchStyle) {
case \PDO::FETCH_BOTH:
return db2_fetch_both($this->_stmt);
case \PDO::FETCH_ASSOC:
return db2_fetch_assoc($this->_stmt);
case \PDO::FETCH_NUM:
return db2_fetch_array($this->_stmt);
default:
throw new DB2Exception("Given Fetch-Style " . $fetchStyle . " is not supported.");
}
}
/**
* {@inheritdoc}
*/
public function fetchAll($fetchStyle = null)
{
$fetchStyle = $fetchStyle ?: $this->_defaultFetchStyle;
$rows = array();
while ($row = $this->fetch($fetchStyle)) {
$rows[] = $row;
}
return $rows;
}
/**
* {@inheritdoc}
*/
public function fetchColumn($columnIndex = 0)
{
$row = $this->fetch(\PDO::FETCH_NUM);
if ($row && isset($row[$columnIndex])) {
return $row[$columnIndex];
}
return false;
}
/**
* {@inheritdoc}
*/
public function rowCount()
{
return (@db2_num_rows($this->_stmt))?:0;
}
}

View File

@@ -0,0 +1,69 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\Mysqli;
use Doctrine\DBAL\Driver as DriverInterface;
/**
* @author Kim Hemsø Rasmussen <kimhemsoe@gmail.com>
*/
class Driver implements DriverInterface
{
/**
* {@inheritdoc}
*/
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
{
return new MysqliConnection($params, $username, $password, $driverOptions);
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'mysqli';
}
/**
* {@inheritdoc}
*/
public function getSchemaManager(\Doctrine\DBAL\Connection $conn)
{
return new \Doctrine\DBAL\Schema\MySqlSchemaManager($conn);
}
/**
* {@inheritdoc}
*/
public function getDatabasePlatform()
{
return new \Doctrine\DBAL\Platforms\MySqlPlatform();
}
/**
* {@inheritdoc}
*/
public function getDatabase(\Doctrine\DBAL\Connection $conn)
{
$params = $conn->getParams();
return $params['dbname'];
}
}

View File

@@ -0,0 +1,146 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\Mysqli;
use Doctrine\DBAL\Driver\Connection as Connection;
/**
* @author Kim Hemsø Rasmussen <kimhemsoe@gmail.com>
*/
class MysqliConnection implements Connection
{
/**
* @var \mysqli
*/
private $_conn;
public function __construct(array $params, $username, $password, array $driverOptions = array())
{
$port = isset($params['port']) ? $params['port'] : ini_get('mysqli.default_port');
$socket = isset($params['unix_socket']) ? $params['unix_socket'] : ini_get('mysqli.default_socket');
$this->_conn = mysqli_init();
if (!$this->_conn->real_connect($params['host'], $username, $password, $params['dbname'], $port, $socket)) {
throw new MysqliException($this->_conn->connect_error, $this->_conn->connect_errno);
}
if (isset($params['charset'])) {
$this->_conn->set_charset($params['charset']);
}
}
/**
* Retrieve mysqli native resource handle.
*
* Could be used if part of your application is not using DBAL
*
* @return mysqli
*/
public function getWrappedResourceHandle()
{
return $this->_conn;
}
/**
* {@inheritdoc}
*/
public function prepare($prepareString)
{
return new MysqliStatement($this->_conn, $prepareString);
}
/**
* {@inheritdoc}
*/
public function query()
{
$args = func_get_args();
$sql = $args[0];
$stmt = $this->prepare($sql);
$stmt->execute();
return $stmt;
}
/**
* {@inheritdoc}
*/
public function quote($input, $type=\PDO::PARAM_STR)
{
return "'". $this->_conn->escape_string($input) ."'";
}
/**
* {@inheritdoc}
*/
public function exec($statement)
{
$this->_conn->query($statement);
return $this->_conn->affected_rows;
}
/**
* {@inheritdoc}
*/
public function lastInsertId($name = null)
{
return $this->_conn->insert_id;
}
/**
* {@inheritdoc}
*/
public function beginTransaction()
{
$this->_conn->query('START TRANSACTION');
return true;
}
/**
* {@inheritdoc}
*/
public function commit()
{
return $this->_conn->commit();
}
/**
* {@inheritdoc}non-PHPdoc)
*/
public function rollBack()
{
return $this->_conn->rollback();
}
/**
* {@inheritdoc}
*/
public function errorCode()
{
return $this->_conn->errno;
}
/**
* {@inheritdoc}
*/
public function errorInfo()
{
return $this->_conn->error;
}
}

View File

@@ -0,0 +1,26 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\Mysqli;
/**
* @author Kim Hemsø Rasmussen <kimhemsoe@gmail.com>
*/
class MysqliException extends \Exception
{}

View File

@@ -0,0 +1,335 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\Mysqli;
use Doctrine\DBAL\Driver\Statement;
use PDO;
/**
* @author Kim Hemsø Rasmussen <kimhemsoe@gmail.com>
*/
class MysqliStatement implements \IteratorAggregate, Statement
{
protected static $_paramTypeMap = array(
PDO::PARAM_STR => 's',
PDO::PARAM_BOOL => 'i',
PDO::PARAM_NULL => 's',
PDO::PARAM_INT => 'i',
PDO::PARAM_LOB => 's' // TODO Support LOB bigger then max package size.
);
protected $_conn;
protected $_stmt;
/**
* @var null|false|array
*/
protected $_columnNames;
/**
* @var null|array
*/
protected $_rowBindedValues;
/**
* @var array
*/
protected $_bindedValues;
/**
* Contains ref values for bindValue()
*
* @var array
*/
protected $_values = array();
protected $_defaultFetchStyle = PDO::FETCH_BOTH;
public function __construct(\mysqli $conn, $prepareString)
{
$this->_conn = $conn;
$this->_stmt = $conn->prepare($prepareString);
if (false === $this->_stmt) {
throw new MysqliException($this->_conn->error, $this->_conn->errno);
}
$paramCount = $this->_stmt->param_count;
if (0 < $paramCount) {
// Index 0 is types
// Need to init the string else php think we are trying to access it as a array.
$bindedValues = array(0 => str_repeat('s', $paramCount));
$null = null;
for ($i = 1; $i < $paramCount; $i++) {
$bindedValues[] =& $null;
}
$this->_bindedValues = $bindedValues;
}
}
/**
* {@inheritdoc}
*/
public function bindParam($column, &$variable, $type = null)
{
if (null === $type) {
$type = 's';
} else {
if (isset(self::$_paramTypeMap[$type])) {
$type = self::$_paramTypeMap[$type];
} else {
throw new MysqliException("Unkown type: '{$type}'");
}
}
$this->_bindedValues[$column] =& $variable;
$this->_bindedValues[0][$column - 1] = 's';
return true;
}
/**
* {@inheritdoc}
*/
public function bindValue($param, $value, $type = null)
{
if (null === $type) {
$type = 's';
} else {
if (isset(self::$_paramTypeMap[$type])) {
$type = self::$_paramTypeMap[$type];
} else {
throw new MysqliException("Unknown type: '{$type}'");
}
}
$this->_values[$param] = $value;
$this->_bindedValues[$param] =& $this->_values[$param];
$this->_bindedValues[0][$param - 1] = 's';
return true;
}
/**
* {@inheritdoc}
*/
public function execute($params = null)
{
if (null !== $this->_bindedValues) {
if (null !== $params) {
if (!$this->_bindValues($params)) {
throw new MysqliException($this->_stmt->error, $this->_stmt->errno);
}
} else {
if (!call_user_func_array(array($this->_stmt, 'bind_param'), $this->_bindedValues)) {
throw new MysqliException($this->_stmt->error, $this->_stmt->errno);
}
}
}
if (!$this->_stmt->execute()) {
throw new MysqliException($this->_stmt->error, $this->_stmt->errno);
}
if (null === $this->_columnNames) {
$meta = $this->_stmt->result_metadata();
if (false !== $meta) {
$columnNames = array();
foreach ($meta->fetch_fields() as $col) {
$columnNames[] = $col->name;
}
$meta->free();
$this->_columnNames = $columnNames;
$this->_rowBindedValues = array_fill(0, count($columnNames), NULL);
$refs = array();
foreach ($this->_rowBindedValues as $key => &$value) {
$refs[$key] =& $value;
}
if (!call_user_func_array(array($this->_stmt, 'bind_result'), $refs)) {
throw new MysqliException($this->_stmt->error, $this->_stmt->errno);
}
} else {
$this->_columnNames = false;
}
}
// We have a result.
if (false !== $this->_columnNames) {
$this->_stmt->store_result();
}
return true;
}
/**
* Bind a array of values to bound parameters
*
* @param array $values
* @return boolean
*/
private function _bindValues($values)
{
$params = array();
$types = str_repeat('s', count($values));
$params[0] = $types;
foreach ($values as &$v) {
$params[] =& $v;
}
return call_user_func_array(array($this->_stmt, 'bind_param'), $params);
}
/**
* @return null|false|array
*/
private function _fetch()
{
$ret = $this->_stmt->fetch();
if (true === $ret) {
$values = array();
foreach ($this->_rowBindedValues as $v) {
// Mysqli converts them to a scalar type it can fit in.
$values[] = null === $v ? null : (string)$v;
}
return $values;
}
return $ret;
}
/**
* {@inheritdoc}
*/
public function fetch($fetchStyle = null)
{
$values = $this->_fetch();
if (null === $values) {
return null;
}
if (false === $values) {
throw new MysqliException($this->_stmt->error, $this->_stmt->errno);
}
$fetchStyle = $fetchStyle ?: $this->_defaultFetchStyle;
switch ($fetchStyle) {
case PDO::FETCH_NUM:
return $values;
case PDO::FETCH_ASSOC:
return array_combine($this->_columnNames, $values);
case PDO::FETCH_BOTH:
$ret = array_combine($this->_columnNames, $values);
$ret += $values;
return $ret;
default:
throw new MysqliException("Unknown fetch type '{$fetchStyle}'");
}
}
/**
* {@inheritdoc}
*/
public function fetchAll($fetchStyle = null)
{
$fetchStyle = $fetchStyle ?: $this->_defaultFetchStyle;
$a = array();
while (($row = $this->fetch($fetchStyle)) !== null) {
$a[] = $row;
}
return $a;
}
/**
* {@inheritdoc}
*/
public function fetchColumn($columnIndex = 0)
{
$row = $this->fetch(PDO::FETCH_NUM);
if (null === $row) {
return false;
}
return $row[$columnIndex];
}
/**
* {@inheritdoc}
*/
public function errorCode()
{
return $this->_stmt->errno;
}
/**
* {@inheritdoc}
*/
public function errorInfo()
{
return $this->_stmt->error;
}
/**
* {@inheritdoc}
*/
public function closeCursor()
{
$this->_stmt->free_result();
return true;
}
/**
* {@inheritdoc}
*/
public function rowCount()
{
if (false === $this->_columnNames) {
return $this->_stmt->affected_rows;
}
return $this->_stmt->num_rows;
}
/**
* {@inheritdoc}
*/
public function columnCount()
{
return $this->_stmt->field_count;
}
/**
* {@inheritdoc}
*/
public function setFetchMode($fetchMode = PDO::FETCH_BOTH, $arg2 = null, $arg3 = null)
{
$this->_defaultFetchStyle = $fetchMode;
}
/**
* {@inheritdoc}
*/
public function getIterator()
{
$data = $this->fetchAll($this->_defaultFetchStyle);
return new \ArrayIterator($data);
}
}

View File

@@ -0,0 +1,95 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\OCI8;
use Doctrine\DBAL\Platforms;
/**
* A Doctrine DBAL driver for the Oracle OCI8 PHP extensions.
*
* @author Roman Borschel <roman@code-factory.org>
* @since 2.0
*/
class Driver implements \Doctrine\DBAL\Driver
{
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
{
return new OCI8Connection(
$username,
$password,
$this->_constructDsn($params),
isset($params['charset']) ? $params['charset'] : null,
isset($params['sessionMode']) ? $params['sessionMode'] : OCI_DEFAULT
);
}
/**
* Constructs the Oracle DSN.
*
* @return string The DSN.
*/
protected function _constructDsn(array $params)
{
$dsn = '';
if (isset($params['host']) && $params['host'] != '') {
$dsn .= '(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)' .
'(HOST=' . $params['host'] . ')';
if (isset($params['port'])) {
$dsn .= '(PORT=' . $params['port'] . ')';
} else {
$dsn .= '(PORT=1521)';
}
if (isset($params['service']) && $params['service'] == true) {
$dsn .= '))(CONNECT_DATA=(SERVICE_NAME=' . $params['dbname'] . ')))';
} else {
$dsn .= '))(CONNECT_DATA=(SID=' . $params['dbname'] . ')))';
}
} else {
$dsn .= $params['dbname'];
}
return $dsn;
}
public function getDatabasePlatform()
{
return new \Doctrine\DBAL\Platforms\OraclePlatform();
}
public function getSchemaManager(\Doctrine\DBAL\Connection $conn)
{
return new \Doctrine\DBAL\Schema\OracleSchemaManager($conn);
}
public function getName()
{
return 'oci8';
}
public function getDatabase(\Doctrine\DBAL\Connection $conn)
{
$params = $conn->getParams();
return $params['user'];
}
}

View File

@@ -0,0 +1,172 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\OCI8;
/**
* OCI8 implementation of the Connection interface.
*
* @since 2.0
*/
class OCI8Connection implements \Doctrine\DBAL\Driver\Connection
{
protected $_dbh;
protected $_executeMode = OCI_COMMIT_ON_SUCCESS;
/**
* Create a Connection to an Oracle Database using oci8 extension.
*
* @param string $username
* @param string $password
* @param string $db
*/
public function __construct($username, $password, $db, $charset = null, $sessionMode = OCI_DEFAULT)
{
if (!defined('OCI_NO_AUTO_COMMIT')) {
define('OCI_NO_AUTO_COMMIT', 0);
}
$this->_dbh = @oci_connect($username, $password, $db, $charset, $sessionMode);
if (!$this->_dbh) {
throw OCI8Exception::fromErrorInfo(oci_error());
}
}
/**
* Create a non-executed prepared statement.
*
* @param string $prepareString
* @return OCI8Statement
*/
public function prepare($prepareString)
{
return new OCI8Statement($this->_dbh, $prepareString, $this);
}
/**
* @param string $sql
* @return OCI8Statement
*/
public function query()
{
$args = func_get_args();
$sql = $args[0];
//$fetchMode = $args[1];
$stmt = $this->prepare($sql);
$stmt->execute();
return $stmt;
}
/**
* Quote input value.
*
* @param mixed $input
* @param int $type PDO::PARAM*
* @return mixed
*/
public function quote($value, $type=\PDO::PARAM_STR)
{
if (is_int($value) || is_float($value)) {
return $value;
}
$value = str_replace("'", "''", $value);
return "'" . addcslashes($value, "\000\n\r\\\032") . "'";
}
/**
*
* @param string $statement
* @return int
*/
public function exec($statement)
{
$stmt = $this->prepare($statement);
$stmt->execute();
return $stmt->rowCount();
}
public function lastInsertId($name = null)
{
//TODO: throw exception or support sequences?
}
/**
* Return the current execution mode.
*/
public function getExecuteMode()
{
return $this->_executeMode;
}
/**
* Start a transactiom
*
* Oracle has to explicitly set the autocommit mode off. That means
* after connection, a commit or rollback there is always automatically
* opened a new transaction.
*
* @return bool
*/
public function beginTransaction()
{
$this->_executeMode = OCI_NO_AUTO_COMMIT;
return true;
}
/**
* @throws OCI8Exception
* @return bool
*/
public function commit()
{
if (!oci_commit($this->_dbh)) {
throw OCI8Exception::fromErrorInfo($this->errorInfo());
}
$this->_executeMode = OCI_COMMIT_ON_SUCCESS;
return true;
}
/**
* @throws OCI8Exception
* @return bool
*/
public function rollBack()
{
if (!oci_rollback($this->_dbh)) {
throw OCI8Exception::fromErrorInfo($this->errorInfo());
}
$this->_executeMode = OCI_COMMIT_ON_SUCCESS;
return true;
}
public function errorCode()
{
$error = oci_error($this->_dbh);
if ($error !== false) {
$error = $error['code'];
}
return $error;
}
public function errorInfo()
{
return oci_error($this->_dbh);
}
}

View File

@@ -0,0 +1,30 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\OCI8;
class OCI8Exception extends \Exception
{
static public function fromErrorInfo($error)
{
return new self($error['message'], $error['code']);
}
}

View File

@@ -0,0 +1,258 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\OCI8;
use PDO;
use IteratorAggregate;
use Doctrine\DBAL\Driver\Statement;
/**
* The OCI8 implementation of the Statement interface.
*
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
*/
class OCI8Statement implements \IteratorAggregate, Statement
{
/** Statement handle. */
protected $_dbh;
protected $_sth;
protected $_conn;
protected static $_PARAM = ':param';
protected static $fetchStyleMap = array(
PDO::FETCH_BOTH => OCI_BOTH,
PDO::FETCH_ASSOC => OCI_ASSOC,
PDO::FETCH_NUM => OCI_NUM,
PDO::PARAM_LOB => OCI_B_BLOB,
);
protected $_defaultFetchStyle = PDO::FETCH_BOTH;
protected $_paramMap = array();
/**
* Creates a new OCI8Statement that uses the given connection handle and SQL statement.
*
* @param resource $dbh The connection handle.
* @param string $statement The SQL statement.
*/
public function __construct($dbh, $statement, OCI8Connection $conn)
{
list($statement, $paramMap) = self::convertPositionalToNamedPlaceholders($statement);
$this->_sth = oci_parse($dbh, $statement);
$this->_dbh = $dbh;
$this->_paramMap = $paramMap;
$this->_conn = $conn;
}
/**
* Convert positional (?) into named placeholders (:param<num>)
*
* Oracle does not support positional parameters, hence this method converts all
* positional parameters into artificially named parameters. Note that this conversion
* is not perfect. All question marks (?) in the original statement are treated as
* placeholders and converted to a named parameter.
*
* The algorithm uses a state machine with two possible states: InLiteral and NotInLiteral.
* Question marks inside literal strings are therefore handled correctly by this method.
* This comes at a cost, the whole sql statement has to be looped over.
*
* @todo extract into utility class in Doctrine\DBAL\Util namespace
* @todo review and test for lost spaces. we experienced missing spaces with oci8 in some sql statements.
* @param string $statement The SQL statement to convert.
* @return string
*/
static public function convertPositionalToNamedPlaceholders($statement)
{
$count = 1;
$inLiteral = false; // a valid query never starts with quotes
$stmtLen = strlen($statement);
$paramMap = array();
for ($i = 0; $i < $stmtLen; $i++) {
if ($statement[$i] == '?' && !$inLiteral) {
// real positional parameter detected
$paramMap[$count] = ":param$count";
$len = strlen($paramMap[$count]);
$statement = substr_replace($statement, ":param$count", $i, 1);
$i += $len-1; // jump ahead
$stmtLen = strlen($statement); // adjust statement length
++$count;
} else if ($statement[$i] == "'" || $statement[$i] == '"') {
$inLiteral = ! $inLiteral; // switch state!
}
}
return array($statement, $paramMap);
}
/**
* {@inheritdoc}
*/
public function bindValue($param, $value, $type = null)
{
return $this->bindParam($param, $value, $type);
}
/**
* {@inheritdoc}
*/
public function bindParam($column, &$variable, $type = null)
{
$column = isset($this->_paramMap[$column]) ? $this->_paramMap[$column] : $column;
if ($type == \PDO::PARAM_LOB) {
$lob = oci_new_descriptor($this->_dbh, OCI_D_LOB);
$lob->writeTemporary($variable, OCI_TEMP_BLOB);
return oci_bind_by_name($this->_sth, $column, $lob, -1, OCI_B_BLOB);
} else {
return oci_bind_by_name($this->_sth, $column, $variable);
}
}
/**
* Closes the cursor, enabling the statement to be executed again.
*
* @return boolean Returns TRUE on success or FALSE on failure.
*/
public function closeCursor()
{
return oci_free_statement($this->_sth);
}
/**
* {@inheritdoc}
*/
public function columnCount()
{
return oci_num_fields($this->_sth);
}
/**
* {@inheritdoc}
*/
public function errorCode()
{
$error = oci_error($this->_sth);
if ($error !== false) {
$error = $error['code'];
}
return $error;
}
/**
* {@inheritdoc}
*/
public function errorInfo()
{
return oci_error($this->_sth);
}
/**
* {@inheritdoc}
*/
public function execute($params = null)
{
if ($params) {
$hasZeroIndex = array_key_exists(0, $params);
foreach ($params as $key => $val) {
if ($hasZeroIndex && is_numeric($key)) {
$this->bindValue($key + 1, $val);
} else {
$this->bindValue($key, $val);
}
}
}
$ret = @oci_execute($this->_sth, $this->_conn->getExecuteMode());
if ( ! $ret) {
throw OCI8Exception::fromErrorInfo($this->errorInfo());
}
return $ret;
}
/**
* {@inheritdoc}
*/
public function setFetchMode($fetchStyle = PDO::FETCH_BOTH, $arg2 = null, $arg3 = null)
{
$this->_defaultFetchStyle = $fetchStyle;
}
/**
* {@inheritdoc}
*/
public function getIterator()
{
$data = $this->fetchAll($this->_defaultFetchStyle);
return new \ArrayIterator($data);
}
/**
* {@inheritdoc}
*/
public function fetch($fetchStyle = null)
{
$fetchStyle = $fetchStyle ?: $this->_defaultFetchStyle;
if ( ! isset(self::$fetchStyleMap[$fetchStyle])) {
throw new \InvalidArgumentException("Invalid fetch style: " . $fetchStyle);
}
return oci_fetch_array($this->_sth, self::$fetchStyleMap[$fetchStyle] | OCI_RETURN_NULLS | OCI_RETURN_LOBS);
}
/**
* {@inheritdoc}
*/
public function fetchAll($fetchStyle = null)
{
$fetchStyle = $fetchStyle ?: $this->_defaultFetchStyle;
if ( ! isset(self::$fetchStyleMap[$fetchStyle])) {
throw new \InvalidArgumentException("Invalid fetch style: " . $fetchStyle);
}
$result = array();
if (self::$fetchStyleMap[$fetchStyle] === OCI_BOTH) {
while ($row = $this->fetch($fetchStyle)) {
$result[] = $row;
}
} else {
oci_fetch_all($this->_sth, $result, 0, -1,
self::$fetchStyleMap[$fetchStyle] | OCI_RETURN_NULLS | OCI_FETCHSTATEMENT_BY_ROW | OCI_RETURN_LOBS);
}
return $result;
}
/**
* {@inheritdoc}
*/
public function fetchColumn($columnIndex = 0)
{
$row = oci_fetch_array($this->_sth, OCI_NUM | OCI_RETURN_NULLS | OCI_RETURN_LOBS);
return isset($row[$columnIndex]) ? $row[$columnIndex] : false;
}
/**
* {@inheritdoc}
*/
public function rowCount()
{
return oci_num_rows($this->_sth);
}
}

View File

@@ -0,0 +1,40 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver;
use \PDO;
/**
* PDO implementation of the Connection interface.
* Used by all PDO-based drivers.
*
* @since 2.0
*/
class PDOConnection extends PDO implements Connection
{
public function __construct($dsn, $user = null, $password = null, array $options = null)
{
parent::__construct($dsn, $user, $password, $options);
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('Doctrine\DBAL\Driver\PDOStatement', array()));
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
}

View File

@@ -0,0 +1,126 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\PDOIbm;
use Doctrine\DBAL\Connection;
/**
* Driver for the PDO IBM extension
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 1.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class Driver implements \Doctrine\DBAL\Driver
{
/**
* Attempts to establish a connection with the underlying driver.
*
* @param array $params
* @param string $username
* @param string $password
* @param array $driverOptions
* @return Doctrine\DBAL\Driver\Connection
*/
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
{
$conn = new \Doctrine\DBAL\Driver\PDOConnection(
$this->_constructPdoDsn($params),
$username,
$password,
$driverOptions
);
return $conn;
}
/**
* Constructs the MySql PDO DSN.
*
* @return string The DSN.
*/
private function _constructPdoDsn(array $params)
{
$dsn = 'ibm:';
if (isset($params['host'])) {
$dsn .= 'HOSTNAME=' . $params['host'] . ';';
}
if (isset($params['port'])) {
$dsn .= 'PORT=' . $params['port'] . ';';
}
$dsn .= 'PROTOCOL=TCPIP;';
if (isset($params['dbname'])) {
$dsn .= 'DATABASE=' . $params['dbname'] . ';';
}
return $dsn;
}
/**
* Gets the DatabasePlatform instance that provides all the metadata about
* the platform this driver connects to.
*
* @return Doctrine\DBAL\Platforms\AbstractPlatform The database platform.
*/
public function getDatabasePlatform()
{
return new \Doctrine\DBAL\Platforms\DB2Platform;
}
/**
* Gets the SchemaManager that can be used to inspect and change the underlying
* database schema of the platform this driver connects to.
*
* @param Doctrine\DBAL\Connection $conn
* @return Doctrine\DBAL\SchemaManager
*/
public function getSchemaManager(Connection $conn)
{
return new \Doctrine\DBAL\Schema\DB2SchemaManager($conn);
}
/**
* Gets the name of the driver.
*
* @return string The name of the driver.
*/
public function getName()
{
return 'pdo_ibm';
}
/**
* Get the name of the database connected to for this driver.
*
* @param Doctrine\DBAL\Connection $conn
* @return string $database
*/
public function getDatabase(\Doctrine\DBAL\Connection $conn)
{
$params = $conn->getParams();
return $params['dbname'];
}
}

View File

@@ -0,0 +1,102 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\PDOMySql;
use Doctrine\DBAL\Connection;
/**
* PDO MySql driver.
*
* @since 2.0
*/
class Driver implements \Doctrine\DBAL\Driver
{
/**
* Attempts to establish a connection with the underlying driver.
*
* @param array $params
* @param string $username
* @param string $password
* @param array $driverOptions
* @return Doctrine\DBAL\Driver\Connection
*/
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
{
$conn = new \Doctrine\DBAL\Driver\PDOConnection(
$this->_constructPdoDsn($params),
$username,
$password,
$driverOptions
);
return $conn;
}
/**
* Constructs the MySql PDO DSN.
*
* @return string The DSN.
*/
private function _constructPdoDsn(array $params)
{
$dsn = 'mysql:';
if (isset($params['host']) && $params['host'] != '') {
$dsn .= 'host=' . $params['host'] . ';';
}
if (isset($params['port'])) {
$dsn .= 'port=' . $params['port'] . ';';
}
if (isset($params['dbname'])) {
$dsn .= 'dbname=' . $params['dbname'] . ';';
}
if (isset($params['unix_socket'])) {
$dsn .= 'unix_socket=' . $params['unix_socket'] . ';';
}
if (isset($params['charset'])) {
$dsn .= 'charset=' . $params['charset'] . ';';
}
return $dsn;
}
public function getDatabasePlatform()
{
return new \Doctrine\DBAL\Platforms\MySqlPlatform();
}
public function getSchemaManager(\Doctrine\DBAL\Connection $conn)
{
return new \Doctrine\DBAL\Schema\MySqlSchemaManager($conn);
}
public function getName()
{
return 'pdo_mysql';
}
public function getDatabase(\Doctrine\DBAL\Connection $conn)
{
$params = $conn->getParams();
if (isset($params['dbname'])) {
return $params['dbname'];
}
return $conn->query('SELECT DATABASE()')->fetchColumn();
}
}

View File

@@ -0,0 +1,98 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\PDOOracle;
use Doctrine\DBAL\Platforms;
/**
* PDO Oracle driver
*
* WARNING: This driver gives us segfauls in our testsuites on CLOB and other
* stuff. PDO Oracle is not maintained by Oracle or anyone in the PHP community,
* which leads us to the recommendation to use the "oci8" driver to connect
* to Oracle instead.
*/
class Driver implements \Doctrine\DBAL\Driver
{
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
{
return new \Doctrine\DBAL\Driver\PDOConnection(
$this->_constructPdoDsn($params),
$username,
$password,
$driverOptions
);
}
/**
* Constructs the Oracle PDO DSN.
*
* @return string The DSN.
*/
private function _constructPdoDsn(array $params)
{
$dsn = 'oci:';
if (isset($params['host'])) {
$dsn .= 'dbname=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)' .
'(HOST=' . $params['host'] . ')';
if (isset($params['port'])) {
$dsn .= '(PORT=' . $params['port'] . ')';
} else {
$dsn .= '(PORT=1521)';
}
if (isset($params['service']) && $params['service'] == true) {
$dsn .= '))(CONNECT_DATA=(SERVICE_NAME=' . $params['dbname'] . ')))';
} else {
$dsn .= '))(CONNECT_DATA=(SID=' . $params['dbname'] . ')))';
}
} else {
$dsn .= 'dbname=' . $params['dbname'];
}
if (isset($params['charset'])) {
$dsn .= ';charset=' . $params['charset'];
}
return $dsn;
}
public function getDatabasePlatform()
{
return new \Doctrine\DBAL\Platforms\OraclePlatform();
}
public function getSchemaManager(\Doctrine\DBAL\Connection $conn)
{
return new \Doctrine\DBAL\Schema\OracleSchemaManager($conn);
}
public function getName()
{
return 'pdo_oracle';
}
public function getDatabase(\Doctrine\DBAL\Connection $conn)
{
$params = $conn->getParams();
return $params['user'];
}
}

View File

@@ -0,0 +1,70 @@
<?php
namespace Doctrine\DBAL\Driver\PDOPgSql;
use Doctrine\DBAL\Platforms;
/**
* Driver that connects through pdo_pgsql.
*
* @since 2.0
*/
class Driver implements \Doctrine\DBAL\Driver
{
/**
* Attempts to connect to the database and returns a driver connection on success.
*
* @return Doctrine\DBAL\Driver\Connection
*/
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
{
return new \Doctrine\DBAL\Driver\PDOConnection(
$this->_constructPdoDsn($params),
$username,
$password,
$driverOptions
);
}
/**
* Constructs the Postgres PDO DSN.
*
* @return string The DSN.
*/
private function _constructPdoDsn(array $params)
{
$dsn = 'pgsql:';
if (isset($params['host']) && $params['host'] != '') {
$dsn .= 'host=' . $params['host'] . ' ';
}
if (isset($params['port']) && $params['port'] != '') {
$dsn .= 'port=' . $params['port'] . ' ';
}
if (isset($params['dbname'])) {
$dsn .= 'dbname=' . $params['dbname'] . ' ';
}
return $dsn;
}
public function getDatabasePlatform()
{
return new \Doctrine\DBAL\Platforms\PostgreSqlPlatform();
}
public function getSchemaManager(\Doctrine\DBAL\Connection $conn)
{
return new \Doctrine\DBAL\Schema\PostgreSqlSchemaManager($conn);
}
public function getName()
{
return 'pdo_pgsql';
}
public function getDatabase(\Doctrine\DBAL\Connection $conn)
{
$params = $conn->getParams();
return $params['dbname'];
}
}

View File

@@ -0,0 +1,116 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\PDOSqlite;
/**
* The PDO Sqlite driver.
*
* @since 2.0
*/
class Driver implements \Doctrine\DBAL\Driver
{
/**
* @var array
*/
protected $_userDefinedFunctions = array(
'sqrt' => array('callback' => array('Doctrine\DBAL\Platforms\SqlitePlatform', 'udfSqrt'), 'numArgs' => 1),
'mod' => array('callback' => array('Doctrine\DBAL\Platforms\SqlitePlatform', 'udfMod'), 'numArgs' => 2),
'locate' => array('callback' => array('Doctrine\DBAL\Platforms\SqlitePlatform', 'udfLocate'), 'numArgs' => -1),
);
/**
* Tries to establish a database connection to SQLite.
*
* @param array $params
* @param string $username
* @param string $password
* @param array $driverOptions
* @return Connection
*/
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
{
if (isset($driverOptions['userDefinedFunctions'])) {
$this->_userDefinedFunctions = array_merge(
$this->_userDefinedFunctions, $driverOptions['userDefinedFunctions']);
unset($driverOptions['userDefinedFunctions']);
}
$pdo = new \Doctrine\DBAL\Driver\PDOConnection(
$this->_constructPdoDsn($params),
$username,
$password,
$driverOptions
);
foreach ($this->_userDefinedFunctions AS $fn => $data) {
$pdo->sqliteCreateFunction($fn, $data['callback'], $data['numArgs']);
}
return $pdo;
}
/**
* Constructs the Sqlite PDO DSN.
*
* @return string The DSN.
* @override
*/
protected function _constructPdoDsn(array $params)
{
$dsn = 'sqlite:';
if (isset($params['path'])) {
$dsn .= $params['path'];
} else if (isset($params['memory'])) {
$dsn .= ':memory:';
}
return $dsn;
}
/**
* Gets the database platform that is relevant for this driver.
*/
public function getDatabasePlatform()
{
return new \Doctrine\DBAL\Platforms\SqlitePlatform();
}
/**
* Gets the schema manager that is relevant for this driver.
*
* @param Doctrine\DBAL\Connection $conn
* @return Doctrine\DBAL\Schema\SqliteSchemaManager
*/
public function getSchemaManager(\Doctrine\DBAL\Connection $conn)
{
return new \Doctrine\DBAL\Schema\SqliteSchemaManager($conn);
}
public function getName()
{
return 'pdo_sqlite';
}
public function getDatabase(\Doctrine\DBAL\Connection $conn)
{
$params = $conn->getParams();
return isset($params['path']) ? $params['path'] : null;
}
}

View File

@@ -0,0 +1,45 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\PDOSqlsrv;
/**
* Sqlsrv Connection implementation.
*
* @since 2.0
*/
class Connection extends \Doctrine\DBAL\Driver\PDOConnection implements \Doctrine\DBAL\Driver\Connection
{
/**
* @override
*/
public function quote($value, $type=\PDO::PARAM_STR)
{
$val = parent::quote($value, $type);
// Fix for a driver version terminating all values with null byte
if (strpos($val, "\0") !== false) {
$val = substr($val, 0, -1);
}
return $val;
}
}

View File

@@ -0,0 +1,88 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\PDOSqlsrv;
/**
* The PDO-based Sqlsrv driver.
*
* @since 2.0
*/
class Driver implements \Doctrine\DBAL\Driver
{
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
{
return new Connection(
$this->_constructPdoDsn($params),
$username,
$password,
$driverOptions
);
}
/**
* Constructs the Sqlsrv PDO DSN.
*
* @return string The DSN.
*/
private function _constructPdoDsn(array $params)
{
$dsn = 'sqlsrv:server=';
if (isset($params['host'])) {
$dsn .= $params['host'];
}
if (isset($params['port']) && !empty($params['port'])) {
$dsn .= ',' . $params['port'];
}
if (isset($params['dbname'])) {;
$dsn .= ';Database=' . $params['dbname'];
}
if (isset($params['MultipleActiveResultSets'])) {
$dsn .= '; MultipleActiveResultSets=' . ($params['MultipleActiveResultSets'] ? 'true' : 'false');
}
return $dsn;
}
public function getDatabasePlatform()
{
return new \Doctrine\DBAL\Platforms\SQLServer2008Platform();
}
public function getSchemaManager(\Doctrine\DBAL\Connection $conn)
{
return new \Doctrine\DBAL\Schema\SQLServerSchemaManager($conn);
}
public function getName()
{
return 'pdo_sqlsrv';
}
public function getDatabase(\Doctrine\DBAL\Connection $conn)
{
$params = $conn->getParams();
return $params['dbname'];
}
}

View File

@@ -0,0 +1,50 @@
<?php
/*
* $Id: Interface.php 3882 2008-02-22 18:11:35Z jwage $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver;
/**
* The PDO implementation of the Statement interface.
* Used by all PDO-based drivers.
*
* @since 2.0
*/
class PDOStatement extends \PDOStatement implements Statement
{
private function __construct() {}
public function setFetchMode($fetchStyle, $arg2 = null, $arg3 = null)
{
// This thin wrapper is necessary to shield against the weird signature
// of PDOStatement::setFetchMode(): even if the second and third
// parameters are optional, PHP will not let us remove it from this
// declaration.
if ($arg2 === null && $arg3 === null) {
return parent::setFetchMode($fetchStyle);
}
if ($arg3 === null) {
return parent::setFetchMode($fetchStyle, $arg2);
}
return parent::setFetchMode($fetchStyle, $arg2, $arg3);
}
}

View File

@@ -0,0 +1,113 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver;
use PDO;
/**
* Interface for the reading part of a prepare statement only.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
interface ResultStatement extends \Traversable
{
/**
* Closes the cursor, enabling the statement to be executed again.
*
* @return boolean Returns TRUE on success or FALSE on failure.
*/
function closeCursor();
/**
* columnCount
* Returns the number of columns in the result set
*
* @return integer Returns the number of columns in the result set represented
* by the PDOStatement object. If there is no result set,
* this method should return 0.
*/
function columnCount();
/**
* setFetchMode
* Set the fetch mode to use while iterating this statement.
*
* @param integer $fetchStyle
*/
function setFetchMode($fetchStyle, $arg2 = null, $arg3 = null);
/**
* fetch
*
* @see Query::HYDRATE_* constants
* @param integer $fetchStyle Controls how the next row will be returned to the caller.
* This value must be one of the Query::HYDRATE_* constants,
* defaulting to Query::HYDRATE_BOTH
*
* @param integer $cursorOrientation For a PDOStatement object representing a scrollable cursor,
* this value determines which row will be returned to the caller.
* This value must be one of the Query::HYDRATE_ORI_* constants, defaulting to
* Query::HYDRATE_ORI_NEXT. To request a scrollable cursor for your
* PDOStatement object,
* you must set the PDO::ATTR_CURSOR attribute to Doctrine::CURSOR_SCROLL when you
* prepare the SQL statement with Doctrine_Adapter_Interface->prepare().
*
* @param integer $cursorOffset For a PDOStatement object representing a scrollable cursor for which the
* $cursorOrientation parameter is set to Query::HYDRATE_ORI_ABS, this value specifies
* the absolute number of the row in the result set that shall be fetched.
*
* For a PDOStatement object representing a scrollable cursor for
* which the $cursorOrientation parameter is set to Query::HYDRATE_ORI_REL, this value
* specifies the row to fetch relative to the cursor position before
* PDOStatement->fetch() was called.
*
* @return mixed
*/
function fetch($fetchStyle = PDO::FETCH_BOTH);
/**
* Returns an array containing all of the result set rows
*
* @param integer $fetchStyle Controls how the next row will be returned to the caller.
* This value must be one of the Query::HYDRATE_* constants,
* defaulting to Query::HYDRATE_BOTH
*
* @param integer $columnIndex Returns the indicated 0-indexed column when the value of $fetchStyle is
* Query::HYDRATE_COLUMN. Defaults to 0.
*
* @return array
*/
function fetchAll($fetchStyle = PDO::FETCH_BOTH);
/**
* fetchColumn
* Returns a single column from the next row of a
* result set or FALSE if there are no more rows.
*
* @param integer $columnIndex 0-indexed number of the column you wish to retrieve from the row. If no
* value is supplied, PDOStatement->fetchColumn()
* fetches the first column.
*
* @return string returns a single column in the next row of a result set.
*/
function fetchColumn($columnIndex = 0);
}

View File

@@ -0,0 +1,124 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver;
use \PDO;
/**
* Statement interface.
* Drivers must implement this interface.
*
* This resembles (a subset of) the PDOStatement interface.
*
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Roman Borschel <roman@code-factory.org>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
*/
interface Statement extends ResultStatement
{
/**
* Binds a value to a corresponding named or positional
* placeholder in the SQL statement that was used to prepare the statement.
*
* @param mixed $param Parameter identifier. For a prepared statement using named placeholders,
* this will be a parameter name of the form :name. For a prepared statement
* using question mark placeholders, this will be the 1-indexed position of the parameter
*
* @param mixed $value The value to bind to the parameter.
* @param integer $type Explicit data type for the parameter using the PDO::PARAM_* constants.
*
* @return boolean Returns TRUE on success or FALSE on failure.
*/
function bindValue($param, $value, $type = null);
/**
* Binds a PHP variable to a corresponding named or question mark placeholder in the
* SQL statement that was use to prepare the statement. Unlike PDOStatement->bindValue(),
* the variable is bound as a reference and will only be evaluated at the time
* that PDOStatement->execute() is called.
*
* Most parameters are input parameters, that is, parameters that are
* used in a read-only fashion to build up the query. Some drivers support the invocation
* of stored procedures that return data as output parameters, and some also as input/output
* parameters that both send in data and are updated to receive it.
*
* @param mixed $param Parameter identifier. For a prepared statement using named placeholders,
* this will be a parameter name of the form :name. For a prepared statement
* using question mark placeholders, this will be the 1-indexed position of the parameter
*
* @param mixed $variable Name of the PHP variable to bind to the SQL statement parameter.
*
* @param integer $type Explicit data type for the parameter using the PDO::PARAM_* constants. To return
* an INOUT parameter from a stored procedure, use the bitwise OR operator to set the
* PDO::PARAM_INPUT_OUTPUT bits for the data_type parameter.
* @return boolean Returns TRUE on success or FALSE on failure.
*/
function bindParam($column, &$variable, $type = null);
/**
* errorCode
* Fetch the SQLSTATE associated with the last operation on the statement handle
*
* @see Doctrine_Adapter_Interface::errorCode()
* @return string error code string
*/
function errorCode();
/**
* errorInfo
* Fetch extended error information associated with the last operation on the statement handle
*
* @see Doctrine_Adapter_Interface::errorInfo()
* @return array error info array
*/
function errorInfo();
/**
* Executes a prepared statement
*
* If the prepared statement included parameter markers, you must either:
* call PDOStatement->bindParam() to bind PHP variables to the parameter markers:
* bound variables pass their value as input and receive the output value,
* if any, of their associated parameter markers or pass an array of input-only
* parameter values
*
*
* @param array $params An array of values with as many elements as there are
* bound parameters in the SQL statement being executed.
* @return boolean Returns TRUE on success or FALSE on failure.
*/
function execute($params = null);
/**
* rowCount
* rowCount() returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement
* executed by the corresponding object.
*
* If the last SQL statement executed by the associated Statement object was a SELECT statement,
* some databases may return the number of rows returned by that statement. However,
* this behaviour is not guaranteed for all databases and should not be
* relied on for portable applications.
*
* @return integer Returns the number of rows.
*/
function rowCount();
}

View File

@@ -0,0 +1,165 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL;
use Doctrine\Common\EventManager;
/**
* Factory for creating Doctrine\DBAL\Connection instances.
*
* @author Roman Borschel <roman@code-factory.org>
* @since 2.0
*/
final class DriverManager
{
/**
* List of supported drivers and their mappings to the driver classes.
*
* @var array
* @todo REMOVE. Users should directly supply class names instead.
*/
private static $_driverMap = array(
'pdo_mysql' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
'pdo_sqlite' => 'Doctrine\DBAL\Driver\PDOSqlite\Driver',
'pdo_pgsql' => 'Doctrine\DBAL\Driver\PDOPgSql\Driver',
'pdo_oci' => 'Doctrine\DBAL\Driver\PDOOracle\Driver',
'oci8' => 'Doctrine\DBAL\Driver\OCI8\Driver',
'ibm_db2' => 'Doctrine\DBAL\Driver\IBMDB2\DB2Driver',
'pdo_ibm' => 'Doctrine\DBAL\Driver\PDOIbm\Driver',
'pdo_sqlsrv' => 'Doctrine\DBAL\Driver\PDOSqlsrv\Driver',
'mysqli' => 'Doctrine\DBAL\Driver\Mysqli\Driver',
);
/** Private constructor. This class cannot be instantiated. */
private function __construct() { }
/**
* Creates a connection object based on the specified parameters.
* This method returns a Doctrine\DBAL\Connection which wraps the underlying
* driver connection.
*
* $params must contain at least one of the following.
*
* Either 'driver' with one of the following values:
* pdo_mysql
* pdo_sqlite
* pdo_pgsql
* pdo_oracle
* pdo_sqlsrv
*
* OR 'driverClass' that contains the full class name (with namespace) of the
* driver class to instantiate.
*
* Other (optional) parameters:
*
* <b>user (string)</b>:
* The username to use when connecting.
*
* <b>password (string)</b>:
* The password to use when connecting.
*
* <b>driverOptions (array)</b>:
* Any additional driver-specific options for the driver. These are just passed
* through to the driver.
*
* <b>pdo</b>:
* You can pass an existing PDO instance through this parameter. The PDO
* instance will be wrapped in a Doctrine\DBAL\Connection.
*
* <b>wrapperClass</b>:
* You may specify a custom wrapper class through the 'wrapperClass'
* parameter but this class MUST inherit from Doctrine\DBAL\Connection.
*
* <b>driverClass</b>:
* The driver class to use.
*
* @param array $params The parameters.
* @param Doctrine\DBAL\Configuration The configuration to use.
* @param Doctrine\Common\EventManager The event manager to use.
* @return Doctrine\DBAL\Connection
*/
public static function getConnection(
array $params,
Configuration $config = null,
EventManager $eventManager = null)
{
// create default config and event manager, if not set
if ( ! $config) {
$config = new Configuration();
}
if ( ! $eventManager) {
$eventManager = new EventManager();
}
// check for existing pdo object
if (isset($params['pdo']) && ! $params['pdo'] instanceof \PDO) {
throw DBALException::invalidPdoInstance();
} else if (isset($params['pdo'])) {
$params['pdo']->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$params['driver'] = 'pdo_' . $params['pdo']->getAttribute(\PDO::ATTR_DRIVER_NAME);
} else {
self::_checkParams($params);
}
if (isset($params['driverClass'])) {
$className = $params['driverClass'];
} else {
$className = self::$_driverMap[$params['driver']];
}
$driver = new $className();
$wrapperClass = 'Doctrine\DBAL\Connection';
if (isset($params['wrapperClass'])) {
if (is_subclass_of($params['wrapperClass'], $wrapperClass)) {
$wrapperClass = $params['wrapperClass'];
} else {
throw DBALException::invalidWrapperClass($params['wrapperClass']);
}
}
return new $wrapperClass($params, $driver, $config, $eventManager);
}
/**
* Checks the list of parameters.
*
* @param array $params
*/
private static function _checkParams(array $params)
{
// check existance of mandatory parameters
// driver
if ( ! isset($params['driver']) && ! isset($params['driverClass'])) {
throw DBALException::driverRequired();
}
// check validity of parameters
// driver
if ( isset($params['driver']) && ! isset(self::$_driverMap[$params['driver']])) {
throw DBALException::unknownDriver($params['driver'], array_keys(self::$_driverMap));
}
if (isset($params['driverClass']) && ! in_array('Doctrine\DBAL\Driver', class_implements($params['driverClass'], true))) {
throw DBALException::invalidDriverClass($params['driverClass']);
}
}
}

View File

@@ -0,0 +1,79 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Event;
use Doctrine\Common\EventArgs,
Doctrine\DBAL\Connection;
/**
* Event Arguments used when a Driver connection is established inside Doctrine\DBAL\Connection.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 1.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class ConnectionEventArgs extends EventArgs
{
/**
* @var Connection
*/
private $_connection = null;
public function __construct(Connection $connection)
{
$this->_connection = $connection;
}
/**
* @return Doctrine\DBAL\Connection
*/
public function getConnection()
{
return $this->_connection;
}
/**
* @return Doctrine\DBAL\Driver
*/
public function getDriver()
{
return $this->_connection->getDriver();
}
/**
* @return Doctrine\DBAL\Platforms\AbstractPlatform
*/
public function getDatabasePlatform()
{
return $this->_connection->getDatabasePlatform();
}
/**
* @return Doctrine\DBAL\Schema\AbstractSchemaManager
*/
public function getSchemaManager()
{
return $this->_connection->getSchemaManager();
}
}

View File

@@ -0,0 +1,74 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Event\Listeners;
use Doctrine\DBAL\Event\ConnectionEventArgs;
use Doctrine\DBAL\Events;
use Doctrine\Common\EventSubscriber;
/**
* MySQL Session Init Event Subscriber which allows to set the Client Encoding of the Connection
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 1.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @deprecated Use "charset" option to PDO MySQL Connection instead.
*/
class MysqlSessionInit implements EventSubscriber
{
/**
* @var string
*/
private $_charset;
/**
* @var string
*/
private $_collation;
/**
* Configure Charset and Collation options of MySQL Client for each Connection
*
* @param string $charset
* @param string $collation
*/
public function __construct($charset = 'utf8', $collation = false)
{
$this->_charset = $charset;
$this->_collation = $collation;
}
/**
* @param ConnectionEventArgs $args
* @return void
*/
public function postConnect(ConnectionEventArgs $args)
{
$collation = ($this->_collation) ? " COLLATE ".$this->_collation : "";
$args->getConnection()->executeUpdate("SET NAMES ".$this->_charset . $collation);
}
public function getSubscribedEvents()
{
return array(Events::postConnect);
}
}

View File

@@ -0,0 +1,79 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Event\Listeners;
use Doctrine\DBAL\Event\ConnectionEventArgs;
use Doctrine\DBAL\Events;
use Doctrine\Common\EventSubscriber;
/**
* Should be used when Oracle Server default enviroment does not match the Doctrine requirements.
*
* The following enviroment variables are required for the Doctrine default date format:
*
* NLS_TIME_FORMAT="HH24:MI:SS"
* NLS_DATE_FORMAT="YYYY-MM-DD HH24:MI:SS"
* NLS_TIMESTAMP_FORMAT="YYYY-MM-DD HH24:MI:SS"
* NLS_TIMESTAMP_TZ_FORMAT="YYYY-MM-DD HH24:MI:SS TZH:TZM"
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class OracleSessionInit implements EventSubscriber
{
protected $_defaultSessionVars = array(
'NLS_TIME_FORMAT' => "HH24:MI:SS",
'NLS_DATE_FORMAT' => "YYYY-MM-DD HH24:MI:SS",
'NLS_TIMESTAMP_FORMAT' => "YYYY-MM-DD HH24:MI:SS",
'NLS_TIMESTAMP_TZ_FORMAT' => "YYYY-MM-DD HH24:MI:SS TZH:TZM",
);
/**
* @param array $oracleSessionVars
*/
public function __construct(array $oracleSessionVars = array())
{
$this->_defaultSessionVars = array_merge($this->_defaultSessionVars, $oracleSessionVars);
}
/**
* @param ConnectionEventArgs $args
* @return void
*/
public function postConnect(ConnectionEventArgs $args)
{
if (count($this->_defaultSessionVars)) {
array_change_key_case($this->_defaultSessionVars, \CASE_UPPER);
$vars = array();
foreach ($this->_defaultSessionVars AS $option => $value) {
$vars[] = $option." = '".$value."'";
}
$sql = "ALTER SESSION SET ".implode(" ", $vars);
$args->getConnection()->executeUpdate($sql);
}
}
public function getSubscribedEvents()
{
return array(Events::postConnect);
}
}

View File

@@ -0,0 +1,63 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Event\Listeners;
use Doctrine\DBAL\Event\ConnectionEventArgs;
use Doctrine\DBAL\Events;
use Doctrine\Common\EventSubscriber;
/**
* Session init listener for executing a single SQL statement right after a connection is opened.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.2
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class SQLSessionInit implements EventSubscriber
{
/**
* @var string
*/
protected $sql;
/**
* @param string $sql
*/
public function __construct($sql)
{
$this->sql = $sql;
}
/**
* @param ConnectionEventArgs $args
* @return void
*/
public function postConnect(ConnectionEventArgs $args)
{
$conn = $args->getConnection();
$conn->exec($this->sql);
}
public function getSubscribedEvents()
{
return array(Events::postConnect);
}
}

View File

@@ -0,0 +1,114 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Event;
use Doctrine\DBAL\Platforms\AbstractPlatform,
Doctrine\DBAL\Schema\Column,
Doctrine\DBAL\Schema\TableDiff;
/**
* Event Arguments used when SQL queries for adding table columns are generated inside Doctrine\DBAL\Platform\*Platform.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.2
* @author Jan Sorgalla <jsorgalla@googlemail.com>
*/
class SchemaAlterTableAddColumnEventArgs extends SchemaEventArgs
{
/**
* @var \Doctrine\DBAL\Schema\Column
*/
private $_column = null;
/**
* @var \Doctrine\DBAL\Schema\TableDiff
*/
private $_tableDiff = null;
/**
* @var \Doctrine\DBAL\Platforms\AbstractPlatform
*/
private $_platform = null;
/**
* @var array
*/
private $_sql = array();
/**
* @param \Doctrine\DBAL\Schema\Column $column
* @param \Doctrine\DBAL\Schema\TableDiff $tableDiff
* @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
*/
public function __construct(Column $column, TableDiff $tableDiff, AbstractPlatform $platform)
{
$this->_column = $column;
$this->_tableDiff = $tableDiff;
$this->_platform = $platform;
}
/**
* @return \Doctrine\DBAL\Schema\Column
*/
public function getColumn()
{
return $this->_column;
}
/**
* @return \Doctrine\DBAL\Schema\TableDiff
*/
public function getTableDiff()
{
return $this->_tableDiff;
}
/**
* @return \Doctrine\DBAL\Platforms\AbstractPlatform
*/
public function getPlatform()
{
return $this->_platform;
}
/**
* @param string|array $sql
* @return \Doctrine\DBAL\Event\SchemaAlterTableAddColumnEventArgs
*/
public function addSql($sql)
{
if (is_array($sql)) {
$this->_sql = array_merge($this->_sql, $sql);
} else {
$this->_sql[] = $sql;
}
return $this;
}
/**
* @return array
*/
public function getSql()
{
return $this->_sql;
}
}

View File

@@ -0,0 +1,114 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Event;
use Doctrine\DBAL\Platforms\AbstractPlatform,
Doctrine\DBAL\Schema\ColumnDiff,
Doctrine\DBAL\Schema\TableDiff;
/**
* Event Arguments used when SQL queries for changing table columns are generated inside Doctrine\DBAL\Platform\*Platform.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.2
* @author Jan Sorgalla <jsorgalla@googlemail.com>
*/
class SchemaAlterTableChangeColumnEventArgs extends SchemaEventArgs
{
/**
* @var \Doctrine\DBAL\Schema\ColumnDiff
*/
private $_columnDiff = null;
/**
* @var \Doctrine\DBAL\Schema\TableDiff
*/
private $_tableDiff = null;
/**
* @var \Doctrine\DBAL\Platforms\AbstractPlatform
*/
private $_platform = null;
/**
* @var array
*/
private $_sql = array();
/**
* @param \Doctrine\DBAL\Schema\ColumnDiff $columnDiff
* @param \Doctrine\DBAL\Schema\TableDiff $tableDiff
* @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
*/
public function __construct(ColumnDiff $columnDiff, TableDiff $tableDiff, AbstractPlatform $platform)
{
$this->_columnDiff = $columnDiff;
$this->_tableDiff = $tableDiff;
$this->_platform = $platform;
}
/**
* @return \Doctrine\DBAL\Schema\ColumnDiff
*/
public function getColumnDiff()
{
return $this->_columnDiff;
}
/**
* @return \Doctrine\DBAL\Schema\TableDiff
*/
public function getTableDiff()
{
return $this->_tableDiff;
}
/**
* @return \Doctrine\DBAL\Platforms\AbstractPlatform
*/
public function getPlatform()
{
return $this->_platform;
}
/**
* @param string|array $sql
* @return \Doctrine\DBAL\Event\SchemaAlterTableChangeColumnEventArgs
*/
public function addSql($sql)
{
if (is_array($sql)) {
$this->_sql = array_merge($this->_sql, $sql);
} else {
$this->_sql[] = $sql;
}
return $this;
}
/**
* @return array
*/
public function getSql()
{
return $this->_sql;
}
}

View File

@@ -0,0 +1,99 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Event;
use Doctrine\DBAL\Platforms\AbstractPlatform,
Doctrine\DBAL\Schema\Column,
Doctrine\DBAL\Schema\TableDiff;
/**
* Event Arguments used when SQL queries for creating tables are generated inside Doctrine\DBAL\Platform\*Platform.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.2
* @author Jan Sorgalla <jsorgalla@googlemail.com>
*/
class SchemaAlterTableEventArgs extends SchemaEventArgs
{
/**
* @var \Doctrine\DBAL\Schema\TableDiff
*/
private $_tableDiff = null;
/**
* @var \Doctrine\DBAL\Platforms\AbstractPlatform
*/
private $_platform = null;
/**
* @var array
*/
private $_sql = array();
/**
* @param \Doctrine\DBAL\Schema\TableDiff $tableDiff
* @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
*/
public function __construct(TableDiff $tableDiff, AbstractPlatform $platform)
{
$this->_tableDiff = $tableDiff;
$this->_platform = $platform;
}
/**
* @return \Doctrine\DBAL\Schema\TableDiff
*/
public function getTableDiff()
{
return $this->_tableDiff;
}
/**
* @return \Doctrine\DBAL\Platforms\AbstractPlatform
*/
public function getPlatform()
{
return $this->_platform;
}
/**
* @param string|array $sql
* @return \Doctrine\DBAL\Event\SchemaAlterTableEventArgs
*/
public function addSql($sql)
{
if (is_array($sql)) {
$this->_sql = array_merge($this->_sql, $sql);
} else {
$this->_sql[] = $sql;
}
return $this;
}
/**
* @return array
*/
public function getSql()
{
return $this->_sql;
}
}

View File

@@ -0,0 +1,114 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Event;
use Doctrine\DBAL\Platforms\AbstractPlatform,
Doctrine\DBAL\Schema\Column,
Doctrine\DBAL\Schema\TableDiff;
/**
* Event Arguments used when SQL queries for removing table columns are generated inside Doctrine\DBAL\Platform\*Platform.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.2
* @author Jan Sorgalla <jsorgalla@googlemail.com>
*/
class SchemaAlterTableRemoveColumnEventArgs extends SchemaEventArgs
{
/**
* @var \Doctrine\DBAL\Schema\Column
*/
private $_column = null;
/**
* @var \Doctrine\DBAL\Schema\TableDiff
*/
private $_tableDiff = null;
/**
* @var \Doctrine\DBAL\Platforms\AbstractPlatform
*/
private $_platform = null;
/**
* @var array
*/
private $_sql = array();
/**
* @param \Doctrine\DBAL\Schema\Column $column
* @param \Doctrine\DBAL\Schema\TableDiff $tableDiff
* @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
*/
public function __construct(Column $column, TableDiff $tableDiff, AbstractPlatform $platform)
{
$this->_column = $column;
$this->_tableDiff = $tableDiff;
$this->_platform = $platform;
}
/**
* @return \Doctrine\DBAL\Schema\Column
*/
public function getColumn()
{
return $this->_column;
}
/**
* @return \Doctrine\DBAL\Schema\TableDiff
*/
public function getTableDiff()
{
return $this->_tableDiff;
}
/**
* @return \Doctrine\DBAL\Platforms\AbstractPlatform
*/
public function getPlatform()
{
return $this->_platform;
}
/**
* @param string|array $sql
* @return \Doctrine\DBAL\Event\SchemaAlterTableRemoveColumnEventArgs
*/
public function addSql($sql)
{
if (is_array($sql)) {
$this->_sql = array_merge($this->_sql, $sql);
} else {
$this->_sql[] = $sql;
}
return $this;
}
/**
* @return array
*/
public function getSql()
{
return $this->_sql;
}
}

View File

@@ -0,0 +1,129 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Event;
use Doctrine\DBAL\Platforms\AbstractPlatform,
Doctrine\DBAL\Schema\Column,
Doctrine\DBAL\Schema\TableDiff;
/**
* Event Arguments used when SQL queries for renaming table columns are generated inside Doctrine\DBAL\Platform\*Platform.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.2
* @author Jan Sorgalla <jsorgalla@googlemail.com>
*/
class SchemaAlterTableRenameColumnEventArgs extends SchemaEventArgs
{
/**
* @var string
*/
private $_oldColumnName = null;
/**
* @var \Doctrine\DBAL\Schema\Column
*/
private $_column = null;
/**
* @var \Doctrine\DBAL\Schema\TableDiff
*/
private $_tableDiff = null;
/**
* @var \Doctrine\DBAL\Platforms\AbstractPlatform
*/
private $_platform = null;
/**
* @var array
*/
private $_sql = array();
/**
* @param string $oldColumnName
* @param \Doctrine\DBAL\Schema\Column $column
* @param \Doctrine\DBAL\Schema\TableDiff $tableDiff
* @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
*/
public function __construct($oldColumnName, Column $column, TableDiff $tableDiff, AbstractPlatform $platform)
{
$this->_oldColumnName = $oldColumnName;
$this->_column = $column;
$this->_tableDiff = $tableDiff;
$this->_platform = $platform;
}
/**
* @return string
*/
public function getOldColumnName()
{
return $this->_oldColumnName;
}
/**
* @return \Doctrine\DBAL\Schema\Column
*/
public function getColumn()
{
return $this->_column;
}
/**
* @return \Doctrine\DBAL\Schema\TableDiff
*/
public function getTableDiff()
{
return $this->_tableDiff;
}
/**
* @return \Doctrine\DBAL\Platforms\AbstractPlatform
*/
public function getPlatform()
{
return $this->_platform;
}
/**
* @param string|array $sql
* @return \Doctrine\DBAL\Event\SchemaAlterTableRenameColumnEventArgs
*/
public function addSql($sql)
{
if (is_array($sql)) {
$this->_sql = array_merge($this->_sql, $sql);
} else {
$this->_sql[] = $sql;
}
return $this;
}
/**
* @return array
*/
public function getSql()
{
return $this->_sql;
}
}

View File

@@ -0,0 +1,137 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Event;
use Doctrine\DBAL\Connection,
Doctrine\DBAL\Schema\Column;
/**
* Event Arguments used when the portable column definition is generated inside Doctrine\DBAL\Schema\AbstractSchemaManager.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.2
* @author Jan Sorgalla <jsorgalla@googlemail.com>
*/
class SchemaColumnDefinitionEventArgs extends SchemaEventArgs
{
/**
* @var \Doctrine\DBAL\Schema\Column
*/
private $_column = null;
/**
* Raw column data as fetched from the database
*
* @var array
*/
private $_tableColumn = null;
/**
* @var string
*/
private $_table = null;
/**
* @var string
*/
private $_database = null;
/**
* @var \Doctrine\DBAL\Connection
*/
private $_connection = null;
/**
* @param array $tableColumn
* @param string $table
* @param string $database
* @param \Doctrine\DBAL\Connection $conn
*/
public function __construct(array $tableColumn, $table, $database, Connection $connection)
{
$this->_tableColumn = $tableColumn;
$this->_table = $table;
$this->_database = $database;
$this->_connection = $connection;
}
/**
* Allows to clear the column which means the column will be excluded from
* tables column list.
*
* @param null|\Doctrine\DBAL\Schema\Column $column
* @return SchemaColumnDefinitionEventArgs
*/
public function setColumn(Column $column = null)
{
$this->_column = $column;
return $this;
}
/**
* @return \Doctrine\DBAL\Schema\Column
*/
public function getColumn()
{
return $this->_column;
}
/**
* @return array
*/
public function getTableColumn()
{
return $this->_tableColumn;
}
/**
* @return string
*/
public function getTable()
{
return $this->_table;
}
/**
* @return string
*/
public function getDatabase()
{
return $this->_database;
}
/**
* @return \Doctrine\DBAL\Connection
*/
public function getConnection()
{
return $this->_connection;
}
/**
* @return \Doctrine\DBAL\Platforms\AbstractPlatform
*/
public function getDatabasePlatform()
{
return $this->_connection->getDatabasePlatform();
}
}

View File

@@ -0,0 +1,114 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Event;
use Doctrine\DBAL\Platforms\AbstractPlatform,
Doctrine\DBAL\Schema\Column,
Doctrine\DBAL\Schema\Table;
/**
* Event Arguments used when SQL queries for creating table columns are generated inside Doctrine\DBAL\Platform\AbstractPlatform.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.2
* @author Jan Sorgalla <jsorgalla@googlemail.com>
*/
class SchemaCreateTableColumnEventArgs extends SchemaEventArgs
{
/**
* @var \Doctrine\DBAL\Schema\Column
*/
private $_column = null;
/**
* @var \Doctrine\DBAL\Schema\Table
*/
private $_table = null;
/**
* @var \Doctrine\DBAL\Platforms\AbstractPlatform
*/
private $_platform = null;
/**
* @var array
*/
private $_sql = array();
/**
* @param \Doctrine\DBAL\Schema\Column $column
* @param \Doctrine\DBAL\Schema\Table $table
* @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
*/
public function __construct(Column $column, Table $table, AbstractPlatform $platform)
{
$this->_column = $column;
$this->_table = $table;
$this->_platform = $platform;
}
/**
* @return \Doctrine\DBAL\Schema\Column
*/
public function getColumn()
{
return $this->_column;
}
/**
* @return \Doctrine\DBAL\Schema\Table
*/
public function getTable()
{
return $this->_table;
}
/**
* @return \Doctrine\DBAL\Platforms\AbstractPlatform
*/
public function getPlatform()
{
return $this->_platform;
}
/**
* @param string|array $sql
* @return \Doctrine\DBAL\Event\SchemaCreateTableColumnEventArgs
*/
public function addSql($sql)
{
if (is_array($sql)) {
$this->_sql = array_merge($this->_sql, $sql);
} else {
$this->_sql[] = $sql;
}
return $this;
}
/**
* @return array
*/
public function getSql()
{
return $this->_sql;
}
}

View File

@@ -0,0 +1,128 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Event;
use Doctrine\DBAL\Platforms\AbstractPlatform,
Doctrine\DBAL\Schema\Table;
/**
* Event Arguments used when SQL queries for creating tables are generated inside Doctrine\DBAL\Platform\AbstractPlatform.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.2
* @author Jan Sorgalla <jsorgalla@googlemail.com>
*/
class SchemaCreateTableEventArgs extends SchemaEventArgs
{
/**
* @var \Doctrine\DBAL\Schema\Table
*/
private $_table = null;
/**
* @var array
*/
private $_columns = null;
/**
* @var array
*/
private $_options = null;
/**
* @var \Doctrine\DBAL\Platforms\AbstractPlatform
*/
private $_platform = null;
/**
* @var array
*/
private $_sql = array();
/**
* @param \Doctrine\DBAL\Schema\Table $table
* @param array $columns
* @param array $options
* @param Doctrine\DBAL\Platforms\AbstractPlatform $platform
*/
public function __construct(Table $table, array $columns, array $options, AbstractPlatform $platform)
{
$this->_table = $table;
$this->_columns = $columns;
$this->_options = $options;
$this->_platform = $platform;
}
/**
* @return \Doctrine\DBAL\Schema\Table
*/
public function getTable()
{
return $this->_table;
}
/**
* @return array
*/
public function getColumns()
{
return $this->_columns;
}
/**
* @return array
*/
public function getOptions()
{
return $this->_options;
}
/**
* @return \Doctrine\DBAL\Platforms\AbstractPlatform
*/
public function getPlatform()
{
return $this->_platform;
}
/**
* @param string|array $sql
* @return \Doctrine\DBAL\Event\SchemaCreateTableEventArgs
*/
public function addSql($sql)
{
if (is_array($sql)) {
$this->_sql = array_merge($this->_sql, $sql);
} else {
$this->_sql[] = $sql;
}
return $this;
}
/**
* @return array
*/
public function getSql()
{
return $this->_sql;
}
}

View File

@@ -0,0 +1,98 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Event;
use Doctrine\DBAL\Platforms\AbstractPlatform,
Doctrine\DBAL\Schema\Table;
/**
* Event Arguments used when the SQL query for dropping tables are generated inside Doctrine\DBAL\Platform\AbstractPlatform.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.2
* @author Jan Sorgalla <jsorgalla@googlemail.com>
*/
class SchemaDropTableEventArgs extends SchemaEventArgs
{
/**
* @var string|\Doctrine\DBAL\Schema\Table
*/
private $_table = null;
/**
* @var \Doctrine\DBAL\Platforms\AbstractPlatform
*/
private $_platform = null;
/**
* @var string
*/
private $_sql = null;
/**
* @param string|\Doctrine\DBAL\Schema\Table $table
* @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
*/
public function __construct($table, AbstractPlatform $platform)
{
if (!$table instanceof Table && !is_string($table)) {
throw new \InvalidArgumentException('SchemaCreateTableEventArgs expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.');
}
$this->_table = $table;
$this->_platform = $platform;
}
/**
* @return string|\Doctrine\DBAL\Schema\Table
*/
public function getTable()
{
return $this->_table;
}
/**
* @return \Doctrine\DBAL\Platforms\AbstractPlatform
*/
public function getPlatform()
{
return $this->_platform;
}
/**
* @param string $sql
* @return \Doctrine\DBAL\Event\SchemaDropTableEventArgs
*/
public function setSql($sql)
{
$this->_sql = $sql;
return $this;
}
/**
* @return string
*/
public function getSql()
{
return $this->_sql;
}
}

View File

@@ -0,0 +1,56 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Event;
use Doctrine\Common\EventArgs;
/**
* Base class for schema related events.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.2
* @author Jan Sorgalla <jsorgalla@googlemail.com>
*/
class SchemaEventArgs extends EventArgs
{
/**
* @var boolean
*/
private $_preventDefault = false;
/**
* @return \Doctrine\DBAL\Event\SchemaEventArgs
*/
public function preventDefault()
{
$this->_preventDefault = true;
return $this;
}
/**
* @return boolean
*/
public function isDefaultPrevented()
{
return $this->_preventDefault;
}
}

View File

@@ -0,0 +1,122 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Event;
use Doctrine\DBAL\Connection,
Doctrine\DBAL\Schema\Index;
/**
* Event Arguments used when the portable index definition is generated inside Doctrine\DBAL\Schema\AbstractSchemaManager.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.2
* @author Jan Sorgalla <jsorgalla@googlemail.com>
*/
class SchemaIndexDefinitionEventArgs extends SchemaEventArgs
{
/**
* @var \Doctrine\DBAL\Schema\Index
*/
private $_index = null;
/**
* Raw index data as fetched from the database
*
* @var array
*/
private $_tableIndex = null;
/**
* @var string
*/
private $_table = null;
/**
* @var \Doctrine\DBAL\Connection
*/
private $_connection = null;
/**
* @param array $tableIndex
* @param string $table
* @param \Doctrine\DBAL\Connection $conn
*/
public function __construct(array $tableIndex, $table, Connection $connection)
{
$this->_tableIndex = $tableIndex;
$this->_table = $table;
$this->_connection = $connection;
}
/**
* Allows to clear the index which means the index will be excluded from
* tables index list.
*
* @param null|\Doctrine\DBAL\Schema\Index $index
* @return SchemaIndexDefinitionEventArgs
*/
public function setIndex(Index $index = null)
{
$this->_index = $index;
return $this;
}
/**
* @return \Doctrine\DBAL\Schema\Index
*/
public function getIndex()
{
return $this->_index;
}
/**
* @return array
*/
public function getTableIndex()
{
return $this->_tableIndex;
}
/**
* @return string
*/
public function getTable()
{
return $this->_table;
}
/**
* @return \Doctrine\DBAL\Connection
*/
public function getConnection()
{
return $this->_connection;
}
/**
* @return \Doctrine\DBAL\Platforms\AbstractPlatform
*/
public function getDatabasePlatform()
{
return $this->_connection->getDatabasePlatform();
}
}

View File

@@ -0,0 +1,48 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL;
/**
* Container for all DBAL events.
*
* This class cannot be instantiated.
*
* @author Roman Borschel <roman@code-factory.org>
* @since 2.0
*/
final class Events
{
private function __construct() {}
const postConnect = 'postConnect';
const onSchemaCreateTable = 'onSchemaCreateTable';
const onSchemaCreateTableColumn = 'onSchemaCreateTableColumn';
const onSchemaDropTable = 'onSchemaDropTable';
const onSchemaAlterTable = 'onSchemaAlterTable';
const onSchemaAlterTableAddColumn = 'onSchemaAlterTableAddColumn';
const onSchemaAlterTableRemoveColumn = 'onSchemaAlterTableRemoveColumn';
const onSchemaAlterTableChangeColumn = 'onSchemaAlterTableChangeColumn';
const onSchemaAlterTableRenameColumn = 'onSchemaAlterTableRenameColumn';
const onSchemaColumnDefinition = 'onSchemaColumnDefinition';
const onSchemaIndexDefinition = 'onSchemaIndexDefinition';
}

View File

@@ -0,0 +1,42 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL;
/**
* Contains all DBAL LockModes
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 1.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Roman Borschel <roman@code-factory.org>
*/
class LockMode
{
const NONE = 0;
const OPTIMISTIC = 1;
const PESSIMISTIC_READ = 2;
const PESSIMISTIC_WRITE = 4;
final private function __construct() { }
}

View File

@@ -0,0 +1,67 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Logging;
/**
* Includes executed SQLs in a Debug Stack
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class DebugStack implements SQLLogger
{
/** @var array $queries Executed SQL queries. */
public $queries = array();
/** @var boolean $enabled If Debug Stack is enabled (log queries) or not. */
public $enabled = true;
public $start = null;
public $currentQuery = 0;
/**
* {@inheritdoc}
*/
public function startQuery($sql, array $params = null, array $types = null)
{
if ($this->enabled) {
$this->start = microtime(true);
$this->queries[++$this->currentQuery] = array('sql' => $sql, 'params' => $params, 'types' => $types, 'executionMS' => 0);
}
}
/**
* {@inheritdoc}
*/
public function stopQuery()
{
$this->queries[$this->currentQuery]['executionMS'] = microtime(true) - $this->start;
}
}

View File

@@ -0,0 +1,61 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Logging;
/**
* A SQL logger that logs to the standard output using echo/var_dump.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class EchoSQLLogger implements SQLLogger
{
/**
* {@inheritdoc}
*/
public function startQuery($sql, array $params = null, array $types = null)
{
echo $sql . PHP_EOL;
if ($params) {
var_dump($params);
}
if ($types) {
var_dump($types);
}
}
/**
* {@inheritdoc}
*/
public function stopQuery()
{
}
}

View File

@@ -0,0 +1,64 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Logging;
/**
* Chains multiple SQLLogger
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.2
* @author Christophe Coevoet <stof@notk.org>
*/
class LoggerChain implements SQLLogger
{
private $loggers = array();
/**
* Adds a logger in the chain
*
* @param SQLLogger $logger
*/
public function addLogger(SQLLogger $logger)
{
$this->loggers[] = $logger;
}
/**
* {@inheritdoc}
*/
public function startQuery($sql, array $params = null, array $types = null)
{
foreach ($this->loggers as $logger) {
$logger->startQuery($sql, $params, $types);
}
}
/**
* {@inheritdoc}
*/
public function stopQuery()
{
foreach ($this->loggers as $logger) {
$logger->stopQuery();
}
}
}

View File

@@ -0,0 +1,54 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Logging;
/**
* Interface for SQL loggers.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
interface SQLLogger
{
/**
* Logs a SQL statement somewhere.
*
* @param string $sql The SQL to be executed.
* @param array $params The SQL parameters.
* @param array $types The SQL parameter types.
* @return void
*/
public function startQuery($sql, array $params = null, array $types = null);
/**
* Mark the last started query as stopped. This can be used for timing of queries.
*
* @return void
*/
public function stopQuery();
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,587 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Schema\Index;
use Doctrine\DBAL\Schema\TableDiff;
class DB2Platform extends AbstractPlatform
{
/**
* Gets the SQL Snippet used to declare a BLOB column type.
*/
public function getBlobTypeDeclarationSQL(array $field)
{
throw DBALException::notSupported(__METHOD__);
}
public function initializeDoctrineTypeMappings()
{
$this->doctrineTypeMapping = array(
'smallint' => 'smallint',
'bigint' => 'bigint',
'integer' => 'integer',
'time' => 'time',
'date' => 'date',
'varchar' => 'string',
'character' => 'string',
'clob' => 'text',
'decimal' => 'decimal',
'double' => 'float',
'real' => 'float',
'timestamp' => 'datetime',
);
}
/**
* Gets the SQL snippet used to declare a VARCHAR column type.
*
* @param array $field
*/
protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed)
{
return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)')
: ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)');
}
/**
* Gets the SQL snippet used to declare a CLOB column type.
*
* @param array $field
*/
public function getClobTypeDeclarationSQL(array $field)
{
// todo clob(n) with $field['length'];
return 'CLOB(1M)';
}
/**
* Gets the name of the platform.
*
* @return string
*/
public function getName()
{
return 'db2';
}
/**
* Gets the SQL snippet that declares a boolean column.
*
* @param array $columnDef
* @return string
*/
public function getBooleanTypeDeclarationSQL(array $columnDef)
{
return 'SMALLINT';
}
/**
* Gets the SQL snippet that declares a 4 byte integer column.
*
* @param array $columnDef
* @return string
*/
public function getIntegerTypeDeclarationSQL(array $columnDef)
{
return 'INTEGER' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef);
}
/**
* Gets the SQL snippet that declares an 8 byte integer column.
*
* @param array $columnDef
* @return string
*/
public function getBigIntTypeDeclarationSQL(array $columnDef)
{
return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef);
}
/**
* Gets the SQL snippet that declares a 2 byte integer column.
*
* @param array $columnDef
* @return string
*/
public function getSmallIntTypeDeclarationSQL(array $columnDef)
{
return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef);
}
/**
* Gets the SQL snippet that declares common properties of an integer column.
*
* @param array $columnDef
* @return string
*/
protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef)
{
$autoinc = '';
if ( ! empty($columnDef['autoincrement'])) {
$autoinc = ' GENERATED BY DEFAULT AS IDENTITY';
}
return $autoinc;
}
/**
* Obtain DBMS specific SQL to be used to create datetime fields in
* statements like CREATE TABLE
*
* @param array $fieldDeclaration
* @return string
*/
public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
{
if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] == true) {
return "TIMESTAMP(0) WITH DEFAULT";
}
return 'TIMESTAMP(0)';
}
/**
* Obtain DBMS specific SQL to be used to create date fields in statements
* like CREATE TABLE.
*
* @param array $fieldDeclaration
* @return string
*/
public function getDateTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATE';
}
/**
* Obtain DBMS specific SQL to be used to create time fields in statements
* like CREATE TABLE.
*
* @param array $fieldDeclaration
* @return string
*/
public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIME';
}
public function getListDatabasesSQL()
{
throw DBALException::notSupported(__METHOD__);
}
public function getListSequencesSQL($database)
{
throw DBALException::notSupported(__METHOD__);
}
public function getListTableConstraintsSQL($table)
{
throw DBALException::notSupported(__METHOD__);
}
/**
* This code fragment is originally from the Zend_Db_Adapter_Db2 class.
*
* @license New BSD License
* @param string $table
* @return string
*/
public function getListTableColumnsSQL($table, $database = null)
{
return "SELECT DISTINCT c.tabschema, c.tabname, c.colname, c.colno,
c.typename, c.default, c.nulls, c.length, c.scale,
c.identity, tc.type AS tabconsttype, k.colseq
FROM syscat.columns c
LEFT JOIN (syscat.keycoluse k JOIN syscat.tabconst tc
ON (k.tabschema = tc.tabschema
AND k.tabname = tc.tabname
AND tc.type = 'P'))
ON (c.tabschema = k.tabschema
AND c.tabname = k.tabname
AND c.colname = k.colname)
WHERE UPPER(c.tabname) = UPPER('" . $table . "') ORDER BY c.colno";
}
public function getListTablesSQL()
{
return "SELECT NAME FROM SYSIBM.SYSTABLES WHERE TYPE = 'T'";
}
public function getListUsersSQL()
{
throw DBALException::notSupported(__METHOD__);
}
/**
* Get the SQL to list all views of a database or user.
*
* @param string $database
* @return string
*/
public function getListViewsSQL($database)
{
return "SELECT NAME, TEXT FROM SYSIBM.SYSVIEWS";
}
public function getListTableIndexesSQL($table, $currentDatabase = null)
{
return "SELECT NAME, COLNAMES, UNIQUERULE FROM SYSIBM.SYSINDEXES WHERE TBNAME = UPPER('" . $table . "')";
}
public function getListTableForeignKeysSQL($table)
{
return "SELECT TBNAME, RELNAME, REFTBNAME, DELETERULE, UPDATERULE, FKCOLNAMES, PKCOLNAMES ".
"FROM SYSIBM.SYSRELS WHERE TBNAME = UPPER('".$table."')";
}
public function getCreateViewSQL($name, $sql)
{
return "CREATE VIEW ".$name." AS ".$sql;
}
public function getDropViewSQL($name)
{
return "DROP VIEW ".$name;
}
public function getDropSequenceSQL($sequence)
{
throw DBALException::notSupported(__METHOD__);
}
public function getSequenceNextValSQL($sequenceName)
{
throw DBALException::notSupported(__METHOD__);
}
public function getCreateDatabaseSQL($database)
{
return "CREATE DATABASE ".$database;
}
public function getDropDatabaseSQL($database)
{
return "DROP DATABASE ".$database.";";
}
public function supportsCreateDropDatabase()
{
return false;
}
/**
* Whether the platform supports releasing savepoints.
*
* @return boolean
*/
public function supportsReleaseSavepoints()
{
return false;
}
/**
* Gets the SQL specific for the platform to get the current date.
*
* @return string
*/
public function getCurrentDateSQL()
{
return 'VALUES CURRENT DATE';
}
/**
* Gets the SQL specific for the platform to get the current time.
*
* @return string
*/
public function getCurrentTimeSQL()
{
return 'VALUES CURRENT TIME';
}
/**
* Gets the SQL specific for the platform to get the current timestamp
*
* @return string
*/
public function getCurrentTimestampSQL()
{
return "VALUES CURRENT TIMESTAMP";
}
/**
* Obtain DBMS specific SQL code portion needed to set an index
* declaration to be used in statements like CREATE TABLE.
*
* @param string $name name of the index
* @param Index $index index definition
* @return string DBMS specific SQL code portion needed to set an index
*/
public function getIndexDeclarationSQL($name, Index $index)
{
return $this->getUniqueConstraintDeclarationSQL($name, $index);
}
/**
* @param string $tableName
* @param array $columns
* @param array $options
* @return array
*/
protected function _getCreateTableSQL($tableName, array $columns, array $options = array())
{
$indexes = array();
if (isset($options['indexes'])) {
$indexes = $options['indexes'];
}
$options['indexes'] = array();
$sqls = parent::_getCreateTableSQL($tableName, $columns, $options);
foreach ($indexes as $index => $definition) {
$sqls[] = $this->getCreateIndexSQL($definition, $tableName);
}
return $sqls;
}
/**
* Gets the SQL to alter an existing table.
*
* @param TableDiff $diff
* @return array
*/
public function getAlterTableSQL(TableDiff $diff)
{
$sql = array();
$columnSql = array();
$queryParts = array();
foreach ($diff->addedColumns AS $fieldName => $column) {
if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) {
continue;
}
$queryParts[] = 'ADD COLUMN ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray());
}
foreach ($diff->removedColumns AS $column) {
if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) {
continue;
}
$queryParts[] = 'DROP COLUMN ' . $column->getQuotedName($this);
}
foreach ($diff->changedColumns AS $columnDiff) {
if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) {
continue;
}
/* @var $columnDiff Doctrine\DBAL\Schema\ColumnDiff */
$column = $columnDiff->column;
$queryParts[] = 'ALTER ' . ($columnDiff->oldColumnName) . ' '
. $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray());
}
foreach ($diff->renamedColumns AS $oldColumnName => $column) {
if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) {
continue;
}
$queryParts[] = 'RENAME ' . $oldColumnName . ' TO ' . $column->getQuotedName($this);
}
$tableSql = array();
if (!$this->onSchemaAlterTable($diff, $tableSql)) {
if (count($queryParts) > 0) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . implode(" ", $queryParts);
}
$sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff));
if ($diff->newName !== false) {
$sql[] = 'RENAME TABLE TO ' . $diff->newName;
}
}
return array_merge($sql, $tableSql, $columnSql);
}
public function getDefaultValueDeclarationSQL($field)
{
if (isset($field['notnull']) && $field['notnull'] && !isset($field['default'])) {
if (in_array((string)$field['type'], array("Integer", "BigInteger", "SmallInteger"))) {
$field['default'] = 0;
} else if((string)$field['type'] == "DateTime") {
$field['default'] = "00-00-00 00:00:00";
} else if ((string)$field['type'] == "Date") {
$field['default'] = "00-00-00";
} else if((string)$field['type'] == "Time") {
$field['default'] = "00:00:00";
} else {
$field['default'] = '';
}
}
unset($field['default']); // @todo this needs fixing
if (isset($field['version']) && $field['version']) {
if ((string)$field['type'] != "DateTime") {
$field['default'] = "1";
}
}
return parent::getDefaultValueDeclarationSQL($field);
}
/**
* Get the insert sql for an empty insert statement
*
* @param string $tableName
* @param string $identifierColumnName
* @return string $sql
*/
public function getEmptyIdentityInsertSQL($tableName, $identifierColumnName)
{
return 'INSERT INTO ' . $tableName . ' (' . $identifierColumnName . ') VALUES (DEFAULT)';
}
public function getCreateTemporaryTableSnippetSQL()
{
return "DECLARE GLOBAL TEMPORARY TABLE";
}
/**
* DB2 automatically moves temporary tables into the SESSION. schema.
*
* @param string $tableName
* @return string
*/
public function getTemporaryTableName($tableName)
{
return "SESSION." . $tableName;
}
protected function doModifyLimitQuery($query, $limit, $offset = null)
{
if ($limit === null && $offset === null) {
return $query;
}
$limit = (int)$limit;
$offset = (int)(($offset)?:0);
// Todo OVER() needs ORDER BY data!
$sql = 'SELECT db22.* FROM (SELECT ROW_NUMBER() OVER() AS DC_ROWNUM, db21.* '.
'FROM (' . $query . ') db21) db22 WHERE db22.DC_ROWNUM BETWEEN ' . ($offset+1) .' AND ' . ($offset+$limit);
return $sql;
}
/**
* returns the position of the first occurrence of substring $substr in string $str
*
* @param string $substr literal string to find
* @param string $str literal string
* @param int $pos position to start at, beginning of string by default
* @return integer
*/
public function getLocateExpression($str, $substr, $startPos = false)
{
if ($startPos == false) {
return 'LOCATE(' . $substr . ', ' . $str . ')';
} else {
return 'LOCATE(' . $substr . ', ' . $str . ', '.$startPos.')';
}
}
/**
* return string to call a function to get a substring inside an SQL statement
*
* Note: Not SQL92, but common functionality.
*
* SQLite only supports the 2 parameter variant of this function
*
* @param string $value an sql string literal or column name/alias
* @param integer $from where to start the substring portion
* @param integer $len the substring portion length
* @return string
*/
public function getSubstringExpression($value, $from, $len = null)
{
if ($len === null)
return 'SUBSTR(' . $value . ', ' . $from . ')';
else {
return 'SUBSTR(' . $value . ', ' . $from . ', ' . $len . ')';
}
}
public function supportsIdentityColumns()
{
return true;
}
public function prefersIdentityColumns()
{
return true;
}
/**
* Gets the character casing of a column in an SQL result set of this platform.
*
* DB2 returns all column names in SQL result sets in uppercase.
*
* @param string $column The column name for which to get the correct character casing.
* @return string The column name in the character casing used in SQL result sets.
*/
public function getSQLResultCasing($column)
{
return strtoupper($column);
}
public function getForUpdateSQL()
{
return ' WITH RR USE AND KEEP UPDATE LOCKS';
}
public function getDummySelectSQL()
{
return 'SELECT 1 FROM sysibm.sysdummy1';
}
/**
* DB2 supports savepoints, but they work semantically different than on other vendor platforms.
*
* TODO: We have to investigate how to get DB2 up and running with savepoints.
*
* @return bool
*/
public function supportsSavepoints()
{
return false;
}
protected function getReservedKeywordsClass()
{
return 'Doctrine\DBAL\Platforms\Keywords\DB2Keywords';
}
}

View File

@@ -0,0 +1,438 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms\Keywords;
/**
* DB2 Keywords
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class DB2Keywords extends KeywordList
{
public function getName()
{
return 'DB2';
}
protected function getKeywords()
{
return array(
'ACTIVATE',
'ADD',
'AFTER',
'ALIAS',
'ALL',
'ALLOCATE',
'DOCUMENT',
'DOUBLE',
'DROP',
'DSSIZE',
'DYNAMIC',
'EACH',
'LOCK',
'LOCKMAX',
'LOCKSIZE',
'LONG',
'LOOP',
'MAINTAINED',
'ROUND_CEILING',
'ROUND_DOWN',
'ROUND_FLOOR',
'ROUND_HALF_DOWN',
'ROUND_HALF_EVEN',
'ROUND_HALF_UP',
'ALLOW',
'ALTER',
'AND',
'ANY',
'AS',
'ASENSITIVE',
'ASSOCIATE',
'ASUTIME',
'AT',
'ATTRIBUTES',
'AUDIT',
'AUTHORIZATION',
'AUX',
'AUXILIARY',
'BEFORE',
'BEGIN',
'BETWEEN',
'BINARY',
'BUFFERPOOL',
'BY',
'CACHE',
'CALL',
'CALLED',
'CAPTURE',
'CARDINALITY',
'CASCADED',
'CASE',
'CAST',
'CCSID',
'CHAR',
'CHARACTER',
'CHECK',
'CLONE',
'CLOSE',
'CLUSTER',
'COLLECTION',
'COLLID',
'COLUMN',
'COMMENT',
'COMMIT',
'CONCAT',
'CONDITION',
'CONNECT',
'CONNECTION',
'CONSTRAINT',
'CONTAINS',
'CONTINUE',
'COUNT',
'COUNT_BIG',
'CREATE',
'CROSS',
'CURRENT',
'CURRENT_DATE',
'CURRENT_LC_CTYPE',
'CURRENT_PATH',
'CURRENT_SCHEMA',
'CURRENT_SERVER',
'CURRENT_TIME',
'CURRENT_TIMESTAMP',
'CURRENT_TIMEZONE',
'CURRENT_USER',
'CURSOR',
'CYCLE',
'DATA',
'DATABASE',
'DATAPARTITIONNAME',
'DATAPARTITIONNUM',
'EDITPROC',
'ELSE',
'ELSEIF',
'ENABLE',
'ENCODING',
'ENCRYPTION',
'END',
'END-EXEC',
'ENDING',
'ERASE',
'ESCAPE',
'EVERY',
'EXCEPT',
'EXCEPTION',
'EXCLUDING',
'EXCLUSIVE',
'EXECUTE',
'EXISTS',
'EXIT',
'EXPLAIN',
'EXTERNAL',
'EXTRACT',
'FENCED',
'FETCH',
'FIELDPROC',
'FILE',
'FINAL',
'FOR',
'FOREIGN',
'FREE',
'FROM',
'FULL',
'FUNCTION',
'GENERAL',
'GENERATED',
'GET',
'GLOBAL',
'GO',
'GOTO',
'GRANT',
'GRAPHIC',
'GROUP',
'HANDLER',
'HASH',
'HASHED_VALUE',
'HAVING',
'HINT',
'HOLD',
'HOUR',
'HOURS',
'IDENTITY',
'IF',
'IMMEDIATE',
'IN',
'INCLUDING',
'INCLUSIVE',
'INCREMENT',
'INDEX',
'INDICATOR',
'INF',
'INFINITY',
'INHERIT',
'INNER',
'INOUT',
'INSENSITIVE',
'INSERT',
'INTEGRITY',
'MATERIALIZED',
'MAXVALUE',
'MICROSECOND',
'MICROSECONDS',
'MINUTE',
'MINUTES',
'MINVALUE',
'MODE',
'MODIFIES',
'MONTH',
'MONTHS',
'NAN',
'NEW',
'NEW_TABLE',
'NEXTVAL',
'NO',
'NOCACHE',
'NOCYCLE',
'NODENAME',
'NODENUMBER',
'NOMAXVALUE',
'NOMINVALUE',
'NONE',
'NOORDER',
'NORMALIZED',
'NOT',
'NULL',
'NULLS',
'NUMPARTS',
'OBID',
'OF',
'OLD',
'OLD_TABLE',
'ON',
'OPEN',
'OPTIMIZATION',
'OPTIMIZE',
'OPTION',
'OR',
'ORDER',
'OUT',
'OUTER',
'OVER',
'OVERRIDING',
'PACKAGE',
'PADDED',
'PAGESIZE',
'PARAMETER',
'PART',
'PARTITION',
'PARTITIONED',
'PARTITIONING',
'PARTITIONS',
'PASSWORD',
'PATH',
'PIECESIZE',
'PLAN',
'POSITION',
'PRECISION',
'PREPARE',
'PREVVAL',
'PRIMARY',
'PRIQTY',
'PRIVILEGES',
'PROCEDURE',
'PROGRAM',
'PSID',
'ROUND_UP',
'ROUTINE',
'ROW',
'ROW_NUMBER',
'ROWNUMBER',
'ROWS',
'ROWSET',
'RRN',
'RUN',
'SAVEPOINT',
'SCHEMA',
'SCRATCHPAD',
'SCROLL',
'SEARCH',
'SECOND',
'SECONDS',
'SECQTY',
'SECURITY',
'SELECT',
'SENSITIVE',
'SEQUENCE',
'SESSION',
'SESSION_USER',
'SET',
'SIGNAL',
'SIMPLE',
'SNAN',
'SOME',
'SOURCE',
'SPECIFIC',
'SQL',
'SQLID',
'STACKED',
'STANDARD',
'START',
'STARTING',
'STATEMENT',
'STATIC',
'STATMENT',
'STAY',
'STOGROUP',
'STORES',
'STYLE',
'SUBSTRING',
'SUMMARY',
'SYNONYM',
'SYSFUN',
'SYSIBM',
'SYSPROC',
'SYSTEM',
'SYSTEM_USER',
'TABLE',
'TABLESPACE',
'THEN',
'TIME',
'TIMESTAMP',
'TO',
'TRANSACTION',
'TRIGGER',
'TRIM',
'TRUNCATE',
'TYPE',
'UNDO',
'UNION',
'UNIQUE',
'UNTIL',
'UPDATE',
'DATE',
'DAY',
'DAYS',
'DB2GENERAL',
'DB2GENRL',
'DB2SQL',
'DBINFO',
'DBPARTITIONNAME',
'DBPARTITIONNUM',
'DEALLOCATE',
'DECLARE',
'DEFAULT',
'DEFAULTS',
'DEFINITION',
'DELETE',
'DENSE_RANK',
'DENSERANK',
'DESCRIBE',
'DESCRIPTOR',
'DETERMINISTIC',
'DIAGNOSTICS',
'DISABLE',
'DISALLOW',
'DISCONNECT',
'DISTINCT',
'DO',
'INTERSECT',
'PUBLIC',
'USAGE',
'INTO',
'QUERY',
'USER',
'IS',
'QUERYNO',
'USING',
'ISOBID',
'RANGE',
'VALIDPROC',
'ISOLATION',
'RANK',
'VALUE',
'ITERATE',
'READ',
'VALUES',
'JAR',
'READS',
'VARIABLE',
'JAVA',
'RECOVERY',
'VARIANT',
'JOIN',
'REFERENCES',
'VCAT',
'KEEP',
'REFERENCING',
'VERSION',
'KEY',
'REFRESH',
'VIEW',
'LABEL',
'RELEASE',
'VOLATILE',
'LANGUAGE',
'RENAME',
'VOLUMES',
'LATERAL',
'REPEAT',
'WHEN',
'LC_CTYPE',
'RESET',
'WHENEVER',
'LEAVE',
'RESIGNAL',
'WHERE',
'LEFT',
'RESTART',
'WHILE',
'LIKE',
'RESTRICT',
'WITH',
'LINKTYPE',
'RESULT',
'WITHOUT',
'LOCAL',
'RESULT_SET_LOCATOR WLM',
'LOCALDATE',
'RETURN',
'WRITE',
'LOCALE',
'RETURNS',
'XMLELEMENT',
'LOCALTIME',
'REVOKE',
'XMLEXISTS',
'LOCALTIMESTAMP RIGHT',
'XMLNAMESPACES',
'LOCATOR',
'ROLE',
'YEAR',
'LOCATORS',
'ROLLBACK',
'YEARS',
);
}
}

View File

@@ -0,0 +1,63 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms\Keywords;
/**
* Abstract interface for a SQL reserved keyword dictionary.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
abstract class KeywordList
{
private $keywords = null;
/**
* Check if the given word is a keyword of this dialect/vendor platform.
*
* @param string $word
* @return bool
*/
public function isKeyword($word)
{
if ($this->keywords === null) {
$this->initializeKeywords();
}
return isset($this->keywords[strtoupper($word)]);
}
protected function initializeKeywords()
{
$this->keywords = array_flip(array_map('strtoupper', $this->getKeywords()));
}
abstract protected function getKeywords();
/**
* Name of this keyword list.
*
* @return string
*/
abstract public function getName();
}

View File

@@ -0,0 +1,243 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms\Keywords;
/**
* MsSQL Keywordlist
*
* @license BSD http://www.opensource.org/licenses/bsd-license.php
* @link www.doctrine-project.com
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author David Coallier <davidc@php.net>
*/
class MsSQLKeywords extends KeywordList
{
public function getName()
{
return 'MsSQL';
}
protected function getKeywords()
{
return array(
'ADD',
'CURRENT_TIMESTAMP',
'GROUP',
'OPENQUERY',
'SERIALIZABLE',
'ALL',
'CURRENT_USER',
'HAVING',
'OPENROWSET',
'SESSION_USER',
'ALTER',
'CURSOR',
'HOLDLOCK',
'OPTION',
'SET',
'AND',
'DATABASE',
'IDENTITY',
'OR',
'SETUSER',
'ANY',
'DBCC',
'IDENTITYCOL',
'ORDER',
'SHUTDOWN',
'AS',
'DEALLOCATE',
'IDENTITY_INSERT',
'OUTER',
'SOME',
'ASC',
'DECLARE',
'IF',
'OVER',
'STATISTICS',
'AUTHORIZATION',
'DEFAULT',
'IN',
'PERCENT',
'SUM',
'AVG',
'DELETE',
'INDEX',
'PERM',
'SYSTEM_USER',
'BACKUP',
'DENY',
'INNER',
'PERMANENT',
'TABLE',
'BEGIN',
'DESC',
'INSERT',
'PIPE',
'TAPE',
'BETWEEN',
'DISK',
'INTERSECT',
'PLAN',
'TEMP',
'BREAK',
'DISTINCT',
'INTO',
'PRECISION',
'TEMPORARY',
'BROWSE',
'DISTRIBUTED',
'IS',
'PREPARE',
'TEXTSIZE',
'BULK',
'DOUBLE',
'ISOLATION',
'PRIMARY',
'THEN',
'BY',
'DROP',
'JOIN',
'PRINT',
'TO',
'CASCADE',
'DUMMY',
'KEY',
'PRIVILEGES',
'TOP',
'CASE',
'DUMP',
'KILL',
'PROC',
'TRAN',
'CHECK',
'ELSE',
'LEFT',
'PROCEDURE',
'TRANSACTION',
'CHECKPOINT',
'END',
'LEVEL',
'PROCESSEXIT',
'TRIGGER',
'CLOSE',
'ERRLVL',
'LIKE',
'PUBLIC',
'TRUNCATE',
'CLUSTERED',
'ERROREXIT',
'LINENO',
'RAISERROR',
'TSEQUAL',
'COALESCE',
'ESCAPE',
'LOAD',
'READ',
'UNCOMMITTED',
'COLUMN',
'EXCEPT',
'MAX',
'READTEXT',
'UNION',
'COMMIT',
'EXEC',
'MIN',
'RECONFIGURE',
'UNIQUE',
'COMMITTED',
'EXECUTE',
'MIRROREXIT',
'REFERENCES',
'UPDATE',
'COMPUTE',
'EXISTS',
'NATIONAL',
'REPEATABLE',
'UPDATETEXT',
'CONFIRM',
'EXIT',
'NOCHECK',
'REPLICATION',
'USE',
'CONSTRAINT',
'FETCH',
'NONCLUSTERED',
'RESTORE',
'USER',
'CONTAINS',
'FILE',
'NOT',
'RESTRICT',
'VALUES',
'CONTAINSTABLE',
'FILLFACTOR',
'NULL',
'RETURN',
'VARYING',
'CONTINUE',
'FLOPPY',
'NULLIF',
'REVOKE',
'VIEW',
'CONTROLROW',
'FOR',
'OF',
'RIGHT',
'WAITFOR',
'CONVERT',
'FOREIGN',
'OFF',
'ROLLBACK',
'WHEN',
'COUNT',
'FREETEXT',
'OFFSETS',
'ROWCOUNT',
'WHERE',
'CREATE',
'FREETEXTTABLE',
'ON',
'ROWGUIDCOL',
'WHILE',
'CROSS',
'FROM',
'ONCE',
'RULE',
'WITH',
'CURRENT',
'FULL',
'ONLY',
'SAVE',
'WORK',
'CURRENT_DATE',
'GOTO',
'OPEN',
'SCHEMA',
'WRITETEXT',
'CURRENT_TIME',
'GRANT',
'OPENDATASOURCE',
'SELECT',
);
}
}

View File

@@ -0,0 +1,268 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms\Keywords;
/**
* MySQL Keywordlist
*
* @license BSD http://www.opensource.org/licenses/bsd-license.php
* @link www.doctrine-project.com
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author David Coallier <davidc@php.net>
*/
class MySQLKeywords extends KeywordList
{
public function getName()
{
return 'MySQL';
}
protected function getKeywords()
{
return array(
'ADD',
'ALL',
'ALTER',
'ANALYZE',
'AND',
'AS',
'ASC',
'ASENSITIVE',
'BEFORE',
'BETWEEN',
'BIGINT',
'BINARY',
'BLOB',
'BOTH',
'BY',
'CALL',
'CASCADE',
'CASE',
'CHANGE',
'CHAR',
'CHARACTER',
'CHECK',
'COLLATE',
'COLUMN',
'CONDITION',
'CONNECTION',
'CONSTRAINT',
'CONTINUE',
'CONVERT',
'CREATE',
'CROSS',
'CURRENT_DATE',
'CURRENT_TIME',
'CURRENT_TIMESTAMP',
'CURRENT_USER',
'CURSOR',
'DATABASE',
'DATABASES',
'DAY_HOUR',
'DAY_MICROSECOND',
'DAY_MINUTE',
'DAY_SECOND',
'DEC',
'DECIMAL',
'DECLARE',
'DEFAULT',
'DELAYED',
'DELETE',
'DESC',
'DESCRIBE',
'DETERMINISTIC',
'DISTINCT',
'DISTINCTROW',
'DIV',
'DOUBLE',
'DROP',
'DUAL',
'EACH',
'ELSE',
'ELSEIF',
'ENCLOSED',
'ESCAPED',
'EXISTS',
'EXIT',
'EXPLAIN',
'FALSE',
'FETCH',
'FLOAT',
'FLOAT4',
'FLOAT8',
'FOR',
'FORCE',
'FOREIGN',
'FROM',
'FULLTEXT',
'GOTO',
'GRANT',
'GROUP',
'HAVING',
'HIGH_PRIORITY',
'HOUR_MICROSECOND',
'HOUR_MINUTE',
'HOUR_SECOND',
'IF',
'IGNORE',
'IN',
'INDEX',
'INFILE',
'INNER',
'INOUT',
'INSENSITIVE',
'INSERT',
'INT',
'INT1',
'INT2',
'INT3',
'INT4',
'INT8',
'INTEGER',
'INTERVAL',
'INTO',
'IS',
'ITERATE',
'JOIN',
'KEY',
'KEYS',
'KILL',
'LABEL',
'LEADING',
'LEAVE',
'LEFT',
'LIKE',
'LIMIT',
'LINES',
'LOAD',
'LOCALTIME',
'LOCALTIMESTAMP',
'LOCK',
'LONG',
'LONGBLOB',
'LONGTEXT',
'LOOP',
'LOW_PRIORITY',
'MATCH',
'MEDIUMBLOB',
'MEDIUMINT',
'MEDIUMTEXT',
'MIDDLEINT',
'MINUTE_MICROSECOND',
'MINUTE_SECOND',
'MOD',
'MODIFIES',
'NATURAL',
'NOT',
'NO_WRITE_TO_BINLOG',
'NULL',
'NUMERIC',
'ON',
'OPTIMIZE',
'OPTION',
'OPTIONALLY',
'OR',
'ORDER',
'OUT',
'OUTER',
'OUTFILE',
'PRECISION',
'PRIMARY',
'PROCEDURE',
'PURGE',
'RAID0',
'READ',
'READS',
'REAL',
'REFERENCES',
'REGEXP',
'RELEASE',
'RENAME',
'REPEAT',
'REPLACE',
'REQUIRE',
'RESTRICT',
'RETURN',
'REVOKE',
'RIGHT',
'RLIKE',
'SCHEMA',
'SCHEMAS',
'SECOND_MICROSECOND',
'SELECT',
'SENSITIVE',
'SEPARATOR',
'SET',
'SHOW',
'SMALLINT',
'SONAME',
'SPATIAL',
'SPECIFIC',
'SQL',
'SQLEXCEPTION',
'SQLSTATE',
'SQLWARNING',
'SQL_BIG_RESULT',
'SQL_CALC_FOUND_ROWS',
'SQL_SMALL_RESULT',
'SSL',
'STARTING',
'STRAIGHT_JOIN',
'TABLE',
'TERMINATED',
'THEN',
'TINYBLOB',
'TINYINT',
'TINYTEXT',
'TO',
'TRAILING',
'TRIGGER',
'TRUE',
'UNDO',
'UNION',
'UNIQUE',
'UNLOCK',
'UNSIGNED',
'UPDATE',
'USAGE',
'USE',
'USING',
'UTC_DATE',
'UTC_TIME',
'UTC_TIMESTAMP',
'VALUES',
'VARBINARY',
'VARCHAR',
'VARCHARACTER',
'VARYING',
'WHEN',
'WHERE',
'WHILE',
'WITH',
'WRITE',
'X509',
'XOR',
'YEAR_MONTH',
'ZEROFILL',
);
}
}

View File

@@ -0,0 +1,156 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms\Keywords;
/**
* Oracle Keywordlist
*
* @license BSD http://www.opensource.org/licenses/bsd-license.php
* @link www.doctrine-project.com
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author David Coallier <davidc@php.net>
*/
class OracleKeywords extends KeywordList
{
public function getName()
{
return 'Oracle';
}
protected function getKeywords()
{
return array(
'ACCESS',
'ELSE',
'MODIFY',
'START',
'ADD',
'EXCLUSIVE',
'NOAUDIT',
'SELECT',
'ALL',
'EXISTS',
'NOCOMPRESS',
'SESSION',
'ALTER',
'FILE',
'NOT',
'SET',
'AND',
'FLOAT',
'NOTFOUND ',
'SHARE',
'ANY',
'FOR',
'NOWAIT',
'SIZE',
'ARRAYLEN',
'FROM',
'NULL',
'SMALLINT',
'AS',
'GRANT',
'NUMBER',
'SQLBUF',
'ASC',
'GROUP',
'OF',
'SUCCESSFUL',
'AUDIT',
'HAVING',
'OFFLINE ',
'SYNONYM',
'BETWEEN',
'IDENTIFIED',
'ON',
'SYSDATE',
'BY',
'IMMEDIATE',
'ONLINE',
'TABLE',
'CHAR',
'IN',
'OPTION',
'THEN',
'CHECK',
'INCREMENT',
'OR',
'TO',
'CLUSTER',
'INDEX',
'ORDER',
'TRIGGER',
'COLUMN',
'INITIAL',
'PCTFREE',
'UID',
'COMMENT',
'INSERT',
'PRIOR',
'UNION',
'COMPRESS',
'INTEGER',
'PRIVILEGES',
'UNIQUE',
'CONNECT',
'INTERSECT',
'PUBLIC',
'UPDATE',
'CREATE',
'INTO',
'RAW',
'USER',
'CURRENT',
'IS',
'RENAME',
'VALIDATE',
'DATE',
'LEVEL',
'RESOURCE',
'VALUES',
'DECIMAL',
'LIKE',
'REVOKE',
'VARCHAR',
'DEFAULT',
'LOCK',
'ROW',
'VARCHAR2',
'DELETE',
'LONG',
'ROWID',
'VIEW',
'DESC',
'MAXEXTENTS',
'ROWLABEL',
'WHENEVER',
'DISTINCT',
'MINUS',
'ROWNUM',
'WHERE',
'DROP',
'MODE',
'ROWS',
'WITH',
);
}
}

View File

@@ -0,0 +1,131 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms\Keywords;
/**
* PostgreSQL Keywordlist
*
* @license BSD http://www.opensource.org/licenses/bsd-license.php
* @link www.doctrine-project.com
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Marcelo Santos Araujo <msaraujo@php.net>
*/
class PostgreSQLKeywords extends KeywordList
{
public function getName()
{
return 'PostgreSQL';
}
protected function getKeywords()
{
return array(
'ALL',
'ANALYSE',
'ANALYZE',
'AND',
'ANY',
'AS',
'ASC',
'AUTHORIZATION',
'BETWEEN',
'BINARY',
'BOTH',
'CASE',
'CAST',
'CHECK',
'COLLATE',
'COLUMN',
'CONSTRAINT',
'CREATE',
'CURRENT_DATE',
'CURRENT_TIME',
'CURRENT_TIMESTAMP',
'CURRENT_USER',
'DEFAULT',
'DEFERRABLE',
'DESC',
'DISTINCT',
'DO',
'ELSE',
'END',
'EXCEPT',
'FALSE',
'FOR',
'FOREIGN',
'FREEZE',
'FROM',
'FULL',
'GRANT',
'GROUP',
'HAVING',
'ILIKE',
'IN',
'INITIALLY',
'INNER',
'INTERSECT',
'INTO',
'IS',
'ISNULL',
'JOIN',
'LEADING',
'LEFT',
'LIKE',
'LIMIT',
'LOCALTIME',
'LOCALTIMESTAMP',
'NATURAL',
'NEW',
'NOT',
'NOTNULL',
'NULL',
'OFF',
'OFFSET',
'OLD',
'ON',
'ONLY',
'OR',
'ORDER',
'OUTER',
'OVERLAPS',
'PLACING',
'PRIMARY',
'REFERENCES',
'SELECT',
'SESSION_USER',
'SIMILAR',
'SOME',
'TABLE',
'THEN',
'TO',
'TRAILING',
'TRUE',
'UNION',
'UNIQUE',
'USER',
'USING',
'VERBOSE',
'WHEN',
'WHERE'
);
}
}

View File

@@ -0,0 +1,116 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms\Keywords;
use Doctrine\DBAL\Schema\Visitor\Visitor;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\Sequence;
use Doctrine\DBAL\Schema\Index;
class ReservedKeywordsValidator implements Visitor
{
/**
* @var KeywordList[]
*/
private $keywordLists = array();
/**
* @var array
*/
private $violations = array();
public function __construct(array $keywordLists)
{
$this->keywordLists = $keywordLists;
}
public function getViolations()
{
return $this->violations;
}
/**
* @param string $word
* @return array
*/
private function isReservedWord($word)
{
if ($word[0] == "`") {
$word = str_replace('`', '', $word);
}
$keywordLists = array();
foreach ($this->keywordLists AS $keywordList) {
if ($keywordList->isKeyword($word)) {
$keywordLists[] = $keywordList->getName();
}
}
return $keywordLists;
}
private function addViolation($asset, $violatedPlatforms)
{
if (!$violatedPlatforms) {
return;
}
$this->violations[] = $asset . ' keyword violations: ' . implode(', ', $violatedPlatforms);
}
public function acceptColumn(Table $table, Column $column)
{
$this->addViolation(
'Table ' . $table->getName() . ' column ' . $column->getName(),
$this->isReservedWord($column->getName())
);
}
public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint)
{
}
public function acceptIndex(Table $table, Index $index)
{
}
public function acceptSchema(Schema $schema)
{
}
public function acceptSequence(Sequence $sequence)
{
}
public function acceptTable(Table $table)
{
$this->addViolation(
'Table ' . $table->getName(),
$this->isReservedWord($table->getName())
);
}
}

View File

@@ -0,0 +1,164 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms\Keywords;
/**
* SQLite Keywords
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class SQLiteKeywords extends KeywordList
{
public function getName()
{
return 'SQLite';
}
protected function getKeywords()
{
return array(
'ABORT',
'ACTION',
'ADD',
'AFTER',
'ALL',
'ALTER',
'ANALYZE',
'AND',
'AS',
'ASC',
'ATTACH',
'AUTOINCREMENT',
'BEFORE',
'BEGIN',
'BETWEEN',
'BY',
'CASCADE',
'CASE',
'CAST',
'CHECK',
'COLLATE',
'COLUMN',
'COMMIT',
'CONFLICT',
'CONSTRAINT',
'CREATE',
'CROSS',
'CURRENT_DATE',
'CURRENT_TIME',
'CURRENT_TIMESTAMP',
'DATABASE',
'DEFAULT',
'DEFERRABLE',
'DEFERRED',
'DELETE',
'DESC',
'DETACH',
'DISTINCT',
'DROP',
'EACH',
'ELSE',
'END',
'ESCAPE',
'EXCEPT',
'EXCLUSIVE',
'EXISTS',
'EXPLAIN',
'FAIL',
'FOR',
'FOREIGN',
'FROM',
'FULL',
'GLOB',
'GROUP',
'HAVING',
'IF',
'IGNORE',
'IMMEDIATE',
'IN',
'INDEX',
'INDEXED',
'INITIALLY',
'INNER',
'INSERT',
'INSTEAD',
'INTERSECT',
'INTO',
'IS',
'ISNULL',
'JOIN',
'KEY',
'LEFT',
'LIKE',
'LIMIT',
'MATCH',
'NATURAL',
'NO',
'NOT',
'NOTNULL',
'NULL',
'OF',
'OFFSET',
'ON',
'OR',
'ORDER',
'OUTER',
'PLAN',
'PRAGMA',
'PRIMARY',
'QUERY',
'RAISE',
'REFERENCES',
'REGEXP',
'REINDEX',
'RELEASE',
'RENAME',
'REPLACE',
'RESTRICT',
'RIGHT',
'ROLLBACK',
'ROW',
'SAVEPOINT',
'SELECT',
'SET',
'TABLE',
'TEMP',
'TEMPORARY',
'THEN',
'TO',
'TRANSACTION',
'TRIGGER',
'UNION',
'UNIQUE',
'UPDATE',
'USING',
'VACUUM',
'VALUES',
'VIEW',
'VIRTUAL',
'WHEN',
'WHERE'
);
}
}

View File

@@ -0,0 +1,768 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms;
use Doctrine\DBAL\DBALException,
Doctrine\DBAL\Schema\TableDiff,
Doctrine\DBAL\Schema\Index,
Doctrine\DBAL\Schema\Table;
/**
* The MySqlPlatform provides the behavior, features and SQL dialect of the
* MySQL database platform. This platform represents a MySQL 5.0 or greater platform that
* uses the InnoDB storage engine.
*
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @todo Rename: MySQLPlatform
*/
class MySqlPlatform extends AbstractPlatform
{
/**
* Gets the character used for identifier quoting.
*
* @return string
* @override
*/
public function getIdentifierQuoteCharacter()
{
return '`';
}
/**
* Returns the regular expression operator.
*
* @return string
* @override
*/
public function getRegexpExpression()
{
return 'RLIKE';
}
/**
* Returns global unique identifier
*
* @return string to get global unique identifier
* @override
*/
public function getGuidExpression()
{
return 'UUID()';
}
/**
* returns the position of the first occurrence of substring $substr in string $str
*
* @param string $substr literal string to find
* @param string $str literal string
* @param int $pos position to start at, beginning of string by default
* @return integer
*/
public function getLocateExpression($str, $substr, $startPos = false)
{
if ($startPos == false) {
return 'LOCATE(' . $substr . ', ' . $str . ')';
} else {
return 'LOCATE(' . $substr . ', ' . $str . ', '.$startPos.')';
}
}
/**
* 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.
* @override
*/
public function getConcatExpression()
{
$args = func_get_args();
return 'CONCAT(' . join(', ', (array) $args) . ')';
}
public function getDateDiffExpression($date1, $date2)
{
return 'DATEDIFF(' . $date1 . ', ' . $date2 . ')';
}
public function getDateAddDaysExpression($date, $days)
{
return 'DATE_ADD(' . $date . ', INTERVAL ' . $days . ' DAY)';
}
public function getDateSubDaysExpression($date, $days)
{
return 'DATE_SUB(' . $date . ', INTERVAL ' . $days . ' DAY)';
}
public function getDateAddMonthExpression($date, $months)
{
return 'DATE_ADD(' . $date . ', INTERVAL ' . $months . ' MONTH)';
}
public function getDateSubMonthExpression($date, $months)
{
return 'DATE_SUB(' . $date . ', INTERVAL ' . $months . ' MONTH)';
}
public function getListDatabasesSQL()
{
return 'SHOW DATABASES';
}
public function getListTableConstraintsSQL($table)
{
return 'SHOW INDEX FROM ' . $table;
}
/**
* Two approaches to listing the table indexes. The information_schema is
* prefered, because it doesn't cause problems with SQL keywords such as "order" or "table".
*
* @param string $table
* @param string $currentDatabase
* @return string
*/
public function getListTableIndexesSQL($table, $currentDatabase = null)
{
if ($currentDatabase) {
return "SELECT TABLE_NAME AS `Table`, NON_UNIQUE AS Non_Unique, INDEX_NAME AS Key_name, ".
"SEQ_IN_INDEX AS Seq_in_index, COLUMN_NAME AS Column_Name, COLLATION AS Collation, ".
"CARDINALITY AS Cardinality, SUB_PART AS Sub_Part, PACKED AS Packed, " .
"NULLABLE AS `Null`, INDEX_TYPE AS Index_Type, COMMENT AS Comment " .
"FROM information_schema.STATISTICS WHERE TABLE_NAME = '" . $table . "' AND TABLE_SCHEMA = '" . $currentDatabase . "'";
} else {
return 'SHOW INDEX FROM ' . $table;
}
}
public function getListViewsSQL($database)
{
return "SELECT * FROM information_schema.VIEWS WHERE TABLE_SCHEMA = '".$database."'";
}
public function getListTableForeignKeysSQL($table, $database = null)
{
$sql = "SELECT DISTINCT k.`CONSTRAINT_NAME`, k.`COLUMN_NAME`, k.`REFERENCED_TABLE_NAME`, ".
"k.`REFERENCED_COLUMN_NAME` /*!50116 , c.update_rule, c.delete_rule */ ".
"FROM information_schema.key_column_usage k /*!50116 ".
"INNER JOIN information_schema.referential_constraints c ON ".
" c.constraint_name = k.constraint_name AND ".
" c.table_name = '$table' */ WHERE k.table_name = '$table'";
if ($database) {
$sql .= " AND k.table_schema = '$database' /*!50116 AND c.constraint_schema = '$database' */";
}
$sql .= " AND k.`REFERENCED_COLUMN_NAME` is not NULL";
return $sql;
}
public function getCreateViewSQL($name, $sql)
{
return 'CREATE VIEW ' . $name . ' AS ' . $sql;
}
public function getDropViewSQL($name)
{
return 'DROP VIEW '. $name;
}
/**
* Gets the SQL snippet used to declare a VARCHAR column on the MySql platform.
*
* @params array $field
*/
protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed)
{
return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)')
: ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)');
}
/** @override */
public function getClobTypeDeclarationSQL(array $field)
{
if ( ! empty($field['length']) && is_numeric($field['length'])) {
$length = $field['length'];
if ($length <= 255) {
return 'TINYTEXT';
} else if ($length <= 65532) {
return 'TEXT';
} else if ($length <= 16777215) {
return 'MEDIUMTEXT';
}
}
return 'LONGTEXT';
}
/**
* @override
*/
public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
{
if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] == true) {
return 'TIMESTAMP';
} else {
return 'DATETIME';
}
}
/**
* @override
*/
public function getDateTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATE';
}
/**
* @override
*/
public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIME';
}
/**
* @override
*/
public function getBooleanTypeDeclarationSQL(array $field)
{
return 'TINYINT(1)';
}
/**
* Obtain DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration to be used in statements like CREATE TABLE.
*
* @param string $collation name of the collation
* @return string DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration.
*/
public function getCollationFieldDeclaration($collation)
{
return 'COLLATE ' . $collation;
}
/**
* Whether the platform prefers identity columns for ID generation.
* MySql prefers "autoincrement" identity columns since sequences can only
* be emulated with a table.
*
* @return boolean
* @override
*/
public function prefersIdentityColumns()
{
return true;
}
/**
* Whether the platform supports identity columns.
* MySql supports this through AUTO_INCREMENT columns.
*
* @return boolean
* @override
*/
public function supportsIdentityColumns()
{
return true;
}
public function supportsInlineColumnComments()
{
return true;
}
public function getShowDatabasesSQL()
{
return 'SHOW DATABASES';
}
public function getListTablesSQL()
{
return "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'";
}
public function getListTableColumnsSQL($table, $database = null)
{
if ($database) {
return "SELECT COLUMN_NAME AS Field, COLUMN_TYPE AS Type, IS_NULLABLE AS `Null`, ".
"COLUMN_KEY AS `Key`, COLUMN_DEFAULT AS `Default`, EXTRA AS Extra, COLUMN_COMMENT AS Comment, " .
"CHARACTER_SET_NAME AS CharacterSet, COLLATION_NAME AS CollactionName ".
"FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = '" . $database . "' AND TABLE_NAME = '" . $table . "'";
} else {
return 'DESCRIBE ' . $table;
}
}
/**
* create a new database
*
* @param string $name name of the database that should be created
* @return string
* @override
*/
public function getCreateDatabaseSQL($name)
{
return 'CREATE DATABASE ' . $name;
}
/**
* drop an existing database
*
* @param string $name name of the database that should be dropped
* @return string
* @override
*/
public function getDropDatabaseSQL($name)
{
return 'DROP DATABASE ' . $name;
}
/**
* create a new table
*
* @param string $tableName Name of the database that should be created
* @param array $columns Associative array that contains the definition of each field of the new table
* The indexes of the array entries are the names of the fields of the table an
* the array entry values are associative arrays like those that are meant to be
* passed with the field definitions to get[Type]Declaration() functions.
* array(
* 'id' => array(
* 'type' => 'integer',
* 'unsigned' => 1
* 'notnull' => 1
* 'default' => 0
* ),
* 'name' => array(
* 'type' => 'text',
* 'length' => 12
* ),
* 'password' => array(
* 'type' => 'text',
* 'length' => 12
* )
* );
* @param array $options An associative array of table options:
* array(
* 'comment' => 'Foo',
* 'charset' => 'utf8',
* 'collate' => 'utf8_unicode_ci',
* 'engine' => 'innodb',
* 'foreignKeys' => array(
* new ForeignKeyConstraint(),
* new ForeignKeyConstraint(),
* new ForeignKeyConstraint(),
* // etc
* )
* );
*
* @return void
* @override
*/
protected function _getCreateTableSQL($tableName, array $columns, array $options = array())
{
$queryFields = $this->getColumnDeclarationListSQL($columns);
if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) {
foreach ($options['uniqueConstraints'] as $index => $definition) {
$queryFields .= ', ' . $this->getUniqueConstraintDeclarationSQL($index, $definition);
}
}
// add all indexes
if (isset($options['indexes']) && ! empty($options['indexes'])) {
foreach($options['indexes'] as $index => $definition) {
$queryFields .= ', ' . $this->getIndexDeclarationSQL($index, $definition);
}
}
// attach all primary keys
if (isset($options['primary']) && ! empty($options['primary'])) {
$keyColumns = array_unique(array_values($options['primary']));
$queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')';
}
$query = 'CREATE ';
if (!empty($options['temporary'])) {
$query .= 'TEMPORARY ';
}
$query.= 'TABLE ' . $tableName . ' (' . $queryFields . ')';
$optionStrings = array();
if (isset($options['comment'])) {
$optionStrings['comment'] = 'COMMENT = ' . $options['comment'];
}
if (isset($options['charset'])) {
$optionStrings['charset'] = 'DEFAULT CHARACTER SET ' . $options['charset'];
if (isset($options['collate'])) {
$optionStrings['charset'] .= ' COLLATE ' . $options['collate'];
}
}
// get the type of the table
if (isset($options['engine'])) {
$optionStrings[] = 'ENGINE = ' . $options['engine'];
} else {
// default to innodb
$optionStrings[] = 'ENGINE = InnoDB';
}
if ( ! empty($optionStrings)) {
$query.= ' '.implode(' ', $optionStrings);
}
$sql[] = $query;
if (isset($options['foreignKeys'])) {
foreach ((array) $options['foreignKeys'] as $definition) {
$sql[] = $this->getCreateForeignKeySQL($definition, $tableName);
}
}
return $sql;
}
/**
* Gets the SQL to alter an existing table.
*
* @param TableDiff $diff
* @return array
*/
public function getAlterTableSQL(TableDiff $diff)
{
$columnSql = array();
$queryParts = array();
if ($diff->newName !== false) {
$queryParts[] = 'RENAME TO ' . $diff->newName;
}
foreach ($diff->addedColumns AS $fieldName => $column) {
if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) {
continue;
}
$columnArray = $column->toArray();
$columnArray['comment'] = $this->getColumnComment($column);
$queryParts[] = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray);
}
foreach ($diff->removedColumns AS $column) {
if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) {
continue;
}
$queryParts[] = 'DROP ' . $column->getQuotedName($this);
}
foreach ($diff->changedColumns AS $columnDiff) {
if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) {
continue;
}
/* @var $columnDiff Doctrine\DBAL\Schema\ColumnDiff */
$column = $columnDiff->column;
$columnArray = $column->toArray();
$columnArray['comment'] = $this->getColumnComment($column);
$queryParts[] = 'CHANGE ' . ($columnDiff->oldColumnName) . ' '
. $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray);
}
foreach ($diff->renamedColumns AS $oldColumnName => $column) {
if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) {
continue;
}
$columnArray = $column->toArray();
$columnArray['comment'] = $this->getColumnComment($column);
$queryParts[] = 'CHANGE ' . $oldColumnName . ' '
. $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray);
}
$sql = array();
$tableSql = array();
if (!$this->onSchemaAlterTable($diff, $tableSql)) {
if (count($queryParts) > 0) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . implode(", ", $queryParts);
}
$sql = array_merge(
$this->getPreAlterTableIndexForeignKeySQL($diff),
$sql,
$this->getPostAlterTableIndexForeignKeySQL($diff)
);
}
return array_merge($sql, $tableSql, $columnSql);
}
/**
* Fix for DROP/CREATE index after foreign key change from OneToOne to ManyToOne
*
* @param TableDiff $diff
* @return array
*/
protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff)
{
$sql = array();
$table = $diff->name;
foreach ($diff->removedIndexes AS $remKey => $remIndex) {
foreach ($diff->addedIndexes as $addKey => $addIndex) {
if ($remIndex->getColumns() == $addIndex->getColumns()) {
$columns = $addIndex->getColumns();
$type = '';
if ($addIndex->isUnique()) {
$type = 'UNIQUE ';
}
$query = 'ALTER TABLE ' . $table . ' DROP INDEX ' . $remIndex->getName() . ', ';
$query .= 'ADD ' . $type . 'INDEX ' . $addIndex->getName();
$query .= ' (' . $this->getIndexFieldDeclarationListSQL($columns) . ')';
$sql[] = $query;
unset($diff->removedIndexes[$remKey]);
unset($diff->addedIndexes[$addKey]);
break;
}
}
}
$sql = array_merge($sql, parent::getPreAlterTableIndexForeignKeySQL($diff));
return $sql;
}
/**
* Obtain DBMS specific SQL code portion needed to declare an integer type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes.
* Currently, the types of supported field
* properties are as follows:
*
* unsigned
* Boolean flag that indicates whether the field
* should be declared as unsigned integer if
* possible.
*
* default
* Integer value to be used as default for this
* field.
*
* notnull
* Boolean flag that indicates whether this field is
* constrained to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @override
*/
public function getIntegerTypeDeclarationSQL(array $field)
{
return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/** @override */
public function getBigIntTypeDeclarationSQL(array $field)
{
return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/** @override */
public function getSmallIntTypeDeclarationSQL(array $field)
{
return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/** @override */
protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef)
{
$autoinc = '';
if ( ! empty($columnDef['autoincrement'])) {
$autoinc = ' AUTO_INCREMENT';
}
$unsigned = (isset($columnDef['unsigned']) && $columnDef['unsigned']) ? ' UNSIGNED' : '';
return $unsigned . $autoinc;
}
/**
* Return the FOREIGN KEY query section dealing with non-standard options
* as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
*
* @param ForeignKeyConstraint $foreignKey
* @return string
* @override
*/
public function getAdvancedForeignKeyOptionsSQL(\Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey)
{
$query = '';
if ($foreignKey->hasOption('match')) {
$query .= ' MATCH ' . $foreignKey->getOption('match');
}
$query .= parent::getAdvancedForeignKeyOptionsSQL($foreignKey);
return $query;
}
/**
* Gets the SQL to drop an index of a table.
*
* @param Index $index name of the index to be dropped
* @param string|Table $table name of table that should be used in method
* @override
*/
public function getDropIndexSQL($index, $table=null)
{
if($index instanceof Index) {
$indexName = $index->getQuotedName($this);
} else if(is_string($index)) {
$indexName = $index;
} else {
throw new \InvalidArgumentException('MysqlPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.');
}
if($table instanceof Table) {
$table = $table->getQuotedName($this);
} else if(!is_string($table)) {
throw new \InvalidArgumentException('MysqlPlatform::getDropIndexSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.');
}
if ($index instanceof Index && $index->isPrimary()) {
// mysql primary keys are always named "PRIMARY",
// so we cannot use them in statements because of them being keyword.
return $this->getDropPrimaryKeySQL($table);
}
return 'DROP INDEX ' . $indexName . ' ON ' . $table;
}
/**
* @param Index $index
* @param Table $table
*/
protected function getDropPrimaryKeySQL($table)
{
return 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY';
}
public function getSetTransactionIsolationSQL($level)
{
return 'SET SESSION TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level);
}
/**
* Get the platform name for this instance.
*
* @return string
*/
public function getName()
{
return 'mysql';
}
public function getReadLockSQL()
{
return 'LOCK IN SHARE MODE';
}
protected function initializeDoctrineTypeMappings()
{
$this->doctrineTypeMapping = array(
'tinyint' => 'boolean',
'smallint' => 'smallint',
'mediumint' => 'integer',
'int' => 'integer',
'integer' => 'integer',
'bigint' => 'bigint',
'tinytext' => 'text',
'mediumtext' => 'text',
'longtext' => 'text',
'text' => 'text',
'varchar' => 'string',
'string' => 'string',
'char' => 'string',
'date' => 'date',
'datetime' => 'datetime',
'timestamp' => 'datetime',
'time' => 'time',
'float' => 'float',
'double' => 'float',
'real' => 'float',
'decimal' => 'decimal',
'numeric' => 'decimal',
'year' => 'date',
'longblob' => 'blob',
'blob' => 'blob',
'mediumblob' => 'blob',
'tinyblob' => 'blob',
);
}
public function getVarcharMaxLength()
{
return 65535;
}
protected function getReservedKeywordsClass()
{
return 'Doctrine\DBAL\Platforms\Keywords\MySQLKeywords';
}
/**
* Get SQL to safely drop a temporary table WITHOUT implicitly committing an open transaction.
*
* MySQL commits a transaction implicitly when DROP TABLE is executed, however not
* if DROP TEMPORARY TABLE is executed.
*
* @throws \InvalidArgumentException
* @param $table
* @return string
*/
public function getDropTemporaryTableSQL($table)
{
if ($table instanceof \Doctrine\DBAL\Schema\Table) {
$table = $table->getQuotedName($this);
} else if(!is_string($table)) {
throw new \InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.');
}
return 'DROP TEMPORARY TABLE ' . $table;
}
/**
* Gets the SQL Snippet used to declare a BLOB column type.
*/
public function getBlobTypeDeclarationSQL(array $field)
{
return 'LONGBLOB';
}
}

View File

@@ -0,0 +1,840 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms;
use Doctrine\DBAL\Schema\TableDiff;
/**
* OraclePlatform.
*
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class OraclePlatform extends AbstractPlatform
{
/**
* return string to call a function to get a substring inside an SQL statement
*
* Note: Not SQL92, but common functionality.
*
* @param string $value an sql string literal or column name/alias
* @param integer $position where to start the substring portion
* @param integer $length the substring portion length
* @return string SQL substring function with given parameters
* @override
*/
public function getSubstringExpression($value, $position, $length = null)
{
if ($length !== null) {
return "SUBSTR($value, $position, $length)";
}
return "SUBSTR($value, $position)";
}
/**
* Return string to call a variable with the current timestamp inside an SQL statement
* There are three special variables for current date and time:
* - CURRENT_TIMESTAMP (date and time, TIMESTAMP type)
* - CURRENT_DATE (date, DATE type)
* - CURRENT_TIME (time, TIME type)
*
* @return string to call a variable with the current timestamp
* @override
*/
public function getNowExpression($type = 'timestamp')
{
switch ($type) {
case 'date':
case 'time':
case 'timestamp':
default:
return 'TO_CHAR(CURRENT_TIMESTAMP, \'YYYY-MM-DD HH24:MI:SS\')';
}
}
/**
* returns the position of the first occurrence of substring $substr in string $str
*
* @param string $substr literal string to find
* @param string $str literal string
* @param int $pos position to start at, beginning of string by default
* @return integer
*/
public function getLocateExpression($str, $substr, $startPos = false)
{
if ($startPos == false) {
return 'INSTR('.$str.', '.$substr.')';
} else {
return 'INSTR('.$str.', '.$substr.', '.$startPos.')';
}
}
/**
* Returns global unique identifier
*
* @return string to get global unique identifier
* @override
*/
public function getGuidExpression()
{
return 'SYS_GUID()';
}
/**
* Get the number of days difference between two dates.
*
* Note: Since Oracle timestamp differences are calculated down to the microsecond we have to truncate
* them to the difference in days. This is obviously a restriction of the original functionality, but we
* need to make this a portable function.
*
* @param type $date1
* @param type $date2
* @return type
*/
public function getDateDiffExpression($date1, $date2)
{
return "TRUNC(TO_NUMBER(SUBSTR((" . $date1 . "-" . $date2 . "), 1, INSTR(" . $date1 . "-" . $date2 .", ' '))))";
}
/**
* {@inheritdoc}
*/
public function getDateAddDaysExpression($date, $days)
{
return '(' . $date . '+' . $days . ')';
}
/**
* {@inheritdoc}
*/
public function getDateSubDaysExpression($date, $days)
{
return '(' . $date . '-' . $days . ')';
}
/**
* {@inheritdoc}
*/
public function getDateAddMonthExpression($date, $months)
{
return "ADD_MONTHS(" . $date . ", " . $months . ")";
}
/**
* {@inheritdoc}
*/
public function getDateSubMonthExpression($date, $months)
{
return "ADD_MONTHS(" . $date . ", -" . $months . ")";
}
/**
* {@inheritdoc}
*/
public function getBitAndComparisonExpression($value1, $value2)
{
return 'BITAND('.$value1 . ', ' . $value2 . ')';
}
/**
* {@inheritdoc}
*/
public function getBitOrComparisonExpression($value1, $value2)
{
return '(' . $value1 . '-' .
$this->getBitAndComparisonExpression($value1, $value2)
. '+' . $value2 . ')';
}
/**
* Gets the SQL used to create a sequence that starts with a given value
* and increments by the given allocation size.
*
* Need to specifiy minvalue, since start with is hidden in the system and MINVALUE <= START WITH.
* Therefore we can use MINVALUE to be able to get a hint what START WITH was for later introspection
* in {@see listSequences()}
*
* @param \Doctrine\DBAL\Schema\Sequence $sequence
* @return string
*/
public function getCreateSequenceSQL(\Doctrine\DBAL\Schema\Sequence $sequence)
{
return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) .
' START WITH ' . $sequence->getInitialValue() .
' MINVALUE ' . $sequence->getInitialValue() .
' INCREMENT BY ' . $sequence->getAllocationSize();
}
public function getAlterSequenceSQL(\Doctrine\DBAL\Schema\Sequence $sequence)
{
return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) .
' INCREMENT BY ' . $sequence->getAllocationSize();
}
/**
* {@inheritdoc}
*
* @param string $sequenceName
* @override
*/
public function getSequenceNextValSQL($sequenceName)
{
return 'SELECT ' . $sequenceName . '.nextval FROM DUAL';
}
/**
* {@inheritdoc}
*
* @param integer $level
* @override
*/
public function getSetTransactionIsolationSQL($level)
{
return 'SET TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level);
}
protected function _getTransactionIsolationLevelSQL($level)
{
switch ($level) {
case \Doctrine\DBAL\Connection::TRANSACTION_READ_UNCOMMITTED:
return 'READ UNCOMMITTED';
case \Doctrine\DBAL\Connection::TRANSACTION_READ_COMMITTED:
return 'READ COMMITTED';
case \Doctrine\DBAL\Connection::TRANSACTION_REPEATABLE_READ:
case \Doctrine\DBAL\Connection::TRANSACTION_SERIALIZABLE:
return 'SERIALIZABLE';
default:
return parent::_getTransactionIsolationLevelSQL($level);
}
}
/**
* @override
*/
public function getBooleanTypeDeclarationSQL(array $field)
{
return 'NUMBER(1)';
}
/**
* @override
*/
public function getIntegerTypeDeclarationSQL(array $field)
{
return 'NUMBER(10)';
}
/**
* @override
*/
public function getBigIntTypeDeclarationSQL(array $field)
{
return 'NUMBER(20)';
}
/**
* @override
*/
public function getSmallIntTypeDeclarationSQL(array $field)
{
return 'NUMBER(5)';
}
/**
* @override
*/
public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIMESTAMP(0)';
}
/**
* @override
*/
public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIMESTAMP(0) WITH TIME ZONE';
}
/**
* @override
*/
public function getDateTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATE';
}
/**
* @override
*/
public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATE';
}
/**
* @override
*/
protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef)
{
return '';
}
/**
* Gets the SQL snippet used to declare a VARCHAR column on the Oracle platform.
*
* @params array $field
* @override
*/
protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed)
{
return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(2000)')
: ($length ? 'VARCHAR2(' . $length . ')' : 'VARCHAR2(4000)');
}
/** @override */
public function getClobTypeDeclarationSQL(array $field)
{
return 'CLOB';
}
public function getListDatabasesSQL()
{
return 'SELECT username FROM all_users';
}
public function getListSequencesSQL($database)
{
return "SELECT sequence_name, min_value, increment_by FROM sys.all_sequences ".
"WHERE SEQUENCE_OWNER = '".strtoupper($database)."'";
}
/**
*
* @param string $table
* @param array $columns
* @param array $options
* @return array
*/
protected function _getCreateTableSQL($table, array $columns, array $options = array())
{
$indexes = isset($options['indexes']) ? $options['indexes'] : array();
$options['indexes'] = array();
$sql = parent::_getCreateTableSQL($table, $columns, $options);
foreach ($columns as $name => $column) {
if (isset($column['sequence'])) {
$sql[] = $this->getCreateSequenceSQL($column['sequence'], 1);
}
if (isset($column['autoincrement']) && $column['autoincrement'] ||
(isset($column['autoinc']) && $column['autoinc'])) {
$sql = array_merge($sql, $this->getCreateAutoincrementSql($name, $table));
}
}
if (isset($indexes) && ! empty($indexes)) {
foreach ($indexes as $indexName => $index) {
$sql[] = $this->getCreateIndexSQL($index, $table);
}
}
return $sql;
}
/**
* @license New BSD License
* @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaOracleReader.html
* @param string $table
* @return string
*/
public function getListTableIndexesSQL($table, $currentDatabase = null)
{
$table = strtoupper($table);
return "SELECT uind.index_name AS name, " .
" uind.index_type AS type, " .
" decode( uind.uniqueness, 'NONUNIQUE', 0, 'UNIQUE', 1 ) AS is_unique, " .
" uind_col.column_name AS column_name, " .
" uind_col.column_position AS column_pos, " .
" (SELECT ucon.constraint_type FROM user_constraints ucon WHERE ucon.constraint_name = uind.index_name) AS is_primary ".
"FROM user_indexes uind, user_ind_columns uind_col " .
"WHERE uind.index_name = uind_col.index_name AND uind_col.table_name = '$table' ORDER BY uind_col.column_position ASC";
}
public function getListTablesSQL()
{
return 'SELECT * FROM sys.user_tables';
}
public function getListViewsSQL($database)
{
return 'SELECT view_name, text FROM sys.user_views';
}
public function getCreateViewSQL($name, $sql)
{
return 'CREATE VIEW ' . $name . ' AS ' . $sql;
}
public function getDropViewSQL($name)
{
return 'DROP VIEW '. $name;
}
public function getCreateAutoincrementSql($name, $table, $start = 1)
{
$table = strtoupper($table);
$sql = array();
$indexName = $table . '_AI_PK';
$definition = array(
'primary' => true,
'columns' => array($name => true),
);
$idx = new \Doctrine\DBAL\Schema\Index($indexName, array($name), true, true);
$sql[] = 'DECLARE
constraints_Count NUMBER;
BEGIN
SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = \''.$table.'\' AND CONSTRAINT_TYPE = \'P\';
IF constraints_Count = 0 OR constraints_Count = \'\' THEN
EXECUTE IMMEDIATE \''.$this->getCreateConstraintSQL($idx, $table).'\';
END IF;
END;';
$sequenceName = $table . '_SEQ';
$sequence = new \Doctrine\DBAL\Schema\Sequence($sequenceName, $start);
$sql[] = $this->getCreateSequenceSQL($sequence);
$triggerName = $table . '_AI_PK';
$sql[] = 'CREATE TRIGGER ' . $triggerName . '
BEFORE INSERT
ON ' . $table . '
FOR EACH ROW
DECLARE
last_Sequence NUMBER;
last_InsertID NUMBER;
BEGIN
SELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $name . ' FROM DUAL;
IF (:NEW.' . $name . ' IS NULL OR :NEW.'.$name.' = 0) THEN
SELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $name . ' FROM DUAL;
ELSE
SELECT NVL(Last_Number, 0) INTO last_Sequence
FROM User_Sequences
WHERE Sequence_Name = \'' . $sequenceName . '\';
SELECT :NEW.' . $name . ' INTO last_InsertID FROM DUAL;
WHILE (last_InsertID > last_Sequence) LOOP
SELECT ' . $sequenceName . '.NEXTVAL INTO last_Sequence FROM DUAL;
END LOOP;
END IF;
END;';
return $sql;
}
public function getDropAutoincrementSql($table)
{
$table = strtoupper($table);
$trigger = $table . '_AI_PK';
if ($trigger) {
$sql[] = 'DROP TRIGGER ' . $trigger;
$sql[] = $this->getDropSequenceSQL($table.'_SEQ');
$indexName = $table . '_AI_PK';
$sql[] = $this->getDropConstraintSQL($indexName, $table);
}
return $sql;
}
public function getListTableForeignKeysSQL($table)
{
$table = strtoupper($table);
return "SELECT alc.constraint_name,
alc.DELETE_RULE,
alc.search_condition,
cols.column_name \"local_column\",
cols.position,
r_alc.table_name \"references_table\",
r_cols.column_name \"foreign_column\"
FROM user_cons_columns cols
LEFT JOIN user_constraints alc
ON alc.constraint_name = cols.constraint_name
LEFT JOIN user_constraints r_alc
ON alc.r_constraint_name = r_alc.constraint_name
LEFT JOIN user_cons_columns r_cols
ON r_alc.constraint_name = r_cols.constraint_name
AND cols.position = r_cols.position
WHERE alc.constraint_name = cols.constraint_name
AND alc.constraint_type = 'R'
AND alc.table_name = '".$table."'";
}
public function getListTableConstraintsSQL($table)
{
$table = strtoupper($table);
return 'SELECT * FROM user_constraints WHERE table_name = \'' . $table . '\'';
}
public function getListTableColumnsSQL($table, $database = null)
{
$table = strtoupper($table);
$tabColumnsTableName = "user_tab_columns";
$ownerCondition = '';
if(null !== $database){
$database = strtoupper($database);
$tabColumnsTableName = "all_tab_columns";
$ownerCondition = "AND c.owner = '".$database."'";
}
return "SELECT c.*, d.comments FROM $tabColumnsTableName c ".
"INNER JOIN user_col_comments d ON d.TABLE_NAME = c.TABLE_NAME AND d.COLUMN_NAME = c.COLUMN_NAME ".
"WHERE c.table_name = '" . $table . "' ".$ownerCondition." ORDER BY c.column_name";
}
/**
*
* @param \Doctrine\DBAL\Schema\Sequence $sequence
* @return string
*/
public function getDropSequenceSQL($sequence)
{
if ($sequence instanceof \Doctrine\DBAL\Schema\Sequence) {
$sequence = $sequence->getQuotedName($this);
}
return 'DROP SEQUENCE ' . $sequence;
}
/**
* @param ForeignKeyConstraint|string $foreignKey
* @param Table|string $table
* @return string
*/
public function getDropForeignKeySQL($foreignKey, $table)
{
if ($foreignKey instanceof \Doctrine\DBAL\Schema\ForeignKeyConstraint) {
$foreignKey = $foreignKey->getQuotedName($this);
}
if ($table instanceof \Doctrine\DBAL\Schema\Table) {
$table = $table->getQuotedName($this);
}
return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $foreignKey;
}
public function getDropDatabaseSQL($database)
{
return 'DROP USER ' . $database . ' CASCADE';
}
/**
* Gets the sql statements for altering an existing table.
*
* The method returns an array of sql statements, since some platforms need several statements.
*
* @param string $diff->name name of the table that is intended to be changed.
* @param array $changes associative array that contains the details of each type *
* @param boolean $check indicates whether the function should just check if the DBMS driver
* can perform the requested table alterations if the value is true or
* actually perform them otherwise.
* @return array
*/
public function getAlterTableSQL(TableDiff $diff)
{
$sql = array();
$commentsSQL = array();
$columnSql = array();
$fields = array();
foreach ($diff->addedColumns AS $column) {
if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) {
continue;
}
$fields[] = $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray());
if ($comment = $this->getColumnComment($column)) {
$commentsSQL[] = $this->getCommentOnColumnSQL($diff->name, $column->getName(), $comment);
}
}
if (count($fields)) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' ADD (' . implode(', ', $fields) . ')';
}
$fields = array();
foreach ($diff->changedColumns AS $columnDiff) {
if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) {
continue;
}
$column = $columnDiff->column;
$fields[] = $column->getQuotedName($this). ' ' . $this->getColumnDeclarationSQL('', $column->toArray());
if ($columnDiff->hasChanged('comment') && $comment = $this->getColumnComment($column)) {
$commentsSQL[] = $this->getCommentOnColumnSQL($diff->name, $column->getName(), $comment);
}
}
if (count($fields)) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' MODIFY (' . implode(', ', $fields) . ')';
}
foreach ($diff->renamedColumns AS $oldColumnName => $column) {
if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) {
continue;
}
$sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME COLUMN ' . $oldColumnName .' TO ' . $column->getQuotedName($this);
}
$fields = array();
foreach ($diff->removedColumns AS $column) {
if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) {
continue;
}
$fields[] = $column->getQuotedName($this);
}
if (count($fields)) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' DROP (' . implode(', ', $fields).')';
}
$tableSql = array();
if (!$this->onSchemaAlterTable($diff, $tableSql)) {
if ($diff->newName !== false) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME TO ' . $diff->newName;
}
$sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff), $commentsSQL);
}
return array_merge($sql, $tableSql, $columnSql);
}
/**
* Whether the platform prefers sequences for ID generation.
*
* @return boolean
*/
public function prefersSequences()
{
return true;
}
public function supportsCommentOnStatement()
{
return true;
}
/**
* Get the platform name for this instance
*
* @return string
*/
public function getName()
{
return 'oracle';
}
/**
* Adds an driver-specific LIMIT clause to the query
*
* @param string $query query to modify
* @param integer $limit limit the number of rows
* @param integer $offset start reading from given offset
* @return string the modified query
*/
protected function doModifyLimitQuery($query, $limit, $offset = null)
{
$limit = (int) $limit;
$offset = (int) $offset;
if (preg_match('/^\s*SELECT/i', $query)) {
if (!preg_match('/\sFROM\s/i', $query)) {
$query .= " FROM dual";
}
if ($limit > 0) {
$max = $offset + $limit;
$column = '*';
if ($offset > 0) {
$min = $offset + 1;
$query = 'SELECT * FROM (SELECT a.' . $column . ', rownum AS doctrine_rownum FROM (' .
$query .
') a WHERE rownum <= ' . $max . ') WHERE doctrine_rownum >= ' . $min;
} else {
$query = 'SELECT a.' . $column . ' FROM (' . $query . ') a WHERE ROWNUM <= ' . $max;
}
}
}
return $query;
}
/**
* Gets the character casing of a column in an SQL result set of this platform.
*
* Oracle returns all column names in SQL result sets in uppercase.
*
* @param string $column The column name for which to get the correct character casing.
* @return string The column name in the character casing used in SQL result sets.
*/
public function getSQLResultCasing($column)
{
return strtoupper($column);
}
public function getCreateTemporaryTableSnippetSQL()
{
return "CREATE GLOBAL TEMPORARY TABLE";
}
public function getDateTimeTzFormatString()
{
return 'Y-m-d H:i:sP';
}
public function getDateFormatString()
{
return 'Y-m-d 00:00:00';
}
public function getTimeFormatString()
{
return '1900-01-01 H:i:s';
}
public function fixSchemaElementName($schemaElementName)
{
if (strlen($schemaElementName) > 30) {
// Trim it
return substr($schemaElementName, 0, 30);
}
return $schemaElementName;
}
/**
* Maximum length of any given databse identifier, like tables or column names.
*
* @return int
*/
public function getMaxIdentifierLength()
{
return 30;
}
/**
* Whether the platform supports sequences.
*
* @return boolean
*/
public function supportsSequences()
{
return true;
}
public function supportsForeignKeyOnUpdate()
{
return false;
}
/**
* Whether the platform supports releasing savepoints.
*
* @return boolean
*/
public function supportsReleaseSavepoints()
{
return false;
}
/**
* @inheritdoc
*/
public function getTruncateTableSQL($tableName, $cascade = false)
{
return 'TRUNCATE TABLE '.$tableName;
}
/**
* This is for test reasons, many vendors have special requirements for dummy statements.
*
* @return string
*/
public function getDummySelectSQL()
{
return 'SELECT 1 FROM DUAL';
}
protected function initializeDoctrineTypeMappings()
{
$this->doctrineTypeMapping = array(
'integer' => 'integer',
'number' => 'integer',
'pls_integer' => 'boolean',
'binary_integer' => 'boolean',
'varchar' => 'string',
'varchar2' => 'string',
'nvarchar2' => 'string',
'char' => 'string',
'nchar' => 'string',
'date' => 'datetime',
'timestamp' => 'datetime',
'timestamptz' => 'datetimetz',
'float' => 'float',
'long' => 'string',
'clob' => 'text',
'nclob' => 'text',
'raw' => 'text',
'long raw' => 'text',
'rowid' => 'string',
'urowid' => 'string',
'blob' => 'blob',
);
}
/**
* Generate SQL to release a savepoint
*
* @param string $savepoint
* @return string
*/
public function releaseSavePoint($savepoint)
{
return '';
}
protected function getReservedKeywordsClass()
{
return 'Doctrine\DBAL\Platforms\Keywords\OracleKeywords';
}
/**
* Gets the SQL Snippet used to declare a BLOB column type.
*/
public function getBlobTypeDeclarationSQL(array $field)
{
return 'BLOB';
}
}

View File

@@ -0,0 +1,792 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms;
use Doctrine\DBAL\Schema\TableDiff,
Doctrine\DBAL\Schema\Table;
/**
* PostgreSqlPlatform.
*
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @todo Rename: PostgreSQLPlatform
*/
class PostgreSqlPlatform extends AbstractPlatform
{
/**
* 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.
* @override
*/
public function getSubstringExpression($value, $from, $len = null)
{
if ($len === null) {
return 'SUBSTR(' . $value . ', ' . $from . ')';
} else {
return 'SUBSTR(' . $value . ', ' . $from . ', ' . $len . ')';
}
}
/**
* Returns the SQL string to return the current system date and time.
*
* @return string
*/
public function getNowExpression()
{
return 'LOCALTIMESTAMP(0)';
}
/**
* regexp
*
* @return string the regular expression operator
* @override
*/
public function getRegexpExpression()
{
return 'SIMILAR TO';
}
/**
* returns the position of the first occurrence of substring $substr in string $str
*
* @param string $substr literal string to find
* @param string $str literal string
* @param int $pos position to start at, beginning of string by default
* @return integer
*/
public function getLocateExpression($str, $substr, $startPos = false)
{
if ($startPos !== false) {
$str = $this->getSubstringExpression($str, $startPos);
return 'CASE WHEN (POSITION('.$substr.' IN '.$str.') = 0) THEN 0 ELSE (POSITION('.$substr.' IN '.$str.') + '.($startPos-1).') END';
} else {
return 'POSITION('.$substr.' IN '.$str.')';
}
}
public function getDateDiffExpression($date1, $date2)
{
return '(DATE(' . $date1 . ')-DATE(' . $date2 . '))';
}
public function getDateAddDaysExpression($date, $days)
{
return "(" . $date ." + (" . $days . " || ' day')::interval)";
}
public function getDateSubDaysExpression($date, $days)
{
return "(" . $date ." - (" . $days . " || ' day')::interval)";
}
public function getDateAddMonthExpression($date, $months)
{
return "(" . $date ." + (" . $months . " || ' month')::interval)";
}
public function getDateSubMonthExpression($date, $months)
{
return "(" . $date ." - (" . $months . " || ' month')::interval)";
}
/**
* parses a literal boolean value and returns
* proper sql equivalent
*
* @param string $value boolean value to be parsed
* @return string parsed boolean value
*/
/*public function parseBoolean($value)
{
return $value;
}*/
/**
* Whether the platform supports sequences.
* Postgres has native support for sequences.
*
* @return boolean
*/
public function supportsSequences()
{
return true;
}
/**
* Whether the platform supports database schemas.
*
* @return boolean
*/
public function supportsSchemas()
{
return true;
}
/**
* Whether the platform supports identity columns.
* Postgres supports these through the SERIAL keyword.
*
* @return boolean
*/
public function supportsIdentityColumns()
{
return true;
}
public function supportsCommentOnStatement()
{
return true;
}
/**
* Whether the platform prefers sequences for ID generation.
*
* @return boolean
*/
public function prefersSequences()
{
return true;
}
public function getListDatabasesSQL()
{
return 'SELECT datname FROM pg_database';
}
public function getListSequencesSQL($database)
{
return "SELECT
c.relname, n.nspname AS schemaname
FROM
pg_class c, pg_namespace n
WHERE relkind = 'S' AND n.oid = c.relnamespace AND
(n.nspname NOT LIKE 'pg_%' AND n.nspname != 'information_schema')";
}
public function getListTablesSQL()
{
return "SELECT tablename AS table_name, schemaname AS schema_name
FROM pg_tables WHERE schemaname NOT LIKE 'pg_%' AND schemaname != 'information_schema' AND tablename != 'geometry_columns' AND tablename != 'spatial_ref_sys'";
}
public function getListViewsSQL($database)
{
return 'SELECT viewname, definition FROM pg_views';
}
public function getListTableForeignKeysSQL($table, $database = null)
{
return "SELECT r.conname, pg_catalog.pg_get_constraintdef(r.oid, true) as condef
FROM pg_catalog.pg_constraint r
WHERE r.conrelid =
(
SELECT c.oid
FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n
WHERE " .$this->getTableWhereClause($table) ." AND n.oid = c.relnamespace
)
AND r.contype = 'f'";
}
public function getCreateViewSQL($name, $sql)
{
return 'CREATE VIEW ' . $name . ' AS ' . $sql;
}
public function getDropViewSQL($name)
{
return 'DROP VIEW '. $name;
}
public function getListTableConstraintsSQL($table)
{
return "SELECT
relname
FROM
pg_class
WHERE oid IN (
SELECT indexrelid
FROM pg_index, pg_class
WHERE pg_class.relname = '$table'
AND pg_class.oid = pg_index.indrelid
AND (indisunique = 't' OR indisprimary = 't')
)";
}
/**
* @license New BSD License
* @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html
* @param string $table
* @return string
*/
public function getListTableIndexesSQL($table, $currentDatabase = null)
{
return "SELECT relname, pg_index.indisunique, pg_index.indisprimary,
pg_index.indkey, pg_index.indrelid
FROM pg_class, pg_index
WHERE oid IN (
SELECT indexrelid
FROM pg_index si, pg_class sc, pg_namespace sn
WHERE " . $this->getTableWhereClause($table, 'sc', 'sn')." AND sc.oid=si.indrelid AND sc.relnamespace = sn.oid
) AND pg_index.indexrelid = oid";
}
/**
* @param string $table
* @param string $classAlias
* @param string $namespaceAlias
* @return string
*/
private function getTableWhereClause($table, $classAlias = 'c', $namespaceAlias = 'n')
{
$whereClause = $namespaceAlias.".nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast') AND ";
if (strpos($table, ".") !== false) {
list($schema, $table) = explode(".", $table);
$schema = "'" . $schema . "'";
} else {
$schema = "ANY(string_to_array((select setting from pg_catalog.pg_settings where name = 'search_path'),','))";
}
$whereClause .= "$classAlias.relname = '" . $table . "' AND $namespaceAlias.nspname = $schema";
return $whereClause;
}
public function getListTableColumnsSQL($table, $database = null)
{
return "SELECT
a.attnum,
a.attname AS field,
t.typname AS type,
format_type(a.atttypid, a.atttypmod) AS complete_type,
(SELECT t1.typname FROM pg_catalog.pg_type t1 WHERE t1.oid = t.typbasetype) AS domain_type,
(SELECT format_type(t2.typbasetype, t2.typtypmod) FROM pg_catalog.pg_type t2
WHERE t2.typtype = 'd' AND t2.typname = format_type(a.atttypid, a.atttypmod)) AS domain_complete_type,
a.attnotnull AS isnotnull,
(SELECT 't'
FROM pg_index
WHERE c.oid = pg_index.indrelid
AND pg_index.indkey[0] = a.attnum
AND pg_index.indisprimary = 't'
) AS pri,
(SELECT pg_attrdef.adsrc
FROM pg_attrdef
WHERE c.oid = pg_attrdef.adrelid
AND pg_attrdef.adnum=a.attnum
) AS default,
(SELECT pg_description.description
FROM pg_description WHERE pg_description.objoid = c.oid AND a.attnum = pg_description.objsubid
) AS comment
FROM pg_attribute a, pg_class c, pg_type t, pg_namespace n
WHERE ".$this->getTableWhereClause($table, 'c', 'n') ."
AND a.attnum > 0
AND a.attrelid = c.oid
AND a.atttypid = t.oid
AND n.oid = c.relnamespace
ORDER BY a.attnum";
}
/**
* create a new database
*
* @param string $name name of the database that should be created
* @throws PDOException
* @return void
* @override
*/
public function getCreateDatabaseSQL($name)
{
return 'CREATE DATABASE ' . $name;
}
/**
* drop an existing database
*
* @param string $name name of the database that should be dropped
* @throws PDOException
* @access public
*/
public function getDropDatabaseSQL($name)
{
return 'DROP DATABASE ' . $name;
}
/**
* Return the FOREIGN KEY query section dealing with non-standard options
* as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
*
* @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey foreign key definition
* @return string
* @override
*/
public function getAdvancedForeignKeyOptionsSQL(\Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey)
{
$query = '';
if ($foreignKey->hasOption('match')) {
$query .= ' MATCH ' . $foreignKey->getOption('match');
}
$query .= parent::getAdvancedForeignKeyOptionsSQL($foreignKey);
if ($foreignKey->hasOption('deferrable') && $foreignKey->getOption('deferrable') !== false) {
$query .= ' DEFERRABLE';
} else {
$query .= ' NOT DEFERRABLE';
}
if ($foreignKey->hasOption('feferred') && $foreignKey->getOption('feferred') !== false) {
$query .= ' INITIALLY DEFERRED';
} else {
$query .= ' INITIALLY IMMEDIATE';
}
return $query;
}
/**
* generates the sql for altering an existing table on postgresql
*
* @param string $name name of the table that is intended to be changed.
* @param array $changes associative array that contains the details of each type *
* @param boolean $check indicates whether the function should just check if the DBMS driver
* can perform the requested table alterations if the value is true or
* actually perform them otherwise.
* @see Doctrine_Export::alterTable()
* @return array
* @override
*/
public function getAlterTableSQL(TableDiff $diff)
{
$sql = array();
$commentsSQL = array();
$columnSql = array();
foreach ($diff->addedColumns as $column) {
if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) {
continue;
}
$query = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray());
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query;
if ($comment = $this->getColumnComment($column)) {
$commentsSQL[] = $this->getCommentOnColumnSQL($diff->name, $column->getName(), $comment);
}
}
foreach ($diff->removedColumns as $column) {
if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) {
continue;
}
$query = 'DROP ' . $column->getQuotedName($this);
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query;
}
foreach ($diff->changedColumns AS $columnDiff) {
if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) {
continue;
}
$oldColumnName = $columnDiff->oldColumnName;
$column = $columnDiff->column;
if ($columnDiff->hasChanged('type')) {
$type = $column->getType();
// here was a server version check before, but DBAL API does not support this anymore.
$query = 'ALTER ' . $oldColumnName . ' TYPE ' . $type->getSqlDeclaration($column->toArray(), $this);
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query;
}
if ($columnDiff->hasChanged('default')) {
$query = 'ALTER ' . $oldColumnName . ' SET ' . $this->getDefaultValueDeclarationSQL($column->toArray());
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query;
}
if ($columnDiff->hasChanged('notnull')) {
$query = 'ALTER ' . $oldColumnName . ' ' . ($column->getNotNull() ? 'SET' : 'DROP') . ' NOT NULL';
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query;
}
if ($columnDiff->hasChanged('autoincrement')) {
if ($column->getAutoincrement()) {
// add autoincrement
$seqName = $diff->name . '_' . $oldColumnName . '_seq';
$sql[] = "CREATE SEQUENCE " . $seqName;
$sql[] = "SELECT setval('" . $seqName . "', (SELECT MAX(" . $oldColumnName . ") FROM " . $diff->name . "))";
$query = "ALTER " . $oldColumnName . " SET DEFAULT nextval('" . $seqName . "')";
$sql[] = "ALTER TABLE " . $diff->name . " " . $query;
} else {
// Drop autoincrement, but do NOT drop the sequence. It might be re-used by other tables or have
$query = "ALTER " . $oldColumnName . " " . "DROP DEFAULT";
$sql[] = "ALTER TABLE " . $diff->name . " " . $query;
}
}
if ($columnDiff->hasChanged('comment') && $comment = $this->getColumnComment($column)) {
$commentsSQL[] = $this->getCommentOnColumnSQL($diff->name, $column->getName(), $comment);
}
}
foreach ($diff->renamedColumns as $oldColumnName => $column) {
if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) {
continue;
}
$sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME COLUMN ' . $oldColumnName . ' TO ' . $column->getQuotedName($this);
}
$tableSql = array();
if (!$this->onSchemaAlterTable($diff, $tableSql)) {
if ($diff->newName !== false) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME TO ' . $diff->newName;
}
$sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff), $commentsSQL);
}
return array_merge($sql, $tableSql, $columnSql);
}
/**
* Gets the SQL to create a sequence on this platform.
*
* @param \Doctrine\DBAL\Schema\Sequence $sequence
* @return string
*/
public function getCreateSequenceSQL(\Doctrine\DBAL\Schema\Sequence $sequence)
{
return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) .
' INCREMENT BY ' . $sequence->getAllocationSize() .
' MINVALUE ' . $sequence->getInitialValue() .
' START ' . $sequence->getInitialValue();
}
public function getAlterSequenceSQL(\Doctrine\DBAL\Schema\Sequence $sequence)
{
return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) .
' INCREMENT BY ' . $sequence->getAllocationSize();
}
/**
* Drop existing sequence
* @param \Doctrine\DBAL\Schema\Sequence $sequence
* @return string
*/
public function getDropSequenceSQL($sequence)
{
if ($sequence instanceof \Doctrine\DBAL\Schema\Sequence) {
$sequence = $sequence->getQuotedName($this);
}
return 'DROP SEQUENCE ' . $sequence;
}
/**
* @param ForeignKeyConstraint|string $foreignKey
* @param Table|string $table
* @return string
*/
public function getDropForeignKeySQL($foreignKey, $table)
{
return $this->getDropConstraintSQL($foreignKey, $table);
}
/**
* Gets the SQL used to create a table.
*
* @param unknown_type $tableName
* @param array $columns
* @param array $options
* @return unknown
*/
protected function _getCreateTableSQL($tableName, array $columns, array $options = array())
{
$queryFields = $this->getColumnDeclarationListSQL($columns);
if (isset($options['primary']) && ! empty($options['primary'])) {
$keyColumns = array_unique(array_values($options['primary']));
$queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')';
}
$query = 'CREATE TABLE ' . $tableName . ' (' . $queryFields . ')';
$sql[] = $query;
if (isset($options['indexes']) && ! empty($options['indexes'])) {
foreach ($options['indexes'] AS $index) {
$sql[] = $this->getCreateIndexSQL($index, $tableName);
}
}
if (isset($options['foreignKeys'])) {
foreach ((array) $options['foreignKeys'] as $definition) {
$sql[] = $this->getCreateForeignKeySQL($definition, $tableName);
}
}
return $sql;
}
/**
* Postgres wants boolean values converted to the strings 'true'/'false'.
*
* @param array $item
* @override
*/
public function convertBooleans($item)
{
if (is_array($item)) {
foreach ($item as $key => $value) {
if (is_bool($value) || is_numeric($item)) {
$item[$key] = ($value) ? 'true' : 'false';
}
}
} else {
if (is_bool($item) || is_numeric($item)) {
$item = ($item) ? 'true' : 'false';
}
}
return $item;
}
public function getSequenceNextValSQL($sequenceName)
{
return "SELECT NEXTVAL('" . $sequenceName . "')";
}
public function getSetTransactionIsolationSQL($level)
{
return 'SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL '
. $this->_getTransactionIsolationLevelSQL($level);
}
/**
* @override
*/
public function getBooleanTypeDeclarationSQL(array $field)
{
return 'BOOLEAN';
}
/**
* @override
*/
public function getIntegerTypeDeclarationSQL(array $field)
{
if ( ! empty($field['autoincrement'])) {
return 'SERIAL';
}
return 'INT';
}
/**
* @override
*/
public function getBigIntTypeDeclarationSQL(array $field)
{
if ( ! empty($field['autoincrement'])) {
return 'BIGSERIAL';
}
return 'BIGINT';
}
/**
* @override
*/
public function getSmallIntTypeDeclarationSQL(array $field)
{
return 'SMALLINT';
}
/**
* @override
*/
public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIMESTAMP(0) WITHOUT TIME ZONE';
}
/**
* @override
*/
public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIMESTAMP(0) WITH TIME ZONE';
}
/**
* @override
*/
public function getDateTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATE';
}
/**
* @override
*/
public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIME(0) WITHOUT TIME ZONE';
}
/**
* @override
*/
protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef)
{
return '';
}
/**
* Gets the SQL snippet used to declare a VARCHAR column on the MySql platform.
*
* @params array $field
* @override
*/
protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed)
{
return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)')
: ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)');
}
/** @override */
public function getClobTypeDeclarationSQL(array $field)
{
return 'TEXT';
}
/**
* Get the platform name for this instance
*
* @return string
*/
public function getName()
{
return 'postgresql';
}
/**
* Gets the character casing of a column in an SQL result set.
*
* PostgreSQL returns all column names in SQL result sets in lowercase.
*
* @param string $column The column name for which to get the correct character casing.
* @return string The column name in the character casing used in SQL result sets.
*/
public function getSQLResultCasing($column)
{
return strtolower($column);
}
public function getDateTimeTzFormatString()
{
return 'Y-m-d H:i:sO';
}
/**
* Get the insert sql for an empty insert statement
*
* @param string $tableName
* @param string $identifierColumnName
* @return string $sql
*/
public function getEmptyIdentityInsertSQL($quotedTableName, $quotedIdentifierColumnName)
{
return 'INSERT INTO ' . $quotedTableName . ' (' . $quotedIdentifierColumnName . ') VALUES (DEFAULT)';
}
/**
* @inheritdoc
*/
public function getTruncateTableSQL($tableName, $cascade = false)
{
return 'TRUNCATE '.$tableName.' '.(($cascade)?'CASCADE':'');
}
public function getReadLockSQL()
{
return 'FOR SHARE';
}
protected function initializeDoctrineTypeMappings()
{
$this->doctrineTypeMapping = array(
'smallint' => 'smallint',
'int2' => 'smallint',
'serial' => 'integer',
'serial4' => 'integer',
'int' => 'integer',
'int4' => 'integer',
'integer' => 'integer',
'bigserial' => 'bigint',
'serial8' => 'bigint',
'bigint' => 'bigint',
'int8' => 'bigint',
'bool' => 'boolean',
'boolean' => 'boolean',
'text' => 'text',
'varchar' => 'string',
'interval' => 'string',
'_varchar' => 'string',
'char' => 'string',
'bpchar' => 'string',
'date' => 'date',
'datetime' => 'datetime',
'timestamp' => 'datetime',
'timestamptz' => 'datetimetz',
'time' => 'time',
'timetz' => 'time',
'float' => 'float',
'float4' => 'float',
'float8' => 'float',
'double' => 'float',
'double precision' => 'float',
'real' => 'float',
'decimal' => 'decimal',
'money' => 'decimal',
'numeric' => 'decimal',
'year' => 'date',
'bytea' => 'blob',
);
}
public function getVarcharMaxLength()
{
return 65535;
}
protected function getReservedKeywordsClass()
{
return 'Doctrine\DBAL\Platforms\Keywords\PostgreSQLKeywords';
}
/**
* Gets the SQL Snippet used to declare a BLOB column type.
*/
public function getBlobTypeDeclarationSQL(array $field)
{
return 'BYTEA';
}
}

View File

@@ -0,0 +1,52 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms;
/**
* Platform to ensure compatibility of Doctrine with SQLServer2005 version and
* higher.
*
* Differences to SQL Server 2008 are:
*
* - DATETIME2 datatype does not exist, only DATETIME which has a precision of
* 3. This is not supported by PHP DateTime, so we are emulating it by
* setting .000 manually.
* - Starting with SQLServer2005 VARCHAR(MAX), VARBINARY(MAX) and
* NVARCHAR(max) replace the old TEXT, NTEXT and IMAGE types. See
* {@link http://www.sql-server-helper.com/faq/sql-server-2005-varchar-max-p01.aspx}
* for more information.
*/
class SQLServer2005Platform extends SQLServerPlatform
{
/**
* @override
*/
public function supportsLimitOffset()
{
return true;
}
/** @override */
public function getClobTypeDeclarationSQL(array $field)
{
return 'VARCHAR(MAX)';
}
}

View File

@@ -0,0 +1,90 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms;
/**
* Platform to ensure compatibility of Doctrine with SQLServer2008 version.
*
* Differences to SQL Server 2005 and before are that a new DATETIME2 type was
* introduced that has a higher precision.
*/
class SQLServer2008Platform extends SQLServer2005Platform
{
/**
* @override
*/
public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
{
// 3 - microseconds precision length
// http://msdn.microsoft.com/en-us/library/ms187819.aspx
return 'DATETIME2(6)';
}
/**
* @override
*/
public function getDateTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATE';
}
/**
* @override
*/
public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIME(0)';
}
/**
* @override
*/
public function getDateTimeFormatString()
{
return 'Y-m-d H:i:s.u';
}
/**
* @override
*/
public function getDateFormatString()
{
return 'Y-m-d';
}
/**
* @override
*/
public function getTimeFormatString()
{
return 'H:i:s';
}
/**
* Adding Datetime2 Type
*/
protected function initializeDoctrineTypeMappings()
{
parent::initializeDoctrineTypeMappings();
$this->doctrineTypeMapping['datetime2'] = 'datetime';
$this->doctrineTypeMapping['date'] = 'date';
$this->doctrineTypeMapping['time'] = 'time';
}
}

View File

@@ -0,0 +1,865 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms;
use Doctrine\DBAL\Schema\TableDiff;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Schema\Index,
Doctrine\DBAL\Schema\Table;
/**
* The SQLServerPlatform provides the behavior, features and SQL dialect of the
* Microsoft SQL Server database platform.
*
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
* @author Jonathan H. Wage <jonwage@gmail.com>
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class SQLServerPlatform extends AbstractPlatform
{
/**
* {@inheritDoc}
*/
public function getDateDiffExpression($date1, $date2)
{
return 'DATEDIFF(day, ' . $date2 . ',' . $date1 . ')';
}
public function getDateAddDaysExpression($date, $days)
{
return 'DATEADD(day, ' . $days . ', ' . $date . ')';
}
public function getDateSubDaysExpression($date, $days)
{
return 'DATEADD(day, -1 * ' . $days . ', ' . $date . ')';
}
public function getDateAddMonthExpression($date, $months)
{
return 'DATEADD(month, ' . $months . ', ' . $date . ')';
}
public function getDateSubMonthExpression($date, $months)
{
return 'DATEADD(month, -1 * ' . $months . ', ' . $date . ')';
}
/**
* Whether the platform prefers identity columns for ID generation.
* MsSql prefers "autoincrement" identity columns since sequences can only
* be emulated with a table.
*
* @return boolean
* @override
*/
public function prefersIdentityColumns()
{
return true;
}
/**
* Whether the platform supports identity columns.
* MsSql supports this through AUTO_INCREMENT columns.
*
* @return boolean
* @override
*/
public function supportsIdentityColumns()
{
return true;
}
/**
* Whether the platform supports releasing savepoints.
*
* @return boolean
*/
public function supportsReleaseSavepoints()
{
return false;
}
/**
* create a new database
*
* @param string $name name of the database that should be created
* @return string
* @override
*/
public function getCreateDatabaseSQL($name)
{
return 'CREATE DATABASE ' . $name;
}
/**
* drop an existing database
*
* @param string $name name of the database that should be dropped
* @return string
* @override
*/
public function getDropDatabaseSQL($name)
{
return 'DROP DATABASE ' . $name;
}
/**
* @override
*/
public function supportsCreateDropDatabase()
{
return false;
}
/**
* @override
*/
public function getDropForeignKeySQL($foreignKey, $table)
{
if ($foreignKey instanceof \Doctrine\DBAL\Schema\ForeignKeyConstraint) {
$foreignKey = $foreignKey->getQuotedName($this);
}
if ($table instanceof \Doctrine\DBAL\Schema\Table) {
$table = $table->getQuotedName($this);
}
return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $foreignKey;
}
/**
* @override
*/
public function getDropIndexSQL($index, $table=null)
{
if ($index instanceof \Doctrine\DBAL\Schema\Index) {
$index_ = $index;
$index = $index->getQuotedName($this);
} else if (!is_string($index)) {
throw new \InvalidArgumentException('AbstractPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.');
}
if (!isset($table)) {
return 'DROP INDEX ' . $index;
} else {
if ($table instanceof \Doctrine\DBAL\Schema\Table) {
$table = $table->getQuotedName($this);
}
return "IF EXISTS (SELECT * FROM sysobjects WHERE name = '$index')
ALTER TABLE " . $table . " DROP CONSTRAINT " . $index . "
ELSE
DROP INDEX " . $index . " ON " . $table;
}
}
/**
* @override
*/
protected function _getCreateTableSQL($tableName, array $columns, array $options = array())
{
// @todo does other code breaks because of this?
// foce primary keys to be not null
foreach ($columns as &$column) {
if (isset($column['primary']) && $column['primary']) {
$column['notnull'] = true;
}
}
$columnListSql = $this->getColumnDeclarationListSQL($columns);
if (isset($options['uniqueConstraints']) && !empty($options['uniqueConstraints'])) {
foreach ($options['uniqueConstraints'] as $name => $definition) {
$columnListSql .= ', ' . $this->getUniqueConstraintDeclarationSQL($name, $definition);
}
}
if (isset($options['primary']) && !empty($options['primary'])) {
$columnListSql .= ', PRIMARY KEY(' . implode(', ', array_unique(array_values($options['primary']))) . ')';
}
$query = 'CREATE TABLE ' . $tableName . ' (' . $columnListSql;
$check = $this->getCheckDeclarationSQL($columns);
if (!empty($check)) {
$query .= ', ' . $check;
}
$query .= ')';
$sql[] = $query;
if (isset($options['indexes']) && !empty($options['indexes'])) {
foreach ($options['indexes'] AS $index) {
$sql[] = $this->getCreateIndexSQL($index, $tableName);
}
}
if (isset($options['foreignKeys'])) {
foreach ((array) $options['foreignKeys'] AS $definition) {
$sql[] = $this->getCreateForeignKeySQL($definition, $tableName);
}
}
return $sql;
}
/**
* @override
*/
public function getUniqueConstraintDeclarationSQL($name, Index $index)
{
$constraint = parent::getUniqueConstraintDeclarationSQL($name, $index);
$constraint = $this->_appendUniqueConstraintDefinition($constraint, $index);
return $constraint;
}
/**
* @override
*/
public function getCreateIndexSQL(Index $index, $table)
{
$constraint = parent::getCreateIndexSQL($index, $table);
if ($index->isUnique()) {
$constraint = $this->_appendUniqueConstraintDefinition($constraint, $index);
}
return $constraint;
}
/**
* Extend unique key constraint with required filters
*
* @param string $sql
* @param Index $index
* @return string
*/
private function _appendUniqueConstraintDefinition($sql, Index $index)
{
$fields = array();
foreach ($index->getColumns() as $field => $definition) {
if (!is_array($definition)) {
$field = $definition;
}
$fields[] = $field . ' IS NOT NULL';
}
return $sql . ' WHERE ' . implode(' AND ', $fields);
}
/**
* @override
*/
public function getAlterTableSQL(TableDiff $diff)
{
$queryParts = array();
$sql = array();
$columnSql = array();
if ($diff->newName !== false) {
$queryParts[] = 'RENAME TO ' . $diff->newName;
}
foreach ($diff->addedColumns AS $fieldName => $column) {
if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) {
continue;
}
$queryParts[] = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray());
}
foreach ($diff->removedColumns AS $column) {
if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) {
continue;
}
$queryParts[] = 'DROP COLUMN ' . $column->getQuotedName($this);
}
foreach ($diff->changedColumns AS $columnDiff) {
if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) {
continue;
}
/* @var $columnDiff Doctrine\DBAL\Schema\ColumnDiff */
$column = $columnDiff->column;
$queryParts[] = 'ALTER COLUMN ' .
$this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray());
}
foreach ($diff->renamedColumns AS $oldColumnName => $column) {
if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) {
continue;
}
$sql[] = "sp_RENAME '". $diff->name. ".". $oldColumnName . "' , '".$column->getQuotedName($this)."', 'COLUMN'";
$queryParts[] = 'ALTER COLUMN ' .
$this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray());
}
$tableSql = array();
if ($this->onSchemaAlterTable($diff, $tableSql)) {
return array_merge($tableSql, $columnSql);
}
foreach ($queryParts as $query) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query;
}
$sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff));
return array_merge($sql, $tableSql, $columnSql);
}
/**
* @override
*/
public function getEmptyIdentityInsertSQL($quotedTableName, $quotedIdentifierColumnName)
{
return 'INSERT INTO ' . $quotedTableName . ' DEFAULT VALUES';
}
/**
* @override
*/
public function getShowDatabasesSQL()
{
return 'SHOW DATABASES';
}
/**
* @override
*/
public function getListTablesSQL()
{
// "sysdiagrams" table must be ignored as it's internal SQL Server table for Database Diagrams
return "SELECT name FROM sysobjects WHERE type = 'U' AND name != 'sysdiagrams' ORDER BY name";
}
/**
* @override
*/
public function getListTableColumnsSQL($table, $database = null)
{
return "exec sp_columns @table_name = '" . $table . "'";
}
/**
* @override
*/
public function getListTableForeignKeysSQL($table, $database = null)
{
return "SELECT f.name AS ForeignKey,
SCHEMA_NAME (f.SCHEMA_ID) AS SchemaName,
OBJECT_NAME (f.parent_object_id) AS TableName,
COL_NAME (fc.parent_object_id,fc.parent_column_id) AS ColumnName,
SCHEMA_NAME (o.SCHEMA_ID) ReferenceSchemaName,
OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName,
COL_NAME(fc.referenced_object_id,fc.referenced_column_id) AS ReferenceColumnName,
f.delete_referential_action_desc,
f.update_referential_action_desc
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc
INNER JOIN sys.objects AS o ON o.OBJECT_ID = fc.referenced_object_id
ON f.OBJECT_ID = fc.constraint_object_id
WHERE OBJECT_NAME (f.parent_object_id) = '" . $table . "'";
}
/**
* @override
*/
public function getListTableIndexesSQL($table, $currentDatabase = null)
{
return "exec sp_helpindex '" . $table . "'";
}
/**
* @override
*/
public function getCreateViewSQL($name, $sql)
{
return 'CREATE VIEW ' . $name . ' AS ' . $sql;
}
/**
* @override
*/
public function getListViewsSQL($database)
{
return "SELECT name FROM sysobjects WHERE type = 'V' ORDER BY name";
}
/**
* @override
*/
public function getDropViewSQL($name)
{
return 'DROP VIEW ' . $name;
}
/**
* Returns the regular expression operator.
*
* @return string
* @override
*/
public function getRegexpExpression()
{
return 'RLIKE';
}
/**
* Returns global unique identifier
*
* @return string to get global unique identifier
* @override
*/
public function getGuidExpression()
{
return 'UUID()';
}
/**
* @override
*/
public function getLocateExpression($str, $substr, $startPos = false)
{
if ($startPos == false) {
return 'CHARINDEX(' . $substr . ', ' . $str . ')';
} else {
return 'CHARINDEX(' . $substr . ', ' . $str . ', ' . $startPos . ')';
}
}
/**
* @override
*/
public function getModExpression($expression1, $expression2)
{
return $expression1 . ' % ' . $expression2;
}
/**
* @override
*/
public function getTrimExpression($str, $pos = self::TRIM_UNSPECIFIED, $char = false)
{
$trimFn = '';
if (!$char) {
if ($pos == self::TRIM_LEADING) {
$trimFn = 'LTRIM';
} else if ($pos == self::TRIM_TRAILING) {
$trimFn = 'RTRIM';
} else {
return 'LTRIM(RTRIM(' . $str . '))';
}
return $trimFn . '(' . $str . ')';
} else {
/** Original query used to get those expressions
declare @c varchar(100) = 'xxxBarxxx', @trim_char char(1) = 'x';
declare @pat varchar(10) = '%[^' + @trim_char + ']%';
select @c as string
, @trim_char as trim_char
, stuff(@c, 1, patindex(@pat, @c) - 1, null) as trim_leading
, reverse(stuff(reverse(@c), 1, patindex(@pat, reverse(@c)) - 1, null)) as trim_trailing
, reverse(stuff(reverse(stuff(@c, 1, patindex(@pat, @c) - 1, null)), 1, patindex(@pat, reverse(stuff(@c, 1, patindex(@pat, @c) - 1, null))) - 1, null)) as trim_both;
*/
$pattern = "'%[^' + $char + ']%'";
if ($pos == self::TRIM_LEADING) {
return 'stuff(' . $str . ', 1, patindex(' . $pattern . ', ' . $str . ') - 1, null)';
} else if ($pos == self::TRIM_TRAILING) {
return 'reverse(stuff(reverse(' . $str . '), 1, patindex(' . $pattern . ', reverse(' . $str . ')) - 1, null))';
} else {
return 'reverse(stuff(reverse(stuff(' . $str . ', 1, patindex(' . $pattern . ', ' . $str . ') - 1, null)), 1, patindex(' . $pattern . ', reverse(stuff(' . $str . ', 1, patindex(' . $pattern . ', ' . $str . ') - 1, null))) - 1, null))';
}
}
}
/**
* @override
*/
public function getConcatExpression()
{
$args = func_get_args();
return '(' . implode(' + ', $args) . ')';
}
public function getListDatabasesSQL()
{
return 'SELECT * FROM SYS.DATABASES';
}
/**
* @override
*/
public function getSubstringExpression($value, $from, $len = null)
{
if (!is_null($len)) {
return 'SUBSTRING(' . $value . ', ' . $from . ', ' . $len . ')';
}
return 'SUBSTRING(' . $value . ', ' . $from . ', LEN(' . $value . ') - ' . $from . ' + 1)';
}
/**
* @override
*/
public function getLengthExpression($column)
{
return 'LEN(' . $column . ')';
}
/**
* @override
*/
public function getSetTransactionIsolationSQL($level)
{
return 'SET TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level);
}
/**
* @override
*/
public function getIntegerTypeDeclarationSQL(array $field)
{
return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/**
* @override
*/
public function getBigIntTypeDeclarationSQL(array $field)
{
return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/**
* @override
*/
public function getSmallIntTypeDeclarationSQL(array $field)
{
return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/** @override */
protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed)
{
return $fixed ? ($length ? 'NCHAR(' . $length . ')' : 'CHAR(255)') : ($length ? 'NVARCHAR(' . $length . ')' : 'NVARCHAR(255)');
}
/** @override */
public function getClobTypeDeclarationSQL(array $field)
{
return 'TEXT';
}
/**
* @override
*/
protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef)
{
$autoinc = '';
if (!empty($columnDef['autoincrement'])) {
$autoinc = ' IDENTITY';
}
$unsigned = (isset($columnDef['unsigned']) && $columnDef['unsigned']) ? ' UNSIGNED' : '';
return $unsigned . $autoinc;
}
/**
* @override
*/
public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATETIME';
}
/**
* @override
*/
public function getDateTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATETIME';
}
/**
* @override
*/
public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATETIME';
}
/**
* @override
*/
public function getBooleanTypeDeclarationSQL(array $field)
{
return 'BIT';
}
/**
* Adds an adapter-specific LIMIT clause to the SELECT statement.
*
* @param string $query
* @param integer $limit
* @param integer $offset
* @link http://lists.bestpractical.com/pipermail/rt-devel/2005-June/007339.html
* @return string
*/
protected function doModifyLimitQuery($query, $limit, $offset = null)
{
if ($limit > 0) {
if ($offset == 0) {
$query = preg_replace('/^(SELECT\s(DISTINCT\s)?)/i', '\1TOP ' . $limit . ' ', $query);
} else {
$orderby = stristr($query, 'ORDER BY');
if (!$orderby) {
$over = 'ORDER BY (SELECT 0)';
} else {
$over = preg_replace('/\"[^,]*\".\"([^,]*)\"/i', '"inner_tbl"."$1"', $orderby);
}
// Remove ORDER BY clause from $query
$query = preg_replace('/\s+ORDER BY(.*)/', '', $query);
$query = preg_replace('/^SELECT\s/', '', $query);
$start = $offset + 1;
$end = $offset + $limit;
$query = "SELECT * FROM (SELECT ROW_NUMBER() OVER ($over) AS \"doctrine_rownum\", $query) AS doctrine_tbl WHERE \"doctrine_rownum\" BETWEEN $start AND $end";
}
}
return $query;
}
/**
* @override
*/
public function supportsLimitOffset()
{
return false;
}
/**
* @override
*/
public function convertBooleans($item)
{
if (is_array($item)) {
foreach ($item as $key => $value) {
if (is_bool($value) || is_numeric($item)) {
$item[$key] = ($value) ? 1 : 0;
}
}
} else {
if (is_bool($item) || is_numeric($item)) {
$item = ($item) ? 1 : 0;
}
}
return $item;
}
/**
* @override
*/
public function getCreateTemporaryTableSnippetSQL()
{
return "CREATE TABLE";
}
/**
* @override
*/
public function getTemporaryTableName($tableName)
{
return '#' . $tableName;
}
/**
* @override
*/
public function getDateTimeFormatString()
{
return 'Y-m-d H:i:s.000';
}
/**
* @override
*/
public function getDateFormatString()
{
return 'Y-m-d H:i:s.000';
}
/**
* @override
*/
public function getTimeFormatString()
{
return 'Y-m-d H:i:s.000';
}
/**
* @override
*/
public function getDateTimeTzFormatString()
{
return $this->getDateTimeFormatString();
}
/**
* Get the platform name for this instance
*
* @return string
*/
public function getName()
{
return 'mssql';
}
/**
* @override
*/
protected function initializeDoctrineTypeMappings()
{
$this->doctrineTypeMapping = array(
'bigint' => 'bigint',
'numeric' => 'decimal',
'bit' => 'boolean',
'smallint' => 'smallint',
'decimal' => 'decimal',
'smallmoney' => 'integer',
'int' => 'integer',
'tinyint' => 'smallint',
'money' => 'integer',
'float' => 'float',
'real' => 'float',
'double' => 'float',
'double precision' => 'float',
'datetimeoffset' => 'datetimetz',
'smalldatetime' => 'datetime',
'datetime' => 'datetime',
'char' => 'string',
'varchar' => 'string',
'text' => 'text',
'nchar' => 'string',
'nvarchar' => 'string',
'ntext' => 'text',
'binary' => 'text',
'varbinary' => 'blob',
'image' => 'text',
);
}
/**
* Generate SQL to create a new savepoint
*
* @param string $savepoint
* @return string
*/
public function createSavePoint($savepoint)
{
return 'SAVE TRANSACTION ' . $savepoint;
}
/**
* Generate SQL to release a savepoint
*
* @param string $savepoint
* @return string
*/
public function releaseSavePoint($savepoint)
{
return '';
}
/**
* Generate SQL to rollback a savepoint
*
* @param string $savepoint
* @return string
*/
public function rollbackSavePoint($savepoint)
{
return 'ROLLBACK TRANSACTION ' . $savepoint;
}
/**
* @override
*/
public function appendLockHint($fromClause, $lockMode)
{
// @todo coorect
if ($lockMode == \Doctrine\DBAL\LockMode::PESSIMISTIC_READ) {
return $fromClause . ' WITH (tablockx)';
} else if ($lockMode == \Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE) {
return $fromClause . ' WITH (tablockx)';
} else {
return $fromClause;
}
}
/**
* @override
*/
public function getForUpdateSQL()
{
return ' ';
}
protected function getReservedKeywordsClass()
{
return 'Doctrine\DBAL\Platforms\Keywords\MsSQLKeywords';
}
/**
* {@inheritDoc}
*/
public function quoteSingleIdentifier($str)
{
return "[" . str_replace("]", "][", $str) . "]";
}
public function getTruncateTableSQL($tableName, $cascade = false)
{
return 'TRUNCATE TABLE '.$tableName;
}
/**
* Gets the SQL Snippet used to declare a BLOB column type.
*/
public function getBlobTypeDeclarationSQL(array $field)
{
return 'VARBINARY(MAX)';
}
}

View File

@@ -0,0 +1,519 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms;
use Doctrine\DBAL\DBALException;
/**
* The SqlitePlatform class describes the specifics and dialects of the SQLite
* database platform.
*
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @todo Rename: SQLitePlatform
*/
class SqlitePlatform extends AbstractPlatform
{
/**
* returns the regular expression operator
*
* @return string
* @override
*/
public function getRegexpExpression()
{
return 'RLIKE';
}
/**
* Return string to call a variable with the current timestamp inside an SQL statement
* There are three special variables for current date and time.
*
* @return string sqlite function as string
* @override
*/
public function getNowExpression($type = 'timestamp')
{
switch ($type) {
case 'time':
return 'time(\'now\')';
case 'date':
return 'date(\'now\')';
case 'timestamp':
default:
return 'datetime(\'now\')';
}
}
/**
* Trim a string, leading/trailing/both and with a given char which defaults to space.
*
* @param string $str
* @param int $pos
* @param string $char
* @return string
*/
public function getTrimExpression($str, $pos = self::TRIM_UNSPECIFIED, $char = false)
{
$trimFn = '';
$trimChar = ($char != false) ? (', ' . $char) : '';
if ($pos == self::TRIM_LEADING) {
$trimFn = 'LTRIM';
} else if($pos == self::TRIM_TRAILING) {
$trimFn = 'RTRIM';
} else {
$trimFn = 'TRIM';
}
return $trimFn . '(' . $str . $trimChar . ')';
}
/**
* return string to call a function to get a substring inside an SQL statement
*
* Note: Not SQL92, but common functionality.
*
* SQLite only supports the 2 parameter variant of this function
*
* @param string $value an sql string literal or column name/alias
* @param integer $position where to start the substring portion
* @param integer $length the substring portion length
* @return string SQL substring function with given parameters
* @override
*/
public function getSubstringExpression($value, $position, $length = null)
{
if ($length !== null) {
return 'SUBSTR(' . $value . ', ' . $position . ', ' . $length . ')';
}
return 'SUBSTR(' . $value . ', ' . $position . ', LENGTH(' . $value . '))';
}
/**
* returns the position of the first occurrence of substring $substr in string $str
*
* @param string $substr literal string to find
* @param string $str literal string
* @param int $pos position to start at, beginning of string by default
* @return integer
*/
public function getLocateExpression($str, $substr, $startPos = false)
{
if ($startPos == false) {
return 'LOCATE('.$str.', '.$substr.')';
} else {
return 'LOCATE('.$str.', '.$substr.', '.$startPos.')';
}
}
public function getDateDiffExpression($date1, $date2)
{
return 'ROUND(JULIANDAY('.$date1 . ')-JULIANDAY('.$date2.'))';
}
public function getDateAddDaysExpression($date, $days)
{
return "DATE(" . $date . ",'+". $days . " day')";
}
public function getDateSubDaysExpression($date, $days)
{
return "DATE(" . $date . ",'-". $days . " day')";
}
public function getDateAddMonthExpression($date, $months)
{
return "DATE(" . $date . ",'+". $months . " month')";
}
public function getDateSubMonthExpression($date, $months)
{
return "DATE(" . $date . ",'-". $months . " month')";
}
protected function _getTransactionIsolationLevelSQL($level)
{
switch ($level) {
case \Doctrine\DBAL\Connection::TRANSACTION_READ_UNCOMMITTED:
return 0;
case \Doctrine\DBAL\Connection::TRANSACTION_READ_COMMITTED:
case \Doctrine\DBAL\Connection::TRANSACTION_REPEATABLE_READ:
case \Doctrine\DBAL\Connection::TRANSACTION_SERIALIZABLE:
return 1;
default:
return parent::_getTransactionIsolationLevelSQL($level);
}
}
public function getSetTransactionIsolationSQL($level)
{
return 'PRAGMA read_uncommitted = ' . $this->_getTransactionIsolationLevelSQL($level);
}
/**
* @override
*/
public function prefersIdentityColumns()
{
return true;
}
/**
* @override
*/
public function getBooleanTypeDeclarationSQL(array $field)
{
return 'BOOLEAN';
}
/**
* @override
*/
public function getIntegerTypeDeclarationSQL(array $field)
{
return $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/**
* @override
*/
public function getBigIntTypeDeclarationSQL(array $field)
{
return $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/**
* @override
*/
public function getTinyIntTypeDeclarationSql(array $field)
{
return $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/**
* @override
*/
public function getSmallIntTypeDeclarationSQL(array $field)
{
return $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/**
* @override
*/
public function getMediumIntTypeDeclarationSql(array $field)
{
return $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/**
* @override
*/
public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATETIME';
}
/**
* @override
*/
public function getDateTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATE';
}
/**
* @override
*/
public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIME';
}
/**
* @override
*/
protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef)
{
return 'INTEGER';
}
/**
* create a new table
*
* @param string $name Name of the database that should be created
* @param array $fields Associative array that contains the definition of each field of the new table
* The indexes of the array entries are the names of the fields of the table an
* the array entry values are associative arrays like those that are meant to be
* passed with the field definitions to get[Type]Declaration() functions.
* array(
* 'id' => array(
* 'type' => 'integer',
* 'unsigned' => 1
* 'notnull' => 1
* 'default' => 0
* ),
* 'name' => array(
* 'type' => 'text',
* 'length' => 12
* ),
* 'password' => array(
* 'type' => 'text',
* 'length' => 12
* )
* );
* @param array $options An associative array of table options:
*
* @return void
* @override
*/
protected function _getCreateTableSQL($name, array $columns, array $options = array())
{
$name = str_replace(".", "__", $name);
$queryFields = $this->getColumnDeclarationListSQL($columns);
if (isset($options['primary']) && ! empty($options['primary'])) {
$keyColumns = array_unique(array_values($options['primary']));
$keyColumns = array_map(array($this, 'quoteIdentifier'), $keyColumns);
$queryFields.= ', PRIMARY KEY('.implode(', ', $keyColumns).')';
}
$query[] = 'CREATE TABLE ' . $name . ' (' . $queryFields . ')';
if (isset($options['indexes']) && ! empty($options['indexes'])) {
foreach ($options['indexes'] as $index => $indexDef) {
$query[] = $this->getCreateIndexSQL($indexDef, $name);
}
}
if (isset($options['unique']) && ! empty($options['unique'])) {
foreach ($options['unique'] as $index => $indexDef) {
$query[] = $this->getCreateIndexSQL($indexDef, $name);
}
}
return $query;
}
/**
* {@inheritdoc}
*/
protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed)
{
return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)')
: ($length ? 'VARCHAR(' . $length . ')' : 'TEXT');
}
public function getClobTypeDeclarationSQL(array $field)
{
return 'CLOB';
}
public function getListTableConstraintsSQL($table)
{
$table = str_replace(".", "__", $table);
return "SELECT sql FROM sqlite_master WHERE type='index' AND tbl_name = '$table' AND sql NOT NULL ORDER BY name";
}
public function getListTableColumnsSQL($table, $currentDatabase = null)
{
$table = str_replace(".", "__", $table);
return "PRAGMA table_info($table)";
}
public function getListTableIndexesSQL($table, $currentDatabase = null)
{
$table = str_replace(".", "__", $table);
return "PRAGMA index_list($table)";
}
public function getListTablesSQL()
{
return "SELECT name FROM sqlite_master WHERE type = 'table' AND name != 'sqlite_sequence' AND name != 'geometry_columns' AND name != 'spatial_ref_sys' "
. "UNION ALL SELECT name FROM sqlite_temp_master "
. "WHERE type = 'table' ORDER BY name";
}
public function getListViewsSQL($database)
{
return "SELECT name, sql FROM sqlite_master WHERE type='view' AND sql NOT NULL";
}
public function getCreateViewSQL($name, $sql)
{
return 'CREATE VIEW ' . $name . ' AS ' . $sql;
}
public function getDropViewSQL($name)
{
return 'DROP VIEW '. $name;
}
/**
* SQLite does support foreign key constraints, but only in CREATE TABLE statements...
* This really limits their usefulness and requires SQLite specific handling, so
* we simply say that SQLite does NOT support foreign keys for now...
*
* @return boolean FALSE
* @override
*/
public function supportsForeignKeyConstraints()
{
return false;
}
public function supportsAlterTable()
{
return false;
}
public function supportsIdentityColumns()
{
return true;
}
/**
* Get the platform name for this instance
*
* @return string
*/
public function getName()
{
return 'sqlite';
}
/**
* @inheritdoc
*/
public function getTruncateTableSQL($tableName, $cascade = false)
{
$tableName = str_replace(".", "__", $tableName);
return 'DELETE FROM '.$tableName;
}
/**
* User-defined function for Sqlite that is used with PDO::sqliteCreateFunction()
*
* @param int|float $value
* @return float
*/
static public function udfSqrt($value)
{
return sqrt($value);
}
/**
* User-defined function for Sqlite that implements MOD(a, b)
*/
static public function udfMod($a, $b)
{
return ($a % $b);
}
/**
* @param string $str
* @param string $substr
* @param int $offset
*/
static public function udfLocate($str, $substr, $offset = 0)
{
$pos = strpos($str, $substr, $offset);
if ($pos !== false) {
return $pos+1;
}
return 0;
}
public function getForUpdateSql()
{
return '';
}
protected function initializeDoctrineTypeMappings()
{
$this->doctrineTypeMapping = array(
'boolean' => 'boolean',
'tinyint' => 'boolean',
'smallint' => 'smallint',
'mediumint' => 'integer',
'int' => 'integer',
'integer' => 'integer',
'serial' => 'integer',
'bigint' => 'bigint',
'bigserial' => 'bigint',
'clob' => 'text',
'tinytext' => 'text',
'mediumtext' => 'text',
'longtext' => 'text',
'text' => 'text',
'varchar' => 'string',
'longvarchar' => 'string',
'varchar2' => 'string',
'nvarchar' => 'string',
'image' => 'string',
'ntext' => 'string',
'char' => 'string',
'date' => 'date',
'datetime' => 'datetime',
'timestamp' => 'datetime',
'time' => 'time',
'float' => 'float',
'double' => 'float',
'double precision' => 'float',
'real' => 'float',
'decimal' => 'decimal',
'numeric' => 'decimal',
'blob' => 'blob',
);
}
protected function getReservedKeywordsClass()
{
return 'Doctrine\DBAL\Platforms\Keywords\SQLiteKeywords';
}
/**
* Gets the SQL Snippet used to declare a BLOB column type.
*/
public function getBlobTypeDeclarationSQL(array $field)
{
return 'BLOB';
}
public function getTemporaryTableName($tableName)
{
$tableName = str_replace(".", "__", $tableName);
return $tableName;
}
/**
* Sqlite Platform emulates schema by underscoring each dot and generating tables
* into the default database.
*
* This hack is implemented to be able to use SQLite as testdriver when
* using schema supporting databases.
*
* @return bool
*/
public function canEmulateSchemas()
{
return true;
}
}

View File

@@ -0,0 +1,113 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Portability;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Configuration;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Cache\QueryCacheProfile;
class Connection extends \Doctrine\DBAL\Connection
{
const PORTABILITY_ALL = 255;
const PORTABILITY_NONE = 0;
const PORTABILITY_RTRIM = 1;
const PORTABILITY_EMPTY_TO_NULL = 4;
const PORTABILITY_FIX_CASE = 8;
const PORTABILITY_ORACLE = 9;
const PORTABILITY_POSTGRESQL = 13;
const PORTABILITY_SQLITE = 13;
const PORTABILITY_OTHERVENDORS = 12;
/**
* @var int
*/
private $portability = self::PORTABILITY_NONE;
/**
* @var int
*/
private $case;
public function connect()
{
$ret = parent::connect();
if ($ret) {
$params = $this->getParams();
if (isset($params['portability'])) {
if ($this->_platform->getName() === "oracle") {
$params['portability'] = $params['portability'] & self::PORTABILITY_ORACLE;
} else if ($this->_platform->getName() === "postgresql") {
$params['portability'] = $params['portability'] & self::PORTABILITY_POSTGRESQL;
} else if ($this->_platform->getName() === "sqlite") {
$params['portability'] = $params['portability'] & self::PORTABILITY_SQLITE;
} else {
$params['portability'] = $params['portability'] & self::PORTABILITY_OTHERVENDORS;
}
$this->portability = $params['portability'];
}
if (isset($params['fetch_case']) && $this->portability & self::PORTABILITY_FIX_CASE) {
if ($this->_conn instanceof \Doctrine\DBAL\Driver\PDOConnection) {
// make use of c-level support for case handling
$this->_conn->setAttribute(\PDO::ATTR_CASE, $params['fetch_case']);
} else {
$this->case = ($params['fetch_case'] == \PDO::CASE_LOWER) ? CASE_LOWER : CASE_UPPER;
}
}
}
return $ret;
}
public function getPortability()
{
return $this->portability;
}
public function getFetchCase()
{
return $this->case;
}
public function executeQuery($query, array $params = array(), $types = array(), QueryCacheProfile $qcp = null)
{
return new Statement(parent::executeQuery($query, $params, $types, $qcp), $this);
}
/**
* Prepares an SQL statement.
*
* @param string $statement The SQL statement to prepare.
* @return Doctrine\DBAL\Driver\Statement The prepared statement.
*/
public function prepare($statement)
{
return new Statement(parent::prepare($statement), $this);
}
public function query()
{
$this->connect();
$stmt = call_user_func_array(array($this->_conn, 'query'), func_get_args());
return new Statement($stmt, $this);
}
}

View File

@@ -0,0 +1,191 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Portability;
use PDO;
/**
* Portability Wrapper for a Statement
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class Statement implements \IteratorAggregate, \Doctrine\DBAL\Driver\Statement
{
/**
* @var int
*/
private $portability;
/**
* @var Doctrine\DBAL\Driver\Statement
*/
private $stmt;
/**
* @var int
*/
private $case;
/**
* @var int
*/
private $defaultFetchStyle = PDO::FETCH_BOTH;
/**
* Wraps <tt>Statement</tt> and applies portability measures
*
* @param Doctrine\DBAL\Driver\Statement $stmt
* @param Doctrine\DBAL\Connection $conn
*/
public function __construct($stmt, Connection $conn)
{
$this->stmt = $stmt;
$this->portability = $conn->getPortability();
$this->case = $conn->getFetchCase();
}
public function bindParam($column, &$variable, $type = null)
{
return $this->stmt->bindParam($column, $variable, $type);
}
public function bindValue($param, $value, $type = null)
{
return $this->stmt->bindValue($param, $value, $type);
}
public function closeCursor()
{
return $this->stmt->closeCursor();
}
public function columnCount()
{
return $this->stmt->columnCount();
}
public function errorCode()
{
return $this->stmt->errorCode();
}
public function errorInfo()
{
return $this->stmt->errorInfo();
}
public function execute($params = null)
{
return $this->stmt->execute($params);
}
public function setFetchMode($fetchStyle, $arg1 = null, $arg2 = null)
{
$this->defaultFetchStyle = $fetchStyle;
$this->stmt->setFetchMode($fetchStyle, $arg1, $arg2);
}
public function getIterator()
{
$data = $this->fetchAll($this->defaultFetchStyle);
return new \ArrayIterator($data);
}
public function fetch($fetchStyle = PDO::FETCH_BOTH)
{
$row = $this->stmt->fetch($fetchStyle);
$row = $this->fixRow($row,
$this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM),
!is_null($this->case) && ($fetchStyle == PDO::FETCH_ASSOC || $fetchStyle == PDO::FETCH_BOTH) && ($this->portability & Connection::PORTABILITY_FIX_CASE)
);
return $row;
}
public function fetchAll($fetchStyle = PDO::FETCH_BOTH, $columnIndex = 0)
{
if ($columnIndex != 0) {
$rows = $this->stmt->fetchAll($fetchStyle, $columnIndex);
} else {
$rows = $this->stmt->fetchAll($fetchStyle);
}
$iterateRow = $this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM);
$fixCase = !is_null($this->case) && ($fetchStyle == PDO::FETCH_ASSOC || $fetchStyle == PDO::FETCH_BOTH) && ($this->portability & Connection::PORTABILITY_FIX_CASE);
if (!$iterateRow && !$fixCase) {
return $rows;
}
foreach ($rows AS $num => $row) {
$rows[$num] = $this->fixRow($row, $iterateRow, $fixCase);
}
return $rows;
}
protected function fixRow($row, $iterateRow, $fixCase)
{
if (!$row) {
return $row;
}
if ($fixCase) {
$row = array_change_key_case($row, $this->case);
}
if ($iterateRow) {
foreach ($row AS $k => $v) {
if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) && $v === '') {
$row[$k] = null;
} else if (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($v)) {
$row[$k] = rtrim($v);
}
}
}
return $row;
}
public function fetchColumn($columnIndex = 0)
{
$value = $this->stmt->fetchColumn($columnIndex);
if ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) {
if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) && $value === '') {
$value = null;
} else if (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($value)) {
$value = rtrim($value);
}
}
return $value;
}
public function rowCount()
{
return $this->stmt->rowCount();
}
}

View File

@@ -0,0 +1,130 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Query\Expression;
/**
* Composite expression is responsible to build a group of similar expression.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.1
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class CompositeExpression implements \Countable
{
/**
* Constant that represents an AND composite expression
*/
const TYPE_AND = 'AND';
/**
* Constant that represents an OR composite expression
*/
const TYPE_OR = 'OR';
/**
* @var string Holds the instance type of composite expression
*/
private $type;
/**
* @var array Each expression part of the composite expression
*/
private $parts = array();
/**
* Constructor.
*
* @param string $type Instance type of composite expression
* @param array $parts Composition of expressions to be joined on composite expression
*/
public function __construct($type, array $parts = array())
{
$this->type = $type;
$this->addMultiple($parts);
}
/**
* Adds multiple parts to composite expression.
*
* @param array $args
*
* @return CompositeExpression
*/
public function addMultiple(array $parts = array())
{
foreach ((array) $parts as $part) {
$this->add($part);
}
return $this;
}
/**
* Adds an expression to composite expression.
*
* @param mixed $part
* @return CompositeExpression
*/
public function add($part)
{
if ( ! empty($part) || ($part instanceof self && $part->count() > 0)) {
$this->parts[] = $part;
}
return $this;
}
/**
* Retrieves the amount of expressions on composite expression.
*
* @return integer
*/
public function count()
{
return count($this->parts);
}
/**
* Retrieve the string representation of this composite expression.
*
* @return string
*/
public function __toString()
{
if (count($this->parts) === 1) {
return (string) $this->parts[0];
}
return '(' . implode(') ' . $this->type . ' (', $this->parts) . ')';
}
/**
* Return type of this composite expression (AND/OR)
*
* @return string
*/
public function getType()
{
return $this->type;
}
}

View File

@@ -0,0 +1,264 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Query\Expression;
use Doctrine\DBAL\Connection;
/**
* ExpressionBuilder class is responsible to dynamically create SQL query parts.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.1
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class ExpressionBuilder
{
const EQ = '=';
const NEQ = '<>';
const LT = '<';
const LTE = '<=';
const GT = '>';
const GTE = '>=';
/**
* @var Doctrine\DBAL\Connection DBAL Connection
*/
private $connection = null;
/**
* Initializes a new <tt>ExpressionBuilder</tt>.
*
* @param Doctrine\DBAL\Connection $connection DBAL Connection
*/
public function __construct(Connection $connection)
{
$this->connection = $connection;
}
/**
* Creates a conjunction of the given boolean expressions.
*
* Example:
*
* [php]
* // (u.type = ?) AND (u.role = ?)
* $expr->andX('u.type = ?', 'u.role = ?'));
*
* @param mixed $x Optional clause. Defaults = null, but requires
* at least one defined when converting to string.
* @return CompositeExpression
*/
public function andX($x = null)
{
return new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args());
}
/**
* Creates a disjunction of the given boolean expressions.
*
* Example:
*
* [php]
* // (u.type = ?) OR (u.role = ?)
* $qb->where($qb->expr()->orX('u.type = ?', 'u.role = ?'));
*
* @param mixed $x Optional clause. Defaults = null, but requires
* at least one defined when converting to string.
* @return CompositeExpression
*/
public function orX($x = null)
{
return new CompositeExpression(CompositeExpression::TYPE_OR, func_get_args());
}
/**
* Creates a comparison expression.
*
* @param mixed $x Left expression
* @param string $operator One of the ExpressionBuikder::* constants.
* @param mixed $y Right expression
* @return string
*/
public function comparison($x, $operator, $y)
{
return $x . ' ' . $operator . ' ' . $y;
}
/**
* Creates an equality comparison expression with the given arguments.
*
* First argument is considered the left expression and the second is the right expression.
* When converted to string, it will generated a <left expr> = <right expr>. Example:
*
* [php]
* // u.id = ?
* $expr->eq('u.id', '?');
*
* @param mixed $x Left expression
* @param mixed $y Right expression
* @return string
*/
public function eq($x, $y)
{
return $this->comparison($x, self::EQ, $y);
}
/**
* Creates a non equality comparison expression with the given arguments.
* First argument is considered the left expression and the second is the right expression.
* When converted to string, it will generated a <left expr> <> <right expr>. Example:
*
* [php]
* // u.id <> 1
* $q->where($q->expr()->neq('u.id', '1'));
*
* @param mixed $x Left expression
* @param mixed $y Right expression
* @return string
*/
public function neq($x, $y)
{
return $this->comparison($x, self::NEQ, $y);
}
/**
* Creates a lower-than comparison expression with the given arguments.
* First argument is considered the left expression and the second is the right expression.
* When converted to string, it will generated a <left expr> < <right expr>. Example:
*
* [php]
* // u.id < ?
* $q->where($q->expr()->lt('u.id', '?'));
*
* @param mixed $x Left expression
* @param mixed $y Right expression
* @return string
*/
public function lt($x, $y)
{
return $this->comparison($x, self::LT, $y);
}
/**
* Creates a lower-than-equal comparison expression with the given arguments.
* First argument is considered the left expression and the second is the right expression.
* When converted to string, it will generated a <left expr> <= <right expr>. Example:
*
* [php]
* // u.id <= ?
* $q->where($q->expr()->lte('u.id', '?'));
*
* @param mixed $x Left expression
* @param mixed $y Right expression
* @return string
*/
public function lte($x, $y)
{
return $this->comparison($x, self::LTE, $y);
}
/**
* Creates a greater-than comparison expression with the given arguments.
* First argument is considered the left expression and the second is the right expression.
* When converted to string, it will generated a <left expr> > <right expr>. Example:
*
* [php]
* // u.id > ?
* $q->where($q->expr()->gt('u.id', '?'));
*
* @param mixed $x Left expression
* @param mixed $y Right expression
* @return string
*/
public function gt($x, $y)
{
return $this->comparison($x, self::GT, $y);
}
/**
* Creates a greater-than-equal comparison expression with the given arguments.
* First argument is considered the left expression and the second is the right expression.
* When converted to string, it will generated a <left expr> >= <right expr>. Example:
*
* [php]
* // u.id >= ?
* $q->where($q->expr()->gte('u.id', '?'));
*
* @param mixed $x Left expression
* @param mixed $y Right expression
* @return string
*/
public function gte($x, $y)
{
return $this->comparison($x, self::GTE, $y);
}
/**
* Creates an IS NULL expression with the given arguments.
*
* @param string $x Field in string format to be restricted by IS NULL
*
* @return string
*/
public function isNull($x)
{
return $x . ' IS NULL';
}
/**
* Creates an IS NOT NULL expression with the given arguments.
*
* @param string $x Field in string format to be restricted by IS NOT NULL
*
* @return string
*/
public function isNotNull($x)
{
return $x . ' IS NOT NULL';
}
/**
* Creates a LIKE() comparison expression with the given arguments.
*
* @param string $x Field in string format to be inspected by LIKE() comparison.
* @param mixed $y Argument to be used in LIKE() comparison.
*
* @return string
*/
public function like($x, $y)
{
return $this->comparison($x, 'LIKE', $y);
}
/**
* Quotes a given input parameter.
*
* @param mixed $input Parameter to be quoted.
* @param string $type Type of the parameter.
*
* @return string
*/
public function literal($input, $type = null)
{
return $this->connection->quote($input, $type);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Query;
use Doctrine\DBAL\DBALException;
/**
* Driver interface.
* Interface that all DBAL drivers must implement.
*
* @since 2.1.4
*/
class QueryException extends DBALException
{
static public function unknownFromAlias($alias, $registeredAliases)
{
return new self("The given alias '" . $alias . "' is not part of " .
"any FROM clause table. The currently registered FROM-clause " .
"aliases are: " . implode(", ", $registeredAliases) . ". Join clauses " .
"are bound to from clauses to provide support for mixing of multiple " .
"from and join clauses.");
}
}

View File

View File

@@ -0,0 +1,179 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL;
use Doctrine\DBAL\Connection;
/**
* Utility class that parses sql statements with regard to types and parameters.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class SQLParserUtils
{
/**
* Get an array of the placeholders in an sql statements as keys and their positions in the query string.
*
* Returns an integer => integer pair (indexed from zero) for a positional statement
* and a string => int[] pair for a named statement.
*
* @param string $statement
* @param bool $isPositional
* @return array
*/
static public function getPlaceholderPositions($statement, $isPositional = true)
{
$match = ($isPositional) ? '?' : ':';
if (strpos($statement, $match) === false) {
return array();
}
$count = 0;
$inLiteral = false; // a valid query never starts with quotes
$stmtLen = strlen($statement);
$paramMap = array();
for ($i = 0; $i < $stmtLen; $i++) {
if ($statement[$i] == $match && !$inLiteral) {
// real positional parameter detected
if ($isPositional) {
$paramMap[$count] = $i;
} else {
$name = "";
// TODO: Something faster/better to match this than regex?
for ($j = $i; ($j < $stmtLen && preg_match('(([:a-zA-Z0-9_]{1}))', $statement[$j])); $j++) {
$name .= $statement[$j];
}
$paramMap[$name][] = $i; // named parameters can be duplicated!
$i = $j;
}
++$count;
} else if ($statement[$i] == "'" || $statement[$i] == '"') {
$inLiteral = ! $inLiteral; // switch state!
}
}
return $paramMap;
}
/**
* For a positional query this method can rewrite the sql statement with regard to array parameters.
*
* @param string $query
* @param array $params
* @param array $types
*/
static public function expandListParameters($query, $params, $types)
{
$isPositional = is_int(key($params));
$arrayPositions = array();
$bindIndex = -1;
foreach ($types AS $name => $type) {
++$bindIndex;
if ($type === Connection::PARAM_INT_ARRAY || $type === Connection::PARAM_STR_ARRAY) {
if ($isPositional) {
$name = $bindIndex;
}
$arrayPositions[$name] = false;
}
}
if ((!$arrayPositions && $isPositional) || (count($params) != count($types))) {
return array($query, $params, $types);
}
$paramPos = self::getPlaceholderPositions($query, $isPositional);
if ($isPositional) {
$paramOffset = 0;
$queryOffset = 0;
foreach ($paramPos AS $needle => $needlePos) {
if (!isset($arrayPositions[$needle])) {
continue;
}
$needle += $paramOffset;
$needlePos += $queryOffset;
$len = count($params[$needle]);
$params = array_merge(
array_slice($params, 0, $needle),
$params[$needle],
array_slice($params, $needle + 1)
);
$types = array_merge(
array_slice($types, 0, $needle),
array_fill(0, $len, $types[$needle] - Connection::ARRAY_PARAM_OFFSET), // array needles are at PDO::PARAM_* + 100
array_slice($types, $needle + 1)
);
$expandStr = implode(", ", array_fill(0, $len, "?"));
$query = substr($query, 0, $needlePos) . $expandStr . substr($query, $needlePos + 1);
$paramOffset += ($len - 1); // Grows larger by number of parameters minus the replaced needle.
$queryOffset += (strlen($expandStr) - 1);
}
} else {
$queryOffset= 0;
$typesOrd = array();
$paramsOrd = array();
foreach ($paramPos as $needle => $needlePos) {
$paramLen = strlen($needle);
$token = substr($needle,0,1);
$needle = substr($needle,1);
$value = $params[$needle];
if (!isset($arrayPositions[$needle])) {
foreach ($needlePos as $pos) {
$pos += $queryOffset;
$queryOffset -= ($paramLen - 1);
$paramsOrd[] = $value;
$typesOrd[] = $types[$needle];
$query = substr($query, 0, $pos) . '?' . substr($query, ($pos + $paramLen));
}
} else {
$len = count($value);
$expandStr = implode(", ", array_fill(0, $len, "?"));
foreach ($needlePos as $pos) {
foreach ($value as $val) {
$paramsOrd[] = $val;
$typesOrd[] = $types[$needle] - Connection::ARRAY_PARAM_OFFSET;
}
$pos += $queryOffset;
$queryOffset += (strlen($expandStr) - $paramLen);
$query = substr($query, 0, $pos) . $expandStr . substr($query, ($pos + $paramLen));
}
}
}
$types = $typesOrd;
$params = $paramsOrd;
}
return array($query, $params, $types);
}
}

View File

@@ -0,0 +1,204 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* The abstract asset allows to reset the name of all assets without publishing this to the public userland.
*
* This encapsulation hack is necessary to keep a consistent state of the database schema. Say we have a list of tables
* array($tableName => Table($tableName)); if you want to rename the table, you have to make sure
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
abstract class AbstractAsset
{
/**
* @var string
*/
protected $_name;
/**
* Namespace of the asset. If none isset the default namespace is assumed.
*
* @var string
*/
protected $_namespace;
/**
* @var bool
*/
protected $_quoted = false;
/**
* Set name of this asset
*
* @param string $name
*/
protected function _setName($name)
{
if ($this->isQuoted($name)) {
$this->_quoted = true;
$name = $this->trimQuotes($name);
}
if (strpos($name, ".") !== false) {
$parts = explode(".", $name);
$this->_namespace = $parts[0];
$name = $parts[1];
}
$this->_name = $name;
}
/**
* Is this asset in the default namespace?
*
* @param string $defaultNamespaceName
* @return bool
*/
public function isInDefaultNamespace($defaultNamespaceName)
{
return $this->_namespace == $defaultNamespaceName || $this->_namespace === null;
}
/**
* Get namespace name of this asset.
*
* If NULL is returned this means the default namespace is used.
*
* @return string
*/
public function getNamespaceName()
{
return $this->_namespace;
}
/**
* The shortest name is stripped of the default namespace. All other
* namespaced elements are returned as full-qualified names.
*
* @param string
* @return string
*/
public function getShortestName($defaultNamespaceName)
{
$shortestName = $this->getName();
if ($this->_namespace == $defaultNamespaceName) {
$shortestName = $this->_name;
}
return strtolower($shortestName);
}
/**
* The normalized name is full-qualified and lowerspaced. Lowerspacing is
* actually wrong, but we have to do it to keep our sanity. If you are
* using database objects that only differentiate in the casing (FOO vs
* Foo) then you will NOT be able to use Doctrine Schema abstraction.
*
* Every non-namespaced element is prefixed with the default namespace
* name which is passed as argument to this method.
*
* @return string
*/
public function getFullQualifiedName($defaultNamespaceName)
{
$name = $this->getName();
if (!$this->_namespace) {
$name = $defaultNamespaceName . "." . $name;
}
return strtolower($name);
}
/**
* Check if this identifier is quoted.
*
* @param string $identifier
* @return bool
*/
protected function isQuoted($identifier)
{
return (isset($identifier[0]) && ($identifier[0] == '`' || $identifier[0] == '"'));
}
/**
* Trim quotes from the identifier.
*
* @param string $identifier
* @return string
*/
protected function trimQuotes($identifier)
{
return str_replace(array('`', '"'), '', $identifier);
}
/**
* Return name of this schema asset.
*
* @return string
*/
public function getName()
{
if ($this->_namespace) {
return $this->_namespace . "." . $this->_name;
}
return $this->_name;
}
/**
* Get the quoted representation of this asset but only if it was defined with one. Otherwise
* return the plain unquoted value as inserted.
*
* @param AbstractPlatform $platform
* @return string
*/
public function getQuotedName(AbstractPlatform $platform)
{
$keywords = $platform->getReservedKeywordsList();
$parts = explode(".", $this->getName());
foreach ($parts AS $k => $v) {
$parts[$k] = ($this->_quoted || $keywords->isKeyword($v)) ? $platform->quoteIdentifier($v) : $v;
}
return implode(".", $parts);
}
/**
* Generate an identifier from a list of column names obeying a certain string length.
*
* This is especially important for Oracle, since it does not allow identifiers larger than 30 chars,
* however building idents automatically for foreign keys, composite keys or such can easily create
* very long names.
*
* @param array $columnNames
* @param string $prefix
* @param int $maxSize
* @return string
*/
protected function _generateIdentifierName($columnNames, $prefix='', $maxSize=30)
{
$hash = implode("", array_map(function($column) {
return dechex(crc32($column));
}, $columnNames));
return substr(strtoupper($prefix . "_" . $hash), 0, $maxSize);
}
}

View File

@@ -0,0 +1,890 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Events;
use Doctrine\DBAL\Event\SchemaColumnDefinitionEventArgs;
use Doctrine\DBAL\Event\SchemaIndexDefinitionEventArgs;
use Doctrine\DBAL\Types;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* Base class for schema managers. Schema managers are used to inspect and/or
* modify the database schema/structure.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Roman Borschel <roman@code-factory.org>
* @author Jonathan H. Wage <jonwage@gmail.com>
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @since 2.0
*/
abstract class AbstractSchemaManager
{
/**
* Holds instance of the Doctrine connection for this schema manager
*
* @var \Doctrine\DBAL\Connection
*/
protected $_conn;
/**
* Holds instance of the database platform used for this schema manager
*
* @var \Doctrine\DBAL\Platforms\AbstractPlatform
*/
protected $_platform;
/**
* Constructor. Accepts the Connection instance to manage the schema for
*
* @param \Doctrine\DBAL\Connection $conn
*/
public function __construct(\Doctrine\DBAL\Connection $conn)
{
$this->_conn = $conn;
$this->_platform = $this->_conn->getDatabasePlatform();
}
/**
* Return associated platform.
*
* @return \Doctrine\DBAL\Platform\AbstractPlatform
*/
public function getDatabasePlatform()
{
return $this->_platform;
}
/**
* Try any method on the schema manager. Normally a method throws an
* exception when your DBMS doesn't support it or if an error occurs.
* This method allows you to try and method on your SchemaManager
* instance and will return false if it does not work or is not supported.
*
* <code>
* $result = $sm->tryMethod('dropView', 'view_name');
* </code>
*
* @return mixed
*/
public function tryMethod()
{
$args = func_get_args();
$method = $args[0];
unset($args[0]);
$args = array_values($args);
try {
return call_user_func_array(array($this, $method), $args);
} catch (\Exception $e) {
return false;
}
}
/**
* List the available databases for this connection
*
* @return array $databases
*/
public function listDatabases()
{
$sql = $this->_platform->getListDatabasesSQL();
$databases = $this->_conn->fetchAll($sql);
return $this->_getPortableDatabasesList($databases);
}
/**
* List the available sequences for this connection
*
* @return Sequence[]
*/
public function listSequences($database = null)
{
if (is_null($database)) {
$database = $this->_conn->getDatabase();
}
$sql = $this->_platform->getListSequencesSQL($database);
$sequences = $this->_conn->fetchAll($sql);
return $this->filterAssetNames($this->_getPortableSequencesList($sequences));
}
/**
* List the columns for a given table.
*
* In contrast to other libraries and to the old version of Doctrine,
* this column definition does try to contain the 'primary' field for
* the reason that it is not portable accross different RDBMS. Use
* {@see listTableIndexes($tableName)} to retrieve the primary key
* of a table. We're a RDBMS specifies more details these are held
* in the platformDetails array.
*
* @param string $table The name of the table.
* @param string $database
* @return Column[]
*/
public function listTableColumns($table, $database = null)
{
if (!$database) {
$database = $this->_conn->getDatabase();
}
$sql = $this->_platform->getListTableColumnsSQL($table, $database);
$tableColumns = $this->_conn->fetchAll($sql);
return $this->_getPortableTableColumnList($table, $database, $tableColumns);
}
/**
* List the indexes for a given table returning an array of Index instances.
*
* Keys of the portable indexes list are all lower-cased.
*
* @param string $table The name of the table
* @return Index[] $tableIndexes
*/
public function listTableIndexes($table)
{
$sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase());
$tableIndexes = $this->_conn->fetchAll($sql);
return $this->_getPortableTableIndexesList($tableIndexes, $table);
}
/**
* Return true if all the given tables exist.
*
* @param array $tableNames
* @return bool
*/
public function tablesExist($tableNames)
{
$tableNames = array_map('strtolower', (array)$tableNames);
return count($tableNames) == count(\array_intersect($tableNames, array_map('strtolower', $this->listTableNames())));
}
/**
* Return a list of all tables in the current database
*
* @return array
*/
public function listTableNames()
{
$sql = $this->_platform->getListTablesSQL();
$tables = $this->_conn->fetchAll($sql);
$tableNames = $this->_getPortableTablesList($tables);
return $this->filterAssetNames($tableNames);
}
/**
* Filter asset names if they are configured to return only a subset of all
* the found elements.
*
* @param array $assetNames
* @return array
*/
protected function filterAssetNames($assetNames)
{
$filterExpr = $this->getFilterSchemaAssetsExpression();
if (!$filterExpr) {
return $assetNames;
}
return array_values (
array_filter($assetNames, function ($assetName) use ($filterExpr) {
$assetName = ($assetName instanceof AbstractAsset) ? $assetName->getName() : $assetName;
return preg_match('(' . $filterExpr . ')', $assetName);
})
);
}
protected function getFilterSchemaAssetsExpression()
{
return $this->_conn->getConfiguration()->getFilterSchemaAssetsExpression();
}
/**
* List the tables for this connection
*
* @return Table[]
*/
public function listTables()
{
$tableNames = $this->listTableNames();
$tables = array();
foreach ($tableNames AS $tableName) {
$tables[] = $this->listTableDetails($tableName);
}
return $tables;
}
/**
* @param string $tableName
* @return Table
*/
public function listTableDetails($tableName)
{
$columns = $this->listTableColumns($tableName);
$foreignKeys = array();
if ($this->_platform->supportsForeignKeyConstraints()) {
$foreignKeys = $this->listTableForeignKeys($tableName);
}
$indexes = $this->listTableIndexes($tableName);
return new Table($tableName, $columns, $indexes, $foreignKeys, false, array());
}
/**
* List the views this connection has
*
* @return View[]
*/
public function listViews()
{
$database = $this->_conn->getDatabase();
$sql = $this->_platform->getListViewsSQL($database);
$views = $this->_conn->fetchAll($sql);
return $this->_getPortableViewsList($views);
}
/**
* List the foreign keys for the given table
*
* @param string $table The name of the table
* @return ForeignKeyConstraint[]
*/
public function listTableForeignKeys($table, $database = null)
{
if (is_null($database)) {
$database = $this->_conn->getDatabase();
}
$sql = $this->_platform->getListTableForeignKeysSQL($table, $database);
$tableForeignKeys = $this->_conn->fetchAll($sql);
return $this->_getPortableTableForeignKeysList($tableForeignKeys);
}
/* drop*() Methods */
/**
* Drops a database.
*
* NOTE: You can not drop the database this SchemaManager is currently connected to.
*
* @param string $database The name of the database to drop
*/
public function dropDatabase($database)
{
$this->_execSql($this->_platform->getDropDatabaseSQL($database));
}
/**
* Drop the given table
*
* @param string $table The name of the table to drop
*/
public function dropTable($table)
{
$this->_execSql($this->_platform->getDropTableSQL($table));
}
/**
* Drop the index from the given table
*
* @param Index|string $index The name of the index
* @param string|Table $table The name of the table
*/
public function dropIndex($index, $table)
{
if($index instanceof Index) {
$index = $index->getQuotedName($this->_platform);
}
$this->_execSql($this->_platform->getDropIndexSQL($index, $table));
}
/**
* Drop the constraint from the given table
*
* @param Constraint $constraint
* @param string $table The name of the table
*/
public function dropConstraint(Constraint $constraint, $table)
{
$this->_execSql($this->_platform->getDropConstraintSQL($constraint, $table));
}
/**
* Drops a foreign key from a table.
*
* @param ForeignKeyConstraint|string $table The name of the table with the foreign key.
* @param Table|string $name The name of the foreign key.
* @return boolean $result
*/
public function dropForeignKey($foreignKey, $table)
{
$this->_execSql($this->_platform->getDropForeignKeySQL($foreignKey, $table));
}
/**
* Drops a sequence with a given name.
*
* @param string $name The name of the sequence to drop.
*/
public function dropSequence($name)
{
$this->_execSql($this->_platform->getDropSequenceSQL($name));
}
/**
* Drop a view
*
* @param string $name The name of the view
* @return boolean $result
*/
public function dropView($name)
{
$this->_execSql($this->_platform->getDropViewSQL($name));
}
/* create*() Methods */
/**
* Creates a new database.
*
* @param string $database The name of the database to create.
*/
public function createDatabase($database)
{
$this->_execSql($this->_platform->getCreateDatabaseSQL($database));
}
/**
* Create a new table.
*
* @param Table $table
* @param int $createFlags
*/
public function createTable(Table $table)
{
$createFlags = AbstractPlatform::CREATE_INDEXES|AbstractPlatform::CREATE_FOREIGNKEYS;
$this->_execSql($this->_platform->getCreateTableSQL($table, $createFlags));
}
/**
* Create a new sequence
*
* @param Sequence $sequence
* @throws Doctrine\DBAL\ConnectionException if something fails at database level
*/
public function createSequence($sequence)
{
$this->_execSql($this->_platform->getCreateSequenceSQL($sequence));
}
/**
* Create a constraint on a table
*
* @param Constraint $constraint
* @param string|Table $table
*/
public function createConstraint(Constraint $constraint, $table)
{
$this->_execSql($this->_platform->getCreateConstraintSQL($constraint, $table));
}
/**
* Create a new index on a table
*
* @param Index $index
* @param string $table name of the table on which the index is to be created
*/
public function createIndex(Index $index, $table)
{
$this->_execSql($this->_platform->getCreateIndexSQL($index, $table));
}
/**
* Create a new foreign key
*
* @param ForeignKeyConstraint $foreignKey ForeignKey instance
* @param string|Table $table name of the table on which the foreign key is to be created
*/
public function createForeignKey(ForeignKeyConstraint $foreignKey, $table)
{
$this->_execSql($this->_platform->getCreateForeignKeySQL($foreignKey, $table));
}
/**
* Create a new view
*
* @param View $view
*/
public function createView(View $view)
{
$this->_execSql($this->_platform->getCreateViewSQL($view->getQuotedName($this->_platform), $view->getSql()));
}
/* dropAndCreate*() Methods */
/**
* Drop and create a constraint
*
* @param Constraint $constraint
* @param string $table
* @see dropConstraint()
* @see createConstraint()
*/
public function dropAndCreateConstraint(Constraint $constraint, $table)
{
$this->tryMethod('dropConstraint', $constraint, $table);
$this->createConstraint($constraint, $table);
}
/**
* Drop and create a new index on a table
*
* @param string|Table $table name of the table on which the index is to be created
* @param Index $index
*/
public function dropAndCreateIndex(Index $index, $table)
{
$this->tryMethod('dropIndex', $index->getQuotedName($this->_platform), $table);
$this->createIndex($index, $table);
}
/**
* Drop and create a new foreign key
*
* @param ForeignKeyConstraint $foreignKey associative array that defines properties of the foreign key to be created.
* @param string|Table $table name of the table on which the foreign key is to be created
*/
public function dropAndCreateForeignKey(ForeignKeyConstraint $foreignKey, $table)
{
$this->tryMethod('dropForeignKey', $foreignKey, $table);
$this->createForeignKey($foreignKey, $table);
}
/**
* Drop and create a new sequence
*
* @param Sequence $sequence
* @throws Doctrine\DBAL\ConnectionException if something fails at database level
*/
public function dropAndCreateSequence(Sequence $sequence)
{
$this->tryMethod('dropSequence', $sequence->getQuotedName($this->_platform));
$this->createSequence($sequence);
}
/**
* Drop and create a new table.
*
* @param Table $table
*/
public function dropAndCreateTable(Table $table)
{
$this->tryMethod('dropTable', $table->getQuotedName($this->_platform));
$this->createTable($table);
}
/**
* Drop and creates a new database.
*
* @param string $database The name of the database to create.
*/
public function dropAndCreateDatabase($database)
{
$this->tryMethod('dropDatabase', $database);
$this->createDatabase($database);
}
/**
* Drop and create a new view
*
* @param View $view
*/
public function dropAndCreateView(View $view)
{
$this->tryMethod('dropView', $view->getQuotedName($this->_platform));
$this->createView($view);
}
/* alterTable() Methods */
/**
* Alter an existing tables schema
*
* @param TableDiff $tableDiff
*/
public function alterTable(TableDiff $tableDiff)
{
$queries = $this->_platform->getAlterTableSQL($tableDiff);
if (is_array($queries) && count($queries)) {
foreach ($queries AS $ddlQuery) {
$this->_execSql($ddlQuery);
}
}
}
/**
* Rename a given table to another name
*
* @param string $name The current name of the table
* @param string $newName The new name of the table
*/
public function renameTable($name, $newName)
{
$tableDiff = new TableDiff($name);
$tableDiff->newName = $newName;
$this->alterTable($tableDiff);
}
/**
* Methods for filtering return values of list*() methods to convert
* the native DBMS data definition to a portable Doctrine definition
*/
protected function _getPortableDatabasesList($databases)
{
$list = array();
foreach ($databases as $key => $value) {
if ($value = $this->_getPortableDatabaseDefinition($value)) {
$list[] = $value;
}
}
return $list;
}
protected function _getPortableDatabaseDefinition($database)
{
return $database;
}
protected function _getPortableFunctionsList($functions)
{
$list = array();
foreach ($functions as $key => $value) {
if ($value = $this->_getPortableFunctionDefinition($value)) {
$list[] = $value;
}
}
return $list;
}
protected function _getPortableFunctionDefinition($function)
{
return $function;
}
protected function _getPortableTriggersList($triggers)
{
$list = array();
foreach ($triggers as $key => $value) {
if ($value = $this->_getPortableTriggerDefinition($value)) {
$list[] = $value;
}
}
return $list;
}
protected function _getPortableTriggerDefinition($trigger)
{
return $trigger;
}
protected function _getPortableSequencesList($sequences)
{
$list = array();
foreach ($sequences as $key => $value) {
if ($value = $this->_getPortableSequenceDefinition($value)) {
$list[] = $value;
}
}
return $list;
}
/**
* @param array $sequence
* @return Sequence
*/
protected function _getPortableSequenceDefinition($sequence)
{
throw DBALException::notSupported('Sequences');
}
/**
* Independent of the database the keys of the column list result are lowercased.
*
* The name of the created column instance however is kept in its case.
*
* @param string $table The name of the table.
* @param string $database
* @param array $tableColumns
* @return array
*/
protected function _getPortableTableColumnList($table, $database, $tableColumns)
{
$eventManager = $this->_platform->getEventManager();
$list = array();
foreach ($tableColumns as $key => $tableColumn) {
$column = null;
$defaultPrevented = false;
if (null !== $eventManager && $eventManager->hasListeners(Events::onSchemaColumnDefinition)) {
$eventArgs = new SchemaColumnDefinitionEventArgs($tableColumn, $table, $database, $this->_conn);
$eventManager->dispatchEvent(Events::onSchemaColumnDefinition, $eventArgs);
$defaultPrevented = $eventArgs->isDefaultPrevented();
$column = $eventArgs->getColumn();
}
if (!$defaultPrevented) {
$column = $this->_getPortableTableColumnDefinition($tableColumn);
}
if ($column) {
$name = strtolower($column->getQuotedName($this->_platform));
$list[$name] = $column;
}
}
return $list;
}
/**
* Get Table Column Definition
*
* @param array $tableColumn
* @return Column
*/
abstract protected function _getPortableTableColumnDefinition($tableColumn);
/**
* Aggregate and group the index results according to the required data result.
*
* @param array $tableIndexRows
* @param string $tableName
* @return array
*/
protected function _getPortableTableIndexesList($tableIndexRows, $tableName=null)
{
$result = array();
foreach($tableIndexRows AS $tableIndex) {
$indexName = $keyName = $tableIndex['key_name'];
if($tableIndex['primary']) {
$keyName = 'primary';
}
$keyName = strtolower($keyName);
if(!isset($result[$keyName])) {
$result[$keyName] = array(
'name' => $indexName,
'columns' => array($tableIndex['column_name']),
'unique' => $tableIndex['non_unique'] ? false : true,
'primary' => $tableIndex['primary'],
);
} else {
$result[$keyName]['columns'][] = $tableIndex['column_name'];
}
}
$eventManager = $this->_platform->getEventManager();
$indexes = array();
foreach($result AS $indexKey => $data) {
$index = null;
$defaultPrevented = false;
if (null !== $eventManager && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) {
$eventArgs = new SchemaIndexDefinitionEventArgs($data, $tableName, $this->_conn);
$eventManager->dispatchEvent(Events::onSchemaIndexDefinition, $eventArgs);
$defaultPrevented = $eventArgs->isDefaultPrevented();
$index = $eventArgs->getIndex();
}
if (!$defaultPrevented) {
$index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary']);
}
if ($index) {
$indexes[$indexKey] = $index;
}
}
return $indexes;
}
protected function _getPortableTablesList($tables)
{
$list = array();
foreach ($tables as $key => $value) {
if ($value = $this->_getPortableTableDefinition($value)) {
$list[] = $value;
}
}
return $list;
}
protected function _getPortableTableDefinition($table)
{
return $table;
}
protected function _getPortableUsersList($users)
{
$list = array();
foreach ($users as $key => $value) {
if ($value = $this->_getPortableUserDefinition($value)) {
$list[] = $value;
}
}
return $list;
}
protected function _getPortableUserDefinition($user)
{
return $user;
}
protected function _getPortableViewsList($views)
{
$list = array();
foreach ($views as $key => $value) {
if ($view = $this->_getPortableViewDefinition($value)) {
$viewName = strtolower($view->getQuotedName($this->_platform));
$list[$viewName] = $view;
}
}
return $list;
}
protected function _getPortableViewDefinition($view)
{
return false;
}
protected function _getPortableTableForeignKeysList($tableForeignKeys)
{
$list = array();
foreach ($tableForeignKeys as $key => $value) {
if ($value = $this->_getPortableTableForeignKeyDefinition($value)) {
$list[] = $value;
}
}
return $list;
}
protected function _getPortableTableForeignKeyDefinition($tableForeignKey)
{
return $tableForeignKey;
}
protected function _execSql($sql)
{
foreach ((array) $sql as $query) {
$this->_conn->executeUpdate($query);
}
}
/**
* Create a schema instance for the current database.
*
* @return Schema
*/
public function createSchema()
{
$sequences = array();
if($this->_platform->supportsSequences()) {
$sequences = $this->listSequences();
}
$tables = $this->listTables();
return new Schema($tables, $sequences, $this->createSchemaConfig());
}
/**
* Create the configuration for this schema.
*
* @return SchemaConfig
*/
public function createSchemaConfig()
{
$schemaConfig = new SchemaConfig();
$schemaConfig->setMaxIdentifierLength($this->_platform->getMaxIdentifierLength());
$searchPaths = $this->getSchemaSearchPaths();
if (isset($searchPaths[0])) {
$schemaConfig->setName($searchPaths[0]);
}
return $schemaConfig;
}
/**
* The search path for namespaces in the currently connected database.
*
* The first entry is usually the default namespace in the Schema. All
* further namespaces contain tables/sequences which can also be addressed
* with a short, not full-qualified name.
*
* For databases that don't support subschema/namespaces this method
* returns the name of the currently connected database.
*
* @return array
*/
public function getSchemaSearchPaths()
{
return array($this->_conn->getDatabase());
}
/**
* Given a table comment this method tries to extract a typehint for Doctrine Type, or returns
* the type given as default.
*
* @param string $comment
* @param string $currentType
* @return string
*/
public function extractDoctrineTypeFromComment($comment, $currentType)
{
if (preg_match("(\(DC2Type:([a-zA-Z0-9]+)\))", $comment, $match)) {
$currentType = $match[1];
}
return $currentType;
}
public function removeDoctrineTypeFromComment($comment, $type)
{
return str_replace('(DC2Type:'.$type.')', '', $comment);
}
}

View File

@@ -0,0 +1,423 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
use \Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Schema\Visitor\Visitor;
/**
* Object representation of a database column
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class Column extends AbstractAsset
{
/**
* @var \Doctrine\DBAL\Types\Type
*/
protected $_type;
/**
* @var int
*/
protected $_length = null;
/**
* @var int
*/
protected $_precision = 10;
/**
* @var int
*/
protected $_scale = 0;
/**
* @var bool
*/
protected $_unsigned = false;
/**
* @var bool
*/
protected $_fixed = false;
/**
* @var bool
*/
protected $_notnull = true;
/**
* @var string
*/
protected $_default = null;
/**
* @var bool
*/
protected $_autoincrement = false;
/**
* @var array
*/
protected $_platformOptions = array();
/**
* @var string
*/
protected $_columnDefinition = null;
/**
* @var string
*/
protected $_comment = null;
/**
* @var array
*/
protected $_customSchemaOptions = array();
/**
* Create a new Column
*
* @param string $columnName
* @param Doctrine\DBAL\Types\Type $type
* @param int $length
* @param bool $notNull
* @param mixed $default
* @param bool $unsigned
* @param bool $fixed
* @param int $precision
* @param int $scale
* @param array $platformOptions
*/
public function __construct($columnName, Type $type, array $options=array())
{
$this->_setName($columnName);
$this->setType($type);
$this->setOptions($options);
}
/**
* @param array $options
* @return Column
*/
public function setOptions(array $options)
{
foreach ($options AS $name => $value) {
$method = "set".$name;
if (method_exists($this, $method)) {
$this->$method($value);
}
}
return $this;
}
/**
* @param Type $type
* @return Column
*/
public function setType(Type $type)
{
$this->_type = $type;
return $this;
}
/**
* @param int $length
* @return Column
*/
public function setLength($length)
{
if($length !== null) {
$this->_length = (int)$length;
} else {
$this->_length = null;
}
return $this;
}
/**
* @param int $precision
* @return Column
*/
public function setPrecision($precision)
{
if (!is_numeric($precision)) {
$precision = 10; // defaults to 10 when no valid precision is given.
}
$this->_precision = (int)$precision;
return $this;
}
/**
* @param int $scale
* @return Column
*/
public function setScale($scale)
{
if (!is_numeric($scale)) {
$scale = 0;
}
$this->_scale = (int)$scale;
return $this;
}
/**
*
* @param bool $unsigned
* @return Column
*/
public function setUnsigned($unsigned)
{
$this->_unsigned = (bool)$unsigned;
return $this;
}
/**
*
* @param bool $fixed
* @return Column
*/
public function setFixed($fixed)
{
$this->_fixed = (bool)$fixed;
return $this;
}
/**
* @param bool $notnull
* @return Column
*/
public function setNotnull($notnull)
{
$this->_notnull = (bool)$notnull;
return $this;
}
/**
*
* @param mixed $default
* @return Column
*/
public function setDefault($default)
{
$this->_default = $default;
return $this;
}
/**
*
* @param array $platformOptions
* @return Column
*/
public function setPlatformOptions(array $platformOptions)
{
$this->_platformOptions = $platformOptions;
return $this;
}
/**
*
* @param string $name
* @param mixed $value
* @return Column
*/
public function setPlatformOption($name, $value)
{
$this->_platformOptions[$name] = $value;
return $this;
}
/**
*
* @param string
* @return Column
*/
public function setColumnDefinition($value)
{
$this->_columnDefinition = $value;
return $this;
}
public function getType()
{
return $this->_type;
}
public function getLength()
{
return $this->_length;
}
public function getPrecision()
{
return $this->_precision;
}
public function getScale()
{
return $this->_scale;
}
public function getUnsigned()
{
return $this->_unsigned;
}
public function getFixed()
{
return $this->_fixed;
}
public function getNotnull()
{
return $this->_notnull;
}
public function getDefault()
{
return $this->_default;
}
public function getPlatformOptions()
{
return $this->_platformOptions;
}
public function hasPlatformOption($name)
{
return isset($this->_platformOptions[$name]);
}
public function getPlatformOption($name)
{
return $this->_platformOptions[$name];
}
public function getColumnDefinition()
{
return $this->_columnDefinition;
}
public function getAutoincrement()
{
return $this->_autoincrement;
}
public function setAutoincrement($flag)
{
$this->_autoincrement = $flag;
return $this;
}
public function setComment($comment)
{
$this->_comment = $comment;
return $this;
}
public function getComment()
{
return $this->_comment;
}
/**
* @param string $name
* @param mixed $value
* @return Column
*/
public function setCustomSchemaOption($name, $value)
{
$this->_customSchemaOptions[$name] = $value;
return $this;
}
/**
* @param string $name
* @return boolean
*/
public function hasCustomSchemaOption($name)
{
return isset($this->_customSchemaOptions[$name]);
}
/**
* @param string $name
* @return mixed
*/
public function getCustomSchemaOption($name)
{
return $this->_customSchemaOptions[$name];
}
/**
* @param array $customSchemaOptions
* @return Column
*/
public function setCustomSchemaOptions(array $customSchemaOptions)
{
$this->_customSchemaOptions = $customSchemaOptions;
return $this;
}
/**
* @return array
*/
public function getCustomSchemaOptions()
{
return $this->_customSchemaOptions;
}
/**
* @param Visitor $visitor
*/
public function visit(\Doctrine\DBAL\Schema\Visitor $visitor)
{
$visitor->accept($this);
}
/**
* @return array
*/
public function toArray()
{
return array_merge(array(
'name' => $this->_name,
'type' => $this->_type,
'default' => $this->_default,
'notnull' => $this->_notnull,
'length' => $this->_length,
'precision' => $this->_precision,
'scale' => $this->_scale,
'fixed' => $this->_fixed,
'unsigned' => $this->_unsigned,
'autoincrement' => $this->_autoincrement,
'columnDefinition' => $this->_columnDefinition,
'comment' => $this->_comment,
), $this->_platformOptions, $this->_customSchemaOptions);
}
}

View File

@@ -0,0 +1,58 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* Represent the change of a column
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class ColumnDiff
{
public $oldColumnName;
/**
* @var Column
*/
public $column;
/**
* @var array
*/
public $changedProperties = array();
public function __construct($oldColumnName, Column $column, array $changedProperties = array())
{
$this->oldColumnName = $oldColumnName;
$this->column = $column;
$this->changedProperties = $changedProperties;
}
public function hasChanged($propertyName)
{
return in_array($propertyName, $this->changedProperties);
}
}

View File

@@ -0,0 +1,399 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* Compare to Schemas and return an instance of SchemaDiff
*
* @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
* @license http://ez.no/licenses/new_bsd New BSD License
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class Comparator
{
/**
* @param Schema $fromSchema
* @param Schema $toSchema
* @return SchemaDiff
*/
static public function compareSchemas( Schema $fromSchema, Schema $toSchema )
{
$c = new self();
return $c->compare($fromSchema, $toSchema);
}
/**
* Returns a SchemaDiff object containing the differences between the schemas $fromSchema and $toSchema.
*
* The returned diferences are returned in such a way that they contain the
* operations to change the schema stored in $fromSchema to the schema that is
* stored in $toSchema.
*
* @param Schema $fromSchema
* @param Schema $toSchema
*
* @return SchemaDiff
*/
public function compare(Schema $fromSchema, Schema $toSchema)
{
$diff = new SchemaDiff();
$foreignKeysToTable = array();
foreach ( $toSchema->getTables() AS $table ) {
$tableName = $table->getShortestName($toSchema->getName());
if ( ! $fromSchema->hasTable($tableName)) {
$diff->newTables[$tableName] = $toSchema->getTable($tableName);
} else {
$tableDifferences = $this->diffTable($fromSchema->getTable($tableName), $toSchema->getTable($tableName));
if ($tableDifferences !== false) {
$diff->changedTables[$tableName] = $tableDifferences;
}
}
}
/* Check if there are tables removed */
foreach ($fromSchema->getTables() AS $table) {
$tableName = $table->getShortestName($fromSchema->getName());
$table = $fromSchema->getTable($tableName);
if ( ! $toSchema->hasTable($tableName) ) {
$diff->removedTables[$tableName] = $table;
}
// also remember all foreign keys that point to a specific table
foreach ($table->getForeignKeys() AS $foreignKey) {
$foreignTable = strtolower($foreignKey->getForeignTableName());
if (!isset($foreignKeysToTable[$foreignTable])) {
$foreignKeysToTable[$foreignTable] = array();
}
$foreignKeysToTable[$foreignTable][] = $foreignKey;
}
}
foreach ($diff->removedTables AS $tableName => $table) {
if (isset($foreignKeysToTable[$tableName])) {
$diff->orphanedForeignKeys = array_merge($diff->orphanedForeignKeys, $foreignKeysToTable[$tableName]);
}
}
foreach ($toSchema->getSequences() AS $sequence) {
$sequenceName = $sequence->getShortestName($toSchema->getName());
if (!$fromSchema->hasSequence($sequenceName)) {
$diff->newSequences[] = $sequence;
} else {
if ($this->diffSequence($sequence, $fromSchema->getSequence($sequenceName))) {
$diff->changedSequences[] = $toSchema->getSequence($sequenceName);
}
}
}
foreach ($fromSchema->getSequences() AS $sequence) {
$sequenceName = $sequence->getShortestName($fromSchema->getName());
if (!$toSchema->hasSequence($sequenceName)) {
$diff->removedSequences[] = $sequence;
}
}
return $diff;
}
/**
*
* @param Sequence $sequence1
* @param Sequence $sequence2
*/
public function diffSequence(Sequence $sequence1, Sequence $sequence2)
{
if($sequence1->getAllocationSize() != $sequence2->getAllocationSize()) {
return true;
}
if($sequence1->getInitialValue() != $sequence2->getInitialValue()) {
return true;
}
return false;
}
/**
* Returns the difference between the tables $table1 and $table2.
*
* If there are no differences this method returns the boolean false.
*
* @param Table $table1
* @param Table $table2
*
* @return bool|TableDiff
*/
public function diffTable(Table $table1, Table $table2)
{
$changes = 0;
$tableDifferences = new TableDiff($table1->getName());
$table1Columns = $table1->getColumns();
$table2Columns = $table2->getColumns();
/* See if all the fields in table 1 exist in table 2 */
foreach ( $table2Columns as $columnName => $column ) {
if ( !$table1->hasColumn($columnName) ) {
$tableDifferences->addedColumns[$columnName] = $column;
$changes++;
}
}
/* See if there are any removed fields in table 2 */
foreach ( $table1Columns as $columnName => $column ) {
if ( !$table2->hasColumn($columnName) ) {
$tableDifferences->removedColumns[$columnName] = $column;
$changes++;
}
}
foreach ( $table1Columns as $columnName => $column ) {
if ( $table2->hasColumn($columnName) ) {
$changedProperties = $this->diffColumn( $column, $table2->getColumn($columnName) );
if (count($changedProperties) ) {
$columnDiff = new ColumnDiff($column->getName(), $table2->getColumn($columnName), $changedProperties);
$tableDifferences->changedColumns[$column->getName()] = $columnDiff;
$changes++;
}
}
}
$this->detectColumnRenamings($tableDifferences);
$table1Indexes = $table1->getIndexes();
$table2Indexes = $table2->getIndexes();
foreach ($table2Indexes AS $index2Name => $index2Definition) {
foreach ($table1Indexes AS $index1Name => $index1Definition) {
if ($this->diffIndex($index1Definition, $index2Definition) === false) {
unset($table1Indexes[$index1Name]);
unset($table2Indexes[$index2Name]);
} else {
if ($index1Name == $index2Name) {
$tableDifferences->changedIndexes[$index2Name] = $table2Indexes[$index2Name];
unset($table1Indexes[$index1Name]);
unset($table2Indexes[$index2Name]);
$changes++;
}
}
}
}
foreach ($table1Indexes AS $index1Name => $index1Definition) {
$tableDifferences->removedIndexes[$index1Name] = $index1Definition;
$changes++;
}
foreach ($table2Indexes AS $index2Name => $index2Definition) {
$tableDifferences->addedIndexes[$index2Name] = $index2Definition;
$changes++;
}
$fromFkeys = $table1->getForeignKeys();
$toFkeys = $table2->getForeignKeys();
foreach ($fromFkeys AS $key1 => $constraint1) {
foreach ($toFkeys AS $key2 => $constraint2) {
if($this->diffForeignKey($constraint1, $constraint2) === false) {
unset($fromFkeys[$key1]);
unset($toFkeys[$key2]);
} else {
if (strtolower($constraint1->getName()) == strtolower($constraint2->getName())) {
$tableDifferences->changedForeignKeys[] = $constraint2;
$changes++;
unset($fromFkeys[$key1]);
unset($toFkeys[$key2]);
}
}
}
}
foreach ($fromFkeys AS $key1 => $constraint1) {
$tableDifferences->removedForeignKeys[] = $constraint1;
$changes++;
}
foreach ($toFkeys AS $key2 => $constraint2) {
$tableDifferences->addedForeignKeys[] = $constraint2;
$changes++;
}
return $changes ? $tableDifferences : false;
}
/**
* Try to find columns that only changed their name, rename operations maybe cheaper than add/drop
* however ambiguouties between different possibilites should not lead to renaming at all.
*
* @param TableDiff $tableDifferences
*/
private function detectColumnRenamings(TableDiff $tableDifferences)
{
$renameCandidates = array();
foreach ($tableDifferences->addedColumns AS $addedColumnName => $addedColumn) {
foreach ($tableDifferences->removedColumns AS $removedColumnName => $removedColumn) {
if (count($this->diffColumn($addedColumn, $removedColumn)) == 0) {
$renameCandidates[$addedColumn->getName()][] = array($removedColumn, $addedColumn, $addedColumnName);
}
}
}
foreach ($renameCandidates AS $candidate => $candidateColumns) {
if (count($candidateColumns) == 1) {
list($removedColumn, $addedColumn) = $candidateColumns[0];
$removedColumnName = strtolower($removedColumn->getName());
$addedColumnName = strtolower($addedColumn->getName());
$tableDifferences->renamedColumns[$removedColumnName] = $addedColumn;
unset($tableDifferences->addedColumns[$addedColumnName]);
unset($tableDifferences->removedColumns[$removedColumnName]);
}
}
}
/**
* @param ForeignKeyConstraint $key1
* @param ForeignKeyConstraint $key2
* @return bool
*/
public function diffForeignKey(ForeignKeyConstraint $key1, ForeignKeyConstraint $key2)
{
if (array_map('strtolower', $key1->getLocalColumns()) != array_map('strtolower', $key2->getLocalColumns())) {
return true;
}
if (array_map('strtolower', $key1->getForeignColumns()) != array_map('strtolower', $key2->getForeignColumns())) {
return true;
}
if ($key1->onUpdate() != $key2->onUpdate()) {
return true;
}
if ($key1->onDelete() != $key2->onDelete()) {
return true;
}
return false;
}
/**
* Returns the difference between the fields $field1 and $field2.
*
* If there are differences this method returns $field2, otherwise the
* boolean false.
*
* @param Column $column1
* @param Column $column2
*
* @return array
*/
public function diffColumn(Column $column1, Column $column2)
{
$changedProperties = array();
if ( $column1->getType() != $column2->getType() ) {
$changedProperties[] = 'type';
}
if ($column1->getNotnull() != $column2->getNotnull()) {
$changedProperties[] = 'notnull';
}
if ($column1->getDefault() != $column2->getDefault()) {
$changedProperties[] = 'default';
}
if ($column1->getUnsigned() != $column2->getUnsigned()) {
$changedProperties[] = 'unsigned';
}
if ($column1->getType() instanceof \Doctrine\DBAL\Types\StringType) {
// check if value of length is set at all, default value assumed otherwise.
$length1 = $column1->getLength() ?: 255;
$length2 = $column2->getLength() ?: 255;
if ($length1 != $length2) {
$changedProperties[] = 'length';
}
if ($column1->getFixed() != $column2->getFixed()) {
$changedProperties[] = 'fixed';
}
}
if ($column1->getType() instanceof \Doctrine\DBAL\Types\DecimalType) {
if (($column1->getPrecision()?:10) != ($column2->getPrecision()?:10)) {
$changedProperties[] = 'precision';
}
if ($column1->getScale() != $column2->getScale()) {
$changedProperties[] = 'scale';
}
}
if ($column1->getAutoincrement() != $column2->getAutoincrement()) {
$changedProperties[] = 'autoincrement';
}
// only allow to delete comment if its set to '' not to null.
if ($column1->getComment() !== null && $column1->getComment() != $column2->getComment()) {
$changedProperties[] = 'comment';
}
$options1 = $column1->getCustomSchemaOptions();
$options2 = $column2->getCustomSchemaOptions();
$commonKeys = array_keys(array_intersect_key($options1, $options2));
foreach ($commonKeys as $key) {
if ($options1[$key] !== $options2[$key]) {
$changedProperties[] = $key;
}
}
$diffKeys = array_keys(array_diff_key($options1, $options2) + array_diff_key($options2, $options1));
$changedProperties = array_merge($changedProperties, $diffKeys);
return $changedProperties;
}
/**
* Finds the difference between the indexes $index1 and $index2.
*
* Compares $index1 with $index2 and returns $index2 if there are any
* differences or false in case there are no differences.
*
* @param Index $index1
* @param Index $index2
* @return bool
*/
public function diffIndex(Index $index1, Index $index2)
{
if ($index1->isFullfilledBy($index2) && $index2->isFullfilledBy($index1)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,38 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* Marker interface for contraints
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
interface Constraint
{
public function getName();
public function getColumns();
}

View File

@@ -0,0 +1,214 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Event\SchemaIndexDefinitionEventArgs;
/**
* IBM Db2 Schema Manager
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 1.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class DB2SchemaManager extends AbstractSchemaManager
{
/**
* Return a list of all tables in the current database
*
* Apparently creator is the schema not the user who created it:
* {@link http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=/com.ibm.db29.doc.sqlref/db2z_sysibmsystablestable.htm}
*
* @return array
*/
public function listTableNames()
{
$sql = $this->_platform->getListTablesSQL();
$sql .= " AND CREATOR = UPPER('".$this->_conn->getUsername()."')";
$tables = $this->_conn->fetchAll($sql);
return $this->_getPortableTablesList($tables);
}
/**
* Get Table Column Definition
*
* @param array $tableColumn
* @return Column
*/
protected function _getPortableTableColumnDefinition($tableColumn)
{
$tableColumn = array_change_key_case($tableColumn, \CASE_LOWER);
$length = null;
$fixed = null;
$unsigned = false;
$scale = false;
$precision = false;
$type = $this->_platform->getDoctrineTypeMapping($tableColumn['typename']);
switch (strtolower($tableColumn['typename'])) {
case 'varchar':
$length = $tableColumn['length'];
$fixed = false;
break;
case 'character':
$length = $tableColumn['length'];
$fixed = true;
break;
case 'clob':
$length = $tableColumn['length'];
break;
case 'decimal':
case 'double':
case 'real':
$scale = $tableColumn['scale'];
$precision = $tableColumn['length'];
break;
}
$options = array(
'length' => $length,
'unsigned' => (bool)$unsigned,
'fixed' => (bool)$fixed,
'default' => ($tableColumn['default'] == "NULL") ? null : $tableColumn['default'],
'notnull' => (bool) ($tableColumn['nulls'] == 'N'),
'scale' => null,
'precision' => null,
'platformOptions' => array(),
);
if ($scale !== null && $precision !== null) {
$options['scale'] = $scale;
$options['precision'] = $precision;
}
return new Column($tableColumn['colname'], \Doctrine\DBAL\Types\Type::getType($type), $options);
}
protected function _getPortableTablesList($tables)
{
$tableNames = array();
foreach ($tables AS $tableRow) {
$tableRow = array_change_key_case($tableRow, \CASE_LOWER);
$tableNames[] = $tableRow['name'];
}
return $tableNames;
}
protected function _getPortableTableIndexesList($tableIndexes, $tableName=null)
{
$eventManager = $this->_platform->getEventManager();
$tableIndexRows = array();
$indexes = array();
foreach($tableIndexes AS $indexKey => $data) {
$data = array_change_key_case($data, \CASE_LOWER);
$unique = ($data['uniquerule'] == "D") ? false : true;
$primary = ($data['uniquerule'] == "P");
$indexName = strtolower($data['name']);
if ($primary) {
$keyName = 'primary';
} else {
$keyName = $indexName;
}
$data = array(
'name' => $indexName,
'columns' => explode("+", ltrim($data['colnames'], '+')),
'unique' => $unique,
'primary' => $primary
);
$index = null;
$defaultPrevented = false;
if (null !== $eventManager && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) {
$eventArgs = new SchemaIndexDefinitionEventArgs($data, $tableName, $this->_conn);
$eventManager->dispatchEvent(Events::onSchemaIndexDefinition, $eventArgs);
$defaultPrevented = $eventArgs->isDefaultPrevented();
$index = $eventArgs->getIndex();
}
if (!$defaultPrevented) {
$index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary']);
}
if ($index) {
$indexes[$indexKey] = $index;
}
}
return $indexes;
}
protected function _getPortableTableForeignKeyDefinition($tableForeignKey)
{
$tableForeignKey = array_change_key_case($tableForeignKey, CASE_LOWER);
$tableForeignKey['deleterule'] = $this->_getPortableForeignKeyRuleDef($tableForeignKey['deleterule']);
$tableForeignKey['updaterule'] = $this->_getPortableForeignKeyRuleDef($tableForeignKey['updaterule']);
return new ForeignKeyConstraint(
array_map('trim', (array)$tableForeignKey['fkcolnames']),
$tableForeignKey['reftbname'],
array_map('trim', (array)$tableForeignKey['pkcolnames']),
$tableForeignKey['relname'],
array(
'onUpdate' => $tableForeignKey['updaterule'],
'onDelete' => $tableForeignKey['deleterule'],
)
);
}
protected function _getPortableForeignKeyRuleDef($def)
{
if ($def == "C") {
return "CASCADE";
} else if ($def == "N") {
return "SET NULL";
}
return null;
}
protected function _getPortableViewDefinition($view)
{
$view = array_change_key_case($view, \CASE_LOWER);
// sadly this still segfaults on PDO_IBM, see http://pecl.php.net/bugs/bug.php?id=17199
//$view['text'] = (is_resource($view['text']) ? stream_get_contents($view['text']) : $view['text']);
if (!is_resource($view['text'])) {
$pos = strpos($view['text'], ' AS ');
$sql = substr($view['text'], $pos+4);
} else {
$sql = '';
}
return new View($view['name'], $sql);
}
}

View File

@@ -0,0 +1,164 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Schema\Visitor\Visitor;
class ForeignKeyConstraint extends AbstractAsset implements Constraint
{
/**
* @var Table
*/
protected $_localTable;
/**
* @var array
*/
protected $_localColumnNames;
/**
* @var string
*/
protected $_foreignTableName;
/**
* @var array
*/
protected $_foreignColumnNames;
/**
* @var string
*/
protected $_cascade = '';
/**
* @var array
*/
protected $_options;
/**
*
* @param array $localColumnNames
* @param string $foreignTableName
* @param array $foreignColumnNames
* @param string $cascade
* @param string|null $name
*/
public function __construct(array $localColumnNames, $foreignTableName, array $foreignColumnNames, $name=null, array $options=array())
{
$this->_setName($name);
$this->_localColumnNames = $localColumnNames;
$this->_foreignTableName = $foreignTableName;
$this->_foreignColumnNames = $foreignColumnNames;
$this->_options = $options;
}
/**
* @return string
*/
public function getLocalTableName()
{
return $this->_localTable->getName();
}
/**
* @param Table $table
*/
public function setLocalTable(Table $table)
{
$this->_localTable = $table;
}
/**
* @return array
*/
public function getLocalColumns()
{
return $this->_localColumnNames;
}
public function getColumns()
{
return $this->_localColumnNames;
}
/**
* @return string
*/
public function getForeignTableName()
{
return $this->_foreignTableName;
}
/**
* @return array
*/
public function getForeignColumns()
{
return $this->_foreignColumnNames;
}
public function hasOption($name)
{
return isset($this->_options[$name]);
}
public function getOption($name)
{
return $this->_options[$name];
}
/**
* Foreign Key onUpdate status
*
* @return string|null
*/
public function onUpdate()
{
return $this->_onEvent('onUpdate');
}
/**
* Foreign Key onDelete status
*
* @return string|null
*/
public function onDelete()
{
return $this->_onEvent('onDelete');
}
/**
* @param string $event
* @return string|null
*/
private function _onEvent($event)
{
if (isset($this->_options[$event])) {
$onEvent = strtoupper($this->_options[$event]);
if (!in_array($onEvent, array('NO ACTION', 'RESTRICT'))) {
return $onEvent;
}
}
return false;
}
}

View File

@@ -0,0 +1,188 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Schema\Visitor\Visitor;
class Index extends AbstractAsset implements Constraint
{
/**
* @var array
*/
protected $_columns;
/**
* @var bool
*/
protected $_isUnique = false;
/**
* @var bool
*/
protected $_isPrimary = false;
/**
* @param string $indexName
* @param array $column
* @param bool $isUnique
* @param bool $isPrimary
*/
public function __construct($indexName, array $columns, $isUnique=false, $isPrimary=false)
{
$isUnique = ($isPrimary)?true:$isUnique;
$this->_setName($indexName);
$this->_isUnique = $isUnique;
$this->_isPrimary = $isPrimary;
foreach($columns AS $column) {
$this->_addColumn($column);
}
}
/**
* @param string $column
*/
protected function _addColumn($column)
{
if(is_string($column)) {
$this->_columns[] = $column;
} else {
throw new \InvalidArgumentException("Expecting a string as Index Column");
}
}
/**
* @return array
*/
public function getColumns()
{
return $this->_columns;
}
/**
* Is the index neither unique nor primary key?
*
* @return bool
*/
public function isSimpleIndex()
{
return !$this->_isPrimary && !$this->_isUnique;
}
/**
* @return bool
*/
public function isUnique()
{
return $this->_isUnique;
}
/**
* @return bool
*/
public function isPrimary()
{
return $this->_isPrimary;
}
/**
* @param string $columnName
* @param int $pos
* @return bool
*/
public function hasColumnAtPosition($columnName, $pos=0)
{
$columnName = strtolower($columnName);
$indexColumns = \array_map('strtolower', $this->getColumns());
return \array_search($columnName, $indexColumns) === $pos;
}
/**
* Check if this index exactly spans the given column names in the correct order.
*
* @param array $columnNames
* @return boolean
*/
public function spansColumns(array $columnNames)
{
$sameColumns = true;
for ($i = 0; $i < count($this->_columns); $i++) {
if (!isset($columnNames[$i]) || strtolower($this->_columns[$i]) != strtolower($columnNames[$i])) {
$sameColumns = false;
}
}
return $sameColumns;
}
/**
* Check if the other index already fullfills all the indexing and constraint needs of the current one.
*
* @param Index $other
* @return bool
*/
public function isFullfilledBy(Index $other)
{
// allow the other index to be equally large only. It being larger is an option
// but it creates a problem with scenarios of the kind PRIMARY KEY(foo,bar) UNIQUE(foo)
if (count($other->getColumns()) != count($this->getColumns())) {
return false;
}
// Check if columns are the same, and even in the same order
$sameColumns = $this->spansColumns($other->getColumns());
if ($sameColumns) {
if (!$this->isUnique() && !$this->isPrimary()) {
// this is a special case: If the current key is neither primary or unique, any uniqe or
// primary key will always have the same effect for the index and there cannot be any constraint
// overlaps. This means a primary or unique index can always fullfill the requirements of just an
// index that has no constraints.
return true;
} else if ($other->isPrimary() != $this->isPrimary()) {
return false;
} else if ($other->isUnique() != $this->isUnique()) {
return false;
}
return true;
}
return false;
}
/**
* Detect if the other index is a non-unique, non primary index that can be overwritten by this one.
*
* @param Index $other
* @return bool
*/
public function overrules(Index $other)
{
if ($other->isPrimary()) {
return false;
} else if ($this->isSimpleIndex() && $other->isUnique()) {
return false;
}
if ($this->spansColumns($other->getColumns()) && ($this->isPrimary() || $this->isUnique())) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,211 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* Schema manager for the MySql RDBMS.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Roman Borschel <roman@code-factory.org>
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @version $Revision$
* @since 2.0
*/
class MySqlSchemaManager extends AbstractSchemaManager
{
protected function _getPortableViewDefinition($view)
{
return new View($view['TABLE_NAME'], $view['VIEW_DEFINITION']);
}
protected function _getPortableTableDefinition($table)
{
return array_shift($table);
}
protected function _getPortableUserDefinition($user)
{
return array(
'user' => $user['User'],
'password' => $user['Password'],
);
}
protected function _getPortableTableIndexesList($tableIndexes, $tableName=null)
{
foreach($tableIndexes AS $k => $v) {
$v = array_change_key_case($v, CASE_LOWER);
if($v['key_name'] == 'PRIMARY') {
$v['primary'] = true;
} else {
$v['primary'] = false;
}
$tableIndexes[$k] = $v;
}
return parent::_getPortableTableIndexesList($tableIndexes, $tableName);
}
protected function _getPortableSequenceDefinition($sequence)
{
return end($sequence);
}
protected function _getPortableDatabaseDefinition($database)
{
return $database['Database'];
}
/**
* Gets a portable column definition.
*
* The database type is mapped to a corresponding Doctrine mapping type.
*
* @param $tableColumn
* @return array
*/
protected function _getPortableTableColumnDefinition($tableColumn)
{
$tableColumn = array_change_key_case($tableColumn, CASE_LOWER);
$dbType = strtolower($tableColumn['type']);
$dbType = strtok($dbType, '(), ');
if (isset($tableColumn['length'])) {
$length = $tableColumn['length'];
$decimal = '';
} else {
$length = strtok('(), ');
$decimal = strtok('(), ') ? strtok('(), '):null;
}
$type = array();
$unsigned = $fixed = null;
if ( ! isset($tableColumn['name'])) {
$tableColumn['name'] = '';
}
$scale = null;
$precision = null;
$type = $this->_platform->getDoctrineTypeMapping($dbType);
$type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type);
$tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type);
switch ($dbType) {
case 'char':
$fixed = true;
break;
case 'float':
case 'double':
case 'real':
case 'numeric':
case 'decimal':
if(preg_match('([A-Za-z]+\(([0-9]+)\,([0-9]+)\))', $tableColumn['type'], $match)) {
$precision = $match[1];
$scale = $match[2];
$length = null;
}
break;
case 'tinyint':
case 'smallint':
case 'mediumint':
case 'int':
case 'integer':
case 'bigint':
case 'tinyblob':
case 'mediumblob':
case 'longblob':
case 'blob':
case 'year':
$length = null;
break;
}
$length = ((int) $length == 0) ? null : (int) $length;
$def = array(
'type' => $type,
'length' => $length,
'unsigned' => (bool) $unsigned,
'fixed' => (bool) $fixed
);
$options = array(
'length' => $length,
'unsigned' => (bool)$unsigned,
'fixed' => (bool)$fixed,
'default' => isset($tableColumn['default']) ? $tableColumn['default'] : null,
'notnull' => (bool) ($tableColumn['null'] != 'YES'),
'scale' => null,
'precision' => null,
'autoincrement' => (bool) (strpos($tableColumn['extra'], 'auto_increment') !== false),
'comment' => (isset($tableColumn['comment'])) ? $tableColumn['comment'] : null
);
if ($scale !== null && $precision !== null) {
$options['scale'] = $scale;
$options['precision'] = $precision;
}
return new Column($tableColumn['field'], \Doctrine\DBAL\Types\Type::getType($type), $options);
}
protected function _getPortableTableForeignKeysList($tableForeignKeys)
{
$list = array();
foreach ($tableForeignKeys as $key => $value) {
$value = array_change_key_case($value, CASE_LOWER);
if (!isset($list[$value['constraint_name']])) {
if (!isset($value['delete_rule']) || $value['delete_rule'] == "RESTRICT") {
$value['delete_rule'] = null;
}
if (!isset($value['update_rule']) || $value['update_rule'] == "RESTRICT") {
$value['update_rule'] = null;
}
$list[$value['constraint_name']] = array(
'name' => $value['constraint_name'],
'local' => array(),
'foreign' => array(),
'foreignTable' => $value['referenced_table_name'],
'onDelete' => $value['delete_rule'],
'onUpdate' => $value['update_rule'],
);
}
$list[$value['constraint_name']]['local'][] = $value['column_name'];
$list[$value['constraint_name']]['foreign'][] = $value['referenced_column_name'];
}
$result = array();
foreach($list AS $constraint) {
$result[] = new ForeignKeyConstraint(
array_values($constraint['local']), $constraint['foreignTable'],
array_values($constraint['foreign']), $constraint['name'],
array(
'onDelete' => $constraint['onDelete'],
'onUpdate' => $constraint['onUpdate'],
)
);
}
return $result;
}
}

View File

@@ -0,0 +1,286 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* Oracle Schema Manager
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @version $Revision$
* @since 2.0
*/
class OracleSchemaManager extends AbstractSchemaManager
{
protected function _getPortableViewDefinition($view)
{
$view = \array_change_key_case($view, CASE_LOWER);
return new View($view['view_name'], $view['text']);
}
protected function _getPortableUserDefinition($user)
{
$user = \array_change_key_case($user, CASE_LOWER);
return array(
'user' => $user['username'],
);
}
protected function _getPortableTableDefinition($table)
{
$table = \array_change_key_case($table, CASE_LOWER);
return $table['table_name'];
}
/**
* @license New BSD License
* @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html
* @param array $tableIndexes
* @param string $tableName
* @return array
*/
protected function _getPortableTableIndexesList($tableIndexes, $tableName=null)
{
$indexBuffer = array();
foreach ( $tableIndexes as $tableIndex ) {
$tableIndex = \array_change_key_case($tableIndex, CASE_LOWER);
$keyName = strtolower($tableIndex['name']);
if ( strtolower($tableIndex['is_primary']) == "p" ) {
$keyName = 'primary';
$buffer['primary'] = true;
$buffer['non_unique'] = false;
} else {
$buffer['primary'] = false;
$buffer['non_unique'] = ( $tableIndex['is_unique'] == 0 ) ? true : false;
}
$buffer['key_name'] = $keyName;
$buffer['column_name'] = $tableIndex['column_name'];
$indexBuffer[] = $buffer;
}
return parent::_getPortableTableIndexesList($indexBuffer, $tableName);
}
protected function _getPortableTableColumnDefinition($tableColumn)
{
$tableColumn = \array_change_key_case($tableColumn, CASE_LOWER);
$dbType = strtolower($tableColumn['data_type']);
if(strpos($dbType, "timestamp(") === 0) {
if (strpos($dbType, "WITH TIME ZONE")) {
$dbType = "timestamptz";
} else {
$dbType = "timestamp";
}
}
$type = array();
$length = $unsigned = $fixed = null;
if ( ! empty($tableColumn['data_length'])) {
$length = $tableColumn['data_length'];
}
if ( ! isset($tableColumn['column_name'])) {
$tableColumn['column_name'] = '';
}
if (stripos($tableColumn['data_default'], 'NULL') !== null) {
$tableColumn['data_default'] = null;
}
$precision = null;
$scale = null;
$type = $this->_platform->getDoctrineTypeMapping($dbType);
$type = $this->extractDoctrineTypeFromComment($tableColumn['comments'], $type);
$tableColumn['comments'] = $this->removeDoctrineTypeFromComment($tableColumn['comments'], $type);
switch ($dbType) {
case 'number':
if ($tableColumn['data_precision'] == 20 && $tableColumn['data_scale'] == 0) {
$precision = 20;
$scale = 0;
$type = 'bigint';
} elseif ($tableColumn['data_precision'] == 5 && $tableColumn['data_scale'] == 0) {
$type = 'smallint';
$precision = 5;
$scale = 0;
} elseif ($tableColumn['data_precision'] == 1 && $tableColumn['data_scale'] == 0) {
$precision = 1;
$scale = 0;
$type = 'boolean';
} elseif ($tableColumn['data_scale'] > 0) {
$precision = $tableColumn['data_precision'];
$scale = $tableColumn['data_scale'];
$type = 'decimal';
}
$length = null;
break;
case 'pls_integer':
case 'binary_integer':
$length = null;
break;
case 'varchar':
case 'varchar2':
case 'nvarchar2':
$length = $tableColumn['char_length'];
$fixed = false;
break;
case 'char':
case 'nchar':
$length = $tableColumn['char_length'];
$fixed = true;
break;
case 'date':
case 'timestamp':
$length = null;
break;
case 'float':
$precision = $tableColumn['data_precision'];
$scale = $tableColumn['data_scale'];
$length = null;
break;
case 'clob':
case 'nclob':
$length = null;
break;
case 'blob':
case 'raw':
case 'long raw':
case 'bfile':
$length = null;
break;
case 'rowid':
case 'urowid':
default:
$length = null;
}
$options = array(
'notnull' => (bool) ($tableColumn['nullable'] === 'N'),
'fixed' => (bool) $fixed,
'unsigned' => (bool) $unsigned,
'default' => $tableColumn['data_default'],
'length' => $length,
'precision' => $precision,
'scale' => $scale,
'comment' => (isset($tableColumn['comments'])) ? $tableColumn['comments'] : null,
'platformDetails' => array(),
);
return new Column($tableColumn['column_name'], \Doctrine\DBAL\Types\Type::getType($type), $options);
}
protected function _getPortableTableForeignKeysList($tableForeignKeys)
{
$list = array();
foreach ($tableForeignKeys as $key => $value) {
$value = \array_change_key_case($value, CASE_LOWER);
if (!isset($list[$value['constraint_name']])) {
if ($value['delete_rule'] == "NO ACTION") {
$value['delete_rule'] = null;
}
$list[$value['constraint_name']] = array(
'name' => $value['constraint_name'],
'local' => array(),
'foreign' => array(),
'foreignTable' => $value['references_table'],
'onDelete' => $value['delete_rule'],
);
}
$list[$value['constraint_name']]['local'][$value['position']] = $value['local_column'];
$list[$value['constraint_name']]['foreign'][$value['position']] = $value['foreign_column'];
}
$result = array();
foreach($list AS $constraint) {
$result[] = new ForeignKeyConstraint(
array_values($constraint['local']), $constraint['foreignTable'],
array_values($constraint['foreign']), $constraint['name'],
array('onDelete' => $constraint['onDelete'])
);
}
return $result;
}
protected function _getPortableSequenceDefinition($sequence)
{
$sequence = \array_change_key_case($sequence, CASE_LOWER);
return new Sequence($sequence['sequence_name'], $sequence['increment_by'], $sequence['min_value']);
}
protected function _getPortableFunctionDefinition($function)
{
$function = \array_change_key_case($function, CASE_LOWER);
return $function['name'];
}
protected function _getPortableDatabaseDefinition($database)
{
$database = \array_change_key_case($database, CASE_LOWER);
return $database['username'];
}
public function createDatabase($database = null)
{
if (is_null($database)) {
$database = $this->_conn->getDatabase();
}
$params = $this->_conn->getParams();
$username = $database;
$password = $params['password'];
$query = 'CREATE USER ' . $username . ' IDENTIFIED BY ' . $password;
$result = $this->_conn->executeUpdate($query);
$query = 'GRANT CREATE SESSION, CREATE TABLE, UNLIMITED TABLESPACE, CREATE SEQUENCE, CREATE TRIGGER TO ' . $username;
$result = $this->_conn->executeUpdate($query);
return true;
}
public function dropAutoincrement($table)
{
$sql = $this->_platform->getDropAutoincrementSql($table);
foreach ($sql as $query) {
$this->_conn->executeUpdate($query);
}
return true;
}
public function dropTable($name)
{
$this->dropAutoincrement($name);
return parent::dropTable($name);
}
}

View File

@@ -0,0 +1,359 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* PostgreSQL Schema Manager
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @since 2.0
*/
class PostgreSqlSchemaManager extends AbstractSchemaManager
{
/**
* @var array
*/
private $existingSchemaPaths;
/**
* Get all the existing schema names.
*
* @return array
*/
public function getSchemaNames()
{
$rows = $this->_conn->fetchAll("SELECT nspname as schema_name FROM pg_namespace WHERE nspname !~ '^pg_.*' and nspname != 'information_schema'");
return array_map(function($v) { return $v['schema_name']; }, $rows);
}
/**
* Return an array of schema search paths
*
* This is a PostgreSQL only function.
*
* @return array
*/
public function getSchemaSearchPaths()
{
$params = $this->_conn->getParams();
$schema = explode(",", $this->_conn->fetchColumn('SHOW search_path'));
if (isset($params['user'])) {
$schema = str_replace('"$user"', $params['user'], $schema);
}
return $schema;
}
/**
* Get names of all existing schemas in the current users search path.
*
* This is a PostgreSQL only function.
*
* @return array
*/
public function getExistingSchemaSearchPaths()
{
if ($this->existingSchemaPaths === null) {
$this->determineExistingSchemaSearchPaths();
}
return $this->existingSchemaPaths;
}
/**
* Use this to set or reset the order of the existing schemas in the current search path of the user
*
* This is a PostgreSQL only function.
*
* @return type
*/
public function determineExistingSchemaSearchPaths()
{
$names = $this->getSchemaNames();
$paths = $this->getSchemaSearchPaths();
$this->existingSchemaPaths = array_filter($paths, function ($v) use ($names) {
return in_array($v, $names);
});
}
protected function _getPortableTableForeignKeyDefinition($tableForeignKey)
{
$onUpdate = null;
$onDelete = null;
if (preg_match('(ON UPDATE ([a-zA-Z0-9]+( (NULL|ACTION|DEFAULT))?))', $tableForeignKey['condef'], $match)) {
$onUpdate = $match[1];
}
if (preg_match('(ON DELETE ([a-zA-Z0-9]+( (NULL|ACTION|DEFAULT))?))', $tableForeignKey['condef'], $match)) {
$onDelete = $match[1];
}
if (preg_match('/FOREIGN KEY \((.+)\) REFERENCES (.+)\((.+)\)/', $tableForeignKey['condef'], $values)) {
// PostgreSQL returns identifiers that are keywords with quotes, we need them later, don't get
// the idea to trim them here.
$localColumns = array_map('trim', explode(",", $values[1]));
$foreignColumns = array_map('trim', explode(",", $values[3]));
$foreignTable = $values[2];
}
return new ForeignKeyConstraint(
$localColumns, $foreignTable, $foreignColumns, $tableForeignKey['conname'],
array('onUpdate' => $onUpdate, 'onDelete' => $onDelete)
);
}
public function dropDatabase($database)
{
$params = $this->_conn->getParams();
$params["dbname"] = "postgres";
$tmpPlatform = $this->_platform;
$tmpConn = $this->_conn;
$this->_conn = \Doctrine\DBAL\DriverManager::getConnection($params);
$this->_platform = $this->_conn->getDatabasePlatform();
parent::dropDatabase($database);
$this->_platform = $tmpPlatform;
$this->_conn = $tmpConn;
}
public function createDatabase($database)
{
$params = $this->_conn->getParams();
$params["dbname"] = "postgres";
$tmpPlatform = $this->_platform;
$tmpConn = $this->_conn;
$this->_conn = \Doctrine\DBAL\DriverManager::getConnection($params);
$this->_platform = $this->_conn->getDatabasePlatform();
parent::createDatabase($database);
$this->_platform = $tmpPlatform;
$this->_conn = $tmpConn;
}
protected function _getPortableTriggerDefinition($trigger)
{
return $trigger['trigger_name'];
}
protected function _getPortableViewDefinition($view)
{
return new View($view['viewname'], $view['definition']);
}
protected function _getPortableUserDefinition($user)
{
return array(
'user' => $user['usename'],
'password' => $user['passwd']
);
}
protected function _getPortableTableDefinition($table)
{
$schemas = $this->getExistingSchemaSearchPaths();
$firstSchema = array_shift($schemas);
if ($table['schema_name'] == $firstSchema) {
return $table['table_name'];
} else {
return $table['schema_name'] . "." . $table['table_name'];
}
}
/**
* @license New BSD License
* @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html
* @param array $tableIndexes
* @param string $tableName
* @return array
*/
protected function _getPortableTableIndexesList($tableIndexes, $tableName=null)
{
$buffer = array();
foreach ($tableIndexes AS $row) {
$colNumbers = explode(' ', $row['indkey']);
$colNumbersSql = 'IN (' . join(' ,', $colNumbers) . ' )';
$columnNameSql = "SELECT attnum, attname FROM pg_attribute
WHERE attrelid={$row['indrelid']} AND attnum $colNumbersSql ORDER BY attnum ASC;";
$stmt = $this->_conn->executeQuery($columnNameSql);
$indexColumns = $stmt->fetchAll();
// required for getting the order of the columns right.
foreach ($colNumbers AS $colNum) {
foreach ($indexColumns as $colRow) {
if ($colNum == $colRow['attnum']) {
$buffer[] = array(
'key_name' => $row['relname'],
'column_name' => trim($colRow['attname']),
'non_unique' => !$row['indisunique'],
'primary' => $row['indisprimary']
);
}
}
}
}
return parent::_getPortableTableIndexesList($buffer, $tableName);
}
protected function _getPortableDatabaseDefinition($database)
{
return $database['datname'];
}
protected function _getPortableSequenceDefinition($sequence)
{
if ($sequence['schemaname'] != 'public') {
$sequenceName = $sequence['schemaname'] . "." . $sequence['relname'];
} else {
$sequenceName = $sequence['relname'];
}
$data = $this->_conn->fetchAll('SELECT min_value, increment_by FROM ' . $sequenceName);
return new Sequence($sequenceName, $data[0]['increment_by'], $data[0]['min_value']);
}
protected function _getPortableTableColumnDefinition($tableColumn)
{
$tableColumn = array_change_key_case($tableColumn, CASE_LOWER);
if (strtolower($tableColumn['type']) === 'varchar') {
// get length from varchar definition
$length = preg_replace('~.*\(([0-9]*)\).*~', '$1', $tableColumn['complete_type']);
$tableColumn['length'] = $length;
}
$matches = array();
$autoincrement = false;
if (preg_match("/^nextval\('(.*)'(::.*)?\)$/", $tableColumn['default'], $matches)) {
$tableColumn['sequence'] = $matches[1];
$tableColumn['default'] = null;
$autoincrement = true;
}
if (stripos($tableColumn['default'], 'NULL') === 0) {
$tableColumn['default'] = null;
}
$length = (isset($tableColumn['length'])) ? $tableColumn['length'] : null;
if ($length == '-1' && isset($tableColumn['atttypmod'])) {
$length = $tableColumn['atttypmod'] - 4;
}
if ((int) $length <= 0) {
$length = null;
}
$fixed = null;
if (!isset($tableColumn['name'])) {
$tableColumn['name'] = '';
}
$precision = null;
$scale = null;
$dbType = strtolower($tableColumn['type']);
if (strlen($tableColumn['domain_type']) && !$this->_platform->hasDoctrineTypeMappingFor($tableColumn['type'])) {
$dbType = strtolower($tableColumn['domain_type']);
$tableColumn['complete_type'] = $tableColumn['domain_complete_type'];
}
$type = $this->_platform->getDoctrineTypeMapping($dbType);
$type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type);
$tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type);
switch ($dbType) {
case 'smallint':
case 'int2':
$length = null;
break;
case 'int':
case 'int4':
case 'integer':
$length = null;
break;
case 'bigint':
case 'int8':
$length = null;
break;
case 'bool':
case 'boolean':
$length = null;
break;
case 'text':
$fixed = false;
break;
case 'varchar':
case 'interval':
case '_varchar':
$fixed = false;
break;
case 'char':
case 'bpchar':
$fixed = true;
break;
case 'float':
case 'float4':
case 'float8':
case 'double':
case 'double precision':
case 'real':
case 'decimal':
case 'money':
case 'numeric':
if (preg_match('([A-Za-z]+\(([0-9]+)\,([0-9]+)\))', $tableColumn['complete_type'], $match)) {
$precision = $match[1];
$scale = $match[2];
$length = null;
}
break;
case 'year':
$length = null;
break;
}
if ($tableColumn['default'] && preg_match("('([^']+)'::)", $tableColumn['default'], $match)) {
$tableColumn['default'] = $match[1];
}
$options = array(
'length' => $length,
'notnull' => (bool) $tableColumn['isnotnull'],
'default' => $tableColumn['default'],
'primary' => (bool) ($tableColumn['pri'] == 't'),
'precision' => $precision,
'scale' => $scale,
'fixed' => $fixed,
'unsigned' => false,
'autoincrement' => $autoincrement,
'comment' => $tableColumn['comment'],
);
return new Column($tableColumn['field'], \Doctrine\DBAL\Types\Type::getType($type), $options);
}
}

View File

@@ -0,0 +1,247 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Event\SchemaIndexDefinitionEventArgs;
use Doctrine\DBAL\Events;
/**
* SQL Server Schema Manager
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Juozas Kaziukenas <juozas@juokaz.com>
* @since 2.0
*/
class SQLServerSchemaManager extends AbstractSchemaManager
{
/**
* @override
*/
protected function _getPortableTableColumnDefinition($tableColumn)
{
$dbType = strtolower($tableColumn['TYPE_NAME']);
$autoincrement = false;
if (stripos($dbType, 'identity')) {
$dbType = trim(str_ireplace('identity', '', $dbType));
$autoincrement = true;
}
$type = array();
$unsigned = $fixed = null;
if (!isset($tableColumn['name'])) {
$tableColumn['name'] = '';
}
$default = $tableColumn['COLUMN_DEF'];
while ($default != ($default2 = preg_replace("/^\((.*)\)$/", '$1', $default))) {
$default = trim($default2, "'");
}
$length = (int) $tableColumn['LENGTH'];
$type = $this->_platform->getDoctrineTypeMapping($dbType);
switch ($type) {
case 'char':
if ($tableColumn['LENGTH'] == '1') {
$type = 'boolean';
if (preg_match('/^(is|has)/', $tableColumn['name'])) {
$type = array_reverse($type);
}
}
$fixed = true;
break;
case 'text':
$fixed = false;
break;
}
switch ($dbType) {
case 'nchar':
case 'nvarchar':
case 'ntext':
// Unicode data requires 2 bytes per character
$length = $length / 2;
break;
}
$options = array(
'length' => ($length == 0 || !in_array($type, array('text', 'string'))) ? null : $length,
'unsigned' => (bool) $unsigned,
'fixed' => (bool) $fixed,
'default' => $default !== 'NULL' ? $default : null,
'notnull' => (bool) ($tableColumn['IS_NULLABLE'] != 'YES'),
'scale' => $tableColumn['SCALE'],
'precision' => $tableColumn['PRECISION'],
'autoincrement' => $autoincrement,
);
return new Column($tableColumn['COLUMN_NAME'], \Doctrine\DBAL\Types\Type::getType($type), $options);
}
/**
* @override
*/
protected function _getPortableTableIndexesList($tableIndexRows, $tableName=null)
{
$result = array();
foreach ($tableIndexRows AS $tableIndex) {
$indexName = $keyName = $tableIndex['index_name'];
if (strpos($tableIndex['index_description'], 'primary key') !== false) {
$keyName = 'primary';
}
$keyName = strtolower($keyName);
$result[$keyName] = array(
'name' => $indexName,
'columns' => explode(', ', $tableIndex['index_keys']),
'unique' => strpos($tableIndex['index_description'], 'unique') !== false,
'primary' => strpos($tableIndex['index_description'], 'primary key') !== false,
);
}
$eventManager = $this->_platform->getEventManager();
$indexes = array();
foreach ($result AS $indexKey => $data) {
$index = null;
$defaultPrevented = false;
if (null !== $eventManager && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) {
$eventArgs = new SchemaIndexDefinitionEventArgs($data, $tableName, $this->_conn);
$eventManager->dispatchEvent(Events::onSchemaIndexDefinition, $eventArgs);
$defaultPrevented = $eventArgs->isDefaultPrevented();
$index = $eventArgs->getIndex();
}
if (!$defaultPrevented) {
$index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary']);
}
if ($index) {
$indexes[$indexKey] = $index;
}
}
return $indexes;
}
/**
* @override
*/
public function _getPortableTableForeignKeyDefinition($tableForeignKey)
{
return new ForeignKeyConstraint(
(array) $tableForeignKey['ColumnName'],
$tableForeignKey['ReferenceTableName'],
(array) $tableForeignKey['ReferenceColumnName'],
$tableForeignKey['ForeignKey'],
array(
'onUpdate' => str_replace('_', ' ', $tableForeignKey['update_referential_action_desc']),
'onDelete' => str_replace('_', ' ', $tableForeignKey['delete_referential_action_desc']),
)
);
}
/**
* @override
*/
protected function _getPortableTableDefinition($table)
{
return $table['name'];
}
/**
* @override
*/
protected function _getPortableDatabaseDefinition($database)
{
return $database['name'];
}
/**
* @override
*/
protected function _getPortableViewDefinition($view)
{
// @todo
return new View($view['name'], null);
}
/**
* List the indexes for a given table returning an array of Index instances.
*
* Keys of the portable indexes list are all lower-cased.
*
* @param string $table The name of the table
* @return Index[] $tableIndexes
*/
public function listTableIndexes($table)
{
$sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase());
try {
$tableIndexes = $this->_conn->fetchAll($sql);
} catch(\PDOException $e) {
if ($e->getCode() == "IMSSP") {
return array();
} else {
throw $e;
}
}
return $this->_getPortableTableIndexesList($tableIndexes, $table);
}
/**
* @override
*/
public function alterTable(TableDiff $tableDiff)
{
if(count($tableDiff->removedColumns) > 0) {
foreach($tableDiff->removedColumns as $col){
$columnConstraintSql = $this->getColumnConstraintSQL($tableDiff->name, $col->getName());
foreach ($this->_conn->fetchAll($columnConstraintSql) as $constraint) {
$this->_conn->exec("ALTER TABLE $tableDiff->name DROP CONSTRAINT " . $constraint['Name']);
}
}
}
return parent::alterTable($tableDiff);
}
/**
* This function retrieves the constraints for a given column.
*/
private function getColumnConstraintSQL($table, $column)
{
return "SELECT SysObjects.[Name]
FROM SysObjects INNER JOIN (SELECT [Name],[ID] FROM SysObjects WHERE XType = 'U') AS Tab
ON Tab.[ID] = Sysobjects.[Parent_Obj]
INNER JOIN sys.default_constraints DefCons ON DefCons.[object_id] = Sysobjects.[ID]
INNER JOIN SysColumns Col ON Col.[ColID] = DefCons.[parent_column_id] AND Col.[ID] = Tab.[ID]
WHERE Col.[Name] = " . $this->_conn->quote($column) ." AND Tab.[Name] = " . $this->_conn->quote($table) . "
ORDER BY Col.[Name]";
}
}

View File

@@ -0,0 +1,367 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Schema\Visitor\CreateSchemaSqlCollector;
use Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector;
use Doctrine\DBAL\Schema\Visitor\Visitor;
/**
* Object representation of a database schema
*
* Different vendors have very inconsistent naming with regard to the concept
* of a "schema". Doctrine understands a schema as the entity that conceptually
* wraps a set of database objects such as tables, sequences, indexes and
* foreign keys that belong to each other into a namespace. A Doctrine Schema
* has nothing to do with the "SCHEMA" defined as in PostgreSQL, it is more
* related to the concept of "DATABASE" that exists in MySQL and PostgreSQL.
*
* Every asset in the doctrine schema has a name. A name consists of either a
* namespace.local name pair or just a local unqualified name.
*
* The abstraction layer that covers a PostgreSQL schema is the namespace of an
* database object (asset). A schema can have a name, which will be used as
* default namespace for the unqualified database objects that are created in
* the schema.
*
* In the case of MySQL where cross-database queries are allowed this leads to
* databases being "misinterpreted" as namespaces. This is intentional, however
* the CREATE/DROP SQL visitors will just filter this queries and do not
* execute them. Only the queries for the currently connected database are
* executed.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class Schema extends AbstractAsset
{
/**
* @var array
*/
protected $_tables = array();
/**
* @var array
*/
protected $_sequences = array();
/**
* @var SchemaConfig
*/
protected $_schemaConfig = false;
/**
* @param array $tables
* @param array $sequences
* @param array $views
* @param array $triggers
* @param SchemaConfig $schemaConfig
*/
public function __construct(array $tables=array(), array $sequences=array(), SchemaConfig $schemaConfig=null)
{
if ($schemaConfig == null) {
$schemaConfig = new SchemaConfig();
}
$this->_schemaConfig = $schemaConfig;
$this->_setName($schemaConfig->getName() ?: 'public');
foreach ($tables AS $table) {
$this->_addTable($table);
}
foreach ($sequences AS $sequence) {
$this->_addSequence($sequence);
}
}
/**
* @return bool
*/
public function hasExplicitForeignKeyIndexes()
{
return $this->_schemaConfig->hasExplicitForeignKeyIndexes();
}
/**
* @param Table $table
*/
protected function _addTable(Table $table)
{
$tableName = $table->getFullQualifiedName($this->getName());
if(isset($this->_tables[$tableName])) {
throw SchemaException::tableAlreadyExists($tableName);
}
$this->_tables[$tableName] = $table;
$table->setSchemaConfig($this->_schemaConfig);
}
/**
* @param Sequence $sequence
*/
protected function _addSequence(Sequence $sequence)
{
$seqName = $sequence->getFullQualifiedName($this->getName());
if (isset($this->_sequences[$seqName])) {
throw SchemaException::sequenceAlreadyExists($seqName);
}
$this->_sequences[$seqName] = $sequence;
}
/**
* Get all tables of this schema.
*
* @return array
*/
public function getTables()
{
return $this->_tables;
}
/**
* @param string $tableName
* @return Table
*/
public function getTable($tableName)
{
$tableName = $this->getFullQualifiedAssetName($tableName);
if (!isset($this->_tables[$tableName])) {
throw SchemaException::tableDoesNotExist($tableName);
}
return $this->_tables[$tableName];
}
/**
* @return string
*/
private function getFullQualifiedAssetName($name)
{
if ($this->isQuoted($name)) {
$name = $this->trimQuotes($name);
}
if (strpos($name, ".") === false) {
$name = $this->getName() . "." . $name;
}
return strtolower($name);
}
/**
* Does this schema have a table with the given name?
*
* @param string $tableName
* @return Schema
*/
public function hasTable($tableName)
{
$tableName = $this->getFullQualifiedAssetName($tableName);
return isset($this->_tables[$tableName]);
}
/**
* Get all table names, prefixed with a schema name, even the default one
* if present.
*
* @return array
*/
public function getTableNames()
{
return array_keys($this->_tables);
}
public function hasSequence($sequenceName)
{
$sequenceName = $this->getFullQualifiedAssetName($sequenceName);
return isset($this->_sequences[$sequenceName]);
}
/**
* @throws SchemaException
* @param string $sequenceName
* @return Doctrine\DBAL\Schema\Sequence
*/
public function getSequence($sequenceName)
{
$sequenceName = $this->getFullQualifiedAssetName($sequenceName);
if(!$this->hasSequence($sequenceName)) {
throw SchemaException::sequenceDoesNotExist($sequenceName);
}
return $this->_sequences[$sequenceName];
}
/**
* @return Doctrine\DBAL\Schema\Sequence[]
*/
public function getSequences()
{
return $this->_sequences;
}
/**
* Create a new table
*
* @param string $tableName
* @return Table
*/
public function createTable($tableName)
{
$table = new Table($tableName);
$this->_addTable($table);
return $table;
}
/**
* Rename a table
*
* @param string $oldTableName
* @param string $newTableName
* @return Schema
*/
public function renameTable($oldTableName, $newTableName)
{
$table = $this->getTable($oldTableName);
$table->_setName($newTableName);
$this->dropTable($oldTableName);
$this->_addTable($table);
return $this;
}
/**
* Drop a table from the schema.
*
* @param string $tableName
* @return Schema
*/
public function dropTable($tableName)
{
$tableName = $this->getFullQualifiedAssetName($tableName);
$table = $this->getTable($tableName);
unset($this->_tables[$tableName]);
return $this;
}
/**
* Create a new sequence
*
* @param string $sequenceName
* @param int $allocationSize
* @param int $initialValue
* @return Sequence
*/
public function createSequence($sequenceName, $allocationSize=1, $initialValue=1)
{
$seq = new Sequence($sequenceName, $allocationSize, $initialValue);
$this->_addSequence($seq);
return $seq;
}
/**
* @param string $sequenceName
* @return Schema
*/
public function dropSequence($sequenceName)
{
$sequenceName = $this->getFullQualifiedAssetName($sequenceName);
unset($this->_sequences[$sequenceName]);
return $this;
}
/**
* Return an array of necessary sql queries to create the schema on the given platform.
*
* @param AbstractPlatform $platform
* @return array
*/
public function toSql(\Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{
$sqlCollector = new CreateSchemaSqlCollector($platform);
$this->visit($sqlCollector);
return $sqlCollector->getQueries();
}
/**
* Return an array of necessary sql queries to drop the schema on the given platform.
*
* @param AbstractPlatform $platform
* @return array
*/
public function toDropSql(\Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{
$dropSqlCollector = new DropSchemaSqlCollector($platform);
$this->visit($dropSqlCollector);
return $dropSqlCollector->getQueries();
}
/**
* @param Schema $toSchema
* @param AbstractPlatform $platform
*/
public function getMigrateToSql(Schema $toSchema, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{
$comparator = new Comparator();
$schemaDiff = $comparator->compare($this, $toSchema);
return $schemaDiff->toSql($platform);
}
/**
* @param Schema $fromSchema
* @param AbstractPlatform $platform
*/
public function getMigrateFromSql(Schema $fromSchema, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{
$comparator = new Comparator();
$schemaDiff = $comparator->compare($fromSchema, $this);
return $schemaDiff->toSql($platform);
}
/**
* @param Visitor $visitor
*/
public function visit(Visitor $visitor)
{
$visitor->acceptSchema($this);
foreach ($this->_tables AS $table) {
$table->visit($visitor);
}
foreach ($this->_sequences AS $sequence) {
$sequence->visit($visitor);
}
}
/**
* Cloning a Schema triggers a deep clone of all related assets.
*
* @return void
*/
public function __clone()
{
foreach ($this->_tables AS $k => $table) {
$this->_tables[$k] = clone $table;
}
foreach ($this->_sequences AS $k => $sequence) {
$this->_sequences[$k] = clone $sequence;
}
}
}

View File

@@ -0,0 +1,98 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* Configuration for a Schema
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class SchemaConfig
{
/**
* @var bool
*/
protected $_hasExplicitForeignKeyIndexes = false;
/**
* @var int
*/
protected $_maxIdentifierLength = 63;
/**
* @var string
*/
protected $_name;
/**
* @return bool
*/
public function hasExplicitForeignKeyIndexes()
{
return $this->_hasExplicitForeignKeyIndexes;
}
/**
* @param bool $flag
*/
public function setExplicitForeignKeyIndexes($flag)
{
$this->_hasExplicitForeignKeyIndexes = (bool)$flag;
}
/**
* @param int $length
*/
public function setMaxIdentifierLength($length)
{
$this->_maxIdentifierLength = (int)$length;
}
/**
* @return int
*/
public function getMaxIdentifierLength()
{
return $this->_maxIdentifierLength;
}
/**
* Get default namespace of schema objects.
*
* @return string
*/
public function getName()
{
return $this->_name;
}
/**
* set default namespace name of schema objects.
*
* @param _name the value to set.
*/
public function setName($name)
{
$this->_name = $name;
}
}

View File

@@ -0,0 +1,176 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
use \Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* Schema Diff
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
* @license http://ez.no/licenses/new_bsd New BSD License
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class SchemaDiff
{
/**
* All added tables
*
* @var array(string=>ezcDbSchemaTable)
*/
public $newTables = array();
/**
* All changed tables
*
* @var array(string=>ezcDbSchemaTableDiff)
*/
public $changedTables = array();
/**
* All removed tables
*
* @var array(string=>Table)
*/
public $removedTables = array();
/**
* @var array
*/
public $newSequences = array();
/**
* @var array
*/
public $changedSequences = array();
/**
* @var array
*/
public $removedSequences = array();
/**
* @var array
*/
public $orphanedForeignKeys = array();
/**
* Constructs an SchemaDiff object.
*
* @param array(string=>Table) $newTables
* @param array(string=>TableDiff) $changedTables
* @param array(string=>bool) $removedTables
*/
public function __construct($newTables = array(), $changedTables = array(), $removedTables = array())
{
$this->newTables = $newTables;
$this->changedTables = $changedTables;
$this->removedTables = $removedTables;
}
/**
* The to save sql mode ensures that the following things don't happen:
*
* 1. Tables are deleted
* 2. Sequences are deleted
* 3. Foreign Keys which reference tables that would otherwise be deleted.
*
* This way it is ensured that assets are deleted which might not be relevant to the metadata schema at all.
*
* @param AbstractPlatform $platform
* @return array
*/
public function toSaveSql(AbstractPlatform $platform)
{
return $this->_toSql($platform, true);
}
/**
* @param AbstractPlatform $platform
* @return array
*/
public function toSql(AbstractPlatform $platform)
{
return $this->_toSql($platform, false);
}
/**
* @param AbstractPlatform $platform
* @param bool $saveMode
* @return array
*/
protected function _toSql(AbstractPlatform $platform, $saveMode = false)
{
$sql = array();
if ($platform->supportsForeignKeyConstraints() && $saveMode == false) {
foreach ($this->orphanedForeignKeys AS $orphanedForeignKey) {
$sql[] = $platform->getDropForeignKeySQL($orphanedForeignKey, $orphanedForeignKey->getLocalTableName());
}
}
if ($platform->supportsSequences() == true) {
foreach ($this->changedSequences AS $sequence) {
$sql[] = $platform->getAlterSequenceSQL($sequence);
}
if ($saveMode === false) {
foreach ($this->removedSequences AS $sequence) {
$sql[] = $platform->getDropSequenceSQL($sequence);
}
}
foreach ($this->newSequences AS $sequence) {
$sql[] = $platform->getCreateSequenceSQL($sequence);
}
}
$foreignKeySql = array();
foreach ($this->newTables AS $table) {
$sql = array_merge(
$sql,
$platform->getCreateTableSQL($table, AbstractPlatform::CREATE_INDEXES)
);
if ($platform->supportsForeignKeyConstraints()) {
foreach ($table->getForeignKeys() AS $foreignKey) {
$foreignKeySql[] = $platform->getCreateForeignKeySQL($foreignKey, $table);
}
}
}
$sql = array_merge($sql, $foreignKeySql);
if ($saveMode === false) {
foreach ($this->removedTables AS $table) {
$sql[] = $platform->getDropTableSQL($table);
}
}
foreach ($this->changedTables AS $tableDiff) {
$sql = array_merge($sql, $platform->getAlterTableSQL($tableDiff));
}
return $sql;
}
}

View File

@@ -0,0 +1,126 @@
<?php
namespace Doctrine\DBAL\Schema;
class SchemaException extends \Doctrine\DBAL\DBALException
{
const TABLE_DOESNT_EXIST = 10;
const TABLE_ALREADY_EXISTS = 20;
const COLUMN_DOESNT_EXIST = 30;
const COLUMN_ALREADY_EXISTS = 40;
const INDEX_DOESNT_EXIST = 50;
const INDEX_ALREADY_EXISTS = 60;
const SEQUENCE_DOENST_EXIST = 70;
const SEQUENCE_ALREADY_EXISTS = 80;
const INDEX_INVALID_NAME = 90;
const FOREIGNKEY_DOESNT_EXIST = 100;
/**
* @param string $tableName
* @return SchemaException
*/
static public function tableDoesNotExist($tableName)
{
return new self("There is no table with name '".$tableName."' in the schema.", self::TABLE_DOESNT_EXIST);
}
/**
* @param string $indexName
* @return SchemaException
*/
static public function indexNameInvalid($indexName)
{
return new self("Invalid index-name $indexName given, has to be [a-zA-Z0-9_]", self::INDEX_INVALID_NAME);
}
/**
* @param string $indexName
* @return SchemaException
*/
static public function indexDoesNotExist($indexName, $table)
{
return new self("Index '$indexName' does not exist on table '$table'.", self::INDEX_DOESNT_EXIST);
}
/**
* @param string $indexName
* @return SchemaException
*/
static public function indexAlreadyExists($indexName, $table)
{
return new self("An index with name '$indexName' was already defined on table '$table'.", self::INDEX_ALREADY_EXISTS);
}
/**
* @param string $columnName
* @return SchemaException
*/
static public function columnDoesNotExist($columnName, $table)
{
return new self("There is no column with name '$columnName' on table '$table'.", self::COLUMN_DOESNT_EXIST);
}
/**
*
* @param string $tableName
* @return SchemaException
*/
static public function tableAlreadyExists($tableName)
{
return new self("The table with name '".$tableName."' already exists.", self::TABLE_ALREADY_EXISTS);
}
/**
*
* @param string $tableName
* @param string $columnName
* @return SchemaException
*/
static public function columnAlreadyExists($tableName, $columnName)
{
return new self(
"The column '".$columnName."' on table '".$tableName."' already exists.", self::COLUMN_ALREADY_EXISTS
);
}
/**
* @param string $sequenceName
* @return SchemaException
*/
static public function sequenceAlreadyExists($sequenceName)
{
return new self("The sequence '".$sequenceName."' already exists.", self::SEQUENCE_ALREADY_EXISTS);
}
/**
* @param string $sequenceName
* @return SchemaException
*/
static public function sequenceDoesNotExist($sequenceName)
{
return new self("There exists no sequence with the name '".$sequenceName."'.", self::SEQUENCE_DOENST_EXIST);
}
/**
* @param string $fkName
* @return SchemaException
*/
static public function foreignKeyDoesNotExist($fkName, $table)
{
return new self("There exists no foreign key with the name '$fkName' on table '$table'.", self::FOREIGNKEY_DOESNT_EXIST);
}
static public function namedForeignKeyRequired(Table $localTable, ForeignKeyConstraint $foreignKey)
{
return new self(
"The performed schema operation on ".$localTable->getName()." requires a named foreign key, ".
"but the given foreign key from (".implode(", ", $foreignKey->getColumns()).") onto foreign table ".
"'".$foreignKey->getForeignTableName()."' (".implode(", ", $foreignKey->getForeignColumns()).") is currently ".
"unnamed."
);
}
static public function alterTableChangeNotSupported($changeName) {
return new self ("Alter table change not supported, given '$changeName'");
}
}

View File

@@ -0,0 +1,87 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Schema\Visitor\Visitor;
/**
* Sequence Structure
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class Sequence extends AbstractAsset
{
/**
* @var int
*/
protected $_allocationSize = 1;
/**
* @var int
*/
protected $_initialValue = 1;
/**
*
* @param string $name
* @param int $allocationSize
* @param int $initialValue
*/
public function __construct($name, $allocationSize=1, $initialValue=1)
{
$this->_setName($name);
$this->_allocationSize = (is_numeric($allocationSize))?$allocationSize:1;
$this->_initialValue = (is_numeric($initialValue))?$initialValue:1;
}
public function getAllocationSize()
{
return $this->_allocationSize;
}
public function getInitialValue()
{
return $this->_initialValue;
}
public function setAllocationSize($allocationSize)
{
$this->_allocationSize = (is_numeric($allocationSize))?$allocationSize:1;
}
public function setInitialValue($initialValue)
{
$this->_initialValue = (is_numeric($initialValue))?$initialValue:1;
}
/**
* @param Visitor $visitor
*/
public function visit(Visitor $visitor)
{
$visitor->acceptSequence($this);
}
}

View File

@@ -0,0 +1,190 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* SqliteSchemaManager
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Jonathan H. Wage <jonwage@gmail.com>
* @version $Revision$
* @since 2.0
*/
class SqliteSchemaManager extends AbstractSchemaManager
{
/**
* {@inheritdoc}
*
* @override
*/
public function dropDatabase($database)
{
if (file_exists($database)) {
unlink($database);
}
}
/**
* {@inheritdoc}
*
* @override
*/
public function createDatabase($database)
{
$params = $this->_conn->getParams();
$driver = $params['driver'];
$options = array(
'driver' => $driver,
'path' => $database
);
$conn = \Doctrine\DBAL\DriverManager::getConnection($options);
$conn->connect();
$conn->close();
}
protected function _getPortableTableDefinition($table)
{
return $table['name'];
}
/**
* @license New BSD License
* @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html
* @param array $tableIndexes
* @param string $tableName
* @return array
*/
protected function _getPortableTableIndexesList($tableIndexes, $tableName=null)
{
$indexBuffer = array();
// fetch primary
$stmt = $this->_conn->executeQuery( "PRAGMA TABLE_INFO ('$tableName')" );
$indexArray = $stmt->fetchAll(\PDO::FETCH_ASSOC);
foreach($indexArray AS $indexColumnRow) {
if($indexColumnRow['pk'] == "1") {
$indexBuffer[] = array(
'key_name' => 'primary',
'primary' => true,
'non_unique' => false,
'column_name' => $indexColumnRow['name']
);
}
}
// fetch regular indexes
foreach($tableIndexes AS $tableIndex) {
// Ignore indexes with reserved names, e.g. autoindexes
if (strpos($tableIndex['name'], 'sqlite_') !== 0) {
$keyName = $tableIndex['name'];
$idx = array();
$idx['key_name'] = $keyName;
$idx['primary'] = false;
$idx['non_unique'] = $tableIndex['unique']?false:true;
$stmt = $this->_conn->executeQuery( "PRAGMA INDEX_INFO ( '{$keyName}' )" );
$indexArray = $stmt->fetchAll(\PDO::FETCH_ASSOC);
foreach ( $indexArray as $indexColumnRow ) {
$idx['column_name'] = $indexColumnRow['name'];
$indexBuffer[] = $idx;
}
}
}
return parent::_getPortableTableIndexesList($indexBuffer, $tableName);
}
protected function _getPortableTableIndexDefinition($tableIndex)
{
return array(
'name' => $tableIndex['name'],
'unique' => (bool) $tableIndex['unique']
);
}
protected function _getPortableTableColumnDefinition($tableColumn)
{
$e = explode('(', $tableColumn['type']);
$tableColumn['type'] = $e[0];
if (isset($e[1])) {
$length = trim($e[1], ')');
$tableColumn['length'] = $length;
}
$dbType = strtolower($tableColumn['type']);
$length = isset($tableColumn['length']) ? $tableColumn['length'] : null;
$unsigned = (boolean) isset($tableColumn['unsigned']) ? $tableColumn['unsigned'] : false;
$fixed = false;
$type = $this->_platform->getDoctrineTypeMapping($dbType);
$default = $tableColumn['dflt_value'];
if ($default == 'NULL') {
$default = null;
}
if ($default !== null) {
// SQLite returns strings wrapped in single quotes, so we need to strip them
$default = preg_replace("/^'(.*)'$/", '\1', $default);
}
$notnull = (bool) $tableColumn['notnull'];
if ( ! isset($tableColumn['name'])) {
$tableColumn['name'] = '';
}
$precision = null;
$scale = null;
switch ($dbType) {
case 'char':
$fixed = true;
break;
case 'float':
case 'double':
case 'real':
case 'decimal':
case 'numeric':
if (isset($tableColumn['length'])) {
list($precision, $scale) = array_map('trim', explode(', ', $tableColumn['length']));
}
$length = null;
break;
}
$options = array(
'length' => $length,
'unsigned' => (bool) $unsigned,
'fixed' => $fixed,
'notnull' => $notnull,
'default' => $default,
'precision' => $precision,
'scale' => $scale,
'autoincrement' => false,
);
return new Column($tableColumn['name'], \Doctrine\DBAL\Types\Type::getType($type), $options);
}
protected function _getPortableViewDefinition($view)
{
return new View($view['name'], $view['sql']);
}
}

Some files were not shown because too many files have changed in this diff Show More