pax_global_header00006660000000000000000000000064131347345000014512gustar00rootroot0000000000000052 comment=729340d8d1eec8f01bff708e12e449a3415af873 dbal-2.5.13/000077500000000000000000000000001313473450000125045ustar00rootroot00000000000000dbal-2.5.13/LICENSE000066400000000000000000000020511313473450000135070ustar00rootroot00000000000000Copyright (c) 2006-2012 Doctrine Project Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. dbal-2.5.13/README.md000066400000000000000000000023161313473450000137650ustar00rootroot00000000000000# Doctrine DBAL Powerful database abstraction layer with many features for database schema introspection, schema management and PDO abstraction. * Master: [![Build Status](https://secure.travis-ci.org/doctrine/dbal.png?branch=master)](http://travis-ci.org/doctrine/dbal) [![Dependency Status](https://www.versioneye.com/php/doctrine:dbal/dev-master/badge.png)](https://www.versioneye.com/php/doctrine:dbal/dev-master) * 2.4: [![Build Status](https://secure.travis-ci.org/doctrine/dbal.png?branch=2.4)](http://travis-ci.org/doctrine/dbal) [![Dependency Status](https://www.versioneye.com/php/doctrine:dbal/2.4.2/badge.png)](https://www.versioneye.com/php/doctrine:dbal/2.4.2) * 2.3: [![Build Status](https://secure.travis-ci.org/doctrine/dbal.png?branch=2.3)](http://travis-ci.org/doctrine/dbal) [![Dependency Status](https://www.versioneye.com/php/doctrine:dbal/2.3.4/badge.png)](https://www.versioneye.com/php/doctrine:dbal/2.3.4) ## More resources: * [Website](http://www.doctrine-project.org/projects/dbal.html) * [Documentation](http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/) * [Issue Tracker](http://www.doctrine-project.org/jira/browse/DBAL) * [Downloads](http://github.com/doctrine/dbal/downloads) dbal-2.5.13/SECURITY.md000066400000000000000000000012031313473450000142710ustar00rootroot00000000000000Security ======== The Doctrine library is operating very close to your database and as such needs to handle and make assumptions about SQL injection vulnerabilities. It is vital that you understand how Doctrine approaches security, because we cannot protect you from SQL injection. Please read the documentation chapter on Security in Doctrine DBAL to understand the assumptions we make. - [Latest security.rst page on Github](https://github.com/doctrine/dbal/blob/master/docs/en/reference/security.rst) - [Security Page in rendered documentation](http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/security.html) dbal-2.5.13/UPGRADE.md000066400000000000000000000246401313473450000141230ustar00rootroot00000000000000# Upgrade to 2.5.1 ## MINOR BC BREAK: Doctrine\DBAL\Schema\Table When adding indexes to ``Doctrine\DBAL\Schema\Table`` via ``addIndex()`` or ``addUniqueIndex()``, duplicate indexes are not silently ignored/dropped anymore (based on semantics, not naming!). Duplicate indexes are considered indexes that pass ``isFullfilledBy()`` or ``overrules()`` in ``Doctrine\DBAL\Schema\Index``. This is required to make the index renaming feature introduced in 2.5.0 work properly and avoid issues in the ORM schema tool / DBAL schema manager which pretends users from updating their schemas and migrate to DBAL 2.5.*. Additionally it offers more flexibility in declaring indexes for the user and potentially fixes related issues in the ORM. With this change, the responsibility to decide which index is a "duplicate" is completely deferred to the user. Please also note that adding foreign key constraints to a table via ``addForeignKeyConstraint()``, ``addUnnamedForeignKeyConstraint()`` or ``addNamedForeignKeyConstraint()`` now first checks if an appropriate index is already present and avoids adding an additional auto-generated one eventually. # Upgrade to 2.5 ## BC BREAK: time type resets date fields to UNIX epoch When mapping `time` type field to PHP's `DateTime` instance all unused date fields are reset to UNIX epoch (i.e. 1970-01-01). This might break any logic which relies on comparing `DateTime` instances with date fields set to the current date. Use `!` format prefix (see http://php.net/manual/en/datetime.createfromformat.php) for parsing time strings to prevent having different date fields when comparing user input and `DateTime` instances as mapped by Doctrine. ## BC BREAK: Doctrine\DBAL\Schema\Table The methods ``addIndex()`` and ``addUniqueIndex()`` in ``Doctrine\DBAL\Schema\Table`` have an additional, optional parameter. If you override these methods, you should add this new parameter to the declaration of your overridden methods. ## BC BREAK: Doctrine\DBAL\Connection The visibility of the property ``$_platform`` in ``Doctrine\DBAL\Connection`` was changed from protected to private. If you have subclassed ``Doctrine\DBAL\Connection`` in your application and accessed ``$_platform`` directly, you have to change the code portions to use ``getDatabasePlatform()`` instead to retrieve the underlying database platform. The reason for this change is the new automatic platform version detection feature, which lazily evaluates the appropriate platform class to use for the underlying database server version at runtime. Please also note, that calling ``getDatabasePlatform()`` now needs to establish a connection in order to evaluate the appropriate platform class if ``Doctrine\DBAL\Connection`` is not already connected. Under the following circumstances, it is not possible anymore to retrieve the platform instance from the connection object without having to do a real connect: 1. ``Doctrine\DBAL\Connection`` was instantiated without the ``platform`` connection parameter. 2. ``Doctrine\DBAL\Connection`` was instantiated without the ``serverVersion`` connection parameter. 3. The underlying driver is "version aware" and can provide different platform instances for different versions. 4. The underlying driver connection is "version aware" and can provide the database server version without having to query for it. If one of the above conditions is NOT met, there is no need for ``Doctrine\DBAL\Connection`` to do a connect when calling ``getDatabasePlatform()``. ## datetime Type uses date_create() as fallback Before 2.5 the DateTime type always required a specific format, defined in `$platform->getDateTimeFormatString()`, which could cause quite some troubles on platforms that had various microtime precision formats. Starting with 2.5 whenever the parsing of a date fails with the predefined platform format, the `date_create()` function will be used to parse the date. This could cause some troubles when your date format is weird and not parsed correctly by `date_create`, however since databases are rather strict on dates there should be no problem. ## Support for pdo_ibm driver removed The ``pdo_ibm`` driver is buggy and does not work well with Doctrine. Therefore it will no longer be supported and has been removed from the ``Doctrine\DBAL\DriverManager`` drivers map. It is highly encouraged to to use `ibm_db2` driver instead if you want to connect to an IBM DB2 database as it is much more stable and secure. If for some reason you have to utilize the ``pdo_ibm`` driver you can still use the `driverClass` connection parameter to explicitly specify the ``Doctrine\DBAL\Driver\PDOIbm\Driver`` class. However be aware that you are doing this at your own risk and it will not be guaranteed that Doctrine will work as expected. # Upgrade to 2.4 ## Doctrine\DBAL\Schema\Constraint If you have custom classes that implement the constraint interface, you have to implement an additional method ``getQuotedColumns`` now. This method is used to build proper constraint SQL for columns that need to be quoted, like keywords reserved by the specific platform used. The method has to return the same values as ``getColumns`` only that those column names that need quotation have to be returned quoted for the given platform. # Upgrade to 2.3 ## Oracle Session Init now sets Numeric Character Before 2.3 the Oracle Session Init did not care about the numeric character of the Session. This could lead to problems on non english locale systems that required a comma as a floating point seperator in Oracle. Since 2.3, using the Oracle Session Init on connection start the client session will be altered to set the numeric character to ".,": ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,' See [DBAL-345](http://www.doctrine-project.org/jira/browse/DBAL-345) for more details. ## Doctrine\DBAL\Connection and Doctrine\DBAL\Statement The query related methods including but not limited to executeQuery, exec, query, and executeUpdate now wrap the driver exceptions such as PDOException with DBALException to add more debugging information such as the executed SQL statement, and any bound parameters. If you want to retrieve the driver specific exception, you can retrieve it by calling the ``getPrevious()`` method on DBALException. Before: catch(\PDOException $ex) { // ... } After: catch(\Doctrine\DBAL\DBALException $ex) { $pdoException = $ex->getPrevious(); // ... } ## Doctrine\DBAL\Connection#setCharsetSQL() removed This method only worked on MySQL and it is considered unsafe on MySQL to use SET NAMES UTF-8 instead of setting the charset directly on connection already. Replace this behavior with the connection charset option: Before: $conn = DriverManager::getConnection(array(..)); $conn->setCharset('UTF8'); After: $conn = DriverManager::getConnection(array('charset' => 'UTF8', ..)); ## Doctrine\DBAL\Schema\Table#renameColumn() removed Doctrine\DBAL\Schema\Table#renameColumn() was removed, because it drops and recreates the column instead. There is no fix available, because a schema diff cannot reliably detect if a column was renamed or one column was created and another one dropped. You should use explicit SQL ALTER TABLE statements to change columns names. ## Schema Filter paths The Filter Schema assets expression is not wrapped in () anymore for the regexp automatically. Before: $config->setFilterSchemaAssetsExpression('foo'); After: $config->setFilterSchemaAssetsExpression('(foo)'); ## Creating MySQL Tables now defaults to UTF-8 If you are creating a new MySQL Table through the Doctrine API, charset/collate are now set to 'utf8'/'utf8_unicode_ci' by default. Previously the MySQL server defaults were used. # Upgrade to 2.2 ## Doctrine\DBAL\Connection#insert and Doctrine\DBAL\Connection#update Both methods now accept an optional last parameter $types with binding types of the values passed. This can potentially break child classes that have overwritten one of these methods. ## Doctrine\DBAL\Connection#executeQuery Doctrine\DBAL\Connection#executeQuery() got a new last parameter "QueryCacheProfile $qcp" ## Doctrine\DBAL\Driver\Statement split The Driver statement was split into a ResultStatement and the normal statement extending from it. This separates the configuration and the retrieval API from a statement. ## MsSql Platform/SchemaManager renamed The MsSqlPlatform was renamed to SQLServerPlatform, the MsSqlSchemaManager was renamed to SQLServerSchemaManager. ## Cleanup SQLServer Platform version mess DBAL 2.1 and before were actually only compatible to SQL Server 2008, not earlier versions. Still other parts of the platform did use old features instead of newly introduced datatypes in SQL Server 2005. Starting with DBAL 2.2 you can pick the Doctrine abstraction exactly matching your SQL Server version. The PDO SqlSrv driver now uses the new `SQLServer2008Platform` as default platform. This platform uses new features of SQL Server as of version 2008. This also includes a switch in the used fields for "text" and "blob" field types to: "text" => "VARCHAR(MAX)" "blob" => "VARBINARY(MAX)" Additionally `SQLServerPlatform` in DBAL 2.1 and before used "DATE", "TIME" and "DATETIME2" for dates. This types are only available since version 2008 and the introduction of an explicit SQLServer 2008 platform makes this dependency explicit. An `SQLServer2005Platform` was also introduced to differentiate the features between versions 2003, earlier and 2005. With this change the `SQLServerPlatform` now throws an exception for using limit queries with an offset, since SQLServer 2003 and lower do not support this feature. To use the old SQL Server Platform, because you are using SQL Server 2003 and below use the following configuration code: use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\Platforms\SQLServerPlatform; use Doctrine\DBAL\Platforms\SQLServer2005Platform; // You are using SQL Server 2003 or earlier $conn = DriverManager::getConnection(array( 'driver' => 'pdo_sqlsrv', 'platform' => new SQLServerPlatform() // .. additional parameters )); // You are using SQL Server 2005 $conn = DriverManager::getConnection(array( 'driver' => 'pdo_sqlsrv', 'platform' => new SQLServer2005Platform() // .. additional parameters )); // You are using SQL Server 2008 $conn = DriverManager::getConnection(array( 'driver' => 'pdo_sqlsrv', // 2008 is default platform // .. additional parameters )); dbal-2.5.13/bin/000077500000000000000000000000001313473450000132545ustar00rootroot00000000000000dbal-2.5.13/bin/doctrine-dbal000077500000000000000000000001021313473450000157020ustar00rootroot00000000000000#!/usr/bin/env php . */ use Symfony\Component\Console\Helper\HelperSet; use Doctrine\DBAL\Tools\Console\ConsoleRunner; $files = array(__DIR__ . '/../vendor/autoload.php', __DIR__ . '/../../../autoload.php'); $loader = null; $cwd = getcwd(); $directories = array($cwd, $cwd . DIRECTORY_SEPARATOR . 'config'); $configFile = null; foreach ($files as $file) { if (file_exists($file)) { $loader = require $file; break; } } if ( ! $loader) { throw new RuntimeException('vendor/autoload.php could not be found. Did you run `php composer.phar install`?'); } foreach ($directories as $directory) { $configFile = $directory . DIRECTORY_SEPARATOR . 'cli-config.php'; if (file_exists($configFile)) { break; } } if ( ! file_exists($configFile)) { ConsoleRunner::printCliConfigTemplate(); exit(1); } if ( ! is_readable($configFile)) { echo 'Configuration file [' . $configFile . '] does not have read permission.' . PHP_EOL; exit(1); } $commands = array(); $helperSet = require $configFile; if ( ! $helperSet instanceof HelperSet) { foreach ($GLOBALS as $helperSetCandidate) { if ($helperSetCandidate instanceof HelperSet) { $helperSet = $helperSetCandidate; break; } } } ConsoleRunner::run($helperSet, $commands); dbal-2.5.13/composer.json000066400000000000000000000023021313473450000152230ustar00rootroot00000000000000{ "name": "doctrine/dbal", "type": "library", "description": "Database Abstraction Layer", "keywords": ["dbal", "database", "persistence", "queryobject"], "homepage": "http://www.doctrine-project.org", "license": "MIT", "authors": [ {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, {"name": "Roman Borschel", "email": "roman@code-factory.org"}, {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, {"name": "Jonathan Wage", "email": "jonwage@gmail.com"} ], "require": { "php": ">=5.3.2", "doctrine/common": ">=2.4,<2.8-dev" }, "require-dev": { "phpunit/phpunit": "4.*", "symfony/console": "2.*||^3.0" }, "suggest": { "symfony/console": "For helpful console commands such as SQL execution and import of files." }, "bin": ["bin/doctrine-dbal"], "autoload": { "psr-0": { "Doctrine\\DBAL\\": "lib/" } }, "extra": { "branch-alias": { "dev-master": "2.5.x-dev" } }, "archive": { "exclude": ["!vendor", "tests", "*phpunit.xml", ".travis.yml", "build.xml", "build.properties", "composer.phar"] } } dbal-2.5.13/lib/000077500000000000000000000000001313473450000132525ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/000077500000000000000000000000001313473450000150215ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/000077500000000000000000000000001313473450000155235ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Cache/000077500000000000000000000000001313473450000165265ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Cache/ArrayStatement.php000066400000000000000000000072431313473450000222100ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Cache; use Doctrine\DBAL\Driver\ResultStatement; use PDO; class ArrayStatement implements \IteratorAggregate, ResultStatement { /** * @var array */ private $data; /** * @var integer */ private $columnCount = 0; /** * @var integer */ private $num = 0; /** * @var integer */ private $defaultFetchMode = PDO::FETCH_BOTH; /** * @param array $data */ public function __construct(array $data) { $this->data = $data; if (count($data)) { $this->columnCount = count($data[0]); } } /** * {@inheritdoc} */ public function closeCursor() { unset ($this->data); } /** * {@inheritdoc} */ public function columnCount() { return $this->columnCount; } /** * {@inheritdoc} */ public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) { if ($arg2 !== null || $arg3 !== null) { throw new \InvalidArgumentException("Caching layer does not support 2nd/3rd argument to setFetchMode()"); } $this->defaultFetchMode = $fetchMode; return true; } /** * {@inheritdoc} */ public function getIterator() { $data = $this->fetchAll(); return new \ArrayIterator($data); } /** * {@inheritdoc} */ public function fetch($fetchMode = null) { if (isset($this->data[$this->num])) { $row = $this->data[$this->num++]; $fetchMode = $fetchMode ?: $this->defaultFetchMode; if ($fetchMode === PDO::FETCH_ASSOC) { return $row; } elseif ($fetchMode === PDO::FETCH_NUM) { return array_values($row); } elseif ($fetchMode === PDO::FETCH_BOTH) { return array_merge($row, array_values($row)); } elseif ($fetchMode === PDO::FETCH_COLUMN) { return reset($row); } else { throw new \InvalidArgumentException("Invalid fetch-style given for fetching result."); } } return false; } /** * {@inheritdoc} */ public function fetchAll($fetchMode = null) { $rows = array(); while ($row = $this->fetch($fetchMode)) { $rows[] = $row; } return $rows; } /** * {@inheritdoc} */ 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]; } } dbal-2.5.13/lib/Doctrine/DBAL/Cache/CacheException.php000066400000000000000000000030121313473450000221150ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Cache; /** * @author Benjamin Eberlei * @since 2.2 */ class CacheException extends \Doctrine\DBAL\DBALException { /** * @return \Doctrine\DBAL\Cache\CacheException */ static public function noCacheKey() { return new self("No cache key was set."); } /** * @return \Doctrine\DBAL\Cache\CacheException */ static public function noResultDriverConfigured() { return new self("Trying to cache a query but no result driver is configured."); } } dbal-2.5.13/lib/Doctrine/DBAL/Cache/QueryCacheProfile.php000066400000000000000000000075271313473450000226240ustar00rootroot00000000000000. */ 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 */ class QueryCacheProfile { /** * @var \Doctrine\Common\Cache\Cache|null */ private $resultCacheDriver; /** * @var integer */ private $lifetime = 0; /** * @var string|null */ private $cacheKey; /** * @param integer $lifetime * @param string|null $cacheKey * @param \Doctrine\Common\Cache\Cache|null $resultCache */ public function __construct($lifetime = 0, $cacheKey = null, Cache $resultCache = null) { $this->lifetime = $lifetime; $this->cacheKey = $cacheKey; $this->resultCacheDriver = $resultCache; } /** * @return \Doctrine\Common\Cache\Cache|null */ public function getResultCacheDriver() { return $this->resultCacheDriver; } /** * @return integer */ public function getLifetime() { return $this->lifetime; } /** * @return string * * @throws \Doctrine\DBAL\Cache\CacheException */ public function getCacheKey() { if ($this->cacheKey === null) { throw CacheException::noCacheKey(); } return $this->cacheKey; } /** * Generates 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 \Doctrine\Common\Cache\Cache $cache * * @return \Doctrine\DBAL\Cache\QueryCacheProfile */ public function setResultCacheDriver(Cache $cache) { return new QueryCacheProfile($this->lifetime, $this->cacheKey, $cache); } /** * @param string|null $cacheKey * * @return \Doctrine\DBAL\Cache\QueryCacheProfile */ public function setCacheKey($cacheKey) { return new QueryCacheProfile($this->lifetime, $cacheKey, $this->resultCacheDriver); } /** * @param integer $lifetime * * @return \Doctrine\DBAL\Cache\QueryCacheProfile */ public function setLifetime($lifetime) { return new QueryCacheProfile($lifetime, $this->cacheKey, $this->resultCacheDriver); } } dbal-2.5.13/lib/Doctrine/DBAL/Cache/ResultCacheStatement.php000066400000000000000000000137121313473450000233320ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Cache; use Doctrine\DBAL\Driver\Statement; use Doctrine\DBAL\Driver\ResultStatement; 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 integer */ private $lifetime; /** * @var \Doctrine\DBAL\Driver\Statement */ private $statement; /** * Did we reach the end of the statement? * * @var boolean */ private $emptied = false; /** * @var array */ private $data; /** * @var integer */ private $defaultFetchMode = PDO::FETCH_BOTH; /** * @param \Doctrine\DBAL\Driver\Statement $stmt * @param \Doctrine\Common\Cache\Cache $resultCache * @param string $cacheKey * @param string $realKey * @param integer $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; } /** * {@inheritdoc} */ 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); } } /** * {@inheritdoc} */ public function columnCount() { return $this->statement->columnCount(); } /** * {@inheritdoc} */ public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) { $this->defaultFetchMode = $fetchMode; return true; } /** * {@inheritdoc} */ public function getIterator() { $data = $this->fetchAll(); return new \ArrayIterator($data); } /** * {@inheritdoc} */ public function fetch($fetchMode = null) { if ($this->data === null) { $this->data = array(); } $row = $this->statement->fetch(PDO::FETCH_ASSOC); if ($row) { $this->data[] = $row; $fetchMode = $fetchMode ?: $this->defaultFetchMode; if ($fetchMode == PDO::FETCH_ASSOC) { return $row; } elseif ($fetchMode == PDO::FETCH_NUM) { return array_values($row); } elseif ($fetchMode == PDO::FETCH_BOTH) { return array_merge($row, array_values($row)); } elseif ($fetchMode == PDO::FETCH_COLUMN) { return reset($row); } else { throw new \InvalidArgumentException("Invalid fetch-style given for caching result."); } } $this->emptied = true; return false; } /** * {@inheritdoc} */ public function fetchAll($fetchMode = null) { $rows = array(); while ($row = $this->fetch($fetchMode)) { $rows[] = $row; } return $rows; } /** * {@inheritdoc} */ 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]; } /** * 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 The number of rows. */ public function rowCount() { return $this->statement->rowCount(); } } dbal-2.5.13/lib/Doctrine/DBAL/Configuration.php000066400000000000000000000114241313473450000210450ustar00rootroot00000000000000. */ 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 * @author Jonathan Wage * @author Roman Borschel * @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 \Doctrine\DBAL\Logging\SQLLogger|null $logger * * @return void */ public function setSQLLogger(SQLLogger $logger = null) { $this->_attributes['sqlLogger'] = $logger; } /** * Gets the SQL logger that is used. * * @return \Doctrine\DBAL\Logging\SQLLogger|null */ 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|null */ 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 * * @return void */ public function setResultCacheImpl(Cache $cacheImpl) { $this->_attributes['resultCacheImpl'] = $cacheImpl; } /** * Sets the 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 * * @return void */ public function setFilterSchemaAssetsExpression($filterExpression) { $this->_attributes['filterSchemaAssetsExpression'] = $filterExpression; } /** * Returns filter schema assets expression. * * @return string|null */ public function getFilterSchemaAssetsExpression() { if (isset($this->_attributes['filterSchemaAssetsExpression'])) { return $this->_attributes['filterSchemaAssetsExpression']; } return null; } /** * Sets the default auto-commit mode for connections. * * If a connection is in auto-commit mode, then all its SQL statements will be executed and committed as individual * transactions. Otherwise, its SQL statements are grouped into transactions that are terminated by a call to either * the method commit or the method rollback. By default, new connections are in auto-commit mode. * * @param boolean $autoCommit True to enable auto-commit mode; false to disable it. * * @see getAutoCommit */ public function setAutoCommit($autoCommit) { $this->_attributes['autoCommit'] = (boolean) $autoCommit; } /** * Returns the default auto-commit mode for connections. * * @return boolean True if auto-commit mode is enabled by default for connections, false otherwise. * * @see setAutoCommit */ public function getAutoCommit() { if (isset($this->_attributes['autoCommit'])) { return $this->_attributes['autoCommit']; } return true; } } dbal-2.5.13/lib/Doctrine/DBAL/Connection.php000066400000000000000000001412231313473450000203360ustar00rootroot00000000000000. */ namespace Doctrine\DBAL; use Doctrine\DBAL\Driver\ServerInfoAwareConnection; use Doctrine\DBAL\Exception\InvalidArgumentException; use PDO; use Closure; use Exception; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Driver\Connection as DriverConnection; use Doctrine\Common\EventManager; use Doctrine\DBAL\Cache\ResultCacheStatement; use Doctrine\DBAL\Cache\QueryCacheProfile; use Doctrine\DBAL\Cache\ArrayStatement; use Doctrine\DBAL\Cache\CacheException; use Doctrine\DBAL\Driver\PingableConnection; /** * A wrapper around a Doctrine\DBAL\Driver\Connection that adds features like * events, transaction isolation levels, configuration, emulated transaction nesting, * lazy connecting and more. * * @link www.doctrine-project.org * @since 2.0 * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author Konsta Vesterinen * @author Lukas Smith (MDB2 library) * @author Benjamin Eberlei */ class Connection implements DriverConnection { /** * Constant for transaction isolation level READ UNCOMMITTED. */ const TRANSACTION_READ_UNCOMMITTED = 1; /** * Constant for transaction isolation level READ COMMITTED. */ const TRANSACTION_READ_COMMITTED = 2; /** * Constant for transaction isolation level REPEATABLE READ. */ const TRANSACTION_REPEATABLE_READ = 3; /** * Constant for transaction isolation level SERIALIZABLE. */ const TRANSACTION_SERIALIZABLE = 4; /** * Represents an array of ints to be expanded by Doctrine SQL parsing. * * @var integer */ const PARAM_INT_ARRAY = 101; /** * Represents an array of strings to be expanded by Doctrine SQL parsing. * * @var integer */ const PARAM_STR_ARRAY = 102; /** * Offset by which PARAM_* constants are detected as arrays of the param type. * * @var integer */ const ARRAY_PARAM_OFFSET = 100; /** * The wrapped driver connection. * * @var \Doctrine\DBAL\Driver\Connection */ protected $_conn; /** * @var \Doctrine\DBAL\Configuration */ protected $_config; /** * @var \Doctrine\Common\EventManager */ protected $_eventManager; /** * @var \Doctrine\DBAL\Query\Expression\ExpressionBuilder */ protected $_expr; /** * Whether or not a connection has been established. * * @var boolean */ private $_isConnected = false; /** * The current auto-commit mode of this connection. * * @var boolean */ private $autoCommit = true; /** * The transaction nesting level. * * @var integer */ private $_transactionNestingLevel = 0; /** * The currently active transaction isolation level. * * @var integer */ private $_transactionIsolationLevel; /** * If nested transactions should use savepoints. * * @var boolean */ private $_nestTransactionsWithSavepoints = false; /** * The parameters used during creation of the Connection instance. * * @var array */ private $_params = array(); /** * The DatabasePlatform object that provides information about the * database platform used by the connection. * * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ private $platform; /** * The schema manager. * * @var \Doctrine\DBAL\Schema\AbstractSchemaManager */ protected $_schemaManager; /** * The used DBAL driver. * * @var \Doctrine\DBAL\Driver */ protected $_driver; /** * Flag that indicates whether the current transaction is marked for rollback only. * * @var boolean */ private $_isRollbackOnly = false; /** * @var integer */ protected $defaultFetchMode = PDO::FETCH_ASSOC; /** * Initializes a new instance of the Connection class. * * @param array $params The connection parameters. * @param \Doctrine\DBAL\Driver $driver The driver to use. * @param \Doctrine\DBAL\Configuration|null $config The configuration, optional. * @param \Doctrine\Common\EventManager|null $eventManager The event manager, optional. * * @throws \Doctrine\DBAL\DBALException */ public function __construct(array $params, Driver $driver, Configuration $config = null, EventManager $eventManager = null) { $this->_driver = $driver; $this->_params = $params; if (isset($params['pdo'])) { $this->_conn = $params['pdo']; $this->_isConnected = true; unset($this->_params['pdo']); } // Create default config and event manager if none given if ( ! $config) { $config = new Configuration(); } if ( ! $eventManager) { $eventManager = new EventManager(); } $this->_config = $config; $this->_eventManager = $eventManager; $this->_expr = new Query\Expression\ExpressionBuilder($this); $this->autoCommit = $config->getAutoCommit(); } /** * Gets the parameters used during instantiation. * * @return array */ public function getParams() { return $this->_params; } /** * Gets the name of the database this Connection is connected to. * * @return string */ public function getDatabase() { return $this->_driver->getDatabase($this); } /** * Gets the hostname of the currently connected database. * * @return string|null */ public function getHost() { return isset($this->_params['host']) ? $this->_params['host'] : null; } /** * Gets the port of the currently connected database. * * @return mixed */ public function getPort() { return isset($this->_params['port']) ? $this->_params['port'] : null; } /** * Gets the username used by this connection. * * @return string|null */ public function getUsername() { return isset($this->_params['user']) ? $this->_params['user'] : null; } /** * Gets the password used by this connection. * * @return string|null */ public function getPassword() { return isset($this->_params['password']) ? $this->_params['password'] : null; } /** * Gets the DBAL driver instance. * * @return \Doctrine\DBAL\Driver */ public function getDriver() { return $this->_driver; } /** * Gets the Configuration used by the Connection. * * @return \Doctrine\DBAL\Configuration */ public function getConfiguration() { return $this->_config; } /** * Gets the EventManager used by the Connection. * * @return \Doctrine\Common\EventManager */ public function getEventManager() { return $this->_eventManager; } /** * Gets the DatabasePlatform for the connection. * * @return \Doctrine\DBAL\Platforms\AbstractPlatform */ public function getDatabasePlatform() { if (null == $this->platform) { $this->detectDatabasePlatform(); } return $this->platform; } /** * Gets the ExpressionBuilder for the connection. * * @return \Doctrine\DBAL\Query\Expression\ExpressionBuilder */ public function getExpressionBuilder() { return $this->_expr; } /** * Establishes the connection with the database. * * @return boolean TRUE if the connection was successfully established, FALSE if * the connection is already open. */ public function connect() { if ($this->_isConnected) return false; $driverOptions = isset($this->_params['driverOptions']) ? $this->_params['driverOptions'] : array(); $user = isset($this->_params['user']) ? $this->_params['user'] : null; $password = isset($this->_params['password']) ? $this->_params['password'] : null; $this->_conn = $this->_driver->connect($this->_params, $user, $password, $driverOptions); $this->_isConnected = true; if (null === $this->platform) { $this->detectDatabasePlatform(); } if (false === $this->autoCommit) { $this->beginTransaction(); } if ($this->_eventManager->hasListeners(Events::postConnect)) { $eventArgs = new Event\ConnectionEventArgs($this); $this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs); } return true; } /** * Detects and sets the database platform. * * Evaluates custom platform class and version in order to set the correct platform. * * @throws DBALException if an invalid platform was specified for this connection. */ private function detectDatabasePlatform() { if ( ! isset($this->_params['platform'])) { $version = $this->getDatabasePlatformVersion(); if (null !== $version) { $this->platform = $this->_driver->createDatabasePlatformForVersion($version); } else { $this->platform = $this->_driver->getDatabasePlatform(); } } elseif ($this->_params['platform'] instanceof Platforms\AbstractPlatform) { $this->platform = $this->_params['platform']; } else { throw DBALException::invalidPlatformSpecified(); } $this->platform->setEventManager($this->_eventManager); } /** * Returns the version of the related platform if applicable. * * Returns null if either the driver is not capable to create version * specific platform instances, no explicit server version was specified * or the underlying driver connection cannot determine the platform * version without having to query it (performance reasons). * * @return string|null */ private function getDatabasePlatformVersion() { // Driver does not support version specific platforms. if ( ! $this->_driver instanceof VersionAwarePlatformDriver) { return null; } // Explicit platform version requested (supersedes auto-detection). if (isset($this->_params['serverVersion'])) { return $this->_params['serverVersion']; } // If not connected, we need to connect now to determine the platform version. if (null === $this->_conn) { $this->connect(); } // Automatic platform version detection. if ($this->_conn instanceof ServerInfoAwareConnection && ! $this->_conn->requiresQueryForServerVersion() ) { return $this->_conn->getServerVersion(); } // Unable to detect platform version. return null; } /** * Returns the current auto-commit mode for this connection. * * @return boolean True if auto-commit mode is currently enabled for this connection, false otherwise. * * @see setAutoCommit */ public function isAutoCommit() { return true === $this->autoCommit; } /** * Sets auto-commit mode for this connection. * * If a connection is in auto-commit mode, then all its SQL statements will be executed and committed as individual * transactions. Otherwise, its SQL statements are grouped into transactions that are terminated by a call to either * the method commit or the method rollback. By default, new connections are in auto-commit mode. * * NOTE: If this method is called during a transaction and the auto-commit mode is changed, the transaction is * committed. If this method is called and the auto-commit mode is not changed, the call is a no-op. * * @param boolean $autoCommit True to enable auto-commit mode; false to disable it. * * @see isAutoCommit */ public function setAutoCommit($autoCommit) { $autoCommit = (boolean) $autoCommit; // Mode not changed, no-op. if ($autoCommit === $this->autoCommit) { return; } $this->autoCommit = $autoCommit; // Commit all currently active transactions if any when switching auto-commit mode. if (true === $this->_isConnected && 0 !== $this->_transactionNestingLevel) { $this->commitAll(); } } /** * Sets the fetch mode. * * @param integer $fetchMode * * @return void */ public function setFetchMode($fetchMode) { $this->defaultFetchMode = $fetchMode; } /** * Prepares and executes an SQL query and returns the first row of the result * as an associative array. * * @param string $statement The SQL query. * @param array $params The query parameters. * @param array $types The query parameter types. * * @return array */ public function fetchAssoc($statement, array $params = array(), array $types = array()) { return $this->executeQuery($statement, $params, $types)->fetch(PDO::FETCH_ASSOC); } /** * Prepares and executes an SQL query and returns the first row of the result * as a numerically indexed array. * * @param string $statement The SQL query to be executed. * @param array $params The prepared statement params. * @param array $types The query parameter types. * * @return array */ public function fetchArray($statement, array $params = array(), array $types = array()) { return $this->executeQuery($statement, $params, $types)->fetch(PDO::FETCH_NUM); } /** * Prepares and executes an SQL query and returns the value of a single column * of the first row of the result. * * @param string $statement The SQL query to be executed. * @param array $params The prepared statement params. * @param integer $column The 0-indexed column number to retrieve. * @param array $types The query parameter types. * * @return mixed */ public function fetchColumn($statement, array $params = array(), $column = 0, array $types = array()) { return $this->executeQuery($statement, $params, $types)->fetchColumn($column); } /** * Whether an actual connection to the database is established. * * @return boolean */ public function isConnected() { return $this->_isConnected; } /** * Checks whether a transaction is currently active. * * @return boolean TRUE if a transaction is currently active, FALSE otherwise. */ public function isTransactionActive() { return $this->_transactionNestingLevel > 0; } /** * Executes an SQL DELETE statement on a table. * * Table expression and columns are not escaped and are not safe for user-input. * * @param string $tableExpression The expression of the table on which to delete. * @param array $identifier The deletion criteria. An associative array containing column-value pairs. * @param array $types The types of identifiers. * * @return integer The number of affected rows. * * @throws InvalidArgumentException */ public function delete($tableExpression, array $identifier, array $types = array()) { if (empty($identifier)) { throw InvalidArgumentException::fromEmptyCriteria(); } $columnList = array(); $criteria = array(); $paramValues = array(); foreach ($identifier as $columnName => $value) { $columnList[] = $columnName; $criteria[] = $columnName . ' = ?'; $paramValues[] = $value; } return $this->executeUpdate( 'DELETE FROM ' . $tableExpression . ' WHERE ' . implode(' AND ', $criteria), $paramValues, is_string(key($types)) ? $this->extractTypeValues($columnList, $types) : $types ); } /** * Closes the connection. * * @return void */ public function close() { $this->_conn = null; $this->_isConnected = false; } /** * Sets the transaction isolation level. * * @param integer $level The level to set. * * @return integer */ public function setTransactionIsolation($level) { $this->_transactionIsolationLevel = $level; return $this->executeUpdate($this->getDatabasePlatform()->getSetTransactionIsolationSQL($level)); } /** * Gets the currently active transaction isolation level. * * @return integer The current transaction isolation level. */ public function getTransactionIsolation() { if (null === $this->_transactionIsolationLevel) { $this->_transactionIsolationLevel = $this->getDatabasePlatform()->getDefaultTransactionIsolationLevel(); } return $this->_transactionIsolationLevel; } /** * Executes an SQL UPDATE statement on a table. * * Table expression and columns are not escaped and are not safe for user-input. * * @param string $tableExpression The expression of the table to update quoted or unquoted. * @param array $data An associative array containing column-value pairs. * @param array $identifier The update criteria. An associative array containing column-value pairs. * @param array $types Types of the merged $data and $identifier arrays in that order. * * @return integer The number of affected rows. */ public function update($tableExpression, array $data, array $identifier, array $types = array()) { $columnList = array(); $set = array(); $criteria = array(); $paramValues = array(); foreach ($data as $columnName => $value) { $columnList[] = $columnName; $set[] = $columnName . ' = ?'; $paramValues[] = $value; } foreach ($identifier as $columnName => $value) { $columnList[] = $columnName; $criteria[] = $columnName . ' = ?'; $paramValues[] = $value; } if (is_string(key($types))) { $types = $this->extractTypeValues($columnList, $types); } $sql = 'UPDATE ' . $tableExpression . ' SET ' . implode(', ', $set) . ' WHERE ' . implode(' AND ', $criteria); return $this->executeUpdate($sql, $paramValues, $types); } /** * Inserts a table row with specified data. * * Table expression and columns are not escaped and are not safe for user-input. * * @param string $tableExpression The expression of the table to insert data into, quoted or unquoted. * @param array $data An associative array containing column-value pairs. * @param array $types Types of the inserted data. * * @return integer The number of affected rows. */ public function insert($tableExpression, array $data, array $types = array()) { $this->connect(); if (empty($data)) { return $this->executeUpdate('INSERT INTO ' . $tableExpression . ' ()' . ' VALUES ()'); } $columnList = array(); $paramPlaceholders = array(); $paramValues = array(); foreach ($data as $columnName => $value) { $columnList[] = $columnName; $paramPlaceholders[] = '?'; $paramValues[] = $value; } return $this->executeUpdate( 'INSERT INTO ' . $tableExpression . ' (' . implode(', ', $columnList) . ')' . ' VALUES (' . implode(', ', $paramPlaceholders) . ')', $paramValues, is_string(key($types)) ? $this->extractTypeValues($columnList, $types) : $types ); } /** * Extract ordered type list from an ordered column list and type map. * * @param array $columnList * @param array $types * * @return array */ private function extractTypeValues(array $columnList, array $types) { $typeValues = array(); foreach ($columnList as $columnIndex => $columnName) { $typeValues[] = isset($types[$columnName]) ? $types[$columnName] : \PDO::PARAM_STR; } return $typeValues; } /** * Quotes a string so it can be safely used as a table or column name, even if * it is a reserved name. * * Delimiting style depends on the underlying database platform that is being used. * * NOTE: Just because you CAN use quoted identifiers does not mean * you SHOULD use them. In general, they end up causing way more * problems than they solve. * * @param string $str The name to be quoted. * * @return string The quoted name. */ public function quoteIdentifier($str) { return $this->getDatabasePlatform()->quoteIdentifier($str); } /** * Quotes a given input parameter. * * @param mixed $input The parameter to be quoted. * @param string|null $type The type of the parameter. * * @return string The quoted parameter. */ public function quote($input, $type = null) { $this->connect(); list($value, $bindingType) = $this->getBindingInfo($input, $type); return $this->_conn->quote($value, $bindingType); } /** * Prepares and executes an SQL query and returns the result as an associative array. * * @param string $sql The SQL query. * @param array $params The query parameters. * @param array $types The query parameter types. * * @return array */ public function fetchAll($sql, array $params = array(), $types = array()) { return $this->executeQuery($sql, $params, $types)->fetchAll(); } /** * Prepares an SQL statement. * * @param string $statement The SQL statement to prepare. * * @return \Doctrine\DBAL\Driver\Statement The prepared statement. * * @throws \Doctrine\DBAL\DBALException */ public function prepare($statement) { $this->connect(); try { $stmt = new Statement($statement, $this); } catch (\Exception $ex) { throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $statement); } $stmt->setFetchMode($this->defaultFetchMode); return $stmt; } /** * Executes an, optionally parametrized, SQL query. * * If the query is parametrized, a prepared statement is used. * If an SQLLogger is configured, the execution is logged. * * @param string $query The SQL query to execute. * @param array $params The parameters to bind to the query, if any. * @param array $types The types the previous parameters are in. * @param \Doctrine\DBAL\Cache\QueryCacheProfile|null $qcp The query cache profile, optional. * * @return \Doctrine\DBAL\Driver\Statement The executed statement. * * @throws \Doctrine\DBAL\DBALException */ public function executeQuery($query, array $params = array(), $types = array(), QueryCacheProfile $qcp = null) { if ($qcp !== null) { return $this->executeCacheQuery($query, $params, $types, $qcp); } $this->connect(); $logger = $this->_config->getSQLLogger(); if ($logger) { $logger->startQuery($query, $params, $types); } try { if ($params) { list($query, $params, $types) = SQLParserUtils::expandListParameters($query, $params, $types); $stmt = $this->_conn->prepare($query); if ($types) { $this->_bindTypedValues($stmt, $params, $types); $stmt->execute(); } else { $stmt->execute($params); } } else { $stmt = $this->_conn->query($query); } } catch (\Exception $ex) { throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $query, $this->resolveParams($params, $types)); } $stmt->setFetchMode($this->defaultFetchMode); if ($logger) { $logger->stopQuery(); } return $stmt; } /** * Executes a caching query. * * @param string $query The SQL query to execute. * @param array $params The parameters to bind to the query, if any. * @param array $types The types the previous parameters are in. * @param \Doctrine\DBAL\Cache\QueryCacheProfile $qcp The query cache profile. * * @return \Doctrine\DBAL\Driver\ResultStatement * * @throws \Doctrine\DBAL\Cache\CacheException */ public function executeCacheQuery($query, $params, $types, QueryCacheProfile $qcp) { $resultCache = $qcp->getResultCacheDriver() ?: $this->_config->getResultCacheImpl(); if ( ! $resultCache) { throw CacheException::noResultDriverConfigured(); } list($cacheKey, $realKey) = $qcp->generateCacheKeys($query, $params, $types); // fetch the row pointers entry if ($data = $resultCache->fetch($cacheKey)) { // is the real key part of this row pointers map or is the cache only pointing to other cache keys? if (isset($data[$realKey])) { $stmt = new ArrayStatement($data[$realKey]); } elseif (array_key_exists($realKey, $data)) { $stmt = new ArrayStatement(array()); } } if (!isset($stmt)) { $stmt = new ResultCacheStatement($this->executeQuery($query, $params, $types), $resultCache, $cacheKey, $realKey, $qcp->getLifetime()); } $stmt->setFetchMode($this->defaultFetchMode); return $stmt; } /** * Executes an, optionally parametrized, SQL query and returns the result, * applying a given projection/transformation function on each row of the result. * * @param string $query The SQL query to execute. * @param array $params The parameters, if any. * @param \Closure $function The transformation function that is applied on each row. * The function receives a single parameter, an array, that * represents a row of the result set. * * @return array The projected result of the query. */ public function project($query, array $params, Closure $function) { $result = array(); $stmt = $this->executeQuery($query, $params); while ($row = $stmt->fetch()) { $result[] = $function($row); } $stmt->closeCursor(); return $result; } /** * Executes an SQL statement, returning a result set as a Statement object. * * @return \Doctrine\DBAL\Driver\Statement * * @throws \Doctrine\DBAL\DBALException */ public function query() { $this->connect(); $args = func_get_args(); $logger = $this->_config->getSQLLogger(); if ($logger) { $logger->startQuery($args[0]); } try { switch (func_num_args()) { case 1: $statement = $this->_conn->query($args[0]); break; case 2: $statement = $this->_conn->query($args[0], $args[1]); break; default: $statement = call_user_func_array(array($this->_conn, 'query'), $args); break; } } catch (\Exception $ex) { throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $args[0]); } $statement->setFetchMode($this->defaultFetchMode); if ($logger) { $logger->stopQuery(); } return $statement; } /** * Executes an SQL INSERT/UPDATE/DELETE query with the given parameters * and returns the number of affected rows. * * This method supports PDO binding types as well as DBAL mapping types. * * @param string $query The SQL query. * @param array $params The query parameters. * @param array $types The parameter types. * * @return integer The number of affected rows. * * @throws \Doctrine\DBAL\DBALException */ public function executeUpdate($query, array $params = array(), array $types = array()) { $this->connect(); $logger = $this->_config->getSQLLogger(); if ($logger) { $logger->startQuery($query, $params, $types); } try { if ($params) { list($query, $params, $types) = SQLParserUtils::expandListParameters($query, $params, $types); $stmt = $this->_conn->prepare($query); if ($types) { $this->_bindTypedValues($stmt, $params, $types); $stmt->execute(); } else { $stmt->execute($params); } $result = $stmt->rowCount(); } else { $result = $this->_conn->exec($query); } } catch (\Exception $ex) { throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $query, $this->resolveParams($params, $types)); } if ($logger) { $logger->stopQuery(); } return $result; } /** * Executes an SQL statement and return the number of affected rows. * * @param string $statement * * @return integer The number of affected rows. * * @throws \Doctrine\DBAL\DBALException */ public function exec($statement) { $this->connect(); $logger = $this->_config->getSQLLogger(); if ($logger) { $logger->startQuery($statement); } try { $result = $this->_conn->exec($statement); } catch (\Exception $ex) { throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $statement); } if ($logger) { $logger->stopQuery(); } return $result; } /** * Returns the current transaction nesting level. * * @return integer The nesting level. A value of 0 means there's no active transaction. */ public function getTransactionNestingLevel() { return $this->_transactionNestingLevel; } /** * Fetches the SQLSTATE associated with the last database operation. * * @return integer The last error code. */ public function errorCode() { $this->connect(); return $this->_conn->errorCode(); } /** * Fetches extended error information associated with the last database operation. * * @return array The last error information. */ public function errorInfo() { $this->connect(); return $this->_conn->errorInfo(); } /** * Returns the ID of the last inserted row, or the last value from a sequence object, * depending on the underlying driver. * * Note: This method may not return a meaningful or consistent result across different drivers, * because the underlying database may not even support the notion of AUTO_INCREMENT/IDENTITY * columns or sequences. * * @param string|null $seqName Name of the sequence object from which the ID should be returned. * * @return string A string representation of the last inserted ID. */ public function lastInsertId($seqName = null) { $this->connect(); return $this->_conn->lastInsertId($seqName); } /** * Executes a function in a transaction. * * The function gets passed this Connection instance as an (optional) parameter. * * If an exception occurs during execution of the function or transaction commit, * the transaction is rolled back and the exception re-thrown. * * @param \Closure $func The function to execute transactionally. * * @return void * * @throws \Exception */ public function transactional(Closure $func) { $this->beginTransaction(); try { $func($this); $this->commit(); } catch (Exception $e) { $this->rollback(); throw $e; } } /** * Sets if nested transactions should use savepoints. * * @param boolean $nestTransactionsWithSavepoints * * @return void * * @throws \Doctrine\DBAL\ConnectionException */ public function setNestTransactionsWithSavepoints($nestTransactionsWithSavepoints) { if ($this->_transactionNestingLevel > 0) { throw ConnectionException::mayNotAlterNestedTransactionWithSavepointsInTransaction(); } if ( ! $this->getDatabasePlatform()->supportsSavepoints()) { throw ConnectionException::savepointsNotSupported(); } $this->_nestTransactionsWithSavepoints = (bool) $nestTransactionsWithSavepoints; } /** * Gets if nested transactions should use savepoints. * * @return boolean */ public function getNestTransactionsWithSavepoints() { return $this->_nestTransactionsWithSavepoints; } /** * Returns the savepoint name to use for nested transactions are false if they are not supported * "savepointFormat" parameter is not set * * @return mixed A string with the savepoint name or false. */ protected function _getNestedTransactionSavePointName() { return 'DOCTRINE2_SAVEPOINT_'.$this->_transactionNestingLevel; } /** * Starts a transaction by suspending auto-commit mode. * * @return void */ public function beginTransaction() { $this->connect(); ++$this->_transactionNestingLevel; $logger = $this->_config->getSQLLogger(); if ($this->_transactionNestingLevel == 1) { if ($logger) { $logger->startQuery('"START TRANSACTION"'); } $this->_conn->beginTransaction(); if ($logger) { $logger->stopQuery(); } } elseif ($this->_nestTransactionsWithSavepoints) { if ($logger) { $logger->startQuery('"SAVEPOINT"'); } $this->createSavepoint($this->_getNestedTransactionSavePointName()); if ($logger) { $logger->stopQuery(); } } } /** * Commits the current transaction. * * @return void * * @throws \Doctrine\DBAL\ConnectionException If the commit failed due to no active transaction or * because the transaction was marked for rollback only. */ public function commit() { if ($this->_transactionNestingLevel == 0) { throw ConnectionException::noActiveTransaction(); } if ($this->_isRollbackOnly) { throw ConnectionException::commitFailedRollbackOnly(); } $this->connect(); $logger = $this->_config->getSQLLogger(); if ($this->_transactionNestingLevel == 1) { if ($logger) { $logger->startQuery('"COMMIT"'); } $this->_conn->commit(); if ($logger) { $logger->stopQuery(); } } elseif ($this->_nestTransactionsWithSavepoints) { if ($logger) { $logger->startQuery('"RELEASE SAVEPOINT"'); } $this->releaseSavepoint($this->_getNestedTransactionSavePointName()); if ($logger) { $logger->stopQuery(); } } --$this->_transactionNestingLevel; if (false === $this->autoCommit && 0 === $this->_transactionNestingLevel) { $this->beginTransaction(); } } /** * Commits all current nesting transactions. */ private function commitAll() { while (0 !== $this->_transactionNestingLevel) { if (false === $this->autoCommit && 1 === $this->_transactionNestingLevel) { // When in no auto-commit mode, the last nesting commit immediately starts a new transaction. // Therefore we need to do the final commit here and then leave to avoid an infinite loop. $this->commit(); return; } $this->commit(); } } /** * Cancels any database changes done during the current transaction. * * This method can be listened with onPreTransactionRollback and onTransactionRollback * eventlistener methods. * * @throws \Doctrine\DBAL\ConnectionException If the rollback operation failed. */ public function rollBack() { if ($this->_transactionNestingLevel == 0) { throw ConnectionException::noActiveTransaction(); } $this->connect(); $logger = $this->_config->getSQLLogger(); if ($this->_transactionNestingLevel == 1) { if ($logger) { $logger->startQuery('"ROLLBACK"'); } $this->_transactionNestingLevel = 0; $this->_conn->rollback(); $this->_isRollbackOnly = false; if ($logger) { $logger->stopQuery(); } if (false === $this->autoCommit) { $this->beginTransaction(); } } elseif ($this->_nestTransactionsWithSavepoints) { if ($logger) { $logger->startQuery('"ROLLBACK TO SAVEPOINT"'); } $this->rollbackSavepoint($this->_getNestedTransactionSavePointName()); --$this->_transactionNestingLevel; if ($logger) { $logger->stopQuery(); } } else { $this->_isRollbackOnly = true; --$this->_transactionNestingLevel; } } /** * Creates a new savepoint. * * @param string $savepoint The name of the savepoint to create. * * @return void * * @throws \Doctrine\DBAL\ConnectionException */ public function createSavepoint($savepoint) { if ( ! $this->getDatabasePlatform()->supportsSavepoints()) { throw ConnectionException::savepointsNotSupported(); } $this->_conn->exec($this->platform->createSavePoint($savepoint)); } /** * Releases the given savepoint. * * @param string $savepoint The name of the savepoint to release. * * @return void * * @throws \Doctrine\DBAL\ConnectionException */ public function releaseSavepoint($savepoint) { if ( ! $this->getDatabasePlatform()->supportsSavepoints()) { throw ConnectionException::savepointsNotSupported(); } if ($this->platform->supportsReleaseSavepoints()) { $this->_conn->exec($this->platform->releaseSavePoint($savepoint)); } } /** * Rolls back to the given savepoint. * * @param string $savepoint The name of the savepoint to rollback to. * * @return void * * @throws \Doctrine\DBAL\ConnectionException */ public function rollbackSavepoint($savepoint) { if ( ! $this->getDatabasePlatform()->supportsSavepoints()) { throw ConnectionException::savepointsNotSupported(); } $this->_conn->exec($this->platform->rollbackSavePoint($savepoint)); } /** * Gets the wrapped driver connection. * * @return \Doctrine\DBAL\Driver\Connection */ public function getWrappedConnection() { $this->connect(); return $this->_conn; } /** * Gets the SchemaManager that can be used to inspect or change the * database schema through the connection. * * @return \Doctrine\DBAL\Schema\AbstractSchemaManager */ public function getSchemaManager() { if ( ! $this->_schemaManager) { $this->_schemaManager = $this->_driver->getSchemaManager($this); } return $this->_schemaManager; } /** * Marks the current transaction so that the only possible * outcome for the transaction to be rolled back. * * @return void * * @throws \Doctrine\DBAL\ConnectionException If no transaction is active. */ public function setRollbackOnly() { if ($this->_transactionNestingLevel == 0) { throw ConnectionException::noActiveTransaction(); } $this->_isRollbackOnly = true; } /** * Checks whether the current transaction is marked for rollback only. * * @return boolean * * @throws \Doctrine\DBAL\ConnectionException If no transaction is active. */ public function isRollbackOnly() { if ($this->_transactionNestingLevel == 0) { throw ConnectionException::noActiveTransaction(); } return $this->_isRollbackOnly; } /** * Converts a given value to its database representation according to the conversion * rules of a specific DBAL mapping type. * * @param mixed $value The value to convert. * @param string $type The name of the DBAL mapping type. * * @return mixed The converted value. */ public function convertToDatabaseValue($value, $type) { return Type::getType($type)->convertToDatabaseValue($value, $this->getDatabasePlatform()); } /** * Converts a given value to its PHP representation according to the conversion * rules of a specific DBAL mapping type. * * @param mixed $value The value to convert. * @param string $type The name of the DBAL mapping type. * * @return mixed The converted type. */ public function convertToPHPValue($value, $type) { return Type::getType($type)->convertToPHPValue($value, $this->getDatabasePlatform()); } /** * Binds a set of parameters, some or all of which are typed with a PDO binding type * or DBAL mapping type, to a given statement. * * @param \Doctrine\DBAL\Driver\Statement $stmt The statement to bind the values to. * @param array $params The map/list of named/positional parameters. * @param array $types The parameter types (PDO binding types or DBAL mapping types). * * @return void * * @internal Duck-typing used on the $stmt parameter to support driver statements as well as * raw PDOStatement instances. */ private function _bindTypedValues($stmt, array $params, array $types) { // Check whether parameters are positional or named. Mixing is not allowed, just like in PDO. if (is_int(key($params))) { // Positional parameters $typeOffset = array_key_exists(0, $types) ? -1 : 0; $bindIndex = 1; foreach ($params as $value) { $typeIndex = $bindIndex + $typeOffset; if (isset($types[$typeIndex])) { $type = $types[$typeIndex]; list($value, $bindingType) = $this->getBindingInfo($value, $type); $stmt->bindValue($bindIndex, $value, $bindingType); } else { $stmt->bindValue($bindIndex, $value); } ++$bindIndex; } } else { // Named parameters foreach ($params as $name => $value) { if (isset($types[$name])) { $type = $types[$name]; list($value, $bindingType) = $this->getBindingInfo($value, $type); $stmt->bindValue($name, $value, $bindingType); } else { $stmt->bindValue($name, $value); } } } } /** * Gets the binding type of a given type. The given type can be a PDO or DBAL mapping type. * * @param mixed $value The value to bind. * @param mixed $type The type to bind (PDO or DBAL). * * @return array [0] => the (escaped) value, [1] => the binding type. */ private function getBindingInfo($value, $type) { if (is_string($type)) { $type = Type::getType($type); } if ($type instanceof Type) { $value = $type->convertToDatabaseValue($value, $this->getDatabasePlatform()); $bindingType = $type->getBindingType(); } else { $bindingType = $type; // PDO::PARAM_* constants } return array($value, $bindingType); } /** * Resolves the parameters to a format which can be displayed. * * @internal This is a purely internal method. If you rely on this method, you are advised to * copy/paste the code as this method may change, or be removed without prior notice. * * @param array $params * @param array $types * * @return array */ public function resolveParams(array $params, array $types) { $resolvedParams = array(); // Check whether parameters are positional or named. Mixing is not allowed, just like in PDO. if (is_int(key($params))) { // Positional parameters $typeOffset = array_key_exists(0, $types) ? -1 : 0; $bindIndex = 1; foreach ($params as $value) { $typeIndex = $bindIndex + $typeOffset; if (isset($types[$typeIndex])) { $type = $types[$typeIndex]; list($value,) = $this->getBindingInfo($value, $type); $resolvedParams[$bindIndex] = $value; } else { $resolvedParams[$bindIndex] = $value; } ++$bindIndex; } } else { // Named parameters foreach ($params as $name => $value) { if (isset($types[$name])) { $type = $types[$name]; list($value,) = $this->getBindingInfo($value, $type); $resolvedParams[$name] = $value; } else { $resolvedParams[$name] = $value; } } } return $resolvedParams; } /** * Creates a new instance of a SQL query builder. * * @return \Doctrine\DBAL\Query\QueryBuilder */ public function createQueryBuilder() { return new Query\QueryBuilder($this); } /** * Ping the server * * When the server is not available the method returns FALSE. * It is responsibility of the developer to handle this case * and abort the request or reconnect manually: * * @example * * if ($conn->ping() === false) { * $conn->close(); * $conn->connect(); * } * * It is undefined if the underlying driver attempts to reconnect * or disconnect when the connection is not available anymore * as long it returns TRUE when a reconnect succeeded and * FALSE when the connection was dropped. * * @return bool */ public function ping() { $this->connect(); if ($this->_conn instanceof PingableConnection) { return $this->_conn->ping(); } try { $this->query($this->getDatabasePlatform()->getDummySelectSQL()); return true; } catch (DBALException $e) { return false; } } } dbal-2.5.13/lib/Doctrine/DBAL/ConnectionException.php000066400000000000000000000040551313473450000222160ustar00rootroot00000000000000. */ namespace Doctrine\DBAL; /** * @link www.doctrine-project.org * @since 2.0 * @author Jonathan H. Wage . */ namespace Doctrine\DBAL\Connections; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Driver; use Doctrine\DBAL\Configuration; use Doctrine\Common\EventManager; use Doctrine\DBAL\Event\ConnectionEventArgs; use 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 * @author Benjamin Eberlei */ 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); /** * You can keep the slave connection and then switch back to it * during the request if you know what you are doing. * * @var boolean */ protected $keepSlave = false; /** * Creates Master Slave Connection. * * @param array $params * @param \Doctrine\DBAL\Driver $driver * @param \Doctrine\DBAL\Configuration|null $config * @param \Doctrine\Common\EventManager|null $eventManager * * @throws \InvalidArgumentException */ 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']; } $this->keepSlave = isset($params['keepSlave']) ? (bool) $params['keepSlave'] : false; parent::__construct($params, $driver, $config, $eventManager); } /** * Checks if the connection is currently towards the master or not. * * @return boolean */ public function isConnectedToMaster() { return $this->_conn !== null && $this->_conn === $this->connections['master']; } /** * {@inheritDoc} */ public function connect($connectionName = null) { $requestedConnectionChange = ($connectionName !== null); $connectionName = $connectionName ?: 'slave'; if ($connectionName !== 'slave' && $connectionName !== 'master') { throw new \InvalidArgumentException("Invalid option to connect(), only master or slave allowed."); } // If we have a connection open, and this is not an explicit connection // change request, then abort right here, because we are already done. // This prevents writes to the slave in case of "keepSlave" option enabled. if ($this->_conn && !$requestedConnectionChange) { return false; } $forceMasterAsSlave = false; if ($this->getTransactionNestingLevel() > 0) { $connectionName = 'master'; $forceMasterAsSlave = true; } if ($this->connections[$connectionName]) { $this->_conn = $this->connections[$connectionName]; if ($forceMasterAsSlave && ! $this->keepSlave) { $this->connections['slave'] = $this->_conn; } return false; } if ($connectionName === 'master') { // Set slave connection to master to avoid invalid reads if ($this->connections['slave'] && ! $this->keepSlave) { unset($this->connections['slave']); } $this->connections['master'] = $this->_conn = $this->connectTo($connectionName); if ( ! $this->keepSlave) { $this->connections['slave'] = $this->connections['master']; } } 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; } /** * Connects to a specific connection. * * @param string $connectionName * * @return \Doctrine\DBAL\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); } /** * @param string $connectionName * @param array $params * * @return mixed */ 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'); parent::beginTransaction(); } /** * {@inheritDoc} */ public function commit() { $this->connect('master'); parent::commit(); } /** * {@inheritDoc} */ public function rollBack() { $this->connect('master'); return parent::rollBack(); } /** * {@inheritDoc} */ public function delete($tableName, array $identifier, array $types = array()) { $this->connect('master'); return parent::delete($tableName, $identifier, $types); } /** * {@inheritDoc} */ public function close() { unset($this->connections['master']); unset($this->connections['slave']); parent::close(); $this->_conn = null; $this->connections = array('master' => null, 'slave' => null); } /** * {@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'); parent::createSavepoint($savepoint); } /** * {@inheritDoc} */ public function releaseSavepoint($savepoint) { $this->connect('master'); parent::releaseSavepoint($savepoint); } /** * {@inheritDoc} */ public function rollbackSavepoint($savepoint) { $this->connect('master'); parent::rollbackSavepoint($savepoint); } /** * {@inheritDoc} */ 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; } /** * {@inheritDoc} */ public function prepare($statement) { $this->connect('master'); return parent::prepare($statement); } } dbal-2.5.13/lib/Doctrine/DBAL/DBALException.php000066400000000000000000000203721313473450000206210ustar00rootroot00000000000000. */ namespace Doctrine\DBAL; use Doctrine\DBAL\Driver\DriverException; use Doctrine\DBAL\Driver\ExceptionConverterDriver; class DBALException extends \Exception { /** * @param string $method * * @return \Doctrine\DBAL\DBALException */ public static function notSupported($method) { return new self("Operation '$method' is not supported by platform."); } /** * @return \Doctrine\DBAL\DBALException */ public static function invalidPlatformSpecified() { return new self( "Invalid 'platform' option specified, need to give an instance of ". "\Doctrine\DBAL\Platforms\AbstractPlatform."); } /** * Returns a new instance for an invalid specified platform version. * * @param string $version The invalid platform version given. * @param string $expectedFormat The expected platform version format. * * @return DBALException */ public static function invalidPlatformVersionSpecified($version, $expectedFormat) { return new self( sprintf( 'Invalid platform version "%s" specified. ' . 'The platform version has to be specified in the format: "%s".', $version, $expectedFormat ) ); } /** * @return \Doctrine\DBAL\DBALException */ public static function invalidPdoInstance() { return new self( "The 'pdo' option was used in DriverManager::getConnection() but no ". "instance of PDO was given." ); } /** * @param string|null $url The URL that was provided in the connection parameters (if any). * * @return \Doctrine\DBAL\DBALException */ public static function driverRequired($url = null) { if ($url) { return new self( sprintf( "The options 'driver' or 'driverClass' are mandatory if a connection URL without scheme " . "is given to DriverManager::getConnection(). Given URL: %s", $url ) ); } return new self("The options 'driver' or 'driverClass' are mandatory if no PDO ". "instance is given to DriverManager::getConnection()."); } /** * @param string $unknownDriverName * @param array $knownDrivers * * @return \Doctrine\DBAL\DBALException */ 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)); } /** * @param \Doctrine\DBAL\Driver $driver * @param \Exception $driverEx * @param string $sql * @param array $params * * @return \Doctrine\DBAL\DBALException */ public static function driverExceptionDuringQuery(Driver $driver, \Exception $driverEx, $sql, array $params = array()) { $msg = "An exception occurred while executing '".$sql."'"; if ($params) { $msg .= " with params " . self::formatParameters($params); } $msg .= ":\n\n".$driverEx->getMessage(); if ($driver instanceof ExceptionConverterDriver && $driverEx instanceof DriverException) { return $driver->convertException($msg, $driverEx); } return new self($msg, 0, $driverEx); } /** * @param \Doctrine\DBAL\Driver $driver * @param \Exception $driverEx * * @return \Doctrine\DBAL\DBALException */ public static function driverException(Driver $driver, \Exception $driverEx) { $msg = "An exception occured in driver: " . $driverEx->getMessage(); if ($driver instanceof ExceptionConverterDriver && $driverEx instanceof DriverException) { return $driver->convertException($msg, $driverEx); } return new self($msg, 0, $driverEx); } /** * Returns a human-readable representation of an array of parameters. * This properly handles binary data by returning a hex representation. * * @param array $params * * @return string */ private static function formatParameters(array $params) { return '[' . implode(', ', array_map(function ($param) { $json = @json_encode($param); if (! is_string($json) || $json == 'null' && is_string($param)) { // JSON encoding failed, this is not a UTF-8 string. return '"\x' . implode('\x', str_split(bin2hex($param), 2)) . '"'; } return $json; }, $params)) . ']'; } /** * @param string $wrapperClass * * @return \Doctrine\DBAL\DBALException */ public static function invalidWrapperClass($wrapperClass) { return new self("The given 'wrapperClass' ".$wrapperClass." has to be a ". "subtype of \Doctrine\DBAL\Connection."); } /** * @param string $driverClass * * @return \Doctrine\DBAL\DBALException */ public static function invalidDriverClass($driverClass) { return new self("The given 'driverClass' ".$driverClass." has to implement the ". "\Doctrine\DBAL\Driver interface."); } /** * @param string $tableName * * @return \Doctrine\DBAL\DBALException */ public static function invalidTableName($tableName) { return new self("Invalid table name specified: ".$tableName); } /** * @param string $tableName * * @return \Doctrine\DBAL\DBALException */ public static function noColumnsSpecifiedForTable($tableName) { return new self("No columns specified for table ".$tableName); } /** * @return \Doctrine\DBAL\DBALException */ public static function limitOffsetInvalid() { return new self("Invalid Offset in Limit Query, it has to be larger or equal to 0."); } /** * @param string $name * * @return \Doctrine\DBAL\DBALException */ public static function typeExists($name) { return new self('Type '.$name.' already exists.'); } /** * @param string $name * * @return \Doctrine\DBAL\DBALException */ public static function unknownColumnType($name) { return new self('Unknown column type "'.$name.'" requested. Any Doctrine type that you use has ' . 'to be registered with \Doctrine\DBAL\Types\Type::addType(). You can get a list of all the ' . 'known types with \Doctrine\DBAL\Types\Type::getTypesMap(). If this error occurs during database ' . 'introspection then you might have forgot to register all database types for a Doctrine Type. Use ' . 'AbstractPlatform#registerDoctrineTypeMapping() or have your custom types implement ' . 'Type#getMappedDatabaseTypes(). If the type name is empty you might ' . 'have a problem with the cache or forgot some mapping information.' ); } /** * @param string $name * * @return \Doctrine\DBAL\DBALException */ public static function typeNotFound($name) { return new self('Type to be overwritten '.$name.' does not exist.'); } } dbal-2.5.13/lib/Doctrine/DBAL/Driver.php000066400000000000000000000052441313473450000174740ustar00rootroot00000000000000. */ 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|null $username The username to use when connecting. * @param string|null $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\Schema\AbstractSchemaManager */ public function getSchemaManager(Connection $conn); /** * Gets the name of the driver. * * @return string The name of the driver. */ public function getName(); /** * Gets the name of the database connected to for this driver. * * @param \Doctrine\DBAL\Connection $conn * * @return string The name of the database. */ public function getDatabase(Connection $conn); } dbal-2.5.13/lib/Doctrine/DBAL/Driver/000077500000000000000000000000001313473450000167565ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Driver/AbstractDB2Driver.php000066400000000000000000000035341313473450000227030ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver; use Doctrine\DBAL\Driver; use Doctrine\DBAL\Platforms\DB2Platform; use Doctrine\DBAL\Schema\DB2SchemaManager; /** * Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for IBM DB2 based drivers. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ abstract class AbstractDB2Driver implements Driver { /** * {@inheritdoc} */ public function getDatabase(\Doctrine\DBAL\Connection $conn) { $params = $conn->getParams(); return $params['dbname']; } /** * {@inheritdoc} */ public function getDatabasePlatform() { return new DB2Platform(); } /** * {@inheritdoc} */ public function getSchemaManager(\Doctrine\DBAL\Connection $conn) { return new DB2SchemaManager($conn); } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/AbstractDriverException.php000066400000000000000000000043461313473450000242740ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver; /** * Abstract base implementation of the {@link DriverException} interface. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ abstract class AbstractDriverException extends \Exception implements DriverException { /** * The driver specific error code. * * @var integer|string|null */ private $errorCode; /** * The SQLSTATE of the driver. * * @var string|null */ private $sqlState; /** * Constructor. * * @param string $message The driver error message. * @param string|null $sqlState The SQLSTATE the driver is in at the time the error occured, if any. * @param integer|string|null $errorCode The driver specific error code if any. */ public function __construct($message, $sqlState = null, $errorCode = null) { parent::__construct($message); $this->errorCode = $errorCode; $this->sqlState = $sqlState; } /** * {@inheritdoc} */ public function getErrorCode() { return $this->errorCode; } /** * {@inheritdoc} */ public function getSQLState() { return $this->sqlState; } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php000066400000000000000000000127531313473450000233040ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver; use Doctrine\DBAL\Exception; use Doctrine\DBAL\Platforms\MySQL57Platform; use Doctrine\DBAL\Platforms\MySqlPlatform; use Doctrine\DBAL\Schema\MySqlSchemaManager; use Doctrine\DBAL\VersionAwarePlatformDriver; /** * Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for MySQL based drivers. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ abstract class AbstractMySQLDriver implements Driver, ExceptionConverterDriver, VersionAwarePlatformDriver { /** * {@inheritdoc} * * @link http://dev.mysql.com/doc/refman/5.7/en/error-messages-client.html * @link http://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html */ public function convertException($message, DriverException $exception) { switch ($exception->getErrorCode()) { case '1050': return new Exception\TableExistsException($message, $exception); case '1051': case '1146': return new Exception\TableNotFoundException($message, $exception); case '1216': case '1217': case '1451': case '1452': case '1701': return new Exception\ForeignKeyConstraintViolationException($message, $exception); case '1062': case '1557': case '1569': case '1586': return new Exception\UniqueConstraintViolationException($message, $exception); case '1054': case '1166': case '1611': return new Exception\InvalidFieldNameException($message, $exception); case '1052': case '1060': case '1110': return new Exception\NonUniqueFieldNameException($message, $exception); case '1064': case '1149': case '1287': case '1341': case '1342': case '1343': case '1344': case '1382': case '1479': case '1541': case '1554': case '1626': return new Exception\SyntaxErrorException($message, $exception); case '1044': case '1045': case '1046': case '1049': case '1095': case '1142': case '1143': case '1227': case '1370': case '2002': case '2005': return new Exception\ConnectionException($message, $exception); case '1048': case '1121': case '1138': case '1171': case '1252': case '1263': case '1566': return new Exception\NotNullConstraintViolationException($message, $exception); } return new Exception\DriverException($message, $exception); } /** * {@inheritdoc} */ public function createDatabasePlatformForVersion($version) { if ( ! preg_match('/^(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+))?)?/', $version, $versionParts)) { throw DBALException::invalidPlatformVersionSpecified( $version, '..' ); } if (false !== stripos($version, 'mariadb')) { return $this->getDatabasePlatform(); } $majorVersion = $versionParts['major']; $minorVersion = isset($versionParts['minor']) ? $versionParts['minor'] : 0; $patchVersion = isset($versionParts['patch']) ? $versionParts['patch'] : 0; $version = $majorVersion . '.' . $minorVersion . '.' . $patchVersion; if (version_compare($version, '5.7', '>=')) { return new MySQL57Platform(); } return $this->getDatabasePlatform(); } /** * {@inheritdoc} */ public function getDatabase(\Doctrine\DBAL\Connection $conn) { $params = $conn->getParams(); if (isset($params['dbname'])) { return $params['dbname']; } return $conn->query('SELECT DATABASE()')->fetchColumn(); } /** * {@inheritdoc} */ public function getDatabasePlatform() { return new MySqlPlatform(); } /** * {@inheritdoc} */ public function getSchemaManager(\Doctrine\DBAL\Connection $conn) { return new MySqlSchemaManager($conn); } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/AbstractOracleDriver.php000066400000000000000000000115151313473450000235370ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver; use Doctrine\DBAL\Driver; use Doctrine\DBAL\Exception; use Doctrine\DBAL\Platforms\OraclePlatform; use Doctrine\DBAL\Schema\OracleSchemaManager; /** * Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for Oracle based drivers. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ abstract class AbstractOracleDriver implements Driver, ExceptionConverterDriver { /** * {@inheritdoc} */ public function convertException($message, DriverException $exception) { switch ($exception->getErrorCode()) { case '1': case '2299': case '38911': return new Exception\UniqueConstraintViolationException($message, $exception); case '904': return new Exception\InvalidFieldNameException($message, $exception); case '918': case '960': return new Exception\NonUniqueFieldNameException($message, $exception); case '923': return new Exception\SyntaxErrorException($message, $exception); case '942': return new Exception\TableNotFoundException($message, $exception); case '955': return new Exception\TableExistsException($message, $exception); case '1017': case '12545': return new Exception\ConnectionException($message, $exception); case '1400': return new Exception\NotNullConstraintViolationException($message, $exception); case '2266': case '2291': case '2292': return new Exception\ForeignKeyConstraintViolationException($message, $exception); } return new Exception\DriverException($message, $exception); } /** * {@inheritdoc} */ public function getDatabase(\Doctrine\DBAL\Connection $conn) { $params = $conn->getParams(); return $params['user']; } /** * {@inheritdoc} */ public function getDatabasePlatform() { return new OraclePlatform(); } /** * {@inheritdoc} */ public function getSchemaManager(\Doctrine\DBAL\Connection $conn) { return new OracleSchemaManager($conn); } /** * Returns an appropriate Easy Connect String for the given parameters. * * @param array $params The connection parameters to return the Easy Connect STring for. * * @return string * * @link http://download.oracle.com/docs/cd/E11882_01/network.112/e10836/naming.htm */ protected function getEasyConnectString(array $params) { if ( ! empty($params['host'])) { if ( ! isset($params['port'])) { $params['port'] = 1521; } $serviceName = $params['dbname']; if ( ! empty($params['servicename'])) { $serviceName = $params['servicename']; } $service = 'SID=' . $serviceName; $pooled = ''; $instance = ''; if (isset($params['service']) && $params['service'] == true) { $service = 'SERVICE_NAME=' . $serviceName; } if (isset($params['instancename']) && ! empty($params['instancename'])) { $instance = '(INSTANCE_NAME = ' . $params['instancename'] . ')'; } if (isset($params['pooled']) && $params['pooled'] == true) { $pooled = '(SERVER=POOLED)'; } return '(DESCRIPTION=' . '(ADDRESS=(PROTOCOL=TCP)(HOST=' . $params['host'] . ')(PORT=' . $params['port'] . '))' . '(CONNECT_DATA=(' . $service . ')' . $instance . $pooled . '))'; } return isset($params['dbname']) ? $params['dbname'] : ''; } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/AbstractPostgreSQLDriver.php000066400000000000000000000125741313473450000243430ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver; use Doctrine\DBAL\Exception; use Doctrine\DBAL\Platforms\PostgreSQL91Platform; use Doctrine\DBAL\Platforms\PostgreSQL92Platform; use Doctrine\DBAL\Platforms\PostgreSqlPlatform; use Doctrine\DBAL\Schema\PostgreSqlSchemaManager; use Doctrine\DBAL\VersionAwarePlatformDriver; /** * Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for PostgreSQL based drivers. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ abstract class AbstractPostgreSQLDriver implements Driver, ExceptionConverterDriver, VersionAwarePlatformDriver { /** * {@inheritdoc} * * @link http://www.postgresql.org/docs/9.3/static/errcodes-appendix.html */ public function convertException($message, DriverException $exception) { switch ($exception->getSQLState()) { case '0A000': // Foreign key constraint violations during a TRUNCATE operation // are considered "feature not supported" in PostgreSQL. if (strpos($exception->getMessage(), 'truncate') !== false) { return new Exception\ForeignKeyConstraintViolationException($message, $exception); } break; case '23502': return new Exception\NotNullConstraintViolationException($message, $exception); case '23503': return new Exception\ForeignKeyConstraintViolationException($message, $exception); case '23505': return new Exception\UniqueConstraintViolationException($message, $exception); case '42601': return new Exception\SyntaxErrorException($message, $exception); case '42702': return new Exception\NonUniqueFieldNameException($message, $exception); case '42703': return new Exception\InvalidFieldNameException($message, $exception); case '42P01': return new Exception\TableNotFoundException($message, $exception); case '42P07': return new Exception\TableExistsException($message, $exception); case '7': // In some case (mainly connection errors) the PDO exception does not provide a SQLSTATE via its code. // The exception code is always set to 7 here. // We have to match against the SQLSTATE in the error message in these cases. if (strpos($exception->getMessage(), 'SQLSTATE[08006]') !== false) { return new Exception\ConnectionException($message, $exception); } break; } return new Exception\DriverException($message, $exception); } /** * {@inheritdoc} */ public function createDatabasePlatformForVersion($version) { if ( ! preg_match('/^(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+))?)?/', $version, $versionParts)) { throw DBALException::invalidPlatformVersionSpecified( $version, '..' ); } $majorVersion = $versionParts['major']; $minorVersion = isset($versionParts['minor']) ? $versionParts['minor'] : 0; $patchVersion = isset($versionParts['patch']) ? $versionParts['patch'] : 0; $version = $majorVersion . '.' . $minorVersion . '.' . $patchVersion; switch(true) { case version_compare($version, '9.2', '>='): return new PostgreSQL92Platform(); case version_compare($version, '9.1', '>='): return new PostgreSQL91Platform(); default: return new PostgreSqlPlatform(); } } /** * {@inheritdoc} */ public function getDatabase(\Doctrine\DBAL\Connection $conn) { $params = $conn->getParams(); return (isset($params['dbname'])) ? $params['dbname'] : $conn->query('SELECT CURRENT_DATABASE()')->fetchColumn(); } /** * {@inheritdoc} */ public function getDatabasePlatform() { return new PostgreSqlPlatform(); } /** * {@inheritdoc} */ public function getSchemaManager(\Doctrine\DBAL\Connection $conn) { return new PostgreSqlSchemaManager($conn); } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/AbstractSQLAnywhereDriver.php000066400000000000000000000121271313473450000244740ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver; use Doctrine\DBAL\Exception; use Doctrine\DBAL\Platforms\SQLAnywhere11Platform; use Doctrine\DBAL\Platforms\SQLAnywhere12Platform; use Doctrine\DBAL\Platforms\SQLAnywhere16Platform; use Doctrine\DBAL\Platforms\SQLAnywherePlatform; use Doctrine\DBAL\Schema\SQLAnywhereSchemaManager; use Doctrine\DBAL\VersionAwarePlatformDriver; /** * Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for SAP Sybase SQL Anywhere based drivers. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ abstract class AbstractSQLAnywhereDriver implements Driver, ExceptionConverterDriver, VersionAwarePlatformDriver { /** * {@inheritdoc} * * @link http://dcx.sybase.com/index.html#sa160/en/saerrors/sqlerror.html */ public function convertException($message, DriverException $exception) { switch ($exception->getErrorCode()) { case '-100': case '-103': case '-832': return new Exception\ConnectionException($message, $exception); case '-143': return new Exception\InvalidFieldNameException($message, $exception); case '-193': case '-196': return new Exception\UniqueConstraintViolationException($message, $exception); case '-194': case '-198': return new Exception\ForeignKeyConstraintViolationException($message, $exception); case '-144': return new Exception\NonUniqueFieldNameException($message, $exception); case '-184': case '-195': return new Exception\NotNullConstraintViolationException($message, $exception); case '-131': return new Exception\SyntaxErrorException($message, $exception); case '-110': return new Exception\TableExistsException($message, $exception); case '-141': case '-1041': return new Exception\TableNotFoundException($message, $exception); } return new Exception\DriverException($message, $exception); } /** * {@inheritdoc} */ public function createDatabasePlatformForVersion($version) { if ( ! preg_match( '/^(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+))?)?)?/', $version, $versionParts )) { throw DBALException::invalidPlatformVersionSpecified( $version, '...' ); } $majorVersion = $versionParts['major']; $minorVersion = isset($versionParts['minor']) ? $versionParts['minor'] : 0; $patchVersion = isset($versionParts['patch']) ? $versionParts['patch'] : 0; $buildVersion = isset($versionParts['build']) ? $versionParts['build'] : 0; $version = $majorVersion . '.' . $minorVersion . '.' . $patchVersion . '.' . $buildVersion; switch(true) { case version_compare($version, '16', '>='): return new SQLAnywhere16Platform(); case version_compare($version, '12', '>='): return new SQLAnywhere12Platform(); case version_compare($version, '11', '>='): return new SQLAnywhere11Platform(); default: return new SQLAnywherePlatform(); } } /** * {@inheritdoc} */ public function getDatabase(\Doctrine\DBAL\Connection $conn) { $params = $conn->getParams(); if (isset($params['dbname'])) { return $params['dbname']; } return $conn->query('SELECT DB_NAME()')->fetchColumn(); } /** * {@inheritdoc} */ public function getDatabasePlatform() { return new SQLAnywhere12Platform(); } /** * {@inheritdoc} */ public function getSchemaManager(\Doctrine\DBAL\Connection $conn) { return new SQLAnywhereSchemaManager($conn); } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/AbstractSQLServerDriver.php000066400000000000000000000071171313473450000241630ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver; use Doctrine\DBAL\Platforms\SQLServer2005Platform; use Doctrine\DBAL\Platforms\SQLServer2008Platform; use Doctrine\DBAL\Platforms\SQLServer2012Platform; use Doctrine\DBAL\Platforms\SQLServerPlatform; use Doctrine\DBAL\Schema\SQLServerSchemaManager; use Doctrine\DBAL\VersionAwarePlatformDriver; /** * Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for Microsoft SQL Server based drivers. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ abstract class AbstractSQLServerDriver implements Driver, VersionAwarePlatformDriver { /** * {@inheritdoc} */ public function createDatabasePlatformForVersion($version) { if ( ! preg_match( '/^(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+))?)?)?/', $version, $versionParts )) { throw DBALException::invalidPlatformVersionSpecified( $version, '...' ); } $majorVersion = $versionParts['major']; $minorVersion = isset($versionParts['minor']) ? $versionParts['minor'] : 0; $patchVersion = isset($versionParts['patch']) ? $versionParts['patch'] : 0; $buildVersion = isset($versionParts['build']) ? $versionParts['build'] : 0; $version = $majorVersion . '.' . $minorVersion . '.' . $patchVersion . '.' . $buildVersion; switch(true) { case version_compare($version, '11.00.2100', '>='): return new SQLServer2012Platform(); case version_compare($version, '10.00.1600', '>='): return new SQLServer2008Platform(); case version_compare($version, '9.00.1399', '>='): return new SQLServer2005Platform(); default: return new SQLServerPlatform(); } } /** * {@inheritdoc} */ public function getDatabase(\Doctrine\DBAL\Connection $conn) { $params = $conn->getParams(); if (isset($params['dbname'])) { return $params['dbname']; } return $conn->query('SELECT DB_NAME()')->fetchColumn(); } /** * {@inheritdoc} */ public function getDatabasePlatform() { return new SQLServer2008Platform(); } /** * {@inheritdoc} */ public function getSchemaManager(\Doctrine\DBAL\Connection $conn) { return new SQLServerSchemaManager($conn); } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/AbstractSQLiteDriver.php000066400000000000000000000100561313473450000234720ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver; use Doctrine\DBAL\Driver; use Doctrine\DBAL\Exception; use Doctrine\DBAL\Platforms\SqlitePlatform; use Doctrine\DBAL\Schema\SqliteSchemaManager; /** * Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for SQLite based drivers. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ abstract class AbstractSQLiteDriver implements Driver, ExceptionConverterDriver { /** * {@inheritdoc} * * @link http://www.sqlite.org/c3ref/c_abort.html */ public function convertException($message, DriverException $exception) { if (strpos($exception->getMessage(), 'must be unique') !== false || strpos($exception->getMessage(), 'is not unique') !== false || strpos($exception->getMessage(), 'are not unique') !== false || strpos($exception->getMessage(), 'UNIQUE constraint failed') !== false ) { return new Exception\UniqueConstraintViolationException($message, $exception); } if (strpos($exception->getMessage(), 'may not be NULL') !== false || strpos($exception->getMessage(), 'NOT NULL constraint failed') !== false ) { return new Exception\NotNullConstraintViolationException($message, $exception); } if (strpos($exception->getMessage(), 'no such table:') !== false) { return new Exception\TableNotFoundException($message, $exception); } if (strpos($exception->getMessage(), 'already exists') !== false) { return new Exception\TableExistsException($message, $exception); } if (strpos($exception->getMessage(), 'has no column named') !== false) { return new Exception\InvalidFieldNameException($message, $exception); } if (strpos($exception->getMessage(), 'ambiguous column name') !== false) { return new Exception\NonUniqueFieldNameException($message, $exception); } if (strpos($exception->getMessage(), 'syntax error') !== false) { return new Exception\SyntaxErrorException($message, $exception); } if (strpos($exception->getMessage(), 'attempt to write a readonly database') !== false) { return new Exception\ReadOnlyException($message, $exception); } if (strpos($exception->getMessage(), 'unable to open database file') !== false) { return new Exception\ConnectionException($message, $exception); } return new Exception\DriverException($message, $exception); } /** * {@inheritdoc} */ public function getDatabase(\Doctrine\DBAL\Connection $conn) { $params = $conn->getParams(); return isset($params['path']) ? $params['path'] : null; } /** * {@inheritdoc} */ public function getDatabasePlatform() { return new SqlitePlatform(); } /** * {@inheritdoc} */ public function getSchemaManager(\Doctrine\DBAL\Connection $conn) { return new SqliteSchemaManager($conn); } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/Connection.php000066400000000000000000000060051313473450000215670ustar00rootroot00000000000000. */ 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 { /** * Prepares a statement for execution and returns a Statement object. * * @param string $prepareString * * @return \Doctrine\DBAL\Driver\Statement */ function prepare($prepareString); /** * Executes an SQL statement, returning a result set as a Statement object. * * @return \Doctrine\DBAL\Driver\Statement */ function query(); /** * Quotes a string for use in a query. * * @param string $input * @param integer $type * * @return string */ function quote($input, $type=\PDO::PARAM_STR); /** * Executes an SQL statement and return the number of affected rows. * * @param string $statement * * @return integer */ function exec($statement); /** * Returns the ID of the last inserted row or sequence value. * * @param string|null $name * * @return string */ function lastInsertId($name = null); /** * Initiates a transaction. * * @return boolean TRUE on success or FALSE on failure. */ function beginTransaction(); /** * Commits a transaction. * * @return boolean TRUE on success or FALSE on failure. */ function commit(); /** * Rolls back the current transaction, as initiated by beginTransaction(). * * @return boolean TRUE on success or FALSE on failure. */ function rollBack(); /** * Returns the error code associated with the last operation on the database handle. * * @return string|null The error code, or null if no operation has been run on the database handle. */ function errorCode(); /** * Returns extended error information associated with the last operation on the database handle. * * @return array */ function errorInfo(); } dbal-2.5.13/lib/Doctrine/DBAL/Driver/DriverException.php000066400000000000000000000036731313473450000226120ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver; /** * Contract for a driver exception. * * Driver exceptions provide the SQLSTATE of the driver * and the driver specific error code at the time the error occurred. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ interface DriverException { /** * Returns the driver specific error code if available. * * Returns null if no driver specific error code is available * for the error raised by the driver. * * @return integer|string|null */ public function getErrorCode(); /** * Returns the driver error message. * * @return string */ public function getMessage(); /** * Returns the SQLSTATE the driver was in at the time the error occurred. * * Returns null if the driver does not provide a SQLSTATE for the error occurred. * * @return string|null */ public function getSQLState(); } dbal-2.5.13/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/000077500000000000000000000000001313473450000217325ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Connection.php000066400000000000000000000027271313473450000245520ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\DrizzlePDOMySql; /** * @author Kim Hemsø Rasmussen */ class Connection extends \Doctrine\DBAL\Driver\PDOConnection { /** * {@inheritdoc} */ public function quote($value, $type = \PDO::PARAM_STR) { if (\PDO::PARAM_BOOL === $type) { if ($value) { return 'true'; } else { return 'false'; } } return parent::quote($value, $type); } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Driver.php000066400000000000000000000042421313473450000237000ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\DrizzlePDOMySql; use Doctrine\DBAL\Platforms\DrizzlePlatform; use Doctrine\DBAL\Schema\DrizzleSchemaManager; /** * Drizzle driver using PDO MySql. * * @author Kim Hemsø Rasmussen */ class Driver extends \Doctrine\DBAL\Driver\PDOMySql\Driver { /** * {@inheritdoc} */ public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { $conn = new Connection( $this->constructPdoDsn($params), $username, $password, $driverOptions ); return $conn; } /** * {@inheritdoc} */ public function createDatabasePlatformForVersion($version) { return $this->getDatabasePlatform(); } /** * {@inheritdoc} */ public function getDatabasePlatform() { return new DrizzlePlatform(); } /** * {@inheritdoc} */ public function getSchemaManager(\Doctrine\DBAL\Connection $conn) { return new DrizzleSchemaManager($conn); } /** * {@inheritdoc} */ public function getName() { return 'drizzle_pdo_mysql'; } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/ExceptionConverterDriver.php000066400000000000000000000037421313473450000244770ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver; /** * Contract for a driver that is capable of converting DBAL driver exceptions into standardized DBAL driver exceptions. * * @author Benjamin Eberlei * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ interface ExceptionConverterDriver { /** * Converts a given DBAL driver exception into a standardized DBAL driver exception. * * It evaluates the vendor specific error code and SQLSTATE and transforms * it into a unified {@link Doctrine\DBAL\Exception\DriverException} subclass. * * @param string $message The DBAL exception message to use. * @param \Doctrine\DBAL\Driver\DriverException $exception The DBAL driver exception to convert. * * @return \Doctrine\DBAL\Exception\DriverException An instance of one of the DriverException subclasses. */ public function convertException($message, DriverException $exception); } dbal-2.5.13/lib/Doctrine/DBAL/Driver/IBMDB2/000077500000000000000000000000001313473450000176555ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php000066400000000000000000000104761313473450000227650ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\IBMDB2; use Doctrine\DBAL\Driver\Connection; use Doctrine\DBAL\Driver\ServerInfoAwareConnection; class DB2Connection implements Connection, ServerInfoAwareConnection { /** * @var resource */ private $_conn = null; /** * @param array $params * @param string $username * @param string $password * @param array $driverOptions * * @throws \Doctrine\DBAL\Driver\IBMDB2\DB2Exception */ 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()); } } /** * {@inheritdoc} */ public function getServerVersion() { $serverInfo = db2_server_info($this->_conn); return $serverInfo->DBMS_VER; } /** * {@inheritdoc} */ public function requiresQueryForServerVersion() { return false; } /** * {@inheritdoc} */ public function prepare($sql) { $stmt = @db2_prepare($this->_conn, $sql); if ( ! $stmt) { throw new DB2Exception(db2_stmt_errormsg()); } return new DB2Statement($stmt); } /** * {@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) { $input = db2_escape_string($input); if ($type == \PDO::PARAM_INT) { return $input; } else { return "'".$input."'"; } } /** * {@inheritdoc} */ public function exec($statement) { $stmt = $this->prepare($statement); $stmt->execute(); return $stmt->rowCount(); } /** * {@inheritdoc} */ public function lastInsertId($name = null) { return db2_last_insert_id($this->_conn); } /** * {@inheritdoc} */ public function beginTransaction() { db2_autocommit($this->_conn, DB2_AUTOCOMMIT_OFF); } /** * {@inheritdoc} */ public function commit() { if (!db2_commit($this->_conn)) { throw new DB2Exception(db2_conn_errormsg($this->_conn)); } db2_autocommit($this->_conn, DB2_AUTOCOMMIT_ON); } /** * {@inheritdoc} */ public function rollBack() { if (!db2_rollback($this->_conn)) { throw new DB2Exception(db2_conn_errormsg($this->_conn)); } db2_autocommit($this->_conn, DB2_AUTOCOMMIT_ON); } /** * {@inheritdoc} */ public function errorCode() { return db2_conn_error($this->_conn); } /** * {@inheritdoc} */ public function errorInfo() { return array( 0 => db2_conn_errormsg($this->_conn), 1 => $this->errorCode(), ); } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php000066400000000000000000000044451313473450000221200ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\IBMDB2; use Doctrine\DBAL\Driver\AbstractDB2Driver; /** * IBM DB2 Driver. * * @since 2.0 * @author Benjamin Eberlei */ class DB2Driver extends AbstractDB2Driver { /** * {@inheritdoc} */ 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); } /** * {@inheritdoc} */ public function getName() { return 'ibm_db2'; } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Exception.php000066400000000000000000000020571313473450000226200ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\IBMDB2; class DB2Exception extends \Exception { } dbal-2.5.13/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php000066400000000000000000000235071313473450000226310ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\IBMDB2; use Doctrine\DBAL\Driver\Statement; class DB2Statement implements \IteratorAggregate, Statement { /** * @var resource */ private $_stmt = null; /** * @var array */ private $_bindParam = array(); /** * @var string Name of the default class to instantiate when fetch mode is \PDO::FETCH_CLASS. */ private $defaultFetchClass = '\stdClass'; /** * @var string Constructor arguments for the default class to instantiate when fetch mode is \PDO::FETCH_CLASS. */ private $defaultFetchClassCtorArgs = array(); /** * @var integer */ private $_defaultFetchMode = \PDO::FETCH_BOTH; /** * Indicates whether the statement is in the state when fetching results is possible * * @var bool */ private $result = false; /** * 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, ); /** * @param resource $stmt */ 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, $length = 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(); if (!db2_free_result($this->_stmt)) { return false; } $this->result = false; return true; } /** * {@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; } if ($params === null) { ksort($this->_bindParam); $params = array(); foreach ($this->_bindParam as $column => $value) { $params[] = $value; } } $retval = @db2_execute($this->_stmt, $params); if ($retval === false) { throw new DB2Exception(db2_stmt_errormsg()); } $this->result = true; return $retval; } /** * {@inheritdoc} */ public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) { $this->_defaultFetchMode = $fetchMode; $this->defaultFetchClass = $arg2 ? $arg2 : $this->defaultFetchClass; $this->defaultFetchClassCtorArgs = $arg3 ? (array) $arg3 : $this->defaultFetchClassCtorArgs; return true; } /** * {@inheritdoc} */ public function getIterator() { $data = $this->fetchAll(); return new \ArrayIterator($data); } /** * {@inheritdoc} */ public function fetch($fetchMode = null) { // do not try fetching from the statement if it's not expected to contain result // in order to prevent exceptional situation if (!$this->result) { return false; } $fetchMode = $fetchMode ?: $this->_defaultFetchMode; switch ($fetchMode) { case \PDO::FETCH_BOTH: return db2_fetch_both($this->_stmt); case \PDO::FETCH_ASSOC: return db2_fetch_assoc($this->_stmt); case \PDO::FETCH_CLASS: $className = $this->defaultFetchClass; $ctorArgs = $this->defaultFetchClassCtorArgs; if (func_num_args() >= 2) { $args = func_get_args(); $className = $args[1]; $ctorArgs = isset($args[2]) ? $args[2] : array(); } $result = db2_fetch_object($this->_stmt); if ($result instanceof \stdClass) { $result = $this->castObject($result, $className, $ctorArgs); } return $result; case \PDO::FETCH_NUM: return db2_fetch_array($this->_stmt); case \PDO::FETCH_OBJ: return db2_fetch_object($this->_stmt); default: throw new DB2Exception("Given Fetch-Style " . $fetchMode . " is not supported."); } } /** * {@inheritdoc} */ public function fetchAll($fetchMode = null) { $rows = array(); switch ($fetchMode) { case \PDO::FETCH_CLASS: while ($row = call_user_func_array(array($this, 'fetch'), func_get_args())) { $rows[] = $row; } break; case \PDO::FETCH_COLUMN: while ($row = $this->fetchColumn()) { $rows[] = $row; } break; default: while ($row = $this->fetch($fetchMode)) { $rows[] = $row; } } return $rows; } /** * {@inheritdoc} */ public function fetchColumn($columnIndex = 0) { $row = $this->fetch(\PDO::FETCH_NUM); if (false === $row) { return false; } return isset($row[$columnIndex]) ? $row[$columnIndex] : null; } /** * {@inheritdoc} */ public function rowCount() { return (@db2_num_rows($this->_stmt))?:0; } /** * Casts a stdClass object to the given class name mapping its' properties. * * @param \stdClass $sourceObject Object to cast from. * @param string|object $destinationClass Name of the class or class instance to cast to. * @param array $ctorArgs Arguments to use for constructing the destination class instance. * * @return object * * @throws DB2Exception */ private function castObject(\stdClass $sourceObject, $destinationClass, array $ctorArgs = array()) { if ( ! is_string($destinationClass)) { if ( ! is_object($destinationClass)) { throw new DB2Exception(sprintf( 'Destination class has to be of type string or object, %s given.', gettype($destinationClass) )); } } else { $destinationClass = new \ReflectionClass($destinationClass); $destinationClass = $destinationClass->newInstanceArgs($ctorArgs); } $sourceReflection = new \ReflectionObject($sourceObject); $destinationClassReflection = new \ReflectionObject($destinationClass); /** @var \ReflectionProperty[] $destinationProperties */ $destinationProperties = array_change_key_case($destinationClassReflection->getProperties(), \CASE_LOWER); foreach ($sourceReflection->getProperties() as $sourceProperty) { $sourceProperty->setAccessible(true); $name = $sourceProperty->getName(); $value = $sourceProperty->getValue($sourceObject); // Try to find a case-matching property. if ($destinationClassReflection->hasProperty($name)) { $destinationProperty = $destinationClassReflection->getProperty($name); $destinationProperty->setAccessible(true); $destinationProperty->setValue($destinationClass, $value); continue; } $name = strtolower($name); // Try to find a property without matching case. // Fallback for the driver returning either all uppercase or all lowercase column names. if (isset($destinationProperties[$name])) { $destinationProperty = $destinationProperties[$name]; $destinationProperty->setAccessible(true); $destinationProperty->setValue($destinationClass, $value); continue; } $destinationClass->$name = $value; } return $destinationClass; } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/Mysqli/000077500000000000000000000000001313473450000202345ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Driver/Mysqli/Driver.php000066400000000000000000000032351313473450000222030ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\Mysqli; use Doctrine\DBAL\Driver\AbstractMySQLDriver; use Doctrine\DBAL\DBALException; /** * @author Kim Hemsø Rasmussen */ class Driver extends AbstractMySQLDriver { /** * {@inheritdoc} */ public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { try { return new MysqliConnection($params, $username, $password, $driverOptions); } catch (MysqliException $e) { throw DBALException::driverException($this, $e); } } /** * {@inheritdoc} */ public function getName() { return 'mysqli'; } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php000066400000000000000000000160401313473450000242440ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\Mysqli; use Doctrine\DBAL\Driver\Connection as Connection; use Doctrine\DBAL\Driver\PingableConnection; use Doctrine\DBAL\Driver\ServerInfoAwareConnection; /** * @author Kim Hemsø Rasmussen * @author Till Klampaeckel */ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwareConnection { /** * Name of the option to set connection flags */ const OPTION_FLAGS = 'flags'; /** * @var \mysqli */ private $_conn; /** * @param array $params * @param string $username * @param string $password * @param array $driverOptions * * @throws \Doctrine\DBAL\Driver\Mysqli\MysqliException */ public function __construct(array $params, $username, $password, array $driverOptions = array()) { $port = isset($params['port']) ? $params['port'] : ini_get('mysqli.default_port'); // Fallback to default MySQL port if not given. if ( ! $port) { $port = 3306; } $socket = isset($params['unix_socket']) ? $params['unix_socket'] : ini_get('mysqli.default_socket'); $dbname = isset($params['dbname']) ? $params['dbname'] : null; $flags = isset($driverOptions[static::OPTION_FLAGS]) ? $driverOptions[static::OPTION_FLAGS] : null; $this->_conn = mysqli_init(); $this->setDriverOptions($driverOptions); set_error_handler(function () {}); if ( ! $this->_conn->real_connect($params['host'], $username, $password, $dbname, $port, $socket, $flags)) { restore_error_handler(); throw new MysqliException($this->_conn->connect_error, @$this->_conn->sqlstate ?: 'HY000', $this->_conn->connect_errno); } restore_error_handler(); if (isset($params['charset'])) { $this->_conn->set_charset($params['charset']); } } /** * Retrieves 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 getServerVersion() { $majorVersion = floor($this->_conn->server_version / 10000); $minorVersion = floor(($this->_conn->server_version - $majorVersion * 10000) / 100); $patchVersion = floor($this->_conn->server_version - $majorVersion * 10000 - $minorVersion * 100); return $majorVersion . '.' . $minorVersion . '.' . $patchVersion; } /** * {@inheritdoc} */ public function requiresQueryForServerVersion() { return false; } /** * {@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) { if (false === $this->_conn->query($statement)) { throw new MysqliException($this->_conn->error, $this->_conn->sqlstate, $this->_conn->errno); } 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; } /** * Apply the driver options to the connection. * * @param array $driverOptions * * @throws MysqliException When one of of the options is not supported. * @throws MysqliException When applying doesn't work - e.g. due to incorrect value. */ private function setDriverOptions(array $driverOptions = array()) { $supportedDriverOptions = array( \MYSQLI_OPT_CONNECT_TIMEOUT, \MYSQLI_OPT_LOCAL_INFILE, \MYSQLI_INIT_COMMAND, \MYSQLI_READ_DEFAULT_FILE, \MYSQLI_READ_DEFAULT_GROUP, ); if (defined('MYSQLI_SERVER_PUBLIC_KEY')) { $supportedDriverOptions[] = \MYSQLI_SERVER_PUBLIC_KEY; } $exceptionMsg = "%s option '%s' with value '%s'"; foreach ($driverOptions as $option => $value) { if ($option === static::OPTION_FLAGS) { continue; } if (!in_array($option, $supportedDriverOptions, true)) { throw new MysqliException( sprintf($exceptionMsg, 'Unsupported', $option, $value) ); } if (@mysqli_options($this->_conn, $option, $value)) { continue; } $msg = sprintf($exceptionMsg, 'Failed to set', $option, $value); $msg .= sprintf(', error: %s (%d)', mysqli_error($this->_conn), mysqli_errno($this->_conn)); throw new MysqliException( $msg, $this->_conn->sqlstate, $this->_conn->errno ); } } /** * Pings the server and re-connects when `mysqli.reconnect = 1` * * @return bool */ public function ping() { return $this->_conn->ping(); } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/Mysqli/MysqliException.php000066400000000000000000000024351313473450000241060ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\Mysqli; use Doctrine\DBAL\Driver\AbstractDriverException; /** * Exception thrown in case the mysqli driver errors. * * @author Kim Hemsø Rasmussen * @author Steve Müller */ class MysqliException extends AbstractDriverException { } dbal-2.5.13/lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php000066400000000000000000000251541313473450000241170ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\Mysqli; use Doctrine\DBAL\Driver\Statement; use PDO; /** * @author Kim Hemsø Rasmussen */ class MysqliStatement implements \IteratorAggregate, Statement { /** * @var array */ 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. ); /** * @var \mysqli */ protected $_conn; /** * @var \mysqli_stmt */ protected $_stmt; /** * @var null|boolean|array */ protected $_columnNames; /** * @var null|array */ protected $_rowBindedValues; /** * @var array */ protected $_bindedValues; /** * @var string */ protected $types; /** * Contains ref values for bindValue(). * * @var array */ protected $_values = array(); /** * @var integer */ protected $_defaultFetchMode = PDO::FETCH_BOTH; /** * Indicates whether the statement is in the state when fetching results is possible * * @var bool */ private $result = false; /** * @param \mysqli $conn * @param string $prepareString * * @throws \Doctrine\DBAL\Driver\Mysqli\MysqliException */ 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->sqlstate, $this->_conn->errno); } $paramCount = $this->_stmt->param_count; if (0 < $paramCount) { $this->types = str_repeat('s', $paramCount); $this->_bindedValues = array_fill(1, $paramCount, null); } } /** * {@inheritdoc} */ public function bindParam($column, &$variable, $type = null, $length = null) { if (null === $type) { $type = 's'; } else { if (isset(self::$_paramTypeMap[$type])) { $type = self::$_paramTypeMap[$type]; } else { throw new MysqliException("Unknown type: '{$type}'"); } } $this->_bindedValues[$column] =& $variable; $this->types[$column - 1] = $type; 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->types[$param - 1] = $type; 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'), array($this->types) + $this->_bindedValues)) { throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno); } } } if ( ! $this->_stmt->execute()) { throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $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; } else { $this->_columnNames = false; } } if (false !== $this->_columnNames) { // Store result of every execution which has it. Otherwise it will be impossible // to execute a new statement in case if the previous one has non-fetched rows // @link http://dev.mysql.com/doc/refman/5.7/en/commands-out-of-sync.html $this->_stmt->store_result(); // Bind row values _after_ storing the result. Otherwise, if mysqli is compiled with libmysql, // it will have to allocate as much memory as it may be needed for the given column type // (e.g. for a LONGBLOB field it's 4 gigabytes) // @link https://bugs.php.net/bug.php?id=51386#1270673122 // // Make sure that the values are bound after each execution. Otherwise, if closeCursor() has been // previously called on the statement, the values are unbound making the statement unusable. // // It's also important that row values are bound after _each_ call to store_result(). Otherwise, // if mysqli is compiled with libmysql, subsequently fetched string values will get truncated // to the length of the ones fetched during the previous execution. $this->_rowBindedValues = array_fill(0, count($this->_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->sqlstate, $this->_stmt->errno); } } $this->result = true; return true; } /** * Binds 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 boolean|array */ private function _fetch() { $ret = $this->_stmt->fetch(); if (true === $ret) { $values = array(); foreach ($this->_rowBindedValues as $v) { $values[] = $v; } return $values; } return $ret; } /** * {@inheritdoc} */ public function fetch($fetchMode = null) { // do not try fetching from the statement if it's not expected to contain result // in order to prevent exceptional situation if (!$this->result) { return false; } $values = $this->_fetch(); if (null === $values) { return false; } if (false === $values) { throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno); } $fetchMode = $fetchMode ?: $this->_defaultFetchMode; switch ($fetchMode) { 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 '{$fetchMode}'"); } } /** * {@inheritdoc} */ public function fetchAll($fetchMode = null) { $fetchMode = $fetchMode ?: $this->_defaultFetchMode; $rows = array(); if (PDO::FETCH_COLUMN == $fetchMode) { while (($row = $this->fetchColumn()) !== false) { $rows[] = $row; } } else { while (($row = $this->fetch($fetchMode)) !== false) { $rows[] = $row; } } return $rows; } /** * {@inheritdoc} */ public function fetchColumn($columnIndex = 0) { $row = $this->fetch(PDO::FETCH_NUM); if (false === $row) { return false; } return isset($row[$columnIndex]) ? $row[$columnIndex] : null; } /** * {@inheritdoc} */ public function errorCode() { return $this->_stmt->errno; } /** * {@inheritdoc} */ public function errorInfo() { return $this->_stmt->error; } /** * {@inheritdoc} */ public function closeCursor() { $this->_stmt->free_result(); $this->result = false; 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, $arg2 = null, $arg3 = null) { $this->_defaultFetchMode = $fetchMode; return true; } /** * {@inheritdoc} */ public function getIterator() { $data = $this->fetchAll(); return new \ArrayIterator($data); } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/OCI8/000077500000000000000000000000001313473450000174605ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Driver/OCI8/Driver.php000066400000000000000000000044031313473450000214250ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\OCI8; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver\AbstractOracleDriver; /** * A Doctrine DBAL driver for the Oracle OCI8 PHP extensions. * * @author Roman Borschel * @since 2.0 */ class Driver extends AbstractOracleDriver { /** * {@inheritdoc} */ public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { try { return new OCI8Connection( $username, $password, $this->_constructDsn($params), isset($params['charset']) ? $params['charset'] : null, isset($params['sessionMode']) ? $params['sessionMode'] : OCI_DEFAULT, isset($params['persistent']) ? $params['persistent'] : false ); } catch (OCI8Exception $e) { throw DBALException::driverException($this, $e); } } /** * Constructs the Oracle DSN. * * @param array $params * * @return string The DSN. */ protected function _constructDsn(array $params) { return $this->getEasyConnectString($params); } /** * {@inheritdoc} */ public function getName() { return 'oci8'; } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php000066400000000000000000000135361313473450000227230ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\OCI8; use Doctrine\DBAL\Driver\Connection; use Doctrine\DBAL\Driver\ServerInfoAwareConnection; use Doctrine\DBAL\Platforms\OraclePlatform; /** * OCI8 implementation of the Connection interface. * * @since 2.0 */ class OCI8Connection implements Connection, ServerInfoAwareConnection { /** * @var resource */ protected $dbh; /** * @var integer */ protected $executeMode = OCI_COMMIT_ON_SUCCESS; /** * Creates a Connection to an Oracle Database using oci8 extension. * * @param string $username * @param string $password * @param string $db * @param string|null $charset * @param integer $sessionMode * @param boolean $persistent * * @throws OCI8Exception */ public function __construct($username, $password, $db, $charset = null, $sessionMode = OCI_DEFAULT, $persistent = false) { if (!defined('OCI_NO_AUTO_COMMIT')) { define('OCI_NO_AUTO_COMMIT', 0); } $this->dbh = $persistent ? @oci_pconnect($username, $password, $db, $charset, $sessionMode) : @oci_connect($username, $password, $db, $charset, $sessionMode); if ( ! $this->dbh) { throw OCI8Exception::fromErrorInfo(oci_error()); } } /** * {@inheritdoc} * * @throws \UnexpectedValueException if the version string returned by the database server * does not contain a parsable version number. */ public function getServerVersion() { if ( ! preg_match('/\s+(\d+\.\d+\.\d+\.\d+\.\d+)\s+/', oci_server_version($this->dbh), $version)) { throw new \UnexpectedValueException( sprintf( 'Unexpected database version string "%s". Cannot parse an appropriate version number from it. ' . 'Please report this database version string to the Doctrine team.', oci_server_version($this->dbh) ) ); } return $version[1]; } /** * {@inheritdoc} */ public function requiresQueryForServerVersion() { return false; } /** * {@inheritdoc} */ public function prepare($prepareString) { return new OCI8Statement($this->dbh, $prepareString, $this); } /** * {@inheritdoc} */ public function query() { $args = func_get_args(); $sql = $args[0]; //$fetchMode = $args[1]; $stmt = $this->prepare($sql); $stmt->execute(); return $stmt; } /** * {@inheritdoc} */ 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") . "'"; } /** * {@inheritdoc} */ public function exec($statement) { $stmt = $this->prepare($statement); $stmt->execute(); return $stmt->rowCount(); } /** * {@inheritdoc} */ public function lastInsertId($name = null) { if ($name === null) { return false; } OraclePlatform::assertValidIdentifier($name); $sql = 'SELECT ' . $name . '.CURRVAL FROM DUAL'; $stmt = $this->query($sql); $result = $stmt->fetch(\PDO::FETCH_ASSOC); if ($result === false || !isset($result['CURRVAL'])) { throw new OCI8Exception("lastInsertId failed: Query was executed but no result was returned."); } return (int) $result['CURRVAL']; } /** * Returns the current execution mode. * * @return integer */ public function getExecuteMode() { return $this->executeMode; } /** * {@inheritdoc} */ public function beginTransaction() { $this->executeMode = OCI_NO_AUTO_COMMIT; return true; } /** * {@inheritdoc} */ public function commit() { if (!oci_commit($this->dbh)) { throw OCI8Exception::fromErrorInfo($this->errorInfo()); } $this->executeMode = OCI_COMMIT_ON_SUCCESS; return true; } /** * {@inheritdoc} */ public function rollBack() { if (!oci_rollback($this->dbh)) { throw OCI8Exception::fromErrorInfo($this->errorInfo()); } $this->executeMode = OCI_COMMIT_ON_SUCCESS; return true; } /** * {@inheritdoc} */ public function errorCode() { $error = oci_error($this->dbh); if ($error !== false) { $error = $error['code']; } return $error; } /** * {@inheritdoc} */ public function errorInfo() { return oci_error($this->dbh); } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/OCI8/OCI8Exception.php000066400000000000000000000025271313473450000225600ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\OCI8; use Doctrine\DBAL\Driver\AbstractDriverException; class OCI8Exception extends AbstractDriverException { /** * @param array $error * * @return \Doctrine\DBAL\Driver\OCI8\OCI8Exception */ public static function fromErrorInfo($error) { return new self($error['message'], null, $error['code']); } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php000066400000000000000000000240701313473450000225630ustar00rootroot00000000000000. */ 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 */ class OCI8Statement implements \IteratorAggregate, Statement { /** * @var resource */ protected $_dbh; /** * @var resource */ protected $_sth; /** * @var \Doctrine\DBAL\Driver\OCI8\OCI8Connection */ protected $_conn; /** * @var string */ protected static $_PARAM = ':param'; /** * @var array */ protected static $fetchModeMap = array( PDO::FETCH_BOTH => OCI_BOTH, PDO::FETCH_ASSOC => OCI_ASSOC, PDO::FETCH_NUM => OCI_NUM, PDO::FETCH_COLUMN => OCI_NUM, ); /** * @var integer */ protected $_defaultFetchMode = PDO::FETCH_BOTH; /** * @var array */ protected $_paramMap = array(); /** * Holds references to bound parameter values. * * This is a new requirement for PHP7's oci8 extension that prevents bound values from being garbage collected. * * @var array */ private $boundValues = array(); /** * Indicates whether the statement is in the state when fetching results is possible * * @var bool */ private $result = false; /** * 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. * @param \Doctrine\DBAL\Driver\OCI8\OCI8Connection $conn */ 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; } /** * Converts positional (?) into named placeholders (:param). * * 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; } elseif ($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, null); } /** * {@inheritdoc} */ public function bindParam($column, &$variable, $type = null, $length = 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); $this->boundValues[$column] =& $lob; return oci_bind_by_name($this->_sth, $column, $lob, -1, OCI_B_BLOB); } elseif ($length !== null) { $this->boundValues[$column] =& $variable; return oci_bind_by_name($this->_sth, $column, $variable, $length); } $this->boundValues[$column] =& $variable; return oci_bind_by_name($this->_sth, $column, $variable); } /** * {@inheritdoc} */ public function closeCursor() { // not having the result means there's nothing to close if (!$this->result) { return true; } oci_cancel($this->_sth); $this->result = false; return true; } /** * {@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()); } $this->result = true; return $ret; } /** * {@inheritdoc} */ public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) { $this->_defaultFetchMode = $fetchMode; return true; } /** * {@inheritdoc} */ public function getIterator() { $data = $this->fetchAll(); return new \ArrayIterator($data); } /** * {@inheritdoc} */ public function fetch($fetchMode = null) { // do not try fetching from the statement if it's not expected to contain result // in order to prevent exceptional situation if (!$this->result) { return false; } $fetchMode = $fetchMode ?: $this->_defaultFetchMode; if ( ! isset(self::$fetchModeMap[$fetchMode])) { throw new \InvalidArgumentException("Invalid fetch style: " . $fetchMode); } return oci_fetch_array($this->_sth, self::$fetchModeMap[$fetchMode] | OCI_RETURN_NULLS | OCI_RETURN_LOBS); } /** * {@inheritdoc} */ public function fetchAll($fetchMode = null) { $fetchMode = $fetchMode ?: $this->_defaultFetchMode; if ( ! isset(self::$fetchModeMap[$fetchMode])) { throw new \InvalidArgumentException("Invalid fetch style: " . $fetchMode); } $result = array(); if (self::$fetchModeMap[$fetchMode] === OCI_BOTH) { while ($row = $this->fetch($fetchMode)) { $result[] = $row; } } else { $fetchStructure = OCI_FETCHSTATEMENT_BY_ROW; if ($fetchMode == PDO::FETCH_COLUMN) { $fetchStructure = OCI_FETCHSTATEMENT_BY_COLUMN; } // do not try fetching from the statement if it's not expected to contain result // in order to prevent exceptional situation if (!$this->result) { return array(); } oci_fetch_all($this->_sth, $result, 0, -1, self::$fetchModeMap[$fetchMode] | OCI_RETURN_NULLS | $fetchStructure | OCI_RETURN_LOBS); if ($fetchMode == PDO::FETCH_COLUMN) { $result = $result[0]; } } return $result; } /** * {@inheritdoc} */ public function fetchColumn($columnIndex = 0) { // do not try fetching from the statement if it's not expected to contain result // in order to prevent exceptional situation if (!$this->result) { return false; } $row = oci_fetch_array($this->_sth, OCI_NUM | OCI_RETURN_NULLS | OCI_RETURN_LOBS); if (false === $row) { return false; } return isset($row[$columnIndex]) ? $row[$columnIndex] : null; } /** * {@inheritdoc} */ public function rowCount() { return oci_num_rows($this->_sth); } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/PDOConnection.php000066400000000000000000000071571313473450000221430ustar00rootroot00000000000000. */ 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, ServerInfoAwareConnection { /** * @param string $dsn * @param string|null $user * @param string|null $password * @param array|null $options * * @throws PDOException in case of an error. */ public function __construct($dsn, $user = null, $password = null, array $options = null) { try { 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); } catch (\PDOException $exception) { throw new PDOException($exception); } } /** * {@inheritdoc} */ public function exec($statement) { try { return parent::exec($statement); } catch (\PDOException $exception) { throw new PDOException($exception); } } /** * {@inheritdoc} */ public function getServerVersion() { return PDO::getAttribute(PDO::ATTR_SERVER_VERSION); } /** * {@inheritdoc} */ public function prepare($prepareString, $driverOptions = array()) { try { return parent::prepare($prepareString, $driverOptions); } catch (\PDOException $exception) { throw new PDOException($exception); } } /** * {@inheritdoc} */ public function query() { $args = func_get_args(); $argsCount = count($args); try { if ($argsCount == 4) { return parent::query($args[0], $args[1], $args[2], $args[3]); } if ($argsCount == 3) { return parent::query($args[0], $args[1], $args[2]); } if ($argsCount == 2) { return parent::query($args[0], $args[1]); } return parent::query($args[0]); } catch (\PDOException $exception) { throw new PDOException($exception); } } /** * {@inheritdoc} */ public function quote($input, $type = \PDO::PARAM_STR) { return parent::quote($input, $type); } /** * {@inheritdoc} */ public function lastInsertId($name = null) { return parent::lastInsertId($name); } /** * {@inheritdoc} */ public function requiresQueryForServerVersion() { return false; } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/PDOException.php000066400000000000000000000044361313473450000217770ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver; /** * Tiny wrapper for PDOException instances to implement the {@link DriverException} interface. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class PDOException extends \PDOException implements DriverException { /** * The driver specific error code. * * @var integer|string|null */ private $errorCode; /** * The SQLSTATE of the driver. * * @var string|null */ private $sqlState; /** * Constructor. * * @param \PDOException $exception The PDO exception to wrap. */ public function __construct(\PDOException $exception) { parent::__construct($exception->getMessage(), 0, $exception); $this->code = $exception->getCode(); $this->errorInfo = $exception->errorInfo; $this->errorCode = isset($exception->errorInfo[1]) ? $exception->errorInfo[1] : $exception->getCode(); $this->sqlState = isset($exception->errorInfo[0]) ? $exception->errorInfo[0] : $exception->getCode(); } /** * {@inheritdoc} */ public function getErrorCode() { return $this->errorCode; } /** * {@inheritdoc} */ public function getSQLState() { return $this->sqlState; } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/PDOIbm/000077500000000000000000000000001313473450000200305ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Driver/PDOIbm/Driver.php000066400000000000000000000047031313473450000220000ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\PDOIbm; use Doctrine\DBAL\Driver\AbstractDB2Driver; use Doctrine\DBAL\Driver\PDOConnection; /** * Driver for the PDO IBM extension. * * @link www.doctrine-project.org * @since 1.0 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel */ class Driver extends AbstractDB2Driver { /** * {@inheritdoc} */ public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { $conn = new PDOConnection( $this->_constructPdoDsn($params), $username, $password, $driverOptions ); return $conn; } /** * Constructs the IBM PDO DSN. * * @param array $params * * @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; } /** * {@inheritdoc} */ public function getName() { return 'pdo_ibm'; } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/PDOMySql/000077500000000000000000000000001313473450000203665ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php000066400000000000000000000051521313473450000223350ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\PDOMySql; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver\AbstractMySQLDriver; use Doctrine\DBAL\Driver\PDOConnection; use PDOException; /** * PDO MySql driver. * * @since 2.0 */ class Driver extends AbstractMySQLDriver { /** * {@inheritdoc} */ public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { try { $conn = new PDOConnection( $this->constructPdoDsn($params), $username, $password, $driverOptions ); } catch (PDOException $e) { throw DBALException::driverException($this, $e); } return $conn; } /** * Constructs the MySql PDO DSN. * * @param array $params * * @return string The DSN. */ protected 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; } /** * {@inheritdoc} */ public function getName() { return 'pdo_mysql'; } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/PDOOracle/000077500000000000000000000000001313473450000205265ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php000066400000000000000000000046311313473450000224760ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\PDOOracle; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver\AbstractOracleDriver; use Doctrine\DBAL\Driver\PDOConnection; /** * PDO Oracle driver. * * WARNING: This driver gives us segfaults 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 extends AbstractOracleDriver { /** * {@inheritdoc} */ public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { try { return new PDOConnection( $this->constructPdoDsn($params), $username, $password, $driverOptions ); } catch (\PDOException $e) { throw DBALException::driverException($this, $e); } } /** * Constructs the Oracle PDO DSN. * * @param array $params * * @return string The DSN. */ private function constructPdoDsn(array $params) { $dsn = 'oci:dbname=' . $this->getEasyConnectString($params); if (isset($params['charset'])) { $dsn .= ';charset=' . $params['charset']; } return $dsn; } /** * {@inheritdoc} */ public function getName() { return 'pdo_oracle'; } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/PDOPgSql/000077500000000000000000000000001313473450000203475ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php000066400000000000000000000072151313473450000223200ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\PDOPgSql; use Doctrine\DBAL\Driver\AbstractPostgreSQLDriver; use Doctrine\DBAL\Driver\PDOConnection; use Doctrine\DBAL\DBALException; use PDOException; use PDO; /** * Driver that connects through pdo_pgsql. * * @since 2.0 */ class Driver extends AbstractPostgreSQLDriver { /** * {@inheritdoc} */ public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { try { $pdo = new PDOConnection( $this->_constructPdoDsn($params), $username, $password, $driverOptions ); if (defined('PDO::PGSQL_ATTR_DISABLE_PREPARES') && (! isset($driverOptions[PDO::PGSQL_ATTR_DISABLE_PREPARES]) || true === $driverOptions[PDO::PGSQL_ATTR_DISABLE_PREPARES] ) ) { $pdo->setAttribute(PDO::PGSQL_ATTR_DISABLE_PREPARES, true); } /* defining client_encoding via SET NAMES to avoid inconsistent DSN support * - the 'client_encoding' connection param only works with postgres >= 9.1 * - passing client_encoding via the 'options' param breaks pgbouncer support */ if (isset($params['charset'])) { $pdo->query('SET NAMES \''.$params['charset'].'\''); } return $pdo; } catch (PDOException $e) { throw DBALException::driverException($this, $e); } } /** * Constructs the Postgres PDO DSN. * * @param array $params * * @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'] . ' '; } else { // Used for temporary connections to allow operations like dropping the database currently connected to. // Connecting without an explicit database does not work, therefore "postgres" database is used // as it is certainly present in every server setup. $dsn .= 'dbname=postgres' . ' '; } if (isset($params['sslmode'])) { $dsn .= 'sslmode=' . $params['sslmode'] . ' '; } return $dsn; } /** * {@inheritdoc} */ public function getName() { return 'pdo_pgsql'; } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/PDOSqlite/000077500000000000000000000000001313473450000205625ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Driver/PDOSqlite/Driver.php000066400000000000000000000061121313473450000225260ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\PDOSqlite; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver\AbstractSQLiteDriver; use Doctrine\DBAL\Driver\PDOConnection; use PDOException; /** * The PDO Sqlite driver. * * @since 2.0 */ class Driver extends AbstractSQLiteDriver { /** * @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), ); /** * {@inheritdoc} */ 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']); } try { $pdo = new PDOConnection( $this->_constructPdoDsn($params), $username, $password, $driverOptions ); } catch (PDOException $ex) { throw DBALException::driverException($this, $ex); } foreach ($this->_userDefinedFunctions as $fn => $data) { $pdo->sqliteCreateFunction($fn, $data['callback'], $data['numArgs']); } return $pdo; } /** * Constructs the Sqlite PDO DSN. * * @param array $params * * @return string The DSN. */ protected function _constructPdoDsn(array $params) { $dsn = 'sqlite:'; if (isset($params['path'])) { $dsn .= $params['path']; } elseif (isset($params['memory'])) { $dsn .= ':memory:'; } return $dsn; } /** * {@inheritdoc} */ public function getName() { return 'pdo_sqlite'; } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/PDOSqlsrv/000077500000000000000000000000001313473450000206135ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php000066400000000000000000000042701313473450000234260ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\PDOSqlsrv; use Doctrine\DBAL\Driver\PDOConnection; /** * Sqlsrv Connection implementation. * * @since 2.0 */ class Connection extends PDOConnection implements \Doctrine\DBAL\Driver\Connection { /** * {@inheritdoc} */ public function __construct($dsn, $user = null, $password = null, array $options = null) { parent::__construct($dsn, $user, $password, $options); $this->setAttribute(\PDO::ATTR_STATEMENT_CLASS, array(Statement::class, array())); } /** * @override */ public function lastInsertId($name = null) { if (null === $name) { return parent::lastInsertId($name); } $stmt = $this->prepare('SELECT CONVERT(VARCHAR(MAX), current_value) FROM sys.sequences WHERE name = ?'); $stmt->execute(array($name)); return $stmt->fetchColumn(); } /** * {@inheritDoc} */ 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; } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php000066400000000000000000000044651313473450000225700ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\PDOSqlsrv; use Doctrine\DBAL\Driver\AbstractSQLServerDriver; /** * The PDO-based Sqlsrv driver. * * @since 2.0 */ class Driver extends AbstractSQLServerDriver { /** * {@inheritdoc} */ 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. * * @param array $params * * @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; } /** * {@inheritdoc} */ public function getName() { return 'pdo_sqlsrv'; } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Statement.php000066400000000000000000000032671313473450000233000ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\PDOSqlsrv; use Doctrine\DBAL\Driver\PDOStatement; use PDO; /** * PDO SQL Server Statement */ class Statement extends PDOStatement { /** * {@inheritdoc} */ public function bindParam($column, &$variable, $type = PDO::PARAM_STR, $length = null, $driverOptions = null) { if ($type === PDO::PARAM_LOB && $driverOptions === null) { $driverOptions = PDO::SQLSRV_ENCODING_BINARY; } return parent::bindParam($column, $variable, $type, $length, $driverOptions); } /** * {@inheritdoc} */ public function bindValue($param, $value, $type = PDO::PARAM_STR) { return $this->bindParam($param, $value, $type); } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/PDOStatement.php000066400000000000000000000120511313473450000217750ustar00rootroot00000000000000. */ 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 { /** * Protected constructor. */ protected function __construct() { } /** * {@inheritdoc} */ public function setFetchMode($fetchMode, $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. try { if ($arg2 === null && $arg3 === null) { return parent::setFetchMode($fetchMode); } if ($arg3 === null) { return parent::setFetchMode($fetchMode, $arg2); } return parent::setFetchMode($fetchMode, $arg2, $arg3); } catch (\PDOException $exception) { throw new PDOException($exception); } } /** * {@inheritdoc} */ public function bindValue($param, $value, $type = \PDO::PARAM_STR) { try { return parent::bindValue($param, $value, $type); } catch (\PDOException $exception) { throw new PDOException($exception); } } /** * {@inheritdoc} */ public function bindParam($column, &$variable, $type = \PDO::PARAM_STR, $length = null, $driverOptions = null) { try { return parent::bindParam($column, $variable, $type, $length, $driverOptions); } catch (\PDOException $exception) { throw new PDOException($exception); } } /** * {@inheritdoc} */ public function closeCursor() { try { return parent::closeCursor(); } catch (\PDOException $exception) { // Exceptions not allowed by the interface. // In case driver implementations do not adhere to the interface, silence exceptions here. return true; } } /** * {@inheritdoc} */ public function execute($params = null) { try { return parent::execute($params); } catch (\PDOException $exception) { throw new PDOException($exception); } } /** * {@inheritdoc} */ public function fetch($fetchMode = null, $cursorOrientation = null, $cursorOffset = null) { try { if ($fetchMode === null && $cursorOrientation === null && $cursorOffset === null) { return parent::fetch(); } if ($cursorOrientation === null && $cursorOffset === null) { return parent::fetch($fetchMode); } if ($cursorOffset === null) { return parent::fetch($fetchMode, $cursorOrientation); } return parent::fetch($fetchMode, $cursorOrientation, $cursorOffset); } catch (\PDOException $exception) { throw new PDOException($exception); } } /** * {@inheritdoc} */ public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) { try { if ($fetchMode === null && $fetchArgument === null && $ctorArgs === null) { return parent::fetchAll(); } if ($fetchArgument === null && $ctorArgs === null) { return parent::fetchAll($fetchMode); } if ($ctorArgs === null) { return parent::fetchAll($fetchMode, $fetchArgument); } return parent::fetchAll($fetchMode, $fetchArgument, $ctorArgs); } catch (\PDOException $exception) { throw new PDOException($exception); } } /** * {@inheritdoc} */ public function fetchColumn($columnIndex = 0) { try { return parent::fetchColumn($columnIndex); } catch (\PDOException $exception) { throw new PDOException($exception); } } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/PingableConnection.php000066400000000000000000000027341313473450000232360ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver; /** * An interface for connections which support a "native" ping method. * * @link www.doctrine-project.org * @since 2.5 * @author Till Klampaeckel * @author Benjamin Eberlei */ interface PingableConnection { /** * Pings the database server to determine if the connection is still * available. Return true/false based on if that was successful or not. * * @return bool */ public function ping(); } dbal-2.5.13/lib/Doctrine/DBAL/Driver/ResultStatement.php000066400000000000000000000071351313473450000226400ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver; /** * Interface for the reading part of a prepare statement only. * * @author Benjamin Eberlei */ interface ResultStatement extends \Traversable { /** * Closes the cursor, enabling the statement to be executed again. * * @return boolean TRUE on success or FALSE on failure. */ public function closeCursor(); /** * Returns the number of columns in the result set * * @return integer 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(); /** * Sets the fetch mode to use while iterating this statement. * * @param integer $fetchMode The fetch mode must be one of the PDO::FETCH_* constants. * @param mixed $arg2 * @param mixed $arg3 * * @return boolean * * @see PDO::FETCH_* constants. */ public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null); /** * Returns the next row of a result set. * * @param integer|null $fetchMode Controls how the next row will be returned to the caller. * The value must be one of the PDO::FETCH_* constants, * defaulting to PDO::FETCH_BOTH. * * @return mixed The return value of this method on success depends on the fetch mode. In all cases, FALSE is * returned on failure. * * @see PDO::FETCH_* constants. */ public function fetch($fetchMode = null); /** * Returns an array containing all of the result set rows. * * @param integer|null $fetchMode Controls how the next row will be returned to the caller. * The value must be one of the PDO::FETCH_* constants, * defaulting to PDO::FETCH_BOTH. * * @return array * * @see PDO::FETCH_* constants. */ public function fetchAll($fetchMode = null); /** * 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|boolean A single column in the next row of a result set, or FALSE if there are no more rows. */ public function fetchColumn($columnIndex = 0); } dbal-2.5.13/lib/Doctrine/DBAL/Driver/SQLAnywhere/000077500000000000000000000000001313473450000211205ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Driver/SQLAnywhere/Driver.php000066400000000000000000000100161313473450000230620ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\SQLAnywhere; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver\AbstractSQLAnywhereDriver; /** * A Doctrine DBAL driver for the SAP Sybase SQL Anywhere PHP extension. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class Driver extends AbstractSQLAnywhereDriver { /** * {@inheritdoc} * * @throws \Doctrine\DBAL\DBALException if there was a problem establishing the connection. */ public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { try { return new SQLAnywhereConnection( $this->buildDsn( isset($params['host']) ? $params['host'] : null, isset($params['port']) ? $params['port'] : null, isset($params['server']) ? $params['server'] : null, isset($params['dbname']) ? $params['dbname'] : null, $username, $password, $driverOptions ), isset($params['persistent']) ? $params['persistent'] : false ); } catch (SQLAnywhereException $e) { throw DBALException::driverException($this, $e); } } /** * {@inheritdoc} */ public function getName() { return 'sqlanywhere'; } /** * Build the connection string for given connection parameters and driver options. * * @param string $host Host address to connect to. * @param integer $port Port to use for the connection (default to SQL Anywhere standard port 2638). * @param string $server Database server name on the host to connect to. * SQL Anywhere allows multiple database server instances on the same host, * therefore specifying the server instance name to use is mandatory. * @param string $dbname Name of the database on the server instance to connect to. * @param string $username User name to use for connection authentication. * @param string $password Password to use for connection authentication. * @param array $driverOptions Additional parameters to use for the connection. * * @return string */ private function buildDsn($host, $port, $server, $dbname, $username = null, $password = null, array $driverOptions = array()) { $host = $host ?: 'localhost'; $port = $port ?: 2638; if (! empty($server)) { $server = ';ServerName=' . $server; } return 'HOST=' . $host . ':' . $port . $server . ';DBN=' . $dbname . ';UID=' . $username . ';PWD=' . $password . ';' . implode( ';', array_map(function ($key, $value) { return $key . '=' . $value; }, array_keys($driverOptions), $driverOptions) ); } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereConnection.php000066400000000000000000000132371313473450000260210ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\SQLAnywhere; use Doctrine\DBAL\Driver\Connection; use Doctrine\DBAL\Driver\ServerInfoAwareConnection; /** * SAP Sybase SQL Anywhere implementation of the Connection interface. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class SQLAnywhereConnection implements Connection, ServerInfoAwareConnection { /** * @var resource The SQL Anywhere connection resource. */ private $connection; /** * Constructor. * * Connects to database with given connection string. * * @param string $dsn The connection string. * @param boolean $persistent Whether or not to establish a persistent connection. * * @throws SQLAnywhereException */ public function __construct($dsn, $persistent = false) { $this->connection = $persistent ? @sasql_pconnect($dsn) : @sasql_connect($dsn); if ( ! is_resource($this->connection)) { throw SQLAnywhereException::fromSQLAnywhereError(); } // Disable PHP warnings on error. if ( ! sasql_set_option($this->connection, 'verbose_errors', false)) { throw SQLAnywhereException::fromSQLAnywhereError($this->connection); } // Enable auto committing by default. if ( ! sasql_set_option($this->connection, 'auto_commit', 'on')) { throw SQLAnywhereException::fromSQLAnywhereError($this->connection); } // Enable exact, non-approximated row count retrieval. if ( ! sasql_set_option($this->connection, 'row_counts', true)) { throw SQLAnywhereException::fromSQLAnywhereError($this->connection); } } /** * {@inheritdoc} * * @throws SQLAnywhereException */ public function beginTransaction() { if ( ! sasql_set_option($this->connection, 'auto_commit', 'off')) { throw SQLAnywhereException::fromSQLAnywhereError($this->connection); } return true; } /** * {@inheritdoc} * * @throws SQLAnywhereException */ public function commit() { if ( ! sasql_commit($this->connection)) { throw SQLAnywhereException::fromSQLAnywhereError($this->connection); } $this->endTransaction(); return true; } /** * {@inheritdoc} */ public function errorCode() { return sasql_errorcode($this->connection); } /** * {@inheritdoc} */ public function errorInfo() { return sasql_error($this->connection); } /** * {@inheritdoc} */ public function exec($statement) { $stmt = $this->prepare($statement); $stmt->execute(); return $stmt->rowCount(); } /** * {@inheritdoc} */ public function getServerVersion() { return $this->query("SELECT PROPERTY('ProductVersion')")->fetchColumn(); } /** * {@inheritdoc} */ public function lastInsertId($name = null) { if (null === $name) { return sasql_insert_id($this->connection); } return $this->query('SELECT ' . $name . '.CURRVAL')->fetchColumn(); } /** * {@inheritdoc} */ public function prepare($prepareString) { return new SQLAnywhereStatement($this->connection, $prepareString); } /** * {@inheritdoc} */ public function query() { $args = func_get_args(); $stmt = $this->prepare($args[0]); $stmt->execute(); return $stmt; } /** * {@inheritdoc} */ public function quote($input, $type = \PDO::PARAM_STR) { if (is_int($input) || is_float($input)) { return $input; } return "'" . sasql_escape_string($this->connection, $input) . "'"; } /** * {@inheritdoc} */ public function requiresQueryForServerVersion() { return true; } /** * {@inheritdoc} * * @throws SQLAnywhereException */ public function rollBack() { if ( ! sasql_rollback($this->connection)) { throw SQLAnywhereException::fromSQLAnywhereError($this->connection); } $this->endTransaction(); return true; } /** * Ends transactional mode and enables auto commit again. * * @throws SQLAnywhereException * * @return boolean Whether or not ending transactional mode succeeded. */ private function endTransaction() { if ( ! sasql_set_option($this->connection, 'auto_commit', 'on')) { throw SQLAnywhereException::fromSQLAnywhereError($this->connection); } return true; } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereException.php000066400000000000000000000070701313473450000256560ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\SQLAnywhere; use Doctrine\DBAL\Driver\AbstractDriverException; /** * SAP Sybase SQL Anywhere driver exception. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class SQLAnywhereException extends AbstractDriverException { /** * Helper method to turn SQL Anywhere error into exception. * * @param resource|null $conn The SQL Anywhere connection resource to retrieve the last error from. * @param resource|null $stmt The SQL Anywhere statement resource to retrieve the last error from. * * @return SQLAnywhereException * * @throws \InvalidArgumentException */ public static function fromSQLAnywhereError($conn = null, $stmt = null) { if (null !== $conn && ! (is_resource($conn))) { throw new \InvalidArgumentException('Invalid SQL Anywhere connection resource given: ' . $conn); } if (null !== $stmt && ! (is_resource($stmt))) { throw new \InvalidArgumentException('Invalid SQL Anywhere statement resource given: ' . $stmt); } $state = $conn ? sasql_sqlstate($conn) : sasql_sqlstate(); $code = null; $message = null; /** * Try retrieving the last error from statement resource if given */ if ($stmt) { $code = sasql_stmt_errno($stmt); $message = sasql_stmt_error($stmt); } /** * Try retrieving the last error from the connection resource * if either the statement resource is not given or the statement * resource is given but the last error could not be retrieved from it (fallback). * Depending on the type of error, it is sometimes necessary to retrieve * it from the connection resource even though it occurred during * a prepared statement. */ if ($conn && ! $code) { $code = sasql_errorcode($conn); $message = sasql_error($conn); } /** * Fallback mode if either no connection resource is given * or the last error could not be retrieved from the given * connection / statement resource. */ if ( ! $conn || ! $code) { $code = sasql_errorcode(); $message = sasql_error(); } if ($message) { return new self('SQLSTATE [' . $state . '] [' . $code . '] ' . $message, $state, $code); } return new self('SQL Anywhere error occurred but no error message was retrieved from driver.', $state, $code); } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereStatement.php000066400000000000000000000234541313473450000256700ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\SQLAnywhere; use IteratorAggregate; use PDO; use Doctrine\DBAL\Driver\Statement; /** * SAP SQL Anywhere implementation of the Statement interface. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class SQLAnywhereStatement implements IteratorAggregate, Statement { /** * @var resource The connection resource. */ private $conn; /** * @var string Name of the default class to instantiate when fetch mode is \PDO::FETCH_CLASS. */ private $defaultFetchClass = '\stdClass'; /** * @var string Constructor arguments for the default class to instantiate when fetch mode is \PDO::FETCH_CLASS. */ private $defaultFetchClassCtorArgs = array(); /** * @var int Default fetch mode to use. */ private $defaultFetchMode = PDO::FETCH_BOTH; /** * @var resource The result set resource to fetch. */ private $result; /** * @var resource The prepared SQL statement to execute. */ private $stmt; /** * Constructor. * * Prepares given statement for given connection. * * @param resource $conn The connection resource to use. * @param string $sql The SQL statement to prepare. * * @throws SQLAnywhereException */ public function __construct($conn, $sql) { if ( ! is_resource($conn)) { throw new SQLAnywhereException('Invalid SQL Anywhere connection resource: ' . $conn); } $this->conn = $conn; $this->stmt = sasql_prepare($conn, $sql); if ( ! is_resource($this->stmt)) { throw SQLAnywhereException::fromSQLAnywhereError($conn); } } /** * {@inheritdoc} * * @throws SQLAnywhereException */ public function bindParam($column, &$variable, $type = null, $length = null) { switch ($type) { case PDO::PARAM_INT: case PDO::PARAM_BOOL: $type = 'i'; break; case PDO::PARAM_LOB: $type = 'b'; break; case PDO::PARAM_NULL: case PDO::PARAM_STR: $type = 's'; break; default: throw new SQLAnywhereException('Unknown type: ' . $type); } if ( ! sasql_stmt_bind_param_ex($this->stmt, $column - 1, $variable, $type, $variable === null)) { throw SQLAnywhereException::fromSQLAnywhereError($this->conn, $this->stmt); } return true; } /** * {@inheritdoc} */ public function bindValue($param, $value, $type = null) { return $this->bindParam($param, $value, $type); } /** * {@inheritdoc} * * @throws SQLAnywhereException */ public function closeCursor() { if (!sasql_stmt_reset($this->stmt)) { throw SQLAnywhereException::fromSQLAnywhereError($this->conn, $this->stmt); } return true; } /** * {@inheritdoc} */ public function columnCount() { return sasql_stmt_field_count($this->stmt); } /** * {@inheritdoc} */ public function errorCode() { return sasql_stmt_errno($this->stmt); } /** * {@inheritdoc} */ public function errorInfo() { return sasql_stmt_error($this->stmt); } /** * {@inheritdoc} * * @throws SQLAnywhereException */ public function execute($params = null) { if (is_array($params)) { $hasZeroIndex = array_key_exists(0, $params); foreach ($params as $key => $val) { $key = ($hasZeroIndex && is_numeric($key)) ? $key + 1 : $key; $this->bindValue($key, $val); } } if ( ! sasql_stmt_execute($this->stmt)) { throw SQLAnywhereException::fromSQLAnywhereError($this->conn, $this->stmt); } $this->result = sasql_stmt_result_metadata($this->stmt); return true; } /** * {@inheritdoc} * * @throws SQLAnywhereException */ public function fetch($fetchMode = null) { if ( ! is_resource($this->result)) { return false; } $fetchMode = $fetchMode ?: $this->defaultFetchMode; switch ($fetchMode) { case PDO::FETCH_ASSOC: return sasql_fetch_assoc($this->result); case PDO::FETCH_BOTH: return sasql_fetch_array($this->result, SASQL_BOTH); case PDO::FETCH_CLASS: $className = $this->defaultFetchClass; $ctorArgs = $this->defaultFetchClassCtorArgs; if (func_num_args() >= 2) { $args = func_get_args(); $className = $args[1]; $ctorArgs = isset($args[2]) ? $args[2] : array(); } $result = sasql_fetch_object($this->result); if ($result instanceof \stdClass) { $result = $this->castObject($result, $className, $ctorArgs); } return $result; case PDO::FETCH_NUM: return sasql_fetch_row($this->result); case PDO::FETCH_OBJ: return sasql_fetch_object($this->result); default: throw new SQLAnywhereException('Fetch mode is not supported: ' . $fetchMode); } } /** * {@inheritdoc} */ public function fetchAll($fetchMode = null) { $rows = array(); switch ($fetchMode) { case PDO::FETCH_CLASS: while ($row = call_user_func_array(array($this, 'fetch'), func_get_args())) { $rows[] = $row; } break; case PDO::FETCH_COLUMN: while ($row = $this->fetchColumn()) { $rows[] = $row; } break; default: while ($row = $this->fetch($fetchMode)) { $rows[] = $row; } } return $rows; } /** * {@inheritdoc} */ public function fetchColumn($columnIndex = 0) { $row = $this->fetch(PDO::FETCH_NUM); if (false === $row) { return false; } return isset($row[$columnIndex]) ? $row[$columnIndex] : null; } /** * {@inheritdoc} */ public function getIterator() { return new \ArrayIterator($this->fetchAll()); } /** * {@inheritdoc} */ public function rowCount() { return sasql_stmt_affected_rows($this->stmt); } /** * {@inheritdoc} */ public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) { $this->defaultFetchMode = $fetchMode; $this->defaultFetchClass = $arg2 ? $arg2 : $this->defaultFetchClass; $this->defaultFetchClassCtorArgs = $arg3 ? (array) $arg3 : $this->defaultFetchClassCtorArgs; } /** * Casts a stdClass object to the given class name mapping its' properties. * * @param \stdClass $sourceObject Object to cast from. * @param string|object $destinationClass Name of the class or class instance to cast to. * @param array $ctorArgs Arguments to use for constructing the destination class instance. * * @return object * * @throws SQLAnywhereException */ private function castObject(\stdClass $sourceObject, $destinationClass, array $ctorArgs = array()) { if ( ! is_string($destinationClass)) { if ( ! is_object($destinationClass)) { throw new SQLAnywhereException(sprintf( 'Destination class has to be of type string or object, %s given.', gettype($destinationClass) )); } } else { $destinationClass = new \ReflectionClass($destinationClass); $destinationClass = $destinationClass->newInstanceArgs($ctorArgs); } $sourceReflection = new \ReflectionObject($sourceObject); $destinationClassReflection = new \ReflectionObject($destinationClass); foreach ($sourceReflection->getProperties() as $sourceProperty) { $sourceProperty->setAccessible(true); $name = $sourceProperty->getName(); $value = $sourceProperty->getValue($sourceObject); if ($destinationClassReflection->hasProperty($name)) { $destinationProperty = $destinationClassReflection->getProperty($name); $destinationProperty->setAccessible(true); $destinationProperty->setValue($destinationClass, $value); } else { $destinationClass->$name = $value; } } return $destinationClass; } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/SQLSrv/000077500000000000000000000000001313473450000201105ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Driver/SQLSrv/Driver.php000066400000000000000000000042641313473450000220620ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\SQLSrv; use Doctrine\DBAL\Driver\AbstractSQLServerDriver; /** * Driver for ext/sqlsrv. */ class Driver extends AbstractSQLServerDriver { /** * {@inheritdoc} */ public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { if (!isset($params['host'])) { throw new SQLSrvException("Missing 'host' in configuration for sqlsrv driver."); } $serverName = $params['host']; if (isset($params['port'])) { $serverName .= ', ' . $params['port']; } if (isset($params['dbname'])) { $driverOptions['Database'] = $params['dbname']; } if (isset($params['charset'])) { $driverOptions['CharacterSet'] = $params['charset']; } $driverOptions['UID'] = $username; $driverOptions['PWD'] = $password; if (!isset($driverOptions['ReturnDatesAsStrings'])) { $driverOptions['ReturnDatesAsStrings'] = 1; } return new SQLSrvConnection($serverName, $driverOptions); } /** * {@inheritdoc} */ public function getName() { return 'sqlsrv'; } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/SQLSrv/LastInsertId.php000066400000000000000000000026201313473450000231660ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\SQLSrv; /** * Last Id Data Container. * * @since 2.3 * @author Benjamin Eberlei */ class LastInsertId { /** * @var integer */ private $id; /** * @param integer $id */ public function setId($id) { $this->id = $id; } /** * @return integer */ public function getId() { return $this->id; } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php000066400000000000000000000110631313473450000237740ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\SQLSrv; use Doctrine\DBAL\Driver\Connection; use Doctrine\DBAL\Driver\ServerInfoAwareConnection; /** * SQL Server implementation for the Connection interface. * * @since 2.3 * @author Benjamin Eberlei */ class SQLSrvConnection implements Connection, ServerInfoAwareConnection { /** * @var resource */ protected $conn; /** * @var \Doctrine\DBAL\Driver\SQLSrv\LastInsertId */ protected $lastInsertId; /** * @param string $serverName * @param array $connectionOptions * * @throws \Doctrine\DBAL\Driver\SQLSrv\SQLSrvException */ public function __construct($serverName, $connectionOptions) { if ( ! sqlsrv_configure('WarningsReturnAsErrors', 0)) { throw SQLSrvException::fromSqlSrvErrors(); } $this->conn = sqlsrv_connect($serverName, $connectionOptions); if ( ! $this->conn) { throw SQLSrvException::fromSqlSrvErrors(); } $this->lastInsertId = new LastInsertId(); } /** * {@inheritdoc} */ public function getServerVersion() { $serverInfo = sqlsrv_server_info($this->conn); return $serverInfo['SQLServerVersion']; } /** * {@inheritdoc} */ public function requiresQueryForServerVersion() { return false; } /** * {@inheritDoc} */ public function prepare($sql) { return new SQLSrvStatement($this->conn, $sql, $this->lastInsertId); } /** * {@inheritDoc} */ public function query() { $args = func_get_args(); $sql = $args[0]; $stmt = $this->prepare($sql); $stmt->execute(); return $stmt; } /** * {@inheritDoc} * @license New BSD, code from Zend Framework */ public function quote($value, $type=\PDO::PARAM_STR) { if (is_int($value)) { return $value; } elseif (is_float($value)) { return sprintf('%F', $value); } return "'" . str_replace("'", "''", $value) . "'"; } /** * {@inheritDoc} */ public function exec($statement) { $stmt = $this->prepare($statement); $stmt->execute(); return $stmt->rowCount(); } /** * {@inheritDoc} */ public function lastInsertId($name = null) { if ($name !== null) { $stmt = $this->prepare('SELECT CONVERT(VARCHAR(MAX), current_value) FROM sys.sequences WHERE name = ?'); $stmt->execute(array($name)); return $stmt->fetchColumn(); } return $this->lastInsertId->getId(); } /** * {@inheritDoc} */ public function beginTransaction() { if ( ! sqlsrv_begin_transaction($this->conn)) { throw SQLSrvException::fromSqlSrvErrors(); } } /** * {@inheritDoc} */ public function commit() { if ( ! sqlsrv_commit($this->conn)) { throw SQLSrvException::fromSqlSrvErrors(); } } /** * {@inheritDoc} */ public function rollBack() { if ( ! sqlsrv_rollback($this->conn)) { throw SQLSrvException::fromSqlSrvErrors(); } } /** * {@inheritDoc} */ public function errorCode() { $errors = sqlsrv_errors(SQLSRV_ERR_ERRORS); if ($errors) { return $errors[0]['code']; } return false; } /** * {@inheritDoc} */ public function errorInfo() { return sqlsrv_errors(SQLSRV_ERR_ERRORS); } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvException.php000066400000000000000000000037561313473450000236450ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\SQLSrv; use Doctrine\DBAL\Driver\AbstractDriverException; class SQLSrvException extends AbstractDriverException { /** * Helper method to turn sql server errors into exception. * * @return \Doctrine\DBAL\Driver\SQLSrv\SQLSrvException */ static public function fromSqlSrvErrors() { $errors = sqlsrv_errors(SQLSRV_ERR_ERRORS); $message = ""; $sqlState = null; $errorCode = null; foreach ($errors as $error) { $message .= "SQLSTATE [".$error['SQLSTATE'].", ".$error['code']."]: ". $error['message']."\n"; if (null === $sqlState) { $sqlState = $error['SQLSTATE']; } if (null === $errorCode) { $errorCode = $error['code']; } } if ( ! $message) { $message = "SQL Server error occurred but no error message was retrieved from driver."; } return new self(rtrim($message), $sqlState, $errorCode); } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php000066400000000000000000000234571313473450000236530ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver\SQLSrv; use PDO; use IteratorAggregate; use Doctrine\DBAL\Driver\Statement; /** * SQL Server Statement. * * @since 2.3 * @author Benjamin Eberlei */ class SQLSrvStatement implements IteratorAggregate, Statement { /** * The SQLSRV Resource. * * @var resource */ private $conn; /** * The SQL statement to execute. * * @var string */ private $sql; /** * The SQLSRV statement resource. * * @var resource */ private $stmt; /** * References to the variables bound as statement parameters. * * @var array */ private $variables = array(); /** * Bound parameter types. * * @var array */ private $types = array(); /** * Translations. * * @var array */ private static $fetchMap = array( PDO::FETCH_BOTH => SQLSRV_FETCH_BOTH, PDO::FETCH_ASSOC => SQLSRV_FETCH_ASSOC, PDO::FETCH_NUM => SQLSRV_FETCH_NUMERIC, ); /** * The name of the default class to instantiate when fetch mode is \PDO::FETCH_CLASS. * * @var string */ private $defaultFetchClass = '\stdClass'; /** * The constructor arguments for the default class to instantiate when fetch mode is \PDO::FETCH_CLASS. * * @var string */ private $defaultFetchClassCtorArgs = array(); /** * The fetch style. * * @param integer */ private $defaultFetchMode = PDO::FETCH_BOTH; /** * The last insert ID. * * @var \Doctrine\DBAL\Driver\SQLSrv\LastInsertId|null */ private $lastInsertId; /** * Indicates whether the statement is in the state when fetching results is possible * * @var bool */ private $result = false; /** * Append to any INSERT query to retrieve the last insert id. * * @var string */ const LAST_INSERT_ID_SQL = ';SELECT SCOPE_IDENTITY() AS LastInsertId;'; /** * @param resource $conn * @param string $sql * @param \Doctrine\DBAL\Driver\SQLSrv\LastInsertId|null $lastInsertId */ public function __construct($conn, $sql, LastInsertId $lastInsertId = null) { $this->conn = $conn; $this->sql = $sql; if (stripos($sql, 'INSERT INTO ') === 0) { $this->sql .= self::LAST_INSERT_ID_SQL; $this->lastInsertId = $lastInsertId; } } /** * {@inheritdoc} */ public function bindValue($param, $value, $type = null) { if (!is_numeric($param)) { throw new SQLSrvException( 'sqlsrv does not support named parameters to queries, use question mark (?) placeholders instead.' ); } $this->variables[$param] = $value; $this->types[$param] = $type; } /** * {@inheritdoc} */ public function bindParam($column, &$variable, $type = null, $length = null) { if (!is_numeric($column)) { throw new SQLSrvException("sqlsrv does not support named parameters to queries, use question mark (?) placeholders instead."); } $this->variables[$column] =& $variable; $this->types[$column] = $type; // unset the statement resource if it exists as the new one will need to be bound to the new variable $this->stmt = null; } /** * {@inheritdoc} */ public function closeCursor() { // not having the result means there's nothing to close if (!$this->result) { return true; } // emulate it by fetching and discarding rows, similarly to what PDO does in this case // @link http://php.net/manual/en/pdostatement.closecursor.php // @link https://github.com/php/php-src/blob/php-7.0.11/ext/pdo/pdo_stmt.c#L2075 // deliberately do not consider multiple result sets, since doctrine/dbal doesn't support them while (sqlsrv_fetch($this->stmt)); $this->result = false; return true; } /** * {@inheritdoc} */ public function columnCount() { return sqlsrv_num_fields($this->stmt); } /** * {@inheritdoc} */ public function errorCode() { $errors = sqlsrv_errors(SQLSRV_ERR_ERRORS); if ($errors) { return $errors[0]['code']; } return false; } /** * {@inheritdoc} */ public function errorInfo() { return sqlsrv_errors(SQLSRV_ERR_ERRORS); } /** * {@inheritdoc} */ public function execute($params = null) { if ($params) { $hasZeroIndex = array_key_exists(0, $params); foreach ($params as $key => $val) { $key = ($hasZeroIndex && is_numeric($key)) ? $key + 1 : $key; $this->bindValue($key, $val); } } if ( ! $this->stmt) { $this->stmt = $this->prepare(); } if (!sqlsrv_execute($this->stmt)) { throw SQLSrvException::fromSqlSrvErrors(); } if ($this->lastInsertId) { sqlsrv_next_result($this->stmt); sqlsrv_fetch($this->stmt); $this->lastInsertId->setId(sqlsrv_get_field($this->stmt, 0)); } $this->result = true; } /** * Prepares SQL Server statement resource * * @return resource * @throws SQLSrvException */ private function prepare() { $params = array(); foreach ($this->variables as $column => &$variable) { if ($this->types[$column] === \PDO::PARAM_LOB) { $params[$column - 1] = array( &$variable, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY), SQLSRV_SQLTYPE_VARBINARY('max'), ); } else { $params[$column - 1] =& $variable; } } $stmt = sqlsrv_prepare($this->conn, $this->sql, $params); if (!$stmt) { throw SQLSrvException::fromSqlSrvErrors(); } return $stmt; } /** * {@inheritdoc} */ public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) { $this->defaultFetchMode = $fetchMode; $this->defaultFetchClass = $arg2 ?: $this->defaultFetchClass; $this->defaultFetchClassCtorArgs = $arg3 ? (array) $arg3 : $this->defaultFetchClassCtorArgs; return true; } /** * {@inheritdoc} */ public function getIterator() { $data = $this->fetchAll(); return new \ArrayIterator($data); } /** * {@inheritdoc} */ public function fetch($fetchMode = null) { // do not try fetching from the statement if it's not expected to contain result // in order to prevent exceptional situation if (!$this->result) { return false; } $args = func_get_args(); $fetchMode = $fetchMode ?: $this->defaultFetchMode; if (isset(self::$fetchMap[$fetchMode])) { return sqlsrv_fetch_array($this->stmt, self::$fetchMap[$fetchMode]) ?: false; } if ($fetchMode == PDO::FETCH_OBJ || $fetchMode == PDO::FETCH_CLASS) { $className = $this->defaultFetchClass; $ctorArgs = $this->defaultFetchClassCtorArgs; if (count($args) >= 2) { $className = $args[1]; $ctorArgs = (isset($args[2])) ? $args[2] : array(); } return sqlsrv_fetch_object($this->stmt, $className, $ctorArgs) ?: false; } throw new SQLSrvException("Fetch mode is not supported!"); } /** * {@inheritdoc} */ public function fetchAll($fetchMode = null) { $rows = array(); switch ($fetchMode) { case PDO::FETCH_CLASS: while ($row = call_user_func_array(array($this, 'fetch'), func_get_args())) { $rows[] = $row; } break; case PDO::FETCH_COLUMN: while ($row = $this->fetchColumn()) { $rows[] = $row; } break; default: while ($row = $this->fetch($fetchMode)) { $rows[] = $row; } } return $rows; } /** * {@inheritdoc} */ public function fetchColumn($columnIndex = 0) { $row = $this->fetch(PDO::FETCH_NUM); if (false === $row) { return false; } return isset($row[$columnIndex]) ? $row[$columnIndex] : null; } /** * {@inheritdoc} */ public function rowCount() { return sqlsrv_rows_affected($this->stmt); } } dbal-2.5.13/lib/Doctrine/DBAL/Driver/ServerInfoAwareConnection.php000066400000000000000000000032471313473450000245570ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver; /** * Contract for a connection that is able to provide information about the server it is connected to. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ interface ServerInfoAwareConnection { /** * Returns the version number of the database server connected to. * * @return string */ public function getServerVersion(); /** * Checks whether a query is required to retrieve the database server version. * * @return boolean True if a query is required to retrieve the database server version, false otherwise. */ public function requiresQueryForServerVersion(); } dbal-2.5.13/lib/Doctrine/DBAL/Driver/Statement.php000066400000000000000000000141671313473450000214440ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Driver; /** * Statement interface. * Drivers must implement this interface. * * This resembles (a subset of) the PDOStatement interface. * * @author Konsta Vesterinen * @author Roman Borschel * @link www.doctrine-project.org * @since 2.0 */ interface Statement extends ResultStatement { /** * Binds a value to a corresponding named (not supported by mysqli driver, see comment below) or positional * placeholder in the SQL statement that was used to prepare the statement. * * As mentioned above, the named parameters are not natively supported by the mysqli driver, use executeQuery(), * fetchAll(), fetchArray(), fetchColumn(), fetchAssoc() methods to have the named parameter emulated by doctrine. * * @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 TRUE on success or FALSE on failure. */ function bindValue($param, $value, $type = null); /** * Binds a PHP variable to a corresponding named (not supported by mysqli driver, see comment below) 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. * * As mentioned above, the named parameters are not natively supported by the mysqli driver, use executeQuery(), * fetchAll(), fetchArray(), fetchColumn(), fetchAssoc() methods to have the named parameter emulated by doctrine. * * 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 $column 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|null $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. * @param integer|null $length You must specify maxlength when using an OUT bind * so that PHP allocates enough memory to hold the returned value. * * @return boolean TRUE on success or FALSE on failure. */ function bindParam($column, &$variable, $type = null, $length = null); /** * Fetches the SQLSTATE associated with the last operation on the statement handle. * * @see Doctrine_Adapter_Interface::errorCode() * * @return string The error code string. */ function errorCode(); /** * Fetches extended error information associated with the last operation on the statement handle. * * @see Doctrine_Adapter_Interface::errorInfo() * * @return array The 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|null $params An array of values with as many elements as there are * bound parameters in the SQL statement being executed. * * @return boolean TRUE on success or FALSE on failure. */ function execute($params = null); /** * 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 The number of rows. */ function rowCount(); } dbal-2.5.13/lib/Doctrine/DBAL/DriverManager.php000066400000000000000000000351121313473450000207640ustar00rootroot00000000000000. */ namespace Doctrine\DBAL; use Doctrine\Common\EventManager; /** * Factory for creating Doctrine\DBAL\Connection instances. * * @author Roman Borschel * @since 2.0 */ final class DriverManager { /** * List of supported drivers and their mappings to the driver classes. * * To add your own driver use the 'driverClass' parameter to * {@link DriverManager::getConnection()}. * * @var array */ 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_sqlsrv' => 'Doctrine\DBAL\Driver\PDOSqlsrv\Driver', 'mysqli' => 'Doctrine\DBAL\Driver\Mysqli\Driver', 'drizzle_pdo_mysql' => 'Doctrine\DBAL\Driver\DrizzlePDOMySql\Driver', 'sqlanywhere' => 'Doctrine\DBAL\Driver\SQLAnywhere\Driver', 'sqlsrv' => 'Doctrine\DBAL\Driver\SQLSrv\Driver', ); /** * List of URL schemes from a database URL and their mappings to driver. */ private static $driverSchemeAliases = array( 'db2' => 'ibm_db2', 'mssql' => 'pdo_sqlsrv', 'mysql' => 'pdo_mysql', 'mysql2' => 'pdo_mysql', // Amazon RDS, for some weird reason 'postgres' => 'pdo_pgsql', 'postgresql' => 'pdo_pgsql', 'pgsql' => 'pdo_pgsql', 'sqlite' => 'pdo_sqlite', 'sqlite3' => 'pdo_sqlite', ); /** * 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_oci (unstable) * pdo_sqlsrv * pdo_sqlsrv * mysqli * sqlanywhere * sqlsrv * ibm_db2 (unstable) * drizzle_pdo_mysql * * OR 'driverClass' that contains the full class name (with namespace) of the * driver class to instantiate. * * Other (optional) parameters: * * user (string): * The username to use when connecting. * * password (string): * The password to use when connecting. * * driverOptions (array): * Any additional driver-specific options for the driver. These are just passed * through to the driver. * * pdo: * You can pass an existing PDO instance through this parameter. The PDO * instance will be wrapped in a Doctrine\DBAL\Connection. * * wrapperClass: * You may specify a custom wrapper class through the 'wrapperClass' * parameter but this class MUST inherit from Doctrine\DBAL\Connection. * * driverClass: * The driver class to use. * * @param array $params The parameters. * @param \Doctrine\DBAL\Configuration|null $config The configuration to use. * @param \Doctrine\Common\EventManager|null $eventManager The event manager to use. * * @return \Doctrine\DBAL\Connection * * @throws \Doctrine\DBAL\DBALException */ 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(); } $params = self::parseDatabaseUrl($params); // check for existing pdo object if (isset($params['pdo']) && ! $params['pdo'] instanceof \PDO) { throw DBALException::invalidPdoInstance(); } elseif (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); } /** * Returns the list of supported drivers. * * @return array */ public static function getAvailableDrivers() { return array_keys(self::$_driverMap); } /** * Checks the list of parameters. * * @param array $params The list of parameters. * * @return void * * @throws \Doctrine\DBAL\DBALException */ private static function _checkParams(array $params) { // check existence 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']); } } /** * Normalizes the given connection URL path. * * @param string $urlPath * * @return string The normalized connection URL path */ private static function normalizeDatabaseUrlPath($urlPath) { // Trim leading slash from URL path. return substr($urlPath, 1); } /** * Extracts parts from a database URL, if present, and returns an * updated list of parameters. * * @param array $params The list of parameters. * * @param array A modified list of parameters with info from a database * URL extracted into indidivual parameter parts. * */ private static function parseDatabaseUrl(array $params) { if (!isset($params['url'])) { return $params; } // (pdo_)?sqlite3?:///... => (pdo_)?sqlite3?://localhost/... or else the URL will be invalid $url = preg_replace('#^((?:pdo_)?sqlite3?):///#', '$1://localhost/', $params['url']); // PHP < 5.4.8 doesn't parse schemeless urls properly. // See: https://php.net/parse-url#refsect1-function.parse-url-changelog if (PHP_VERSION_ID < 50408 && strpos($url, '//') === 0) { $url = parse_url('fake:' . $url); unset($url['scheme']); } else { $url = parse_url($url); } if ($url === false) { throw new DBALException('Malformed parameter "url".'); } // If we have a connection URL, we have to unset the default PDO instance connection parameter (if any) // as we cannot merge connection details from the URL into the PDO instance (URL takes precedence). unset($params['pdo']); $params = self::parseDatabaseUrlScheme($url, $params); if (isset($url['host'])) { $params['host'] = $url['host']; } if (isset($url['port'])) { $params['port'] = $url['port']; } if (isset($url['user'])) { $params['user'] = $url['user']; } if (isset($url['pass'])) { $params['password'] = $url['pass']; } $params = self::parseDatabaseUrlPath($url, $params); $params = self::parseDatabaseUrlQuery($url, $params); return $params; } /** * Parses the given connection URL and resolves the given connection parameters. * * Assumes that the connection URL scheme is already parsed and resolved into the given connection parameters * via {@link parseDatabaseUrlScheme}. * * @param array $url The URL parts to evaluate. * @param array $params The connection parameters to resolve. * * @return array The resolved connection parameters. * * @see parseDatabaseUrlScheme */ private static function parseDatabaseUrlPath(array $url, array $params) { if (! isset($url['path'])) { return $params; } $url['path'] = self::normalizeDatabaseUrlPath($url['path']); // If we do not have a known DBAL driver, we do not know any connection URL path semantics to evaluate // and therefore treat the path as regular DBAL connection URL path. if (! isset($params['driver'])) { return self::parseRegularDatabaseUrlPath($url, $params); } if (strpos($params['driver'], 'sqlite') !== false) { return self::parseSqliteDatabaseUrlPath($url, $params); } return self::parseRegularDatabaseUrlPath($url, $params); } /** * Parses the query part of the given connection URL and resolves the given connection parameters. * * @param array $url The connection URL parts to evaluate. * @param array $params The connection parameters to resolve. * * @return array The resolved connection parameters. */ private static function parseDatabaseUrlQuery(array $url, array $params) { if (! isset($url['query'])) { return $params; } $query = array(); parse_str($url['query'], $query); // simply ingest query as extra params, e.g. charset or sslmode return array_merge($params, $query); // parse_str wipes existing array elements } /** * Parses the given regular connection URL and resolves the given connection parameters. * * Assumes that the "path" URL part is already normalized via {@link normalizeDatabaseUrlPath}. * * @param array $url The regular connection URL parts to evaluate. * @param array $params The connection parameters to resolve. * * @return array The resolved connection parameters. * * @see normalizeDatabaseUrlPath */ private static function parseRegularDatabaseUrlPath(array $url, array $params) { $params['dbname'] = $url['path']; return $params; } /** * Parses the given SQLite connection URL and resolves the given connection parameters. * * Assumes that the "path" URL part is already normalized via {@link normalizeDatabaseUrlPath}. * * @param array $url The SQLite connection URL parts to evaluate. * @param array $params The connection parameters to resolve. * * @return array The resolved connection parameters. * * @see normalizeDatabaseUrlPath */ private static function parseSqliteDatabaseUrlPath(array $url, array $params) { if ($url['path'] === ':memory:') { $params['memory'] = true; return $params; } $params['path'] = $url['path']; // pdo_sqlite driver uses 'path' instead of 'dbname' key return $params; } /** * Parses the scheme part from given connection URL and resolves the given connection parameters. * * @param array $url The connection URL parts to evaluate. * @param array $params The connection parameters to resolve. * * @return array The resolved connection parameters. * * @throws DBALException if parsing failed or resolution is not possible. */ private static function parseDatabaseUrlScheme(array $url, array $params) { if (isset($url['scheme'])) { // The requested driver from the URL scheme takes precedence // over the default custom driver from the connection parameters (if any). unset($params['driverClass']); // URL schemes must not contain underscores, but dashes are ok $driver = str_replace('-', '_', $url['scheme']); // The requested driver from the URL scheme takes precedence // over the default driver from the connection parameters (if any). $params['driver'] = isset(self::$driverSchemeAliases[$driver]) // use alias like "postgres", else we just let checkParams decide later // if the driver exists (for literal "pdo-pgsql" etc) ? self::$driverSchemeAliases[$driver] : $driver; return $params; } // If a schemeless connection URL is given, we require a default driver or default custom driver // as connection parameter. if (! isset($params['driverClass']) && ! isset($params['driver'])) { throw DBALException::driverRequired($params['url']); } return $params; } } dbal-2.5.13/lib/Doctrine/DBAL/Event/000077500000000000000000000000001313473450000166045ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Event/ConnectionEventArgs.php000066400000000000000000000043161313473450000232370ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Event; use Doctrine\Common\EventArgs; use Doctrine\DBAL\Connection; /** * Event Arguments used when a Driver connection is established inside Doctrine\DBAL\Connection. * * @link www.doctrine-project.org * @since 1.0 * @author Benjamin Eberlei */ class ConnectionEventArgs extends EventArgs { /** * @var \Doctrine\DBAL\Connection */ private $_connection; /** * @param \Doctrine\DBAL\Connection $connection */ 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(); } } dbal-2.5.13/lib/Doctrine/DBAL/Event/Listeners/000077500000000000000000000000001313473450000205545ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Event/Listeners/MysqlSessionInit.php000066400000000000000000000050171313473450000245650ustar00rootroot00000000000000. */ 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. * * @link www.doctrine-project.org * @since 1.0 * @author Benjamin Eberlei * @deprecated Use "charset" option to PDO MySQL Connection instead. */ class MysqlSessionInit implements EventSubscriber { /** * The charset. * * @var string */ private $_charset; /** * The collation, or FALSE if no collation. * * @var string|boolean */ private $_collation; /** * Configure Charset and Collation options of MySQL Client for each Connection. * * @param string $charset The charset. * @param string|boolean $collation The collation, or FALSE if no collation. */ public function __construct($charset = 'utf8', $collation = false) { $this->_charset = $charset; $this->_collation = $collation; } /** * @param \Doctrine\DBAL\Event\ConnectionEventArgs $args * * @return void */ public function postConnect(ConnectionEventArgs $args) { $collation = ($this->_collation) ? " COLLATE ".$this->_collation : ""; $args->getConnection()->executeUpdate("SET NAMES ".$this->_charset . $collation); } /** * {@inheritdoc} */ public function getSubscribedEvents() { return array(Events::postConnect); } } dbal-2.5.13/lib/Doctrine/DBAL/Event/Listeners/OracleSessionInit.php000066400000000000000000000061341313473450000246660ustar00rootroot00000000000000. */ 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 environment does not match the Doctrine requirements. * * The following environment 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" * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ class OracleSessionInit implements EventSubscriber { /** * @var array */ 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", 'NLS_NUMERIC_CHARACTERS' => ".,", ); /** * @param array $oracleSessionVars */ public function __construct(array $oracleSessionVars = array()) { $this->_defaultSessionVars = array_merge($this->_defaultSessionVars, $oracleSessionVars); } /** * @param \Doctrine\DBAL\Event\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) { if ($option === 'CURRENT_SCHEMA') { $vars[] = $option . " = " . $value; } else { $vars[] = $option . " = '" . $value . "'"; } } $sql = "ALTER SESSION SET ".implode(" ", $vars); $args->getConnection()->executeUpdate($sql); } } /** * {@inheritdoc} */ public function getSubscribedEvents() { return array(Events::postConnect); } } dbal-2.5.13/lib/Doctrine/DBAL/Event/Listeners/SQLSessionInit.php000066400000000000000000000036541313473450000241240ustar00rootroot00000000000000. */ 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. * * @link www.doctrine-project.org * @since 2.2 * @author Benjamin Eberlei */ class SQLSessionInit implements EventSubscriber { /** * @var string */ protected $sql; /** * @param string $sql */ public function __construct($sql) { $this->sql = $sql; } /** * @param \Doctrine\DBAL\Event\ConnectionEventArgs $args * * @return void */ public function postConnect(ConnectionEventArgs $args) { $conn = $args->getConnection(); $conn->exec($this->sql); } /** * {@inheritdoc} */ public function getSubscribedEvents() { return array(Events::postConnect); } } dbal-2.5.13/lib/Doctrine/DBAL/Event/SchemaAlterTableAddColumnEventArgs.php000066400000000000000000000060211313473450000260620ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Event; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\TableDiff; /** * Event Arguments used when SQL queries for adding table columns are generated inside Doctrine\DBAL\Platform\*Platform. * * @link www.doctrine-project.org * @since 2.2 * @author Jan Sorgalla */ class SchemaAlterTableAddColumnEventArgs extends SchemaEventArgs { /** * @var \Doctrine\DBAL\Schema\Column */ private $_column; /** * @var \Doctrine\DBAL\Schema\TableDiff */ private $_tableDiff; /** * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ private $_platform; /** * @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; } } dbal-2.5.13/lib/Doctrine/DBAL/Event/SchemaAlterTableChangeColumnEventArgs.php000066400000000000000000000061041313473450000265610ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Event; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Schema\ColumnDiff; use Doctrine\DBAL\Schema\TableDiff; /** * Event Arguments used when SQL queries for changing table columns are generated inside Doctrine\DBAL\Platform\*Platform. * * @link www.doctrine-project.org * @since 2.2 * @author Jan Sorgalla */ class SchemaAlterTableChangeColumnEventArgs extends SchemaEventArgs { /** * @var \Doctrine\DBAL\Schema\ColumnDiff */ private $_columnDiff; /** * @var \Doctrine\DBAL\Schema\TableDiff */ private $_tableDiff; /** * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ private $_platform; /** * @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; } } dbal-2.5.13/lib/Doctrine/DBAL/Event/SchemaAlterTableEventArgs.php000066400000000000000000000052141313473450000242760ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Event; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Schema\TableDiff; /** * Event Arguments used when SQL queries for creating tables are generated inside Doctrine\DBAL\Platform\*Platform. * * @link www.doctrine-project.org * @since 2.2 * @author Jan Sorgalla */ class SchemaAlterTableEventArgs extends SchemaEventArgs { /** * @var \Doctrine\DBAL\Schema\TableDiff */ private $_tableDiff; /** * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ private $_platform; /** * @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; } } dbal-2.5.13/lib/Doctrine/DBAL/Event/SchemaAlterTableRemoveColumnEventArgs.php000066400000000000000000000060311313473450000266300ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Event; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\TableDiff; /** * Event Arguments used when SQL queries for removing table columns are generated inside Doctrine\DBAL\Platform\*Platform. * * @link www.doctrine-project.org * @since 2.2 * @author Jan Sorgalla */ class SchemaAlterTableRemoveColumnEventArgs extends SchemaEventArgs { /** * @var \Doctrine\DBAL\Schema\Column */ private $_column; /** * @var \Doctrine\DBAL\Schema\TableDiff */ private $_tableDiff; /** * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ private $_platform; /** * @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; } } dbal-2.5.13/lib/Doctrine/DBAL/Event/SchemaAlterTableRenameColumnEventArgs.php000066400000000000000000000065551313473450000266150ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Event; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\TableDiff; /** * Event Arguments used when SQL queries for renaming table columns are generated inside Doctrine\DBAL\Platform\*Platform. * * @link www.doctrine-project.org * @since 2.2 * @author Jan Sorgalla */ class SchemaAlterTableRenameColumnEventArgs extends SchemaEventArgs { /** * @var string */ private $_oldColumnName; /** * @var \Doctrine\DBAL\Schema\Column */ private $_column; /** * @var \Doctrine\DBAL\Schema\TableDiff */ private $_tableDiff; /** * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ private $_platform; /** * @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; } } dbal-2.5.13/lib/Doctrine/DBAL/Event/SchemaColumnDefinitionEventArgs.php000066400000000000000000000066471313473450000255400ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Event; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Schema\Column; /** * Event Arguments used when the portable column definition is generated inside Doctrine\DBAL\Schema\AbstractSchemaManager. * * @link www.doctrine-project.org * @since 2.2 * @author Jan Sorgalla */ class SchemaColumnDefinitionEventArgs extends SchemaEventArgs { /** * @var \Doctrine\DBAL\Schema\Column|null */ private $_column = null; /** * Raw column data as fetched from the database. * * @var array */ private $_tableColumn; /** * @var string */ private $_table; /** * @var string */ private $_database; /** * @var \Doctrine\DBAL\Connection */ private $_connection; /** * @param array $tableColumn * @param string $table * @param string $database * @param \Doctrine\DBAL\Connection $connection */ 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 \Doctrine\DBAL\Event\SchemaColumnDefinitionEventArgs */ public function setColumn(Column $column = null) { $this->_column = $column; return $this; } /** * @return \Doctrine\DBAL\Schema\Column|null */ 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(); } } dbal-2.5.13/lib/Doctrine/DBAL/Event/SchemaCreateTableColumnEventArgs.php000066400000000000000000000057531313473450000256200ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Event; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\Table; /** * Event Arguments used when SQL queries for creating table columns are generated inside Doctrine\DBAL\Platform\AbstractPlatform. * * @link www.doctrine-project.org * @since 2.2 * @author Jan Sorgalla */ class SchemaCreateTableColumnEventArgs extends SchemaEventArgs { /** * @var \Doctrine\DBAL\Schema\Column */ private $_column; /** * @var \Doctrine\DBAL\Schema\Table */ private $_table; /** * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ private $_platform; /** * @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; } } dbal-2.5.13/lib/Doctrine/DBAL/Event/SchemaCreateTableEventArgs.php000066400000000000000000000062611313473450000244350ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Event; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Schema\Table; /** * Event Arguments used when SQL queries for creating tables are generated inside Doctrine\DBAL\Platform\AbstractPlatform. * * @link www.doctrine-project.org * @since 2.2 * @author Jan Sorgalla */ class SchemaCreateTableEventArgs extends SchemaEventArgs { /** * @var \Doctrine\DBAL\Schema\Table */ private $_table; /** * @var array */ private $_columns; /** * @var array */ private $_options; /** * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ private $_platform; /** * @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; } } dbal-2.5.13/lib/Doctrine/DBAL/Event/SchemaDropTableEventArgs.php000066400000000000000000000054111313473450000241320ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Event; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Schema\Table; /** * Event Arguments used when the SQL query for dropping tables are generated inside Doctrine\DBAL\Platform\AbstractPlatform. * * @link www.doctrine-project.org * @since 2.2 * @author Jan Sorgalla */ class SchemaDropTableEventArgs extends SchemaEventArgs { /** * @var string|\Doctrine\DBAL\Schema\Table */ private $_table; /** * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ private $_platform; /** * @var string|null */ private $_sql = null; /** * @param string|\Doctrine\DBAL\Schema\Table $table * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform * * @throws \InvalidArgumentException */ public function __construct($table, AbstractPlatform $platform) { if ( ! $table instanceof Table && !is_string($table)) { throw new \InvalidArgumentException('SchemaDropTableEventArgs 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|null */ public function getSql() { return $this->_sql; } } dbal-2.5.13/lib/Doctrine/DBAL/Event/SchemaEventArgs.php000066400000000000000000000031451313473450000223370ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Event; use Doctrine\Common\EventArgs; /** * Base class for schema related events. * * @link www.doctrine-project.org * @since 2.2 * @author Jan Sorgalla */ 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; } } dbal-2.5.13/lib/Doctrine/DBAL/Event/SchemaIndexDefinitionEventArgs.php000066400000000000000000000061261313473450000253420ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Event; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Schema\Index; /** * Event Arguments used when the portable index definition is generated inside Doctrine\DBAL\Schema\AbstractSchemaManager. * * @link www.doctrine-project.org * @since 2.2 * @author Jan Sorgalla */ class SchemaIndexDefinitionEventArgs extends SchemaEventArgs { /** * @var \Doctrine\DBAL\Schema\Index|null */ private $_index = null; /** * Raw index data as fetched from the database. * * @var array */ private $_tableIndex; /** * @var string */ private $_table; /** * @var \Doctrine\DBAL\Connection */ private $_connection; /** * @param array $tableIndex * @param string $table * @param \Doctrine\DBAL\Connection $connection */ 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|null */ 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(); } } dbal-2.5.13/lib/Doctrine/DBAL/Events.php000066400000000000000000000040371313473450000175040ustar00rootroot00000000000000. */ namespace Doctrine\DBAL; /** * Container for all DBAL events. * * This class cannot be instantiated. * * @author Roman Borschel * @since 2.0 */ final class Events { /** * Private constructor. This class cannot be instantiated. */ 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'; } dbal-2.5.13/lib/Doctrine/DBAL/Exception/000077500000000000000000000000001313473450000174615ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Exception/ConnectionException.php000066400000000000000000000023611313473450000241520ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Exception; /** * Base class for all connection related errors detected in the driver. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class ConnectionException extends DriverException { } dbal-2.5.13/lib/Doctrine/DBAL/Exception/ConstraintViolationException.php000066400000000000000000000024041313473450000260620ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Exception; /** * Base class for all constraint violation related errors detected in the driver. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class ConstraintViolationException extends ServerException { } dbal-2.5.13/lib/Doctrine/DBAL/Exception/DatabaseObjectExistsException.php000066400000000000000000000027271313473450000261140ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Exception; /** * Base class for all already existing database object related errors detected in the driver. * * A database object is considered any asset that can be created in a database * such as schemas, tables, views, sequences, triggers, constraints, indexes, * functions, stored procedures etc. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class DatabaseObjectExistsException extends ServerException { } dbal-2.5.13/lib/Doctrine/DBAL/Exception/DatabaseObjectNotFoundException.php000066400000000000000000000027201313473450000263620ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Exception; /** * Base class for all unknown database object related errors detected in the driver. * * A database object is considered any asset that can be created in a database * such as schemas, tables, views, sequences, triggers, constraints, indexes, * functions, stored procedures etc. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class DatabaseObjectNotFoundException extends ServerException { } dbal-2.5.13/lib/Doctrine/DBAL/Exception/DriverException.php000066400000000000000000000050551313473450000233110ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Exception; use Doctrine\DBAL\DBALException; /** * Base class for all errors detected in the driver. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class DriverException extends DBALException { /** * The previous DBAL driver exception. * * @var \Doctrine\DBAL\Driver\DriverException */ private $driverException; /** * Constructor. * * @param string $message The exception message. * @param \Doctrine\DBAL\Driver\DriverException $driverException The DBAL driver exception to chain. */ public function __construct($message, \Doctrine\DBAL\Driver\DriverException $driverException) { $exception = null; if ($driverException instanceof \Exception) { $exception = $driverException; } parent::__construct($message, 0, $exception); $this->driverException = $driverException; } /** * Returns the driver specific error code if given. * * Returns null if no error code was given by the driver. * * @return integer|string|null */ public function getErrorCode() { return $this->driverException->getErrorCode(); } /** * Returns the SQLSTATE the driver was in at the time the error occurred, if given. * * Returns null if no SQLSTATE was given by the driver. * * @return string|null */ public function getSQLState() { return $this->driverException->getSQLState(); } } dbal-2.5.13/lib/Doctrine/DBAL/Exception/ForeignKeyConstraintViolationException.php000066400000000000000000000025071313473450000300510ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Exception; /** * Exception for a foreign key constraint violation detected in the driver. * * @author Benjamin Eberlei * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class ForeignKeyConstraintViolationException extends ConstraintViolationException { } dbal-2.5.13/lib/Doctrine/DBAL/Exception/InvalidArgumentException.php000066400000000000000000000027041313473450000251450ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Exception; use Doctrine\DBAL\DBALException; /** * Exception to be thrown when invalid arguments are passed to any DBAL API * * @author Marco Pivetta * @link www.doctrine-project.org * @since 2.5 */ class InvalidArgumentException extends DBALException { /** * @return self */ public static function fromEmptyCriteria() { return new self('Empty criteria was used, expected non-empty criteria'); } } dbal-2.5.13/lib/Doctrine/DBAL/Exception/InvalidFieldNameException.php000066400000000000000000000024071313473450000252070ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Exception; /** * Exception for an invalid specified field name in a statement detected in the driver. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class InvalidFieldNameException extends ServerException { } dbal-2.5.13/lib/Doctrine/DBAL/Exception/NonUniqueFieldNameException.php000066400000000000000000000024251313473450000255420ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Exception; /** * Exception for a non-unique/ambiguous specified field name in a statement detected in the driver. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class NonUniqueFieldNameException extends ServerException { } dbal-2.5.13/lib/Doctrine/DBAL/Exception/NotNullConstraintViolationException.php000066400000000000000000000025011313473450000273740ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Exception; /** * Exception for a NOT NULL constraint violation detected in the driver. * * @author Benjamin Eberlei * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class NotNullConstraintViolationException extends ConstraintViolationException { } dbal-2.5.13/lib/Doctrine/DBAL/Exception/ReadOnlyException.php000066400000000000000000000024121313473450000235650ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Exception; /** * Exception for a write operation attempt on a read-only database element detected in the driver. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class ReadOnlyException extends ServerException { } dbal-2.5.13/lib/Doctrine/DBAL/Exception/ServerException.php000066400000000000000000000023511313473450000233200ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Exception; /** * Base class for all server related errors detected in the driver. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class ServerException extends DriverException { } dbal-2.5.13/lib/Doctrine/DBAL/Exception/SyntaxErrorException.php000066400000000000000000000023611313473450000243530ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Exception; /** * Exception for a syntax error in a statement detected in the driver. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class SyntaxErrorException extends ServerException { } dbal-2.5.13/lib/Doctrine/DBAL/Exception/TableExistsException.php000066400000000000000000000024251313473450000243030ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Exception; /** * Exception for an already existing table referenced in a statement detected in the driver. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class TableExistsException extends DatabaseObjectExistsException { } dbal-2.5.13/lib/Doctrine/DBAL/Exception/TableNotFoundException.php000066400000000000000000000024201313473450000245530ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Exception; /** * Exception for an unknown table referenced in a statement detected in the driver. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class TableNotFoundException extends DatabaseObjectNotFoundException { } dbal-2.5.13/lib/Doctrine/DBAL/Exception/UniqueConstraintViolationException.php000066400000000000000000000024761313473450000272620ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Exception; /** * Exception for a unique constraint violation detected in the driver. * * @author Benjamin Eberlei * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class UniqueConstraintViolationException extends ConstraintViolationException { } dbal-2.5.13/lib/Doctrine/DBAL/Id/000077500000000000000000000000001313473450000160575ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Id/TableGenerator.php000066400000000000000000000141561313473450000214750ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Id; use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\Connection; /** * Table ID Generator for those poor languages that are missing sequences. * * WARNING: The Table Id Generator clones a second independent database * connection to work correctly. This means using the generator requests that * generate IDs will have two open database connections. This is necessary to * be safe from transaction failures in the main connection. Make sure to only * ever use one TableGenerator otherwise you end up with many connections. * * TableID Generator does not work with SQLite. * * The TableGenerator does not take care of creating the SQL Table itself. You * should look at the `TableGeneratorSchemaVisitor` to do this for you. * Otherwise the schema for a table looks like: * * CREATE sequences ( * sequence_name VARCHAR(255) NOT NULL, * sequence_value INT NOT NULL DEFAULT '1', * sequence_increment_by INT NOT NULL DEFAULT '1', * PRIMARY KEY (table_name) * ); * * Technically this generator works as follows: * * 1. Use a robust transaction serialization level. * 2. Open transaction * 3. Acquire a read lock on the table row (SELECT .. FOR UPDATE) * 4. Increment current value by one and write back to database * 5. Commit transaction * * If you are using a sequence_increment_by value that is larger than one the * ID Generator will keep incrementing values until it hits the incrementation * gap before issuing another query. * * If no row is present for a given sequence a new one will be created with the * default values 'value' = 1 and 'increment_by' = 1 * * @author Benjamin Eberlei */ class TableGenerator { /** * @var \Doctrine\DBAL\Connection */ private $conn; /** * @var string */ private $generatorTableName; /** * @var array */ private $sequences = array(); /** * @param \Doctrine\DBAL\Connection $conn * @param string $generatorTableName * * @throws \Doctrine\DBAL\DBALException */ public function __construct(Connection $conn, $generatorTableName = 'sequences') { $params = $conn->getParams(); if ($params['driver'] == 'pdo_sqlite') { throw new \Doctrine\DBAL\DBALException("Cannot use TableGenerator with SQLite."); } $this->conn = DriverManager::getConnection($params, $conn->getConfiguration(), $conn->getEventManager()); $this->generatorTableName = $generatorTableName; } /** * Generates the next unused value for the given sequence name. * * @param string $sequenceName * * @return integer * * @throws \Doctrine\DBAL\DBALException */ public function nextValue($sequenceName) { if (isset($this->sequences[$sequenceName])) { $value = $this->sequences[$sequenceName]['value']; $this->sequences[$sequenceName]['value']++; if ($this->sequences[$sequenceName]['value'] >= $this->sequences[$sequenceName]['max']) { unset ($this->sequences[$sequenceName]); } return $value; } $this->conn->beginTransaction(); try { $platform = $this->conn->getDatabasePlatform(); $sql = "SELECT sequence_value, sequence_increment_by " . "FROM " . $platform->appendLockHint($this->generatorTableName, \Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE) . " " . "WHERE sequence_name = ? " . $platform->getWriteLockSQL(); $stmt = $this->conn->executeQuery($sql, array($sequenceName)); if ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { $row = array_change_key_case($row, CASE_LOWER); $value = $row['sequence_value']; $value++; if ($row['sequence_increment_by'] > 1) { $this->sequences[$sequenceName] = array( 'value' => $value, 'max' => $row['sequence_value'] + $row['sequence_increment_by'] ); } $sql = "UPDATE " . $this->generatorTableName . " ". "SET sequence_value = sequence_value + sequence_increment_by " . "WHERE sequence_name = ? AND sequence_value = ?"; $rows = $this->conn->executeUpdate($sql, array($sequenceName, $row['sequence_value'])); if ($rows != 1) { throw new \Doctrine\DBAL\DBALException("Race-condition detected while updating sequence. Aborting generation"); } } else { $this->conn->insert( $this->generatorTableName, array('sequence_name' => $sequenceName, 'sequence_value' => 1, 'sequence_increment_by' => 1) ); $value = 1; } $this->conn->commit(); } catch (\Exception $e) { $this->conn->rollback(); throw new \Doctrine\DBAL\DBALException("Error occurred while generating ID with TableGenerator, aborted generation: " . $e->getMessage(), 0, $e); } return $value; } } dbal-2.5.13/lib/Doctrine/DBAL/Id/TableGeneratorSchemaVisitor.php000066400000000000000000000047421313473450000241760ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Id; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\Sequence; use Doctrine\DBAL\Schema\Index; class TableGeneratorSchemaVisitor implements \Doctrine\DBAL\Schema\Visitor\Visitor { /** * @var string */ private $generatorTableName; /** * @param string $generatorTableName */ public function __construct($generatorTableName = 'sequences') { $this->generatorTableName = $generatorTableName; } /** * {@inheritdoc} */ public function acceptSchema(Schema $schema) { $table = $schema->createTable($this->generatorTableName); $table->addColumn('sequence_name', 'string'); $table->addColumn('sequence_value', 'integer', array('default' => 1)); $table->addColumn('sequence_increment_by', 'integer', array('default' => 1)); } /** * {@inheritdoc} */ public function acceptTable(Table $table) { } /** * {@inheritdoc} */ public function acceptColumn(Table $table, Column $column) { } /** * {@inheritdoc} */ public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) { } /** * {@inheritdoc} */ public function acceptIndex(Table $table, Index $index) { } /** * {@inheritdoc} */ public function acceptSequence(Sequence $sequence) { } } dbal-2.5.13/lib/Doctrine/DBAL/LockMode.php000066400000000000000000000027011313473450000177310ustar00rootroot00000000000000. */ namespace Doctrine\DBAL; /** * Contains all DBAL LockModes. * * @link www.doctrine-project.org * @since 1.0 * @author Benjamin Eberlei * @author Roman Borschel */ class LockMode { const NONE = 0; const OPTIMISTIC = 1; const PESSIMISTIC_READ = 2; const PESSIMISTIC_WRITE = 4; /** * Private constructor. This class cannot be instantiated. */ final private function __construct() { } } dbal-2.5.13/lib/Doctrine/DBAL/Logging/000077500000000000000000000000001313473450000171115ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Logging/DebugStack.php000066400000000000000000000043771313473450000216510ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Logging; /** * Includes executed SQLs in a Debug Stack. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel */ class DebugStack implements SQLLogger { /** * Executed SQL queries. * * @var array */ public $queries = array(); /** * If Debug Stack is enabled (log queries) or not. * * @var boolean */ public $enabled = true; /** * @var float|null */ public $start = null; /** * @var integer */ 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() { if ($this->enabled) { $this->queries[$this->currentQuery]['executionMS'] = microtime(true) - $this->start; } } } dbal-2.5.13/lib/Doctrine/DBAL/Logging/EchoSQLLogger.php000066400000000000000000000033541313473450000222250ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Logging; /** * A SQL logger that logs to the standard output using echo/var_dump. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel */ 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() { } } dbal-2.5.13/lib/Doctrine/DBAL/Logging/LoggerChain.php000066400000000000000000000036371313473450000220150ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Logging; /** * Chains multiple SQLLogger. * * @link www.doctrine-project.org * @since 2.2 * @author Christophe Coevoet */ class LoggerChain implements SQLLogger { /** * @var \Doctrine\DBAL\Logging\SQLLogger[] */ private $loggers = array(); /** * Adds a logger in the chain. * * @param \Doctrine\DBAL\Logging\SQLLogger $logger * * @return void */ 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(); } } } dbal-2.5.13/lib/Doctrine/DBAL/Logging/SQLLogger.php000066400000000000000000000034661313473450000214320ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Logging; /** * Interface for SQL loggers. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel */ interface SQLLogger { /** * Logs a SQL statement somewhere. * * @param string $sql The SQL to be executed. * @param array|null $params The SQL parameters. * @param array|null $types The SQL parameter types. * * @return void */ public function startQuery($sql, array $params = null, array $types = null); /** * Marks the last started query as stopped. This can be used for timing of queries. * * @return void */ public function stopQuery(); } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/000077500000000000000000000000001313473450000174725ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php000066400000000000000000003113711313473450000234610ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Schema\Identifier; use Doctrine\DBAL\Types; use Doctrine\DBAL\Schema\Constraint; use Doctrine\DBAL\Schema\Sequence; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\ColumnDiff; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Events; use Doctrine\Common\EventManager; use Doctrine\DBAL\Event\SchemaCreateTableEventArgs; use Doctrine\DBAL\Event\SchemaCreateTableColumnEventArgs; use Doctrine\DBAL\Event\SchemaDropTableEventArgs; use Doctrine\DBAL\Event\SchemaAlterTableEventArgs; use Doctrine\DBAL\Event\SchemaAlterTableAddColumnEventArgs; use Doctrine\DBAL\Event\SchemaAlterTableRemoveColumnEventArgs; use Doctrine\DBAL\Event\SchemaAlterTableChangeColumnEventArgs; use Doctrine\DBAL\Event\SchemaAlterTableRenameColumnEventArgs; /** * Base class for all DatabasePlatforms. The DatabasePlatforms are the central * point of abstraction of platform-specific behaviors, features and SQL dialects. * They are a passive source of information. * * @link www.doctrine-project.org * @since 2.0 * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author Lukas Smith (PEAR MDB2 library) * @author Benjamin Eberlei * @todo Remove any unnecessary methods. */ abstract class AbstractPlatform { /** * @var integer */ const CREATE_INDEXES = 1; /** * @var integer */ const CREATE_FOREIGNKEYS = 2; /** * @var string */ const DATE_INTERVAL_UNIT_SECOND = 'SECOND'; /** * @var string */ const DATE_INTERVAL_UNIT_MINUTE = 'MINUTE'; /** * @var string */ const DATE_INTERVAL_UNIT_HOUR = 'HOUR'; /** * @var string */ const DATE_INTERVAL_UNIT_DAY = 'DAY'; /** * @var string */ const DATE_INTERVAL_UNIT_WEEK = 'WEEK'; /** * @var string */ const DATE_INTERVAL_UNIT_MONTH = 'MONTH'; /** * @var string */ const DATE_INTERVAL_UNIT_QUARTER = 'QUARTER'; /** * @var string */ const DATE_INTERVAL_UNIT_YEAR = 'YEAR'; /** * @var integer */ const TRIM_UNSPECIFIED = 0; /** * @var integer */ const TRIM_LEADING = 1; /** * @var integer */ const TRIM_TRAILING = 2; /** * @var integer */ const TRIM_BOTH = 3; /** * @var array|null */ protected $doctrineTypeMapping = null; /** * Contains a list of all columns that should generate parseable column comments for type-detection * in reverse engineering scenarios. * * @var array|null */ protected $doctrineTypeComments = null; /** * @var \Doctrine\Common\EventManager */ protected $_eventManager; /** * Holds the KeywordList instance for the current platform. * * @var \Doctrine\DBAL\Platforms\Keywords\KeywordList */ protected $_keywords; /** * Constructor. */ public function __construct() { } /** * Sets the EventManager used by the Platform. * * @param \Doctrine\Common\EventManager $eventManager */ public function setEventManager(EventManager $eventManager) { $this->_eventManager = $eventManager; } /** * Gets the EventManager used by the Platform. * * @return \Doctrine\Common\EventManager */ public function getEventManager() { return $this->_eventManager; } /** * Returns the SQL snippet that declares a boolean column. * * @param array $columnDef * * @return string */ abstract public function getBooleanTypeDeclarationSQL(array $columnDef); /** * Returns the SQL snippet that declares a 4 byte integer column. * * @param array $columnDef * * @return string */ abstract public function getIntegerTypeDeclarationSQL(array $columnDef); /** * Returns the SQL snippet that declares an 8 byte integer column. * * @param array $columnDef * * @return string */ abstract public function getBigIntTypeDeclarationSQL(array $columnDef); /** * Returns the SQL snippet that declares a 2 byte integer column. * * @param array $columnDef * * @return string */ abstract public function getSmallIntTypeDeclarationSQL(array $columnDef); /** * Returns the SQL snippet that declares common properties of an integer column. * * @param array $columnDef * * @return string */ abstract protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef); /** * Lazy load Doctrine Type Mappings. * * @return void */ abstract protected function initializeDoctrineTypeMappings(); /** * Initializes Doctrine Type Mappings with the platform defaults * and with all additional type mappings. * * @return void */ private function initializeAllDoctrineTypeMappings() { $this->initializeDoctrineTypeMappings(); foreach (Type::getTypesMap() as $typeName => $className) { foreach (Type::getType($typeName)->getMappedDatabaseTypes($this) as $dbType) { $this->doctrineTypeMapping[$dbType] = $typeName; } } } /** * Returns the SQL snippet used to declare a VARCHAR column type. * * @param array $field * * @return string */ public function getVarcharTypeDeclarationSQL(array $field) { if ( !isset($field['length'])) { $field['length'] = $this->getVarcharDefaultLength(); } $fixed = (isset($field['fixed'])) ? $field['fixed'] : false; if ($field['length'] > $this->getVarcharMaxLength()) { return $this->getClobTypeDeclarationSQL($field); } return $this->getVarcharTypeDeclarationSQLSnippet($field['length'], $fixed); } /** * Returns the SQL snippet used to declare a BINARY/VARBINARY column type. * * @param array $field The column definition. * * @return string */ public function getBinaryTypeDeclarationSQL(array $field) { if ( ! isset($field['length'])) { $field['length'] = $this->getBinaryDefaultLength(); } $fixed = isset($field['fixed']) ? $field['fixed'] : false; if ($field['length'] > $this->getBinaryMaxLength()) { return $this->getBlobTypeDeclarationSQL($field); } return $this->getBinaryTypeDeclarationSQLSnippet($field['length'], $fixed); } /** * Returns the SQL snippet to declare a GUID/UUID field. * * By default this maps directly to a CHAR(36) and only maps to more * special datatypes when the underlying databases support this datatype. * * @param array $field * * @return string */ public function getGuidTypeDeclarationSQL(array $field) { $field['length'] = 36; $field['fixed'] = true; return $this->getVarcharTypeDeclarationSQL($field); } /** * Returns the SQL snippet to declare a JSON field. * * By default this maps directly to a CLOB and only maps to more * special datatypes when the underlying databases support this datatype. * * @param array $field * * @return string */ public function getJsonTypeDeclarationSQL(array $field) { return $this->getClobTypeDeclarationSQL($field); } /** * @param integer $length * @param boolean $fixed * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) { throw DBALException::notSupported('VARCHARs not supported by Platform.'); } /** * Returns the SQL snippet used to declare a BINARY/VARBINARY column type. * * @param integer $length The length of the column. * @param boolean $fixed Whether the column length is fixed. * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) { throw DBALException::notSupported('BINARY/VARBINARY column types are not supported by this platform.'); } /** * Returns the SQL snippet used to declare a CLOB column type. * * @param array $field * * @return string */ abstract public function getClobTypeDeclarationSQL(array $field); /** * Returns the SQL Snippet used to declare a BLOB column type. * * @param array $field * * @return string */ abstract public function getBlobTypeDeclarationSQL(array $field); /** * Gets the name of the platform. * * @return string */ abstract public function getName(); /** * Registers a doctrine type to be used in conjunction with a column type of this platform. * * @param string $dbType * @param string $doctrineType * * @throws \Doctrine\DBAL\DBALException If the type is not found. */ public function registerDoctrineTypeMapping($dbType, $doctrineType) { if ($this->doctrineTypeMapping === null) { $this->initializeAllDoctrineTypeMappings(); } if (!Types\Type::hasType($doctrineType)) { throw DBALException::typeNotFound($doctrineType); } $dbType = strtolower($dbType); $this->doctrineTypeMapping[$dbType] = $doctrineType; } /** * Gets the Doctrine type that is mapped for the given database column type. * * @param string $dbType * * @return string * * @throws \Doctrine\DBAL\DBALException */ public function getDoctrineTypeMapping($dbType) { if ($this->doctrineTypeMapping === null) { $this->initializeAllDoctrineTypeMappings(); } $dbType = strtolower($dbType); if (!isset($this->doctrineTypeMapping[$dbType])) { throw new \Doctrine\DBAL\DBALException("Unknown database type ".$dbType." requested, " . get_class($this) . " may not support it."); } return $this->doctrineTypeMapping[$dbType]; } /** * Checks if a database type is currently supported by this platform. * * @param string $dbType * * @return boolean */ public function hasDoctrineTypeMappingFor($dbType) { if ($this->doctrineTypeMapping === null) { $this->initializeAllDoctrineTypeMappings(); } $dbType = strtolower($dbType); return isset($this->doctrineTypeMapping[$dbType]); } /** * Initializes the Doctrine Type comments instance variable for in_array() checks. * * @return void */ protected function initializeCommentedDoctrineTypes() { $this->doctrineTypeComments = array(); foreach (Type::getTypesMap() as $typeName => $className) { $type = Type::getType($typeName); if ($type->requiresSQLCommentHint($this)) { $this->doctrineTypeComments[] = $typeName; } } } /** * Is it necessary for the platform to add a parsable type comment to allow reverse engineering the given type? * * @param \Doctrine\DBAL\Types\Type $doctrineType * * @return boolean */ public function isCommentedDoctrineType(Type $doctrineType) { if ($this->doctrineTypeComments === null) { $this->initializeCommentedDoctrineTypes(); } return in_array($doctrineType->getName(), $this->doctrineTypeComments); } /** * Marks this type as to be commented in ALTER TABLE and CREATE TABLE statements. * * @param string|\Doctrine\DBAL\Types\Type $doctrineType * * @return void */ public function markDoctrineTypeCommented($doctrineType) { if ($this->doctrineTypeComments === null) { $this->initializeCommentedDoctrineTypes(); } $this->doctrineTypeComments[] = $doctrineType instanceof Type ? $doctrineType->getName() : $doctrineType; } /** * Gets the comment to append to a column comment that helps parsing this type in reverse engineering. * * @param \Doctrine\DBAL\Types\Type $doctrineType * * @return string */ public function getDoctrineTypeComment(Type $doctrineType) { return '(DC2Type:' . $doctrineType->getName() . ')'; } /** * Gets the comment of a passed column modified by potential doctrine type comment hints. * * @param \Doctrine\DBAL\Schema\Column $column * * @return string */ protected function getColumnComment(Column $column) { $comment = $column->getComment(); if ($this->isCommentedDoctrineType($column->getType())) { $comment .= $this->getDoctrineTypeComment($column->getType()); } return $comment; } /** * Gets the character used for identifier quoting. * * @return string */ public function getIdentifierQuoteCharacter() { return '"'; } /** * Gets the string portion that starts an SQL comment. * * @return string */ public function getSqlCommentStartString() { return "--"; } /** * Gets the string portion that ends an SQL comment. * * @return string */ public function getSqlCommentEndString() { return "\n"; } /** * Gets the maximum length of a varchar field. * * @return integer */ public function getVarcharMaxLength() { return 4000; } /** * Gets the default length of a varchar field. * * @return integer */ public function getVarcharDefaultLength() { return 255; } /** * Gets the maximum length of a binary field. * * @return integer */ public function getBinaryMaxLength() { return 4000; } /** * Gets the default length of a binary field. * * @return integer */ public function getBinaryDefaultLength() { return 255; } /** * Gets all SQL wildcard characters of the platform. * * @return array */ public function getWildcards() { return array('%', '_'); } /** * Returns the regular expression operator. * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getRegexpExpression() { throw DBALException::notSupported(__METHOD__); } /** * Returns the global unique identifier expression. * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getGuidExpression() { throw DBALException::notSupported(__METHOD__); } /** * Returns the SQL snippet to get the average value of a column. * * @param string $column The column to use. * * @return string Generated SQL including an AVG aggregate function. */ public function getAvgExpression($column) { return 'AVG(' . $column . ')'; } /** * Returns the SQL snippet to get the number of rows (without a NULL value) of a column. * * If a '*' is used instead of a column the number of selected rows is returned. * * @param string|integer $column The column to use. * * @return string Generated SQL including a COUNT aggregate function. */ public function getCountExpression($column) { return 'COUNT(' . $column . ')'; } /** * Returns the SQL snippet to get the highest value of a column. * * @param string $column The column to use. * * @return string Generated SQL including a MAX aggregate function. */ public function getMaxExpression($column) { return 'MAX(' . $column . ')'; } /** * Returns the SQL snippet to get the lowest value of a column. * * @param string $column The column to use. * * @return string Generated SQL including a MIN aggregate function. */ public function getMinExpression($column) { return 'MIN(' . $column . ')'; } /** * Returns the SQL snippet to get the total sum of a column. * * @param string $column The column to use. * * @return string Generated SQL including a SUM aggregate function. */ public function getSumExpression($column) { return 'SUM(' . $column . ')'; } // scalar functions /** * Returns the SQL snippet to get the md5 sum of a field. * * Note: Not SQL92, but common functionality. * * @param string $column * * @return string */ public function getMd5Expression($column) { return 'MD5(' . $column . ')'; } /** * Returns the SQL snippet to get the length of a text field. * * @param string $column * * @return string */ public function getLengthExpression($column) { return 'LENGTH(' . $column . ')'; } /** * Returns the SQL snippet to get the squared value of a column. * * @param string $column The column to use. * * @return string Generated SQL including an SQRT aggregate function. */ public function getSqrtExpression($column) { return 'SQRT(' . $column . ')'; } /** * Returns the SQL snippet to round a numeric field to the number of decimals specified. * * @param string $column * @param integer $decimals * * @return string */ public function getRoundExpression($column, $decimals = 0) { return 'ROUND(' . $column . ', ' . $decimals . ')'; } /** * Returns the SQL snippet to get the remainder of the division operation $expression1 / $expression2. * * @param string $expression1 * @param string $expression2 * * @return string */ public function getModExpression($expression1, $expression2) { return 'MOD(' . $expression1 . ', ' . $expression2 . ')'; } /** * Returns the SQL snippet to trim a string. * * @param string $str The expression to apply the trim to. * @param integer $pos The position of the trim (leading/trailing/both). * @param string|boolean $char The char to trim, has to be quoted already. Defaults to space. * * @return string */ public function getTrimExpression($str, $pos = self::TRIM_UNSPECIFIED, $char = false) { $expression = ''; switch ($pos) { case self::TRIM_LEADING: $expression = 'LEADING '; break; case self::TRIM_TRAILING: $expression = 'TRAILING '; break; case self::TRIM_BOTH: $expression = 'BOTH '; break; } if (false !== $char) { $expression .= $char . ' '; } if ($pos || false !== $char) { $expression .= 'FROM '; } return 'TRIM(' . $expression . $str . ')'; } /** * Returns the SQL snippet to trim trailing space characters from the expression. * * @param string $str Literal string or column name. * * @return string */ public function getRtrimExpression($str) { return 'RTRIM(' . $str . ')'; } /** * Returns the SQL snippet to trim leading space characters from the expression. * * @param string $str Literal string or column name. * * @return string */ public function getLtrimExpression($str) { return 'LTRIM(' . $str . ')'; } /** * Returns the SQL snippet to change all characters from the expression to uppercase, * according to the current character set mapping. * * @param string $str Literal string or column name. * * @return string */ public function getUpperExpression($str) { return 'UPPER(' . $str . ')'; } /** * Returns the SQL snippet to change all characters from the expression to lowercase, * according to the current character set mapping. * * @param string $str Literal string or column name. * * @return string */ public function getLowerExpression($str) { return 'LOWER(' . $str . ')'; } /** * Returns the SQL snippet to get the position of the first occurrence of substring $substr in string $str. * * @param string $str Literal string. * @param string $substr Literal string to find. * @param integer|boolean $startPos Position to start at, beginning of string by default. * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getLocateExpression($str, $substr, $startPos = false) { throw DBALException::notSupported(__METHOD__); } /** * Returns the SQL snippet to get the current system date. * * @return string */ public function getNowExpression() { return 'NOW()'; } /** * Returns a SQL snippet 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|null $length The substring portion length. * * @return string */ public function getSubstringExpression($value, $from, $length = null) { if ($length === null) { return 'SUBSTRING(' . $value . ' FROM ' . $from . ')'; } return 'SUBSTRING(' . $value . ' FROM ' . $from . ' FOR ' . $length . ')'; } /** * Returns a SQL snippet to concatenate the given expressions. * * Accepts an arbitrary number of string parameters. Each parameter must contain an expression. * * @return string */ public function getConcatExpression() { return join(' || ', func_get_args()); } /** * Returns the SQL for a logical not. * * Example: * * $q = new Doctrine_Query(); * $e = $q->expr; * $q->select('*')->from('table') * ->where($e->eq('id', $e->not('null')); * * * @param string $expression * * @return string The logical expression. */ public function getNotExpression($expression) { return 'NOT(' . $expression . ')'; } /** * Returns the SQL that checks if an expression is null. * * @param string $expression The expression that should be compared to null. * * @return string The logical expression. */ public function getIsNullExpression($expression) { return $expression . ' IS NULL'; } /** * Returns the SQL that checks if an expression is not null. * * @param string $expression The expression that should be compared to null. * * @return string The logical expression. */ public function getIsNotNullExpression($expression) { return $expression . ' IS NOT NULL'; } /** * Returns the SQL that checks if an expression evaluates to a value between two values. * * The parameter $expression is checked if it is between $value1 and $value2. * * Note: There is a slight difference in the way BETWEEN works on some databases. * http://www.w3schools.com/sql/sql_between.asp. If you want complete database * independence you should avoid using between(). * * @param string $expression The value to compare to. * @param string $value1 The lower value to compare with. * @param string $value2 The higher value to compare with. * * @return string The logical expression. */ public function getBetweenExpression($expression, $value1, $value2) { return $expression . ' BETWEEN ' .$value1 . ' AND ' . $value2; } /** * Returns the SQL to get the arccosine of a value. * * @param string $value * * @return string */ public function getAcosExpression($value) { return 'ACOS(' . $value . ')'; } /** * Returns the SQL to get the sine of a value. * * @param string $value * * @return string */ public function getSinExpression($value) { return 'SIN(' . $value . ')'; } /** * Returns the SQL to get the PI value. * * @return string */ public function getPiExpression() { return 'PI()'; } /** * Returns the SQL to get the cosine of a value. * * @param string $value * * @return string */ public function getCosExpression($value) { return 'COS(' . $value . ')'; } /** * Returns the SQL to calculate the difference in days between the two passed dates. * * Computes diff = date1 - date2. * * @param string $date1 * @param string $date2 * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDateDiffExpression($date1, $date2) { throw DBALException::notSupported(__METHOD__); } /** * Returns the SQL to add the number of given seconds to a date. * * @param string $date * @param integer $seconds * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDateAddSecondsExpression($date, $seconds) { return $this->getDateArithmeticIntervalExpression($date, '+', $seconds, self::DATE_INTERVAL_UNIT_SECOND); } /** * Returns the SQL to subtract the number of given seconds from a date. * * @param string $date * @param integer $seconds * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDateSubSecondsExpression($date, $seconds) { return $this->getDateArithmeticIntervalExpression($date, '-', $seconds, self::DATE_INTERVAL_UNIT_SECOND); } /** * Returns the SQL to add the number of given minutes to a date. * * @param string $date * @param integer $minutes * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDateAddMinutesExpression($date, $minutes) { return $this->getDateArithmeticIntervalExpression($date, '+', $minutes, self::DATE_INTERVAL_UNIT_MINUTE); } /** * Returns the SQL to subtract the number of given minutes from a date. * * @param string $date * @param integer $minutes * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDateSubMinutesExpression($date, $minutes) { return $this->getDateArithmeticIntervalExpression($date, '-', $minutes, self::DATE_INTERVAL_UNIT_MINUTE); } /** * Returns the SQL to add the number of given hours to a date. * * @param string $date * @param integer $hours * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDateAddHourExpression($date, $hours) { return $this->getDateArithmeticIntervalExpression($date, '+', $hours, self::DATE_INTERVAL_UNIT_HOUR); } /** * Returns the SQL to subtract the number of given hours to a date. * * @param string $date * @param integer $hours * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDateSubHourExpression($date, $hours) { return $this->getDateArithmeticIntervalExpression($date, '-', $hours, self::DATE_INTERVAL_UNIT_HOUR); } /** * Returns the SQL to add the number of given days to a date. * * @param string $date * @param integer $days * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDateAddDaysExpression($date, $days) { return $this->getDateArithmeticIntervalExpression($date, '+', $days, self::DATE_INTERVAL_UNIT_DAY); } /** * Returns the SQL to subtract the number of given days to a date. * * @param string $date * @param integer $days * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDateSubDaysExpression($date, $days) { return $this->getDateArithmeticIntervalExpression($date, '-', $days, self::DATE_INTERVAL_UNIT_DAY); } /** * Returns the SQL to add the number of given weeks to a date. * * @param string $date * @param integer $weeks * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDateAddWeeksExpression($date, $weeks) { return $this->getDateArithmeticIntervalExpression($date, '+', $weeks, self::DATE_INTERVAL_UNIT_WEEK); } /** * Returns the SQL to subtract the number of given weeks from a date. * * @param string $date * @param integer $weeks * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDateSubWeeksExpression($date, $weeks) { return $this->getDateArithmeticIntervalExpression($date, '-', $weeks, self::DATE_INTERVAL_UNIT_WEEK); } /** * Returns the SQL to add the number of given months to a date. * * @param string $date * @param integer $months * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDateAddMonthExpression($date, $months) { return $this->getDateArithmeticIntervalExpression($date, '+', $months, self::DATE_INTERVAL_UNIT_MONTH); } /** * Returns the SQL to subtract the number of given months to a date. * * @param string $date * @param integer $months * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDateSubMonthExpression($date, $months) { return $this->getDateArithmeticIntervalExpression($date, '-', $months, self::DATE_INTERVAL_UNIT_MONTH); } /** * Returns the SQL to add the number of given quarters to a date. * * @param string $date * @param integer $quarters * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDateAddQuartersExpression($date, $quarters) { return $this->getDateArithmeticIntervalExpression($date, '+', $quarters, self::DATE_INTERVAL_UNIT_QUARTER); } /** * Returns the SQL to subtract the number of given quarters from a date. * * @param string $date * @param integer $quarters * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDateSubQuartersExpression($date, $quarters) { return $this->getDateArithmeticIntervalExpression($date, '-', $quarters, self::DATE_INTERVAL_UNIT_QUARTER); } /** * Returns the SQL to add the number of given years to a date. * * @param string $date * @param integer $years * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDateAddYearsExpression($date, $years) { return $this->getDateArithmeticIntervalExpression($date, '+', $years, self::DATE_INTERVAL_UNIT_YEAR); } /** * Returns the SQL to subtract the number of given years from a date. * * @param string $date * @param integer $years * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDateSubYearsExpression($date, $years) { return $this->getDateArithmeticIntervalExpression($date, '-', $years, self::DATE_INTERVAL_UNIT_YEAR); } /** * Returns the SQL for a date arithmetic expression. * * @param string $date The column or literal representing a date to perform the arithmetic operation on. * @param string $operator The arithmetic operator (+ or -). * @param integer $interval The interval that shall be calculated into the date. * @param string $unit The unit of the interval that shall be calculated into the date. * One of the DATE_INTERVAL_UNIT_* constants. * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) { throw DBALException::notSupported(__METHOD__); } /** * Returns the SQL bit AND comparison expression. * * @param string $value1 * @param string $value2 * * @return string */ public function getBitAndComparisonExpression($value1, $value2) { return '(' . $value1 . ' & ' . $value2 . ')'; } /** * Returns the SQL bit OR comparison expression. * * @param string $value1 * @param string $value2 * * @return string */ public function getBitOrComparisonExpression($value1, $value2) { return '(' . $value1 . ' | ' . $value2 . ')'; } /** * Returns the FOR UPDATE expression. * * @return string */ public function getForUpdateSQL() { return 'FOR UPDATE'; } /** * Honors that some SQL vendors such as MsSql use table hints for locking instead of the ANSI SQL FOR UPDATE specification. * * @param string $fromClause The FROM clause to append the hint for the given lock mode to. * @param integer|null $lockMode One of the Doctrine\DBAL\LockMode::* constants. If null is given, nothing will * be appended to the FROM clause. * * @return string */ public function appendLockHint($fromClause, $lockMode) { return $fromClause; } /** * Returns the SQL snippet to append to any SELECT statement which locks rows in shared read lock. * * This defaults to the ANSI SQL "FOR UPDATE", which is an exclusive lock (Write). Some database * vendors allow to lighten this constraint up to be a real read lock. * * @return string */ public function getReadLockSQL() { return $this->getForUpdateSQL(); } /** * Returns the SQL snippet to append to any SELECT statement which obtains an exclusive lock on the rows. * * The semantics of this lock mode should equal the SELECT .. FOR UPDATE of the ANSI SQL standard. * * @return string */ public function getWriteLockSQL() { return $this->getForUpdateSQL(); } /** * Returns the SQL snippet to drop an existing database. * * @param string $database The name of the database that should be dropped. * * @return string */ public function getDropDatabaseSQL($database) { return 'DROP DATABASE ' . $database; } /** * Returns the SQL snippet to drop an existing table. * * @param \Doctrine\DBAL\Schema\Table|string $table * * @return string * * @throws \InvalidArgumentException */ public function getDropTableSQL($table) { $tableArg = $table; if ($table instanceof Table) { $table = $table->getQuotedName($this); } elseif (!is_string($table)) { throw new \InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); } if (null !== $this->_eventManager && $this->_eventManager->hasListeners(Events::onSchemaDropTable)) { $eventArgs = new SchemaDropTableEventArgs($tableArg, $this); $this->_eventManager->dispatchEvent(Events::onSchemaDropTable, $eventArgs); if ($eventArgs->isDefaultPrevented()) { return $eventArgs->getSql(); } } return 'DROP TABLE ' . $table; } /** * Returns the SQL to safely drop a temporary table WITHOUT implicitly committing an open transaction. * * @param \Doctrine\DBAL\Schema\Table|string $table * * @return string */ public function getDropTemporaryTableSQL($table) { return $this->getDropTableSQL($table); } /** * Returns the SQL to drop an index from a table. * * @param \Doctrine\DBAL\Schema\Index|string $index * @param \Doctrine\DBAL\Schema\Table|string $table * * @return string * * @throws \InvalidArgumentException */ public function getDropIndexSQL($index, $table = null) { if ($index instanceof Index) { $index = $index->getQuotedName($this); } elseif (!is_string($index)) { throw new \InvalidArgumentException('AbstractPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.'); } return 'DROP INDEX ' . $index; } /** * Returns the SQL to drop a constraint. * * @param \Doctrine\DBAL\Schema\Constraint|string $constraint * @param \Doctrine\DBAL\Schema\Table|string $table * * @return string */ public function getDropConstraintSQL($constraint, $table) { if (! $constraint instanceof Constraint) { $constraint = new Identifier($constraint); } if (! $table instanceof Table) { $table = new Identifier($table); } $constraint = $constraint->getQuotedName($this); $table = $table->getQuotedName($this); return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $constraint; } /** * Returns the SQL to drop a foreign key. * * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint|string $foreignKey * @param \Doctrine\DBAL\Schema\Table|string $table * * @return string */ public function getDropForeignKeySQL($foreignKey, $table) { if (! $foreignKey instanceof ForeignKeyConstraint) { $foreignKey = new Identifier($foreignKey); } if (! $table instanceof Table) { $table = new Identifier($table); } $foreignKey = $foreignKey->getQuotedName($this); $table = $table->getQuotedName($this); return 'ALTER TABLE ' . $table . ' DROP FOREIGN KEY ' . $foreignKey; } /** * Returns the SQL statement(s) to create a table with the specified name, columns and constraints * on this platform. * * @param \Doctrine\DBAL\Schema\Table $table * @param integer $createFlags * * @return array The sequence of SQL statements. * * @throws \Doctrine\DBAL\DBALException * @throws \InvalidArgumentException */ public function getCreateTableSQL(Table $table, $createFlags = self::CREATE_INDEXES) { if ( ! is_int($createFlags)) { throw new \InvalidArgumentException("Second argument of AbstractPlatform::getCreateTableSQL() has to be integer."); } if (count($table->getColumns()) === 0) { throw DBALException::noColumnsSpecifiedForTable($table->getName()); } $tableName = $table->getQuotedName($this); $options = $table->getOptions(); $options['uniqueConstraints'] = array(); $options['indexes'] = array(); $options['primary'] = array(); if (($createFlags&self::CREATE_INDEXES) > 0) { foreach ($table->getIndexes() as $index) { /* @var $index Index */ if ($index->isPrimary()) { $options['primary'] = $index->getQuotedColumns($this); $options['primary_index'] = $index; } else { $options['indexes'][$index->getQuotedName($this)] = $index; } } } $columnSql = array(); $columns = array(); foreach ($table->getColumns() as $column) { /* @var \Doctrine\DBAL\Schema\Column $column */ if (null !== $this->_eventManager && $this->_eventManager->hasListeners(Events::onSchemaCreateTableColumn)) { $eventArgs = new SchemaCreateTableColumnEventArgs($column, $table, $this); $this->_eventManager->dispatchEvent(Events::onSchemaCreateTableColumn, $eventArgs); $columnSql = array_merge($columnSql, $eventArgs->getSql()); if ($eventArgs->isDefaultPrevented()) { continue; } } $columnData = $column->toArray(); $columnData['name'] = $column->getQuotedName($this); $columnData['version'] = $column->hasPlatformOption("version") ? $column->getPlatformOption('version') : false; $columnData['comment'] = $this->getColumnComment($column); if (strtolower($columnData['type']) == "string" && $columnData['length'] === null) { $columnData['length'] = 255; } if (in_array($column->getName(), $options['primary'])) { $columnData['primary'] = true; } $columns[$columnData['name']] = $columnData; } if (($createFlags&self::CREATE_FOREIGNKEYS) > 0) { $options['foreignKeys'] = array(); foreach ($table->getForeignKeys() as $fkConstraint) { $options['foreignKeys'][] = $fkConstraint; } } if (null !== $this->_eventManager && $this->_eventManager->hasListeners(Events::onSchemaCreateTable)) { $eventArgs = new SchemaCreateTableEventArgs($table, $columns, $options, $this); $this->_eventManager->dispatchEvent(Events::onSchemaCreateTable, $eventArgs); if ($eventArgs->isDefaultPrevented()) { return array_merge($eventArgs->getSql(), $columnSql); } } $sql = $this->_getCreateTableSQL($tableName, $columns, $options); if ($this->supportsCommentOnStatement()) { foreach ($table->getColumns() as $column) { $comment = $this->getColumnComment($column); if (null !== $comment && '' !== $comment) { $sql[] = $this->getCommentOnColumnSQL($tableName, $column->getQuotedName($this), $comment); } } } return array_merge($sql, $columnSql); } /** * @param string $tableName * @param string $columnName * @param string $comment * * @return string */ public function getCommentOnColumnSQL($tableName, $columnName, $comment) { $tableName = new Identifier($tableName); $columnName = new Identifier($columnName); $comment = $this->quoteStringLiteral($comment); return "COMMENT ON COLUMN " . $tableName->getQuotedName($this) . "." . $columnName->getQuotedName($this) . " IS " . $comment; } /** * Returns the SQL used to create a table. * * @param string $tableName * @param array $columns * @param array $options * * @return array */ protected function _getCreateTableSQL($tableName, array $columns, array $options = array()) { $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']))) . ')'; } if (isset($options['indexes']) && ! empty($options['indexes'])) { foreach ($options['indexes'] as $index => $definition) { $columnListSql .= ', ' . $this->getIndexDeclarationSQL($index, $definition); } } $query = 'CREATE TABLE ' . $tableName . ' (' . $columnListSql; $check = $this->getCheckDeclarationSQL($columns); if ( ! empty($check)) { $query .= ', ' . $check; } $query .= ')'; $sql[] = $query; if (isset($options['foreignKeys'])) { foreach ((array) $options['foreignKeys'] as $definition) { $sql[] = $this->getCreateForeignKeySQL($definition, $tableName); } } return $sql; } /** * @return string */ public function getCreateTemporaryTableSnippetSQL() { return "CREATE TEMPORARY TABLE"; } /** * Returns the SQL to create a sequence on this platform. * * @param \Doctrine\DBAL\Schema\Sequence $sequence * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getCreateSequenceSQL(Sequence $sequence) { throw DBALException::notSupported(__METHOD__); } /** * Returns the SQL to change a sequence on this platform. * * @param \Doctrine\DBAL\Schema\Sequence $sequence * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getAlterSequenceSQL(Sequence $sequence) { throw DBALException::notSupported(__METHOD__); } /** * Returns the SQL to create a constraint on a table on this platform. * * @param \Doctrine\DBAL\Schema\Constraint $constraint * @param \Doctrine\DBAL\Schema\Table|string $table * * @return string * * @throws \InvalidArgumentException */ public function getCreateConstraintSQL(Constraint $constraint, $table) { if ($table instanceof Table) { $table = $table->getQuotedName($this); } $query = 'ALTER TABLE ' . $table . ' ADD CONSTRAINT ' . $constraint->getQuotedName($this); $columnList = '('. implode(', ', $constraint->getQuotedColumns($this)) . ')'; $referencesClause = ''; if ($constraint instanceof Index) { if ($constraint->isPrimary()) { $query .= ' PRIMARY KEY'; } elseif ($constraint->isUnique()) { $query .= ' UNIQUE'; } else { throw new \InvalidArgumentException( 'Can only create primary or unique constraints, no common indexes with getCreateConstraintSQL().' ); } } elseif ($constraint instanceof ForeignKeyConstraint) { $query .= ' FOREIGN KEY'; $referencesClause = ' REFERENCES ' . $constraint->getQuotedForeignTableName($this) . ' (' . implode(', ', $constraint->getQuotedForeignColumns($this)) . ')'; } $query .= ' '.$columnList.$referencesClause; return $query; } /** * Returns the SQL to create an index on a table on this platform. * * @param \Doctrine\DBAL\Schema\Index $index * @param \Doctrine\DBAL\Schema\Table|string $table The name of the table on which the index is to be created. * * @return string * * @throws \InvalidArgumentException */ public function getCreateIndexSQL(Index $index, $table) { if ($table instanceof Table) { $table = $table->getQuotedName($this); } $name = $index->getQuotedName($this); $columns = $index->getQuotedColumns($this); if (count($columns) == 0) { throw new \InvalidArgumentException("Incomplete definition. 'columns' required."); } if ($index->isPrimary()) { return $this->getCreatePrimaryKeySQL($index, $table); } $query = 'CREATE ' . $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name . ' ON ' . $table; $query .= ' (' . $this->getIndexFieldDeclarationListSQL($columns) . ')' . $this->getPartialIndexSQL($index); return $query; } /** * Adds condition for partial index. * * @param \Doctrine\DBAL\Schema\Index $index * * @return string */ protected function getPartialIndexSQL(Index $index) { if ($this->supportsPartialIndexes() && $index->hasOption('where')) { return ' WHERE ' . $index->getOption('where'); } return ''; } /** * Adds additional flags for index generation. * * @param \Doctrine\DBAL\Schema\Index $index * * @return string */ protected function getCreateIndexSQLFlags(Index $index) { return $index->isUnique() ? 'UNIQUE ' : ''; } /** * Returns the SQL to create an unnamed primary key constraint. * * @param \Doctrine\DBAL\Schema\Index $index * @param \Doctrine\DBAL\Schema\Table|string $table * * @return string */ public function getCreatePrimaryKeySQL(Index $index, $table) { return 'ALTER TABLE ' . $table . ' ADD PRIMARY KEY (' . $this->getIndexFieldDeclarationListSQL($index->getQuotedColumns($this)) . ')'; } /** * Returns the SQL to create a named schema. * * @param string $schemaName * * @return string * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getCreateSchemaSQL($schemaName) { throw DBALException::notSupported(__METHOD__); } /** * Quotes a string so that it can be safely used as a table or column name, * even if it is a reserved word of the platform. This also detects identifier * chains separated by dot and quotes them independently. * * NOTE: Just because you CAN use quoted identifiers doesn't mean * you SHOULD use them. In general, they end up causing way more * problems than they solve. * * @param string $str The identifier name to be quoted. * * @return string The quoted identifier string. */ public function quoteIdentifier($str) { if (strpos($str, ".") !== false) { $parts = array_map(array($this, "quoteSingleIdentifier"), explode(".", $str)); return implode(".", $parts); } return $this->quoteSingleIdentifier($str); } /** * Quotes a single identifier (no dot chain separation). * * @param string $str The identifier name to be quoted. * * @return string The quoted identifier string. */ public function quoteSingleIdentifier($str) { $c = $this->getIdentifierQuoteCharacter(); return $c . str_replace($c, $c.$c, $str) . $c; } /** * Returns the SQL to create a new foreign key. * * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey The foreign key constraint. * @param \Doctrine\DBAL\Schema\Table|string $table The name of the table on which the foreign key is to be created. * * @return string */ public function getCreateForeignKeySQL(ForeignKeyConstraint $foreignKey, $table) { if ($table instanceof Table) { $table = $table->getQuotedName($this); } $query = 'ALTER TABLE ' . $table . ' ADD ' . $this->getForeignKeyDeclarationSQL($foreignKey); return $query; } /** * Gets the SQL statements for altering an existing table. * * This method returns an array of SQL statements, since some platforms need several statements. * * @param \Doctrine\DBAL\Schema\TableDiff $diff * * @return array * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getAlterTableSQL(TableDiff $diff) { throw DBALException::notSupported(__METHOD__); } /** * @param \Doctrine\DBAL\Schema\Column $column * @param \Doctrine\DBAL\Schema\TableDiff $diff * @param array $columnSql * * @return boolean */ protected function onSchemaAlterTableAddColumn(Column $column, TableDiff $diff, &$columnSql) { if (null === $this->_eventManager) { return false; } if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTableAddColumn)) { return false; } $eventArgs = new SchemaAlterTableAddColumnEventArgs($column, $diff, $this); $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableAddColumn, $eventArgs); $columnSql = array_merge($columnSql, $eventArgs->getSql()); return $eventArgs->isDefaultPrevented(); } /** * @param \Doctrine\DBAL\Schema\Column $column * @param \Doctrine\DBAL\Schema\TableDiff $diff * @param array $columnSql * * @return boolean */ protected function onSchemaAlterTableRemoveColumn(Column $column, TableDiff $diff, &$columnSql) { if (null === $this->_eventManager) { return false; } if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTableRemoveColumn)) { return false; } $eventArgs = new SchemaAlterTableRemoveColumnEventArgs($column, $diff, $this); $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableRemoveColumn, $eventArgs); $columnSql = array_merge($columnSql, $eventArgs->getSql()); return $eventArgs->isDefaultPrevented(); } /** * @param \Doctrine\DBAL\Schema\ColumnDiff $columnDiff * @param \Doctrine\DBAL\Schema\TableDiff $diff * @param array $columnSql * * @return boolean */ protected function onSchemaAlterTableChangeColumn(ColumnDiff $columnDiff, TableDiff $diff, &$columnSql) { if (null === $this->_eventManager) { return false; } if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTableChangeColumn)) { return false; } $eventArgs = new SchemaAlterTableChangeColumnEventArgs($columnDiff, $diff, $this); $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableChangeColumn, $eventArgs); $columnSql = array_merge($columnSql, $eventArgs->getSql()); return $eventArgs->isDefaultPrevented(); } /** * @param string $oldColumnName * @param \Doctrine\DBAL\Schema\Column $column * @param \Doctrine\DBAL\Schema\TableDiff $diff * @param array $columnSql * * @return boolean */ protected function onSchemaAlterTableRenameColumn($oldColumnName, Column $column, TableDiff $diff, &$columnSql) { if (null === $this->_eventManager) { return false; } if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTableRenameColumn)) { return false; } $eventArgs = new SchemaAlterTableRenameColumnEventArgs($oldColumnName, $column, $diff, $this); $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableRenameColumn, $eventArgs); $columnSql = array_merge($columnSql, $eventArgs->getSql()); return $eventArgs->isDefaultPrevented(); } /** * @param \Doctrine\DBAL\Schema\TableDiff $diff * @param array $sql * * @return boolean */ protected function onSchemaAlterTable(TableDiff $diff, &$sql) { if (null === $this->_eventManager) { return false; } if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTable)) { return false; } $eventArgs = new SchemaAlterTableEventArgs($diff, $this); $this->_eventManager->dispatchEvent(Events::onSchemaAlterTable, $eventArgs); $sql = array_merge($sql, $eventArgs->getSql()); return $eventArgs->isDefaultPrevented(); } /** * @param \Doctrine\DBAL\Schema\TableDiff $diff * * @return array */ protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) { $tableName = $diff->getName($this)->getQuotedName($this); $sql = array(); if ($this->supportsForeignKeyConstraints()) { foreach ($diff->removedForeignKeys as $foreignKey) { $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName); } foreach ($diff->changedForeignKeys as $foreignKey) { $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName); } } foreach ($diff->removedIndexes as $index) { $sql[] = $this->getDropIndexSQL($index, $tableName); } foreach ($diff->changedIndexes as $index) { $sql[] = $this->getDropIndexSQL($index, $tableName); } return $sql; } /** * @param \Doctrine\DBAL\Schema\TableDiff $diff * * @return array */ protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff) { $tableName = (false !== $diff->newName) ? $diff->getNewName()->getQuotedName($this) : $diff->getName($this)->getQuotedName($this); $sql = array(); if ($this->supportsForeignKeyConstraints()) { foreach ($diff->addedForeignKeys as $foreignKey) { $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName); } foreach ($diff->changedForeignKeys as $foreignKey) { $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName); } } foreach ($diff->addedIndexes as $index) { $sql[] = $this->getCreateIndexSQL($index, $tableName); } foreach ($diff->changedIndexes as $index) { $sql[] = $this->getCreateIndexSQL($index, $tableName); } foreach ($diff->renamedIndexes as $oldIndexName => $index) { $oldIndexName = new Identifier($oldIndexName); $sql = array_merge( $sql, $this->getRenameIndexSQL($oldIndexName->getQuotedName($this), $index, $tableName) ); } return $sql; } /** * Returns the SQL for renaming an index on a table. * * @param string $oldIndexName The name of the index to rename from. * @param \Doctrine\DBAL\Schema\Index $index The definition of the index to rename to. * @param string $tableName The table to rename the given index on. * * @return array The sequence of SQL statements for renaming the given index. */ protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) { return array( $this->getDropIndexSQL($oldIndexName, $tableName), $this->getCreateIndexSQL($index, $tableName) ); } /** * Common code for alter table statement generation that updates the changed Index and Foreign Key definitions. * * @param \Doctrine\DBAL\Schema\TableDiff $diff * * @return array */ protected function _getAlterTableIndexForeignKeySQL(TableDiff $diff) { return array_merge($this->getPreAlterTableIndexForeignKeySQL($diff), $this->getPostAlterTableIndexForeignKeySQL($diff)); } /** * Gets declaration of a number of fields in bulk. * * @param array $fields A multidimensional associative array. * The first dimension determines the field name, while the second * dimension is keyed with the name of the properties * of the field being declared as array indexes. Currently, the types * of supported field properties are as follows: * * length * Integer value that determines the maximum length of the text * field. If this argument is missing the field should be * declared to have the longest length allowed by the DBMS. * * default * Text 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. * charset * Text value with the default CHARACTER SET for this field. * collation * Text value with the default COLLATION for this field. * unique * unique constraint * * @return string */ public function getColumnDeclarationListSQL(array $fields) { $queryFields = array(); foreach ($fields as $fieldName => $field) { $queryFields[] = $this->getColumnDeclarationSQL($fieldName, $field); } return implode(', ', $queryFields); } /** * Obtains DBMS specific SQL code portion needed to declare a generic type * field to be used in statements like CREATE TABLE. * * @param string $name The name the field to be declared. * @param array $field An 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: * * length * Integer value that determines the maximum length of the text * field. If this argument is missing the field should be * declared to have the longest length allowed by the DBMS. * * default * Text 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. * charset * Text value with the default CHARACTER SET for this field. * collation * Text value with the default COLLATION for this field. * unique * unique constraint * check * column check constraint * columnDefinition * a string that defines the complete column * * @return string DBMS specific SQL code portion that should be used to declare the column. */ public function getColumnDeclarationSQL($name, array $field) { if (isset($field['columnDefinition'])) { $columnDef = $this->getCustomTypeDeclarationSQL($field); } else { $default = $this->getDefaultValueDeclarationSQL($field); $charset = (isset($field['charset']) && $field['charset']) ? ' ' . $this->getColumnCharsetDeclarationSQL($field['charset']) : ''; $collation = (isset($field['collation']) && $field['collation']) ? ' ' . $this->getColumnCollationDeclarationSQL($field['collation']) : ''; $notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : ''; $unique = (isset($field['unique']) && $field['unique']) ? ' ' . $this->getUniqueFieldDeclarationSQL() : ''; $check = (isset($field['check']) && $field['check']) ? ' ' . $field['check'] : ''; $typeDecl = $field['type']->getSqlDeclaration($field, $this); $columnDef = $typeDecl . $charset . $default . $notnull . $unique . $check . $collation; if ($this->supportsInlineColumnComments() && isset($field['comment']) && $field['comment'] !== '') { $columnDef .= " COMMENT " . $this->quoteStringLiteral($field['comment']); } } return $name . ' ' . $columnDef; } /** * Returns the SQL snippet that declares a floating point column of arbitrary precision. * * @param array $columnDef * * @return string */ public function getDecimalTypeDeclarationSQL(array $columnDef) { $columnDef['precision'] = ( ! isset($columnDef['precision']) || empty($columnDef['precision'])) ? 10 : $columnDef['precision']; $columnDef['scale'] = ( ! isset($columnDef['scale']) || empty($columnDef['scale'])) ? 0 : $columnDef['scale']; return 'NUMERIC(' . $columnDef['precision'] . ', ' . $columnDef['scale'] . ')'; } /** * Obtains DBMS specific SQL code portion needed to set a default value * declaration to be used in statements like CREATE TABLE. * * @param array $field The field definition array. * * @return string DBMS specific SQL code portion needed to set a default value. */ public function getDefaultValueDeclarationSQL($field) { $default = empty($field['notnull']) ? ' DEFAULT NULL' : ''; if (isset($field['default'])) { $default = " DEFAULT '".$field['default']."'"; if (isset($field['type'])) { if (in_array((string) $field['type'], array("Integer", "BigInt", "SmallInt"))) { $default = " DEFAULT ".$field['default']; } elseif (in_array((string) $field['type'], array('DateTime', 'DateTimeTz')) && $field['default'] == $this->getCurrentTimestampSQL()) { $default = " DEFAULT ".$this->getCurrentTimestampSQL(); } elseif ((string) $field['type'] == 'Time' && $field['default'] == $this->getCurrentTimeSQL()) { $default = " DEFAULT ".$this->getCurrentTimeSQL(); } elseif ((string) $field['type'] == 'Date' && $field['default'] == $this->getCurrentDateSQL()) { $default = " DEFAULT ".$this->getCurrentDateSQL(); } elseif ((string) $field['type'] == 'Boolean') { $default = " DEFAULT '" . $this->convertBooleans($field['default']) . "'"; } } } return $default; } /** * Obtains DBMS specific SQL code portion needed to set a CHECK constraint * declaration to be used in statements like CREATE TABLE. * * @param array $definition The check definition. * * @return string DBMS specific SQL code portion needed to set a CHECK constraint. */ public function getCheckDeclarationSQL(array $definition) { $constraints = array(); foreach ($definition as $field => $def) { if (is_string($def)) { $constraints[] = 'CHECK (' . $def . ')'; } else { if (isset($def['min'])) { $constraints[] = 'CHECK (' . $field . ' >= ' . $def['min'] . ')'; } if (isset($def['max'])) { $constraints[] = 'CHECK (' . $field . ' <= ' . $def['max'] . ')'; } } } return implode(', ', $constraints); } /** * Obtains DBMS specific SQL code portion needed to set a unique * constraint declaration to be used in statements like CREATE TABLE. * * @param string $name The name of the unique constraint. * @param \Doctrine\DBAL\Schema\Index $index The index definition. * * @return string DBMS specific SQL code portion needed to set a constraint. * * @throws \InvalidArgumentException */ public function getUniqueConstraintDeclarationSQL($name, Index $index) { $columns = $index->getQuotedColumns($this); $name = new Identifier($name); if (count($columns) === 0) { throw new \InvalidArgumentException("Incomplete definition. 'columns' required."); } return 'CONSTRAINT ' . $name->getQuotedName($this) . ' UNIQUE (' . $this->getIndexFieldDeclarationListSQL($columns) . ')' . $this->getPartialIndexSQL($index); } /** * Obtains DBMS specific SQL code portion needed to set an index * declaration to be used in statements like CREATE TABLE. * * @param string $name The name of the index. * @param \Doctrine\DBAL\Schema\Index $index The index definition. * * @return string DBMS specific SQL code portion needed to set an index. * * @throws \InvalidArgumentException */ public function getIndexDeclarationSQL($name, Index $index) { $columns = $index->getQuotedColumns($this); $name = new Identifier($name); if (count($columns) === 0) { throw new \InvalidArgumentException("Incomplete definition. 'columns' required."); } return $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name->getQuotedName($this) . ' (' . $this->getIndexFieldDeclarationListSQL($columns) . ')' . $this->getPartialIndexSQL($index); } /** * Obtains SQL code portion needed to create a custom column, * e.g. when a field has the "columnDefinition" keyword. * Only "AUTOINCREMENT" and "PRIMARY KEY" are added if appropriate. * * @param array $columnDef * * @return string */ public function getCustomTypeDeclarationSQL(array $columnDef) { return $columnDef['columnDefinition']; } /** * Obtains DBMS specific SQL code portion needed to set an index * declaration to be used in statements like CREATE TABLE. * * @param array $fields * * @return string */ public function getIndexFieldDeclarationListSQL(array $fields) { $ret = array(); foreach ($fields as $field => $definition) { if (is_array($definition)) { $ret[] = $field; } else { $ret[] = $definition; } } return implode(', ', $ret); } /** * Returns the required SQL string that fits between CREATE ... TABLE * to create the table as a temporary table. * * Should be overridden in driver classes to return the correct string for the * specific database type. * * The default is to return the string "TEMPORARY" - this will result in a * SQL error for any database that does not support temporary tables, or that * requires a different SQL command from "CREATE TEMPORARY TABLE". * * @return string The string required to be placed between "CREATE" and "TABLE" * to generate a temporary table, if possible. */ public function getTemporaryTableSQL() { return 'TEMPORARY'; } /** * Some vendors require temporary table names to be qualified specially. * * @param string $tableName * * @return string */ public function getTemporaryTableName($tableName) { return $tableName; } /** * Obtain DBMS specific SQL code portion needed to set the FOREIGN KEY constraint * of a field declaration to be used in statements like CREATE TABLE. * * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey * * @return string DBMS specific SQL code portion needed to set the FOREIGN KEY constraint * of a field declaration. */ public function getForeignKeyDeclarationSQL(ForeignKeyConstraint $foreignKey) { $sql = $this->getForeignKeyBaseDeclarationSQL($foreignKey); $sql .= $this->getAdvancedForeignKeyOptionsSQL($foreignKey); return $sql; } /** * Returns the FOREIGN KEY query section dealing with non-standard options * as MATCH, INITIALLY DEFERRED, ON UPDATE, ... * * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey The foreign key definition. * * @return string */ public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey) { $query = ''; if ($this->supportsForeignKeyOnUpdate() && $foreignKey->hasOption('onUpdate')) { $query .= ' ON UPDATE ' . $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onUpdate')); } if ($foreignKey->hasOption('onDelete')) { $query .= ' ON DELETE ' . $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onDelete')); } return $query; } /** * Returns the given referential action in uppercase if valid, otherwise throws an exception. * * @param string $action The foreign key referential action. * * @return string * * @throws \InvalidArgumentException if unknown referential action given */ public function getForeignKeyReferentialActionSQL($action) { $upper = strtoupper($action); switch ($upper) { case 'CASCADE': case 'SET NULL': case 'NO ACTION': case 'RESTRICT': case 'SET DEFAULT': return $upper; default: throw new \InvalidArgumentException('Invalid foreign key action: ' . $upper); } } /** * Obtains DBMS specific SQL code portion needed to set the FOREIGN KEY constraint * of a field declaration to be used in statements like CREATE TABLE. * * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey * * @return string * * @throws \InvalidArgumentException */ public function getForeignKeyBaseDeclarationSQL(ForeignKeyConstraint $foreignKey) { $sql = ''; if (strlen($foreignKey->getName())) { $sql .= 'CONSTRAINT ' . $foreignKey->getQuotedName($this) . ' '; } $sql .= 'FOREIGN KEY ('; if (count($foreignKey->getLocalColumns()) === 0) { throw new \InvalidArgumentException("Incomplete definition. 'local' required."); } if (count($foreignKey->getForeignColumns()) === 0) { throw new \InvalidArgumentException("Incomplete definition. 'foreign' required."); } if (strlen($foreignKey->getForeignTableName()) === 0) { throw new \InvalidArgumentException("Incomplete definition. 'foreignTable' required."); } $sql .= implode(', ', $foreignKey->getQuotedLocalColumns($this)) . ') REFERENCES ' . $foreignKey->getQuotedForeignTableName($this) . ' (' . implode(', ', $foreignKey->getQuotedForeignColumns($this)) . ')'; return $sql; } /** * Obtains DBMS specific SQL code portion needed to set the UNIQUE constraint * of a field declaration to be used in statements like CREATE TABLE. * * @return string DBMS specific SQL code portion needed to set the UNIQUE constraint * of a field declaration. */ public function getUniqueFieldDeclarationSQL() { return 'UNIQUE'; } /** * Obtains DBMS specific SQL code portion needed to set the CHARACTER SET * of a field declaration to be used in statements like CREATE TABLE. * * @param string $charset The name of the charset. * * @return string DBMS specific SQL code portion needed to set the CHARACTER SET * of a field declaration. */ public function getColumnCharsetDeclarationSQL($charset) { return ''; } /** * Obtains 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 The name of the collation. * * @return string DBMS specific SQL code portion needed to set the COLLATION * of a field declaration. */ public function getColumnCollationDeclarationSQL($collation) { return $this->supportsColumnCollation() ? 'COLLATE ' . $collation : ''; } /** * Whether the platform prefers sequences for ID generation. * Subclasses should override this method to return TRUE if they prefer sequences. * * @return boolean */ public function prefersSequences() { return false; } /** * Whether the platform prefers identity columns (eg. autoincrement) for ID generation. * Subclasses should override this method to return TRUE if they prefer identity columns. * * @return boolean */ public function prefersIdentityColumns() { return false; } /** * Some platforms need the boolean values to be converted. * * The default conversion in this implementation converts to integers (false => 0, true => 1). * * Note: if the input is not a boolean the original input might be returned. * * There are two contexts when converting booleans: Literals and Prepared Statements. * This method should handle the literal case * * @param mixed $item A boolean or an array of them. * * @return mixed A boolean database value or an array of them. */ public function convertBooleans($item) { if (is_array($item)) { foreach ($item as $k => $value) { if (is_bool($value)) { $item[$k] = (int) $value; } } } elseif (is_bool($item)) { $item = (int) $item; } return $item; } /** * Some platforms have boolean literals that needs to be correctly converted * * The default conversion tries to convert value into bool "(bool)$item" * * @param mixed $item * * @return bool|null */ public function convertFromBoolean($item) { return null === $item ? null: (bool) $item ; } /** * This method should handle the prepared statements case. When there is no * distinction, it's OK to use the same method. * * Note: if the input is not a boolean the original input might be returned. * * @param mixed $item A boolean or an array of them. * * @return mixed A boolean database value or an array of them. */ public function convertBooleansToDatabaseValue($item) { return $this->convertBooleans($item); } /** * Returns the SQL specific for the platform to get the current date. * * @return string */ public function getCurrentDateSQL() { return 'CURRENT_DATE'; } /** * Returns the SQL specific for the platform to get the current time. * * @return string */ public function getCurrentTimeSQL() { return 'CURRENT_TIME'; } /** * Returns the SQL specific for the platform to get the current timestamp * * @return string */ public function getCurrentTimestampSQL() { return 'CURRENT_TIMESTAMP'; } /** * Returns the SQL for a given transaction isolation level Connection constant. * * @param integer $level * * @return string * * @throws \InvalidArgumentException */ protected function _getTransactionIsolationLevelSQL($level) { switch ($level) { case Connection::TRANSACTION_READ_UNCOMMITTED: return 'READ UNCOMMITTED'; case Connection::TRANSACTION_READ_COMMITTED: return 'READ COMMITTED'; case Connection::TRANSACTION_REPEATABLE_READ: return 'REPEATABLE READ'; case Connection::TRANSACTION_SERIALIZABLE: return 'SERIALIZABLE'; default: throw new \InvalidArgumentException('Invalid isolation level:' . $level); } } /** * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getListDatabasesSQL() { throw DBALException::notSupported(__METHOD__); } /** * Returns the SQL statement for retrieving the namespaces defined in the database. * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getListNamespacesSQL() { throw DBALException::notSupported(__METHOD__); } /** * @param string $database * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getListSequencesSQL($database) { throw DBALException::notSupported(__METHOD__); } /** * @param string $table * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getListTableConstraintsSQL($table) { throw DBALException::notSupported(__METHOD__); } /** * @param string $table * @param string|null $database * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getListTableColumnsSQL($table, $database = null) { throw DBALException::notSupported(__METHOD__); } /** * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getListTablesSQL() { throw DBALException::notSupported(__METHOD__); } /** * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getListUsersSQL() { throw DBALException::notSupported(__METHOD__); } /** * Returns the SQL to list all views of a database or user. * * @param string $database * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getListViewsSQL($database) { throw DBALException::notSupported(__METHOD__); } /** * Returns the list of indexes for the current database. * * The current database parameter is optional but will always be passed * when using the SchemaManager API and is the database the given table is in. * * Attention: Some platforms only support currentDatabase when they * are connected with that database. Cross-database information schema * requests may be impossible. * * @param string $table * @param string $currentDatabase * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getListTableIndexesSQL($table, $currentDatabase = null) { throw DBALException::notSupported(__METHOD__); } /** * @param string $table * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getListTableForeignKeysSQL($table) { throw DBALException::notSupported(__METHOD__); } /** * @param string $name * @param string $sql * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getCreateViewSQL($name, $sql) { throw DBALException::notSupported(__METHOD__); } /** * @param string $name * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDropViewSQL($name) { throw DBALException::notSupported(__METHOD__); } /** * Returns the SQL snippet to drop an existing sequence. * * @param Sequence|string $sequence * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDropSequenceSQL($sequence) { throw DBALException::notSupported(__METHOD__); } /** * @param string $sequenceName * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getSequenceNextValSQL($sequenceName) { throw DBALException::notSupported(__METHOD__); } /** * Returns the SQL to create a new database. * * @param string $database The name of the database that should be created. * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getCreateDatabaseSQL($database) { throw DBALException::notSupported(__METHOD__); } /** * Returns the SQL to set the transaction isolation level. * * @param integer $level * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getSetTransactionIsolationSQL($level) { throw DBALException::notSupported(__METHOD__); } /** * Obtains DBMS specific SQL to be used to create datetime fields in * statements like CREATE TABLE. * * @param array $fieldDeclaration * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) { throw DBALException::notSupported(__METHOD__); } /** * Obtains DBMS specific SQL to be used to create datetime with timezone offset fields. * * @param array $fieldDeclaration * * @return string */ public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration) { return $this->getDateTimeTypeDeclarationSQL($fieldDeclaration); } /** * Obtains DBMS specific SQL to be used to create date fields in statements * like CREATE TABLE. * * @param array $fieldDeclaration * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDateTypeDeclarationSQL(array $fieldDeclaration) { throw DBALException::notSupported(__METHOD__); } /** * Obtains DBMS specific SQL to be used to create time fields in statements * like CREATE TABLE. * * @param array $fieldDeclaration * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getTimeTypeDeclarationSQL(array $fieldDeclaration) { throw DBALException::notSupported(__METHOD__); } /** * @param array $fieldDeclaration * * @return string */ public function getFloatDeclarationSQL(array $fieldDeclaration) { return 'DOUBLE PRECISION'; } /** * Gets the default transaction isolation level of the platform. * * @return integer The default isolation level. * * @see Doctrine\DBAL\Connection\TRANSACTION_* constants. */ public function getDefaultTransactionIsolationLevel() { return Connection::TRANSACTION_READ_COMMITTED; } /* supports*() methods */ /** * Whether the platform supports sequences. * * @return boolean */ public function supportsSequences() { return false; } /** * Whether the platform supports identity columns. * * Identity columns are columns that receive an auto-generated value from the * database on insert of a row. * * @return boolean */ public function supportsIdentityColumns() { return false; } /** * Whether the platform emulates identity columns through sequences. * * Some platforms that do not support identity columns natively * but support sequences can emulate identity columns by using * sequences. * * @return boolean */ public function usesSequenceEmulatedIdentityColumns() { return false; } /** * Returns the name of the sequence for a particular identity column in a particular table. * * @param string $tableName The name of the table to return the sequence name for. * @param string $columnName The name of the identity column in the table to return the sequence name for. * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. * * @see usesSequenceEmulatedIdentityColumns */ public function getIdentitySequenceName($tableName, $columnName) { throw DBALException::notSupported(__METHOD__); } /** * Whether the platform supports indexes. * * @return boolean */ public function supportsIndexes() { return true; } /** * Whether the platform supports partial indexes. * * @return boolean */ public function supportsPartialIndexes() { return false; } /** * Whether the platform supports altering tables. * * @return boolean */ public function supportsAlterTable() { return true; } /** * Whether the platform supports transactions. * * @return boolean */ public function supportsTransactions() { return true; } /** * Whether the platform supports savepoints. * * @return boolean */ public function supportsSavepoints() { return true; } /** * Whether the platform supports releasing savepoints. * * @return boolean */ public function supportsReleaseSavepoints() { return $this->supportsSavepoints(); } /** * Whether the platform supports primary key constraints. * * @return boolean */ public function supportsPrimaryConstraints() { return true; } /** * Whether the platform supports foreign key constraints. * * @return boolean */ public function supportsForeignKeyConstraints() { return true; } /** * Whether this platform supports onUpdate in foreign key constraints. * * @return boolean */ public function supportsForeignKeyOnUpdate() { return ($this->supportsForeignKeyConstraints() && true); } /** * Whether the platform supports database schemas. * * @return boolean */ public function supportsSchemas() { return false; } /** * Whether this platform can emulate schemas. * * Platforms that either support or emulate schemas don't automatically * filter a schema for the namespaced elements in {@link * AbstractManager#createSchema}. * * @return boolean */ public function canEmulateSchemas() { return false; } /** * Returns the default schema name. * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDefaultSchemaName() { throw DBALException::notSupported(__METHOD__); } /** * Whether this platform supports create database. * * Some databases don't allow to create and drop databases at all or only with certain tools. * * @return boolean */ public function supportsCreateDropDatabase() { return true; } /** * Whether the platform supports getting the affected rows of a recent update/delete type query. * * @return boolean */ public function supportsGettingAffectedRows() { return true; } /** * Whether this platform support to add inline column comments as postfix. * * @return boolean */ public function supportsInlineColumnComments() { return false; } /** * Whether this platform support the proprietary syntax "COMMENT ON asset". * * @return boolean */ public function supportsCommentOnStatement() { return false; } /** * Does this platform have native guid type. * * @return boolean */ public function hasNativeGuidType() { return false; } /** * Does this platform have native JSON type. * * @return boolean */ public function hasNativeJsonType() { return false; } /** * @deprecated * @todo Remove in 3.0 */ public function getIdentityColumnNullInsertSQL() { return ""; } /** * Whether this platform supports views. * * @return boolean */ public function supportsViews() { return true; } /** * Does this platform support column collation? * * @return boolean */ public function supportsColumnCollation() { return false; } /** * Gets the format string, as accepted by the date() function, that describes * the format of a stored datetime value of this platform. * * @return string The format string. */ public function getDateTimeFormatString() { return 'Y-m-d H:i:s'; } /** * Gets the format string, as accepted by the date() function, that describes * the format of a stored datetime with timezone value of this platform. * * @return string The format string. */ public function getDateTimeTzFormatString() { return 'Y-m-d H:i:s'; } /** * Gets the format string, as accepted by the date() function, that describes * the format of a stored date value of this platform. * * @return string The format string. */ public function getDateFormatString() { return 'Y-m-d'; } /** * Gets the format string, as accepted by the date() function, that describes * the format of a stored time value of this platform. * * @return string The format string. */ public function getTimeFormatString() { return 'H:i:s'; } /** * Adds an driver-specific LIMIT clause to the query. * * @param string $query * @param integer|null $limit * @param integer|null $offset * * @return string * * @throws DBALException */ final public function modifyLimitQuery($query, $limit, $offset = null) { if ($limit !== null) { $limit = (int) $limit; } if ($offset !== null) { $offset = (int) $offset; if ($offset < 0) { throw new DBALException("LIMIT argument offset=$offset is not valid"); } if ($offset > 0 && ! $this->supportsLimitOffset()) { throw new DBALException(sprintf("Platform %s does not support offset values in limit queries.", $this->getName())); } } return $this->doModifyLimitQuery($query, $limit, $offset); } /** * Adds an driver-specific LIMIT clause to the query. * * @param string $query * @param integer|null $limit * @param integer|null $offset * * @return string */ protected function doModifyLimitQuery($query, $limit, $offset) { if ($limit !== null) { $query .= ' LIMIT ' . $limit; } if ($offset !== null) { $query .= ' OFFSET ' . $offset; } return $query; } /** * Whether the database platform support offsets in modify limit clauses. * * @return boolean */ public function supportsLimitOffset() { return true; } /** * Gets the character casing of a column in an SQL result set of this platform. * * @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 $column; } /** * Makes any fixes to a name of a schema element (table, sequence, ...) that are required * by restrictions of the platform, like a maximum length. * * @param string $schemaElementName * * @return string */ public function fixSchemaElementName($schemaElementName) { return $schemaElementName; } /** * Maximum length of any given database identifier, like tables or column names. * * @return integer */ public function getMaxIdentifierLength() { return 63; } /** * Returns the insert SQL for an empty insert statement. * * @param string $tableName * @param string $identifierColumnName * * @return string */ public function getEmptyIdentityInsertSQL($tableName, $identifierColumnName) { return 'INSERT INTO ' . $tableName . ' (' . $identifierColumnName . ') VALUES (null)'; } /** * Generates a Truncate Table SQL statement for a given table. * * Cascade is not supported on many platforms but would optionally cascade the truncate by * following the foreign keys. * * @param string $tableName * @param boolean $cascade * * @return string */ public function getTruncateTableSQL($tableName, $cascade = false) { $tableIdentifier = new Identifier($tableName); return 'TRUNCATE ' . $tableIdentifier->getQuotedName($this); } /** * This is for test reasons, many vendors have special requirements for dummy statements. * * @return string */ public function getDummySelectSQL() { return 'SELECT 1'; } /** * Returns the SQL to create a new savepoint. * * @param string $savepoint * * @return string */ public function createSavePoint($savepoint) { return 'SAVEPOINT ' . $savepoint; } /** * Returns the SQL to release a savepoint. * * @param string $savepoint * * @return string */ public function releaseSavePoint($savepoint) { return 'RELEASE SAVEPOINT ' . $savepoint; } /** * Returns the SQL to rollback a savepoint. * * @param string $savepoint * * @return string */ public function rollbackSavePoint($savepoint) { return 'ROLLBACK TO SAVEPOINT ' . $savepoint; } /** * Returns the keyword list instance of this platform. * * @return \Doctrine\DBAL\Platforms\Keywords\KeywordList * * @throws \Doctrine\DBAL\DBALException If no keyword list is specified. */ final public function getReservedKeywordsList() { // Check for an existing instantiation of the keywords class. if ($this->_keywords) { return $this->_keywords; } $class = $this->getReservedKeywordsClass(); $keywords = new $class; if ( ! $keywords instanceof \Doctrine\DBAL\Platforms\Keywords\KeywordList) { throw DBALException::notSupported(__METHOD__); } // Store the instance so it doesn't need to be generated on every request. $this->_keywords = $keywords; return $keywords; } /** * Returns the class name of the reserved keywords list. * * @return string * * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ protected function getReservedKeywordsClass() { throw DBALException::notSupported(__METHOD__); } /** * Quotes a literal string. * This method is NOT meant to fix SQL injections! * It is only meant to escape this platform's string literal * quote character inside the given literal string. * * @param string $str The literal string to be quoted. * * @return string The quoted literal string. */ public function quoteStringLiteral($str) { $c = $this->getStringLiteralQuoteCharacter(); return $c . str_replace($c, $c . $c, $str) . $c; } /** * Gets the character used for string literal quoting. * * @return string */ public function getStringLiteralQuoteCharacter() { return "'"; } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/DB2Platform.php000066400000000000000000000611731313473450000222670ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\ColumnDiff; use Doctrine\DBAL\Schema\Identifier; use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\Types\Type; class DB2Platform extends AbstractPlatform { /** * {@inheritdoc} */ public function getBinaryMaxLength() { return 32704; } /** * {@inheritdoc} */ public function getBinaryDefaultLength() { return 1; } /** * {@inheritDoc} */ public function getBlobTypeDeclarationSQL(array $field) { // todo blob(n) with $field['length']; return 'BLOB(1M)'; } /** * {@inheritDoc} */ public function initializeDoctrineTypeMappings() { $this->doctrineTypeMapping = array( 'smallint' => 'smallint', 'bigint' => 'bigint', 'integer' => 'integer', 'time' => 'time', 'date' => 'date', 'varchar' => 'string', 'character' => 'string', 'varbinary' => 'binary', 'binary' => 'binary', 'clob' => 'text', 'blob' => 'blob', 'decimal' => 'decimal', 'double' => 'float', 'real' => 'float', 'timestamp' => 'datetime', ); } /** * {@inheritdoc} */ public function isCommentedDoctrineType(Type $doctrineType) { if ($doctrineType->getName() === Type::BOOLEAN) { // We require a commented boolean type in order to distinguish between boolean and smallint // as both (have to) map to the same native type. return true; } return parent::isCommentedDoctrineType($doctrineType); } /** * {@inheritDoc} */ protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) { return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'); } /** * {@inheritdoc} */ protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) { return $fixed ? 'BINARY(' . ($length ?: 255) . ')' : 'VARBINARY(' . ($length ?: 255) . ')'; } /** * {@inheritDoc} */ public function getClobTypeDeclarationSQL(array $field) { // todo clob(n) with $field['length']; return 'CLOB(1M)'; } /** * {@inheritDoc} */ public function getName() { return 'db2'; } /** * {@inheritDoc} */ public function getBooleanTypeDeclarationSQL(array $columnDef) { return 'SMALLINT'; } /** * {@inheritDoc} */ public function getIntegerTypeDeclarationSQL(array $columnDef) { return 'INTEGER' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef); } /** * {@inheritDoc} */ public function getBigIntTypeDeclarationSQL(array $columnDef) { return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef); } /** * {@inheritDoc} */ public function getSmallIntTypeDeclarationSQL(array $columnDef) { return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef); } /** * {@inheritDoc} */ protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) { $autoinc = ''; if ( ! empty($columnDef['autoincrement'])) { $autoinc = ' GENERATED BY DEFAULT AS IDENTITY'; } return $autoinc; } /** * {@inheritdoc} */ public function getBitAndComparisonExpression($value1, $value2) { return 'BITAND(' . $value1 . ', ' . $value2 . ')'; } /** * {@inheritdoc} */ public function getBitOrComparisonExpression($value1, $value2) { return 'BITOR(' . $value1 . ', ' . $value2 . ')'; } /** * {@inheritdoc} */ protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) { switch ($unit) { case self::DATE_INTERVAL_UNIT_WEEK: $interval *= 7; $unit = self::DATE_INTERVAL_UNIT_DAY; break; case self::DATE_INTERVAL_UNIT_QUARTER: $interval *= 3; $unit = self::DATE_INTERVAL_UNIT_MONTH; break; } return $date . ' ' . $operator . ' ' . $interval . ' ' . $unit; } /** * {@inheritdoc} */ public function getDateDiffExpression($date1, $date2) { return 'DAYS(' . $date1 . ') - DAYS(' . $date2 . ')'; } /** * {@inheritDoc} */ public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) { if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] == true) { return "TIMESTAMP(0) WITH DEFAULT"; } return 'TIMESTAMP(0)'; } /** * {@inheritDoc} */ public function getDateTypeDeclarationSQL(array $fieldDeclaration) { return 'DATE'; } /** * {@inheritDoc} */ public function getTimeTypeDeclarationSQL(array $fieldDeclaration) { return 'TIME'; } /** * {@inheritdoc} */ public function getTruncateTableSQL($tableName, $cascade = false) { $tableIdentifier = new Identifier($tableName); return 'TRUNCATE ' . $tableIdentifier->getQuotedName($this) . ' IMMEDIATE'; } /** * This code fragment is originally from the Zend_Db_Adapter_Db2 class, but has been edited. * * @license New BSD License * * @param string $table * @param string $database * * @return string */ public function getListTableColumnsSQL($table, $database = null) { $table = $this->quoteStringLiteral($table); // We do the funky subquery and join syscat.columns.default this crazy way because // as of db2 v10, the column is CLOB(64k) and the distinct operator won't allow a CLOB, // it wants shorter stuff like a varchar. return " SELECT cols.default, subq.* FROM ( SELECT DISTINCT c.tabschema, c.tabname, c.colname, c.colno, c.typename, c.nulls, c.length, c.scale, c.identity, tc.type AS tabconsttype, c.remarks AS comment, k.colseq, CASE WHEN c.generated = 'D' THEN 1 ELSE 0 END AS autoincrement 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 ) subq JOIN syscat.columns cols ON subq.tabschema = cols.tabschema AND subq.tabname = cols.tabname AND subq.colno = cols.colno ORDER BY subq.colno "; } /** * {@inheritDoc} */ public function getListTablesSQL() { return "SELECT NAME FROM SYSIBM.SYSTABLES WHERE TYPE = 'T'"; } /** * {@inheritDoc} */ public function getListViewsSQL($database) { return "SELECT NAME, TEXT FROM SYSIBM.SYSVIEWS"; } /** * {@inheritDoc} */ public function getListTableIndexesSQL($table, $currentDatabase = null) { $table = $this->quoteStringLiteral($table); return "SELECT idx.INDNAME AS key_name, idxcol.COLNAME AS column_name, CASE WHEN idx.UNIQUERULE = 'P' THEN 1 ELSE 0 END AS primary, CASE WHEN idx.UNIQUERULE = 'D' THEN 1 ELSE 0 END AS non_unique FROM SYSCAT.INDEXES AS idx JOIN SYSCAT.INDEXCOLUSE AS idxcol ON idx.INDSCHEMA = idxcol.INDSCHEMA AND idx.INDNAME = idxcol.INDNAME WHERE idx.TABNAME = UPPER(" . $table . ") ORDER BY idxcol.COLSEQ ASC"; } /** * {@inheritDoc} */ public function getListTableForeignKeysSQL($table) { $table = $this->quoteStringLiteral($table); return "SELECT fkcol.COLNAME AS local_column, fk.REFTABNAME AS foreign_table, pkcol.COLNAME AS foreign_column, fk.CONSTNAME AS index_name, CASE WHEN fk.UPDATERULE = 'R' THEN 'RESTRICT' ELSE NULL END AS on_update, CASE WHEN fk.DELETERULE = 'C' THEN 'CASCADE' WHEN fk.DELETERULE = 'N' THEN 'SET NULL' WHEN fk.DELETERULE = 'R' THEN 'RESTRICT' ELSE NULL END AS on_delete FROM SYSCAT.REFERENCES AS fk JOIN SYSCAT.KEYCOLUSE AS fkcol ON fk.CONSTNAME = fkcol.CONSTNAME AND fk.TABSCHEMA = fkcol.TABSCHEMA AND fk.TABNAME = fkcol.TABNAME JOIN SYSCAT.KEYCOLUSE AS pkcol ON fk.REFKEYNAME = pkcol.CONSTNAME AND fk.REFTABSCHEMA = pkcol.TABSCHEMA AND fk.REFTABNAME = pkcol.TABNAME WHERE fk.TABNAME = UPPER(" . $table . ") ORDER BY fkcol.COLSEQ ASC"; } /** * {@inheritDoc} */ public function getCreateViewSQL($name, $sql) { return "CREATE VIEW ".$name." AS ".$sql; } /** * {@inheritDoc} */ public function getDropViewSQL($name) { return "DROP VIEW ".$name; } /** * {@inheritDoc} */ public function getCreateDatabaseSQL($database) { return "CREATE DATABASE ".$database; } /** * {@inheritDoc} */ public function getDropDatabaseSQL($database) { return "DROP DATABASE " . $database; } /** * {@inheritDoc} */ public function supportsCreateDropDatabase() { return false; } /** * {@inheritDoc} */ public function supportsReleaseSavepoints() { return false; } /** * {@inheritdoc} */ public function supportsCommentOnStatement() { return true; } /** * {@inheritDoc} */ public function getCurrentDateSQL() { return 'CURRENT DATE'; } /** * {@inheritDoc} */ public function getCurrentTimeSQL() { return 'CURRENT TIME'; } /** * {@inheritDoc} */ public function getCurrentTimestampSQL() { return "CURRENT TIMESTAMP"; } /** * {@inheritDoc} */ public function getIndexDeclarationSQL($name, Index $index) { // Index declaration in statements like CREATE TABLE is not supported. throw DBALException::notSupported(__METHOD__); } /** * {@inheritDoc} */ 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 $definition) { $sqls[] = $this->getCreateIndexSQL($definition, $tableName); } return $sqls; } /** * {@inheritDoc} */ public function getAlterTableSQL(TableDiff $diff) { $sql = array(); $columnSql = array(); $commentsSQL = array(); $queryParts = array(); foreach ($diff->addedColumns as $column) { if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { continue; } $columnDef = $column->toArray(); $queryPart = 'ADD COLUMN ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnDef); // Adding non-nullable columns to a table requires a default value to be specified. if ( ! empty($columnDef['notnull']) && ! isset($columnDef['default']) && empty($columnDef['autoincrement']) ) { $queryPart .= ' WITH DEFAULT'; } $queryParts[] = $queryPart; $comment = $this->getColumnComment($column); if (null !== $comment && '' !== $comment) { $commentsSQL[] = $this->getCommentOnColumnSQL( $diff->getName($this)->getQuotedName($this), $column->getQuotedName($this), $comment ); } } 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; } if ($columnDiff->hasChanged('comment')) { $commentsSQL[] = $this->getCommentOnColumnSQL( $diff->getName($this)->getQuotedName($this), $columnDiff->column->getQuotedName($this), $this->getColumnComment($columnDiff->column) ); if (count($columnDiff->changedProperties) === 1) { continue; } } $this->gatherAlterColumnSQL($diff->fromTable, $columnDiff, $sql, $queryParts); } foreach ($diff->renamedColumns as $oldColumnName => $column) { if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { continue; } $oldColumnName = new Identifier($oldColumnName); $queryParts[] = 'RENAME COLUMN ' . $oldColumnName->getQuotedName($this) . ' TO ' . $column->getQuotedName($this); } $tableSql = array(); if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { if (count($queryParts) > 0) { $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . implode(" ", $queryParts); } // Some table alteration operations require a table reorganization. if ( ! empty($diff->removedColumns) || ! empty($diff->changedColumns)) { $sql[] = "CALL SYSPROC.ADMIN_CMD ('REORG TABLE " . $diff->getName($this)->getQuotedName($this) . "')"; } $sql = array_merge($sql, $commentsSQL); if ($diff->newName !== false) { $sql[] = 'RENAME TABLE ' . $diff->getName($this)->getQuotedName($this) . ' TO ' . $diff->getNewName()->getQuotedName($this); } $sql = array_merge( $this->getPreAlterTableIndexForeignKeySQL($diff), $sql, $this->getPostAlterTableIndexForeignKeySQL($diff) ); } return array_merge($sql, $tableSql, $columnSql); } /** * Gathers the table alteration SQL for a given column diff. * * @param Table $table The table to gather the SQL for. * @param ColumnDiff $columnDiff The column diff to evaluate. * @param array $sql The sequence of table alteration statements to fill. * @param array $queryParts The sequence of column alteration clauses to fill. */ private function gatherAlterColumnSQL(Table $table, ColumnDiff $columnDiff, array &$sql, array &$queryParts) { $alterColumnClauses = $this->getAlterColumnClausesSQL($columnDiff); if (empty($alterColumnClauses)) { return; } // If we have a single column alteration, we can append the clause to the main query. if (count($alterColumnClauses) === 1) { $queryParts[] = current($alterColumnClauses); return; } // We have multiple alterations for the same column, // so we need to trigger a complete ALTER TABLE statement // for each ALTER COLUMN clause. foreach ($alterColumnClauses as $alterColumnClause) { $sql[] = 'ALTER TABLE ' . $table->getQuotedName($this) . ' ' . $alterColumnClause; } } /** * Returns the ALTER COLUMN SQL clauses for altering a column described by the given column diff. * * @param ColumnDiff $columnDiff The column diff to evaluate. * * @return array */ private function getAlterColumnClausesSQL(ColumnDiff $columnDiff) { $column = $columnDiff->column->toArray(); $alterClause = 'ALTER COLUMN ' . $columnDiff->column->getQuotedName($this); if ($column['columnDefinition']) { return array($alterClause . ' ' . $column['columnDefinition']); } $clauses = array(); if ($columnDiff->hasChanged('type') || $columnDiff->hasChanged('length') || $columnDiff->hasChanged('precision') || $columnDiff->hasChanged('scale') || $columnDiff->hasChanged('fixed') ) { $clauses[] = $alterClause . ' SET DATA TYPE ' . $column['type']->getSQLDeclaration($column, $this); } if ($columnDiff->hasChanged('notnull')) { $clauses[] = $column['notnull'] ? $alterClause . ' SET NOT NULL' : $alterClause . ' DROP NOT NULL'; } if ($columnDiff->hasChanged('default')) { if (isset($column['default'])) { $defaultClause = $this->getDefaultValueDeclarationSQL($column); if ($defaultClause) { $clauses[] = $alterClause . ' SET' . $defaultClause; } } else { $clauses[] = $alterClause . ' DROP DEFAULT'; } } return $clauses; } /** * {@inheritDoc} */ protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) { $sql = array(); $table = $diff->getName($this)->getQuotedName($this); foreach ($diff->removedIndexes as $remKey => $remIndex) { foreach ($diff->addedIndexes as $addKey => $addIndex) { if ($remIndex->getColumns() == $addIndex->getColumns()) { if ($remIndex->isPrimary()) { $sql[] = 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY'; } elseif ($remIndex->isUnique()) { $sql[] = 'ALTER TABLE ' . $table . ' DROP UNIQUE ' . $remIndex->getQuotedName($this); } else { $sql[] = $this->getDropIndexSQL($remIndex, $table); } $sql[] = $this->getCreateIndexSQL($addIndex, $table); unset($diff->removedIndexes[$remKey]); unset($diff->addedIndexes[$addKey]); break; } } } $sql = array_merge($sql, parent::getPreAlterTableIndexForeignKeySQL($diff)); return $sql; } /** * {@inheritdoc} */ protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) { if (strpos($tableName, '.') !== false) { list($schema) = explode('.', $tableName); $oldIndexName = $schema . '.' . $oldIndexName; } return array('RENAME INDEX ' . $oldIndexName . ' TO ' . $index->getQuotedName($this)); } /** * {@inheritDoc} */ public function getDefaultValueDeclarationSQL($field) { if ( ! empty($field['autoincrement'])) { return ''; } if (isset($field['version']) && $field['version']) { if ((string) $field['type'] != "DateTime") { $field['default'] = "1"; } } return parent::getDefaultValueDeclarationSQL($field); } /** * {@inheritDoc} */ public function getEmptyIdentityInsertSQL($tableName, $identifierColumnName) { return 'INSERT INTO ' . $tableName . ' (' . $identifierColumnName . ') VALUES (DEFAULT)'; } /** * {@inheritDoc} */ public function getCreateTemporaryTableSnippetSQL() { return "DECLARE GLOBAL TEMPORARY TABLE"; } /** * {@inheritDoc} */ public function getTemporaryTableName($tableName) { return "SESSION." . $tableName; } /** * {@inheritDoc} */ protected function doModifyLimitQuery($query, $limit, $offset = null) { $where = array(); if ($offset > 0) { $where[] = sprintf('db22.DC_ROWNUM >= %d', $offset + 1); } if ($limit !== null) { $where[] = sprintf('db22.DC_ROWNUM <= %d', $offset + $limit); } if (empty($where)) { return $query; } // Todo OVER() needs ORDER BY data! return sprintf( 'SELECT db22.* FROM (SELECT db21.*, ROW_NUMBER() OVER() AS DC_ROWNUM FROM (%s) db21) db22 WHERE %s', $query, implode(' AND ', $where) ); } /** * {@inheritDoc} */ public function getLocateExpression($str, $substr, $startPos = false) { if ($startPos == false) { return 'LOCATE(' . $substr . ', ' . $str . ')'; } return 'LOCATE(' . $substr . ', ' . $str . ', '.$startPos.')'; } /** * {@inheritDoc} */ public function getSubstringExpression($value, $from, $length = null) { if ($length === null) { return 'SUBSTR(' . $value . ', ' . $from . ')'; } return 'SUBSTR(' . $value . ', ' . $from . ', ' . $length . ')'; } /** * {@inheritDoc} */ public function supportsIdentityColumns() { return true; } /** * {@inheritDoc} */ public function prefersIdentityColumns() { return true; } /** * {@inheritDoc} * * DB2 returns all column names in SQL result sets in uppercase. */ public function getSQLResultCasing($column) { return strtoupper($column); } /** * {@inheritDoc} */ public function getForUpdateSQL() { return ' WITH RR USE AND KEEP UPDATE LOCKS'; } /** * {@inheritDoc} */ public function getDummySelectSQL() { return 'SELECT 1 FROM sysibm.sysdummy1'; } /** * {@inheritDoc} * * 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. */ public function supportsSavepoints() { return false; } /** * {@inheritDoc} */ protected function getReservedKeywordsClass() { return 'Doctrine\DBAL\Platforms\Keywords\DB2Keywords'; } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/DrizzlePlatform.php000066400000000000000000000420331313473450000233350ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\Schema\Identifier; use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Types\BinaryType; /** * Drizzle platform * * @author Kim Hemsø Rasmussen */ class DrizzlePlatform extends AbstractPlatform { /** * {@inheritDoc} */ public function getName() { return 'drizzle'; } /** * {@inheritDoc} */ public function getIdentifierQuoteCharacter() { return '`'; } /** * {@inheritDoc} */ public function getConcatExpression() { $args = func_get_args(); return 'CONCAT(' . join(', ', (array) $args) . ')'; } /** * {@inheritdoc} */ protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) { $function = '+' === $operator ? 'DATE_ADD' : 'DATE_SUB'; return $function . '(' . $date . ', INTERVAL ' . $interval . ' ' . $unit . ')'; } /** * {@inheritDoc} */ public function getDateDiffExpression($date1, $date2) { return 'DATEDIFF(' . $date1 . ', ' . $date2 . ')'; } /** * {@inheritDoc} */ public function getBooleanTypeDeclarationSQL(array $field) { return 'BOOLEAN'; } /** * {@inheritDoc} */ public function getIntegerTypeDeclarationSQL(array $field) { return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field); } /** * {@inheritDoc} */ protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) { $autoinc = ''; if ( ! empty($columnDef['autoincrement'])) { $autoinc = ' AUTO_INCREMENT'; } return $autoinc; } /** * {@inheritDoc} */ public function getBigIntTypeDeclarationSQL(array $field) { return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); } /** * {@inheritDoc} */ public function getSmallIntTypeDeclarationSQL(array $field) { return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field); } /** * {@inheritDoc} */ protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) { return $length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'; } /** * {@inheritdoc} */ protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) { return 'VARBINARY(' . ($length ?: 255) . ')'; } /** * {@inheritDoc} */ protected function initializeDoctrineTypeMappings() { $this->doctrineTypeMapping = array( 'boolean' => 'boolean', 'varchar' => 'string', 'varbinary' => 'binary', 'integer' => 'integer', 'blob' => 'blob', 'decimal' => 'decimal', 'datetime' => 'datetime', 'date' => 'date', 'time' => 'time', 'text' => 'text', 'timestamp' => 'datetime', 'double' => 'float', 'bigint' => 'bigint', ); } /** * {@inheritDoc} */ public function getClobTypeDeclarationSQL(array $field) { return 'TEXT'; } /** * {@inheritDoc} */ public function getBlobTypeDeclarationSQL(array $field) { return 'BLOB'; } /** * {@inheritDoc} */ public function getCreateDatabaseSQL($name) { return 'CREATE DATABASE ' . $name; } /** * {@inheritDoc} */ public function getDropDatabaseSQL($name) { return 'DROP DATABASE ' . $name; } /** * {@inheritDoc} */ 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 . ') '; $query .= $this->buildTableOptions($options); $query .= $this->buildPartitionOptions($options); $sql[] = $query; if (isset($options['foreignKeys'])) { foreach ((array) $options['foreignKeys'] as $definition) { $sql[] = $this->getCreateForeignKeySQL($definition, $tableName); } } return $sql; } /** * Build SQL for table options * * @param array $options * * @return string */ private function buildTableOptions(array $options) { if (isset($options['table_options'])) { return $options['table_options']; } $tableOptions = array(); // Collate if ( ! isset($options['collate'])) { $options['collate'] = 'utf8_unicode_ci'; } $tableOptions[] = sprintf('COLLATE %s', $options['collate']); // Engine if ( ! isset($options['engine'])) { $options['engine'] = 'InnoDB'; } $tableOptions[] = sprintf('ENGINE = %s', $options['engine']); // Auto increment if (isset($options['auto_increment'])) { $tableOptions[] = sprintf('AUTO_INCREMENT = %s', $options['auto_increment']); } // Comment if (isset($options['comment'])) { $comment = trim($options['comment'], " '"); $tableOptions[] = sprintf("COMMENT = %s ", $this->quoteStringLiteral($comment)); } // Row format if (isset($options['row_format'])) { $tableOptions[] = sprintf('ROW_FORMAT = %s', $options['row_format']); } return implode(' ', $tableOptions); } /** * Build SQL for partition options. * * @param array $options * * @return string */ private function buildPartitionOptions(array $options) { return (isset($options['partition_options'])) ? ' ' . $options['partition_options'] : ''; } /** * {@inheritDoc} */ public function getListDatabasesSQL() { return "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE CATALOG_NAME='LOCAL'"; } /** * {@inheritDoc} */ protected function getReservedKeywordsClass() { return 'Doctrine\DBAL\Platforms\Keywords\DrizzleKeywords'; } /** * {@inheritDoc} */ public function getListTablesSQL() { return "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE' AND TABLE_SCHEMA=DATABASE()"; } /** * {@inheritDoc} */ public function getListTableColumnsSQL($table, $database = null) { if ($database) { $database = "'" . $database . "'"; } else { $database = 'DATABASE()'; } return "SELECT COLUMN_NAME, DATA_TYPE, COLUMN_COMMENT, IS_NULLABLE, IS_AUTO_INCREMENT, CHARACTER_MAXIMUM_LENGTH, COLUMN_DEFAULT," . " NUMERIC_PRECISION, NUMERIC_SCALE, COLLATION_NAME" . " FROM DATA_DICTIONARY.COLUMNS" . " WHERE TABLE_SCHEMA=" . $database . " AND TABLE_NAME = '" . $table . "'"; } /** * {@inheritDoc} */ public function getListTableForeignKeysSQL($table, $database = null) { if ($database) { $database = "'" . $database . "'"; } else { $database = 'DATABASE()'; } return "SELECT CONSTRAINT_NAME, CONSTRAINT_COLUMNS, REFERENCED_TABLE_NAME, REFERENCED_TABLE_COLUMNS, UPDATE_RULE, DELETE_RULE" . " FROM DATA_DICTIONARY.FOREIGN_KEYS" . " WHERE CONSTRAINT_SCHEMA=" . $database . " AND CONSTRAINT_TABLE='" . $table . "'"; } /** * {@inheritDoc} */ public function getListTableIndexesSQL($table, $database = null) { if ($database) { $database = "'" . $database . "'"; } else { $database = 'DATABASE()'; } return "SELECT INDEX_NAME AS 'key_name', COLUMN_NAME AS 'column_name', IS_USED_IN_PRIMARY AS 'primary', IS_UNIQUE=0 AS 'non_unique'" . " FROM DATA_DICTIONARY.INDEX_PARTS" . " WHERE TABLE_SCHEMA=" . $database . " AND TABLE_NAME='" . $table . "'"; } /** * {@inheritDoc} */ public function prefersIdentityColumns() { return true; } /** * {@inheritDoc} */ public function supportsIdentityColumns() { return true; } /** * {@inheritDoc} */ public function supportsInlineColumnComments() { return true; } /** * {@inheritDoc} */ public function supportsViews() { return false; } /** * {@inheritdoc} */ public function supportsColumnCollation() { return true; } /** * {@inheritDoc} */ public function getDropIndexSQL($index, $table=null) { if ($index instanceof Index) { $indexName = $index->getQuotedName($this); } elseif (is_string($index)) { $indexName = $index; } else { throw new \InvalidArgumentException('DrizzlePlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.'); } if ($table instanceof Table) { $table = $table->getQuotedName($this); } elseif (!is_string($table)) { throw new \InvalidArgumentException('DrizzlePlatform::getDropIndexSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); } if ($index instanceof Index && $index->isPrimary()) { // drizzle 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; } /** * {@inheritDoc} */ protected function getDropPrimaryKeySQL($table) { return 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY'; } /** * {@inheritDoc} */ public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) { if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] == true) { return 'TIMESTAMP'; } return 'DATETIME'; } /** * {@inheritDoc} */ public function getTimeTypeDeclarationSQL(array $fieldDeclaration) { return 'TIME'; } /** * {@inheritDoc} */ public function getDateTypeDeclarationSQL(array $fieldDeclaration) { return 'DATE'; } /** * {@inheritDoc} */ public function getAlterTableSQL(TableDiff $diff) { $columnSql = array(); $queryParts = array(); if ($diff->newName !== false) { $queryParts[] = 'RENAME TO ' . $diff->getNewName()->getQuotedName($this); } foreach ($diff->addedColumns as $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(); // Do not generate column alteration clause if type is binary and only fixed property has changed. // Drizzle only supports binary type columns with variable length. // Avoids unnecessary table alteration statements. if ($columnArray['type'] instanceof BinaryType && $columnDiff->hasChanged('fixed') && count($columnDiff->changedProperties) === 1 ) { continue; } $columnArray['comment'] = $this->getColumnComment($column); $queryParts[] = 'CHANGE ' . ($columnDiff->getOldColumnName()->getQuotedName($this)) . ' ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); } foreach ($diff->renamedColumns as $oldColumnName => $column) { if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { continue; } $oldColumnName = new Identifier($oldColumnName); $columnArray = $column->toArray(); $columnArray['comment'] = $this->getColumnComment($column); $queryParts[] = 'CHANGE ' . $oldColumnName->getQuotedName($this) . ' ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); } $sql = array(); $tableSql = array(); if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { if (count($queryParts) > 0) { $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . implode(", ", $queryParts); } $sql = array_merge( $this->getPreAlterTableIndexForeignKeySQL($diff), $sql, $this->getPostAlterTableIndexForeignKeySQL($diff) ); } return array_merge($sql, $tableSql, $columnSql); } /** * {@inheritDoc} */ public function getDropTemporaryTableSQL($table) { if ($table instanceof Table) { $table = $table->getQuotedName($this); } elseif (!is_string($table)) { throw new \InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); } return 'DROP TEMPORARY TABLE ' . $table; } /** * {@inheritDoc} */ 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'; } } } elseif (is_bool($item) || is_numeric($item)) { $item = ($item) ? 'true' : 'false'; } return $item; } /** * {@inheritDoc} */ public function getLocateExpression($str, $substr, $startPos = false) { if ($startPos == false) { return 'LOCATE(' . $substr . ', ' . $str . ')'; } return 'LOCATE(' . $substr . ', ' . $str . ', '.$startPos.')'; } /** * {@inheritDoc} */ public function getGuidExpression() { return 'UUID()'; } /** * {@inheritDoc} */ public function getRegexpExpression() { return 'RLIKE'; } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/Keywords/000077500000000000000000000000001313473450000213015ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Platforms/Keywords/DB2Keywords.php000066400000000000000000000243231313473450000241150ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * DB2 Keywords. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ class DB2Keywords extends KeywordList { /** * {@inheritdoc} */ public function getName() { return 'DB2'; } /** * {@inheritdoc} */ 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', ); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/Keywords/DrizzleKeywords.php000066400000000000000000000200741313473450000251700ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * Drizzle Keywordlist. * * @author Kim Hemsø Rasmussen */ class DrizzleKeywords extends KeywordList { /** * {@inheritdoc} */ public function getName() { return 'drizzle'; } /** * {@inheritdoc} */ protected function getKeywords() { return array( 'ABS', 'ALL', 'ALLOCATE', 'ALTER', 'AND', 'ANY', 'ARE', 'ARRAY', 'AS', 'ASENSITIVE', 'ASYMMETRIC', 'AT', 'ATOMIC', 'AUTHORIZATION', 'AVG', 'BEGIN', 'BETWEEN', 'BIGINT', 'BINARY', 'BLOB', 'BOOLEAN', 'BOTH', 'BY', 'CALL', 'CALLED', 'CARDINALITY', 'CASCADED', 'CASE', 'CAST', 'CEIL', 'CEILING', 'CHAR', 'CHARACTER', 'CHARACTER_LENGTH', 'CHAR_LENGTH', 'CHECK', 'CLOB', 'CLOSE', 'COALESCE', 'COLLATE', 'COLLECT', 'COLUMN', 'COMMIT', 'CONDITION', 'CONNECT', 'CONSTRAINT', 'CONVERT', 'CORR', 'CORRESPONDING', 'COUNT', 'COVAR_POP', 'COVAR_SAMP', 'CREATE', 'CROSS', 'CUBE', 'CUME_DIST', 'CURRENT', 'CURRENT_DATE', 'CURRENT_DEFAULT_TRANSFORM_GROUP', 'CURRENT_PATH', 'CURRENT_ROLE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURRENT_TRANSFORM_GROUP_FOR_TYPE', 'CURRENT_USER', 'CURSOR', 'CYCLE', 'DATE', 'DAY', 'DEALLOCATE', 'DEC', 'DECIMAL', 'DECLARE', 'DEFAULT', 'DELETE', 'DENSE_RANK', 'DEREF', 'DESCRIBE', 'DETERMINISTIC', 'DISCONNECT', 'DISTINCT', 'DOUBLE', 'DROP', 'DYNAMIC', 'EACH', 'ELEMENT', 'ELSE', 'END', 'ESCAPE', 'EVERY', 'EXCEPT', 'EXEC', 'EXECUTE', 'EXISTS', 'EXP', 'EXTERNAL', 'EXTRACT', 'FALSE', 'FETCH', 'FILTER', 'FLOAT', 'FLOOR', 'FOR', 'FOREIGN', 'FREE', 'FROM', 'FULL', 'FUNCTION', 'FUSION', 'GET', 'GLOBAL', 'GRANT', 'GROUP', 'GROUPING', 'HAVING', 'HOLD', 'HOUR', 'IDENTITY', 'IN', 'INDICATOR', 'INNER', 'INOUT', 'INSENSITIVE', 'INSERT', 'INT', 'INTEGER', 'INTERSECT', 'INTERSECTION', 'INTERVAL', 'INTO', 'IS', 'JOIN', 'LANGUAGE', 'LARGE', 'LATERAL', 'LEADING', 'LEFT', 'LIKE', 'LN', 'LOCAL', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOWER', 'MATCH', 'MAX', 'MEMBER', 'MERGE', 'METHOD', 'MIN', 'MINUTE', 'MOD', 'MODIFIES', 'MODULE', 'MONTH', 'MULTISET', 'NATIONAL', 'NATURAL', 'NCHAR', 'NCLOB', 'NEW', 'NO', 'NONE', 'NORMALIZE', 'NOT', 'NULL_SYM', 'NULLIF', 'NUMERIC', 'OCTET_LENGTH', 'OF', 'OLD', 'ON', 'ONLY', 'OPEN', 'OR', 'ORDER', 'OUT', 'OUTER', 'OVER', 'OVERLAPS', 'OVERLAY', 'PARAMETER', 'PARTITION', 'PERCENTILE_CONT', 'PERCENTILE_DISC', 'PERCENT_RANK', 'POSITION', 'POWER', 'PRECISION', 'PREPARE', 'PRIMARY', 'PROCEDURE', 'RANGE', 'RANK', 'READS', 'REAL', 'RECURSIVE', 'REF', 'REFERENCES', 'REFERENCING', 'REGR_AVGX', 'REGR_AVGY', 'REGR_COUNT', 'REGR_INTERCEPT', 'REGR_R2', 'REGR_SLOPE', 'REGR_SXX', 'REGR_SXY', 'REGR_SYY', 'RELEASE', 'RESULT', 'RETURN', 'RETURNS', 'REVOKE', 'RIGHT', 'ROLLBACK', 'ROLLUP', 'ROW', 'ROWS', 'ROW_NUMBER', 'SAVEPOINT', 'SCOPE', 'SCROLL', 'SEARCH', 'SECOND', 'SELECT', 'SENSITIVE', 'SESSION_USER', 'SET', 'SIMILAR', 'SMALLINT', 'SOME', 'SPECIFIC', 'SPECIFICTYPE', 'SQL', 'SQLEXCEPTION', 'SQLSTATE', 'SQLWARNING', 'SQRT', 'START', 'STATIC', 'STDDEV_POP', 'STDDEV_SAMP', 'SUBMULTISET', 'SUBSTRING', 'SUM', 'SYMMETRIC', 'SYSTEM', 'SYSTEM_USER', 'TABLE', 'TABLESAMPLE', 'THEN', 'TIME', 'TIMESTAMP', 'TIMEZONE_HOUR', 'TIMEZONE_MINUTE', 'TO', 'TRAILING', 'TRANSLATE', 'TRANSLATION', 'TREAT', 'TRIGGER', 'TRIM', 'TRUE', 'UESCAPE', 'UNION', 'UNIQUE', 'UNKNOWN', 'UNNEST', 'UPDATE', 'UPPER', 'USER', 'USING', 'VALUE', 'VALUES', 'VARCHAR', 'VARYING', 'VAR_POP', 'VAR_SAMP', 'WHEN', 'WHENEVER', 'WHERE', 'WIDTH_BUCKET', 'WINDOW', 'WITH', 'WITHIN', 'WITHOUT', 'XML', 'XMLAGG', 'XMLATTRIBUTES', 'XMLBINARY', 'XMLCOMMENT', 'XMLCONCAT', 'XMLELEMENT', 'XMLFOREST', 'XMLNAMESPACES', 'XMLPARSE', 'XMLPI', 'XMLROOT', 'XMLSERIALIZE', 'YEAR', ); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/Keywords/KeywordList.php000066400000000000000000000040731313473450000242760ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * Abstract interface for a SQL reserved keyword dictionary. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ abstract class KeywordList { /** * @var array|null */ private $keywords = null; /** * Checks if the given word is a keyword of this dialect/vendor platform. * * @param string $word * * @return boolean */ public function isKeyword($word) { if ($this->keywords === null) { $this->initializeKeywords(); } return isset($this->keywords[strtoupper($word)]); } /** * @return void */ protected function initializeKeywords() { $this->keywords = array_flip(array_map('strtoupper', $this->getKeywords())); } /** * Returns the list of keywords. * * @return array */ abstract protected function getKeywords(); /** * Returns the name of this keyword list. * * @return string */ abstract public function getName(); } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/Keywords/MsSQLKeywords.php000066400000000000000000000030261313473450000245020ustar00rootroot00000000000000. */ 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 * @author David Coallier * @author Steve Müller * @deprecated Use SQLServerKeywords class instead. */ class MsSQLKeywords extends SQLServerKeywords { /** * {@inheritdoc} */ public function getName() { return 'MsSQL'; } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/Keywords/MySQL57Keywords.php000066400000000000000000000153751313473450000246760ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * MySQL 5.7 reserved keywords list. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class MySQL57Keywords extends MySQLKeywords { /** * {@inheritdoc} */ public function getName() { return 'MySQL57'; } /** * {@inheritdoc} * * @link http://dev.mysql.com/doc/mysqld-version-reference/en/mysqld-version-reference-reservedwords-5-7.html */ protected function getKeywords() { return array( 'ACCESSIBLE', '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', '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', 'GET', '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', 'IO_AFTER_GTIDS', 'IO_BEFORE_GTIDS', 'IS', 'ITERATE', 'JOIN', 'KEY', 'KEYS', 'KILL', 'LEADING', 'LEAVE', 'LEFT', 'LIKE', 'LIMIT', 'LINEAR', 'LINES', 'LOAD', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCK', 'LONG', 'LONGBLOB', 'LONGTEXT', 'LOOP', 'LOW_PRIORITY', 'MASTER_BIND', 'MASTER_SSL_VERIFY_SERVER_CERT', 'MATCH', 'MAXVALUE', 'MEDIUMBLOB', 'MEDIUMINT', 'MEDIUMTEXT', 'MIDDLEINT', 'MINUTE_MICROSECOND', 'MINUTE_SECOND', 'MOD', 'MODIFIES', 'NATURAL', 'NO_WRITE_TO_BINLOG', 'NONBLOCKING', 'NOT', 'NULL', 'NUMERIC', 'ON', 'OPTIMIZE', 'OPTION', 'OPTIONALLY', 'OR', 'ORDER', 'OUT', 'OUTER', 'OUTFILE', 'PARTITION', 'PRECISION', 'PRIMARY', 'PROCEDURE', 'PURGE', 'RANGE', 'READ', 'READ_WRITE', 'READS', 'REAL', 'REFERENCES', 'REGEXP', 'RELEASE', 'RENAME', 'REPEAT', 'REPLACE', 'REQUIRE', 'RESIGNAL', 'RESTRICT', 'RETURN', 'REVOKE', 'RIGHT', 'RLIKE', 'SCHEMA', 'SCHEMAS', 'SECOND_MICROSECOND', 'SELECT', 'SENSITIVE', 'SEPARATOR', 'SET', 'SHOW', 'SIGNAL', 'SMALLINT', 'SPATIAL', 'SPECIFIC', 'SQL', 'SQL_BIG_RESULT', 'SQL_CALC_FOUND_ROWS', 'SQL_SMALL_RESULT', 'SQLEXCEPTION', 'SQLSTATE', 'SQLWARNING', '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', 'XOR', 'YEAR_MONTH', 'ZEROFILL', ); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/Keywords/MySQLKeywords.php000066400000000000000000000146761313473450000245250ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * MySQL Keywordlist. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei * @author David Coallier */ class MySQLKeywords extends KeywordList { /** * {@inheritdoc} */ public function getName() { return 'MySQL'; } /** * {@inheritdoc} */ 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', 'RANGE', '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', ); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/Keywords/OracleKeywords.php000066400000000000000000000075151313473450000247570ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * Oracle Keywordlist. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei * @author David Coallier */ class OracleKeywords extends KeywordList { /** * {@inheritdoc} */ public function getName() { return 'Oracle'; } /** * {@inheritdoc} */ 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', 'RANGE', ); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/Keywords/PostgreSQL91Keywords.php000066400000000000000000000073251313473450000257260ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * PostgreSQL 9.1 reserved keywords list. * * @author Martin Hasoň * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class PostgreSQL91Keywords extends PostgreSQLKeywords { /** * {@inheritdoc} */ public function getName() { return 'PostgreSQL91'; } /** * {@inheritdoc} * * @link http://www.postgresql.org/docs/9.1/static/sql-keywords-appendix.html */ protected function getKeywords() { return array( 'ALL', 'ANALYSE', 'ANALYZE', 'AND', 'ANY', 'ARRAY', 'AS', 'ASC', 'ASYMMETRIC', 'AUTHORIZATION', 'BINARY', 'BOTH', 'CASE', 'CAST', 'CHECK', 'COLLATE', 'COLUMN', 'CONCURRENTLY', 'CONSTRAINT', 'CREATE', 'CROSS', 'CURRENT_CATALOG', 'CURRENT_DATE', 'CURRENT_ROLE', 'CURRENT_SCHEMA', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURRENT_USER', 'DEFAULT', 'DEFERRABLE', 'DESC', 'DISTINCT', 'DO', 'ELSE', 'END', 'EXCEPT', 'FALSE', 'FETCH', 'FOR', 'FOREIGN', 'FREEZE', 'FROM', 'FULL', 'GRANT', 'GROUP', 'HAVING', 'ILIKE', 'IN', 'INITIALLY', 'INNER', 'INTERSECT', 'INTO', 'IS', 'ISNULL', 'JOIN', 'LEADING', 'LEFT', 'LIKE', 'LIMIT', 'LOCALTIME', 'LOCALTIMESTAMP', 'NATURAL', 'NOT', 'NOTNULL', 'NULL', 'OFFSET', 'ON', 'ONLY', 'OR', 'ORDER', 'OUTER', 'OVER', 'OVERLAPS', 'PLACING', 'PRIMARY', 'REFERENCES', 'RETURNING', 'RIGHT', 'SELECT', 'SESSION_USER', 'SIMILAR', 'SOME', 'SYMMETRIC', 'TABLE', 'THEN', 'TO', 'TRAILING', 'TRUE', 'UNION', 'UNIQUE', 'USER', 'USING', 'VARIADIC', 'VERBOSE', 'WHEN', 'WHERE', 'WINDOW', 'WITH', ); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/Keywords/PostgreSQL92Keywords.php000066400000000000000000000031361313473450000257230ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * PostgreSQL 9.2 reserved keywords list. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class PostgreSQL92Keywords extends PostgreSQL91Keywords { /** * {@inheritdoc} */ public function getName() { return 'PostgreSQL92'; } /** * {@inheritdoc} * * @link http://www.postgresql.org/docs/9.2/static/sql-keywords-appendix.html */ protected function getKeywords() { return array_merge(parent::getKeywords(), array( 'COLLATION', )); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/Keywords/PostgreSQLKeywords.php000066400000000000000000000065061313473450000255540ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * PostgreSQL Keywordlist. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei * @author Marcelo Santos Araujo */ class PostgreSQLKeywords extends KeywordList { /** * {@inheritdoc} */ public function getName() { return 'PostgreSQL'; } /** * {@inheritdoc} */ 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' ); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/Keywords/ReservedKeywordsValidator.php000066400000000000000000000070331313473450000271720ustar00rootroot00000000000000. */ 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(); /** * @param \Doctrine\DBAL\Platforms\Keywords\KeywordList[] $keywordLists */ public function __construct(array $keywordLists) { $this->keywordLists = $keywordLists; } /** * @return array */ 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; } /** * @param string $asset * @param array $violatedPlatforms * * @return void */ private function addViolation($asset, $violatedPlatforms) { if ( ! $violatedPlatforms) { return; } $this->violations[] = $asset . ' keyword violations: ' . implode(', ', $violatedPlatforms); } /** * {@inheritdoc} */ public function acceptColumn(Table $table, Column $column) { $this->addViolation( 'Table ' . $table->getName() . ' column ' . $column->getName(), $this->isReservedWord($column->getName()) ); } /** * {@inheritdoc} */ public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) { } /** * {@inheritdoc} */ public function acceptIndex(Table $table, Index $index) { } /** * {@inheritdoc} */ public function acceptSchema(Schema $schema) { } /** * {@inheritdoc} */ public function acceptSequence(Sequence $sequence) { } /** * {@inheritdoc} */ public function acceptTable(Table $table) { $this->addViolation( 'Table ' . $table->getName(), $this->isReservedWord($table->getName()) ); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere11Keywords.php000066400000000000000000000032761313473450000260560ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * SAP Sybase SQL Anywhere 11 reserved keywords list. * * @author Steve Müller */ class SQLAnywhere11Keywords extends SQLAnywhereKeywords { /** * {@inheritdoc} */ public function getName() { return 'SQLAnywhere11'; } /** * {@inheritdoc} * * @link http://dcx.sybase.com/1100/en/dbreference_en11/alhakeywords.html */ protected function getKeywords() { return array_merge( array_diff( parent::getKeywords(), array('IQ') ), array( 'MERGE', 'OPENSTRING' ) ); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere12Keywords.php000066400000000000000000000037111313473450000260510ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * SAP Sybase SQL Anywhere 12 reserved keywords list. * * @author Steve Müller */ class SQLAnywhere12Keywords extends SQLAnywhere11Keywords { /** * {@inheritdoc} */ public function getName() { return 'SQLAnywhere12'; } /** * {@inheritdoc} * * @link http://dcx.sybase.com/1200/en/dbreference/alhakeywords.html */ protected function getKeywords() { return array_merge( array_diff( parent::getKeywords(), array( 'INDEX_LPAREN', 'SYNTAX_ERROR', 'WITH_CUBE', 'WITH_LPAREN', 'WITH_ROLLUP' ) ), array( 'DATETIMEOFFSET', 'LIMIT', 'OPENXML', 'SPATIAL', 'TREAT' ) ); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere16Keywords.php000066400000000000000000000033401313473450000260530ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * SAP Sybase SQL Anywhere 16 reserved keywords list. * * @author Steve Müller */ class SQLAnywhere16Keywords extends SQLAnywhere12Keywords { /** * {@inheritdoc} */ public function getName() { return 'SQLAnywhere16'; } /** * {@inheritdoc} * * @link http://dcx.sybase.com/index.html#sa160/en/dbreference/alhakeywords.html */ protected function getKeywords() { return array_merge( parent::getKeywords(), array( 'ARRAY', 'JSON', 'ROW', 'ROWTYPE', 'UNNEST', 'VARRAY' ) ); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhereKeywords.php000066400000000000000000000151371313473450000257130ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * SAP Sybase SQL Anywhere 10 reserved keywords list. * * @author Steve Müller */ class SQLAnywhereKeywords extends KeywordList { /** * {@inheritdoc} */ public function getName() { return 'SQLAnywhere'; } /** * {@inheritdoc} * * @link http://infocenter.sybase.com/help/topic/com.sybase.dbrfen10/pdf/dbrfen10.pdf?noframes=true */ protected function getKeywords() { return array( 'ADD', 'ALL', 'ALTER', 'AND', 'ANY', 'AS', 'ASC', 'ATTACH', 'BACKUP', 'BEGIN', 'BETWEEN', 'BIGINT', 'BINARY', 'BIT', 'BOTTOM', 'BREAK', 'BY', 'CALL', 'CAPABILITY', 'CASCADE', 'CASE', 'CAST', 'CHAR', 'CHAR_CONVERT', 'CHARACTER', 'CHECK', 'CHECKPOINT', 'CLOSE', 'COMMENT', 'COMMIT', 'COMPRESSED', 'CONFLICT', 'CONNECT', 'CONSTRAINT', 'CONTAINS', 'CONTINUE', 'CONVERT', 'CREATE', 'CROSS', 'CUBE', 'CURRENT', 'CURRENT_TIMESTAMP', 'CURRENT_USER', 'CURSOR', 'DATE', 'DBSPACE', 'DEALLOCATE', 'DEC', 'DECIMAL', 'DECLARE', 'DEFAULT', 'DELETE', 'DELETING', 'DESC', 'DETACH', 'DISTINCT', 'DO', 'DOUBLE', 'DROP', 'DYNAMIC', 'ELSE', 'ELSEIF', 'ENCRYPTED', 'END', 'ENDIF', 'ESCAPE', 'EXCEPT', 'EXCEPTION', 'EXEC', 'EXECUTE', 'EXISTING', 'EXISTS', 'EXTERNLOGIN', 'FETCH', 'FIRST', 'FLOAT', 'FOR', 'FORCE', 'FOREIGN', 'FORWARD', 'FROM', 'FULL', 'GOTO', 'GRANT', 'GROUP', 'HAVING', 'HOLDLOCK', 'IDENTIFIED', 'IF', 'IN', 'INDEX', 'INDEX_LPAREN', 'INNER', 'INOUT', 'INSENSITIVE', 'INSERT', 'INSERTING', 'INSTALL', 'INSTEAD', 'INT', 'INTEGER', 'INTEGRATED', 'INTERSECT', 'INTO', 'IQ', 'IS', 'ISOLATION', 'JOIN', 'KERBEROS', 'KEY', 'LATERAL', 'LEFT', 'LIKE', 'LOCK', 'LOGIN', 'LONG', 'MATCH', 'MEMBERSHIP', 'MESSAGE', 'MODE', 'MODIFY', 'NATURAL', 'NCHAR', 'NEW', 'NO', 'NOHOLDLOCK', 'NOT', 'NOTIFY', 'NULL', 'NUMERIC', 'NVARCHAR', 'OF', 'OFF', 'ON', 'OPEN', 'OPTION', 'OPTIONS', 'OR', 'ORDER', 'OTHERS', 'OUT', 'OUTER', 'OVER', 'PASSTHROUGH', 'PRECISION', 'PREPARE', 'PRIMARY', 'PRINT', 'PRIVILEGES', 'PROC', 'PROCEDURE', 'PUBLICATION', 'RAISERROR', 'READTEXT', 'REAL', 'REFERENCE', 'REFERENCES', 'REFRESH', 'RELEASE', 'REMOTE', 'REMOVE', 'RENAME', 'REORGANIZE', 'RESOURCE', 'RESTORE', 'RESTRICT', 'RETURN', 'REVOKE', 'RIGHT', 'ROLLBACK', 'ROLLUP', 'SAVE', 'SAVEPOINT', 'SCROLL', 'SELECT', 'SENSITIVE', 'SESSION', 'SET', 'SETUSER', 'SHARE', 'SMALLINT', 'SOME', 'SQLCODE', 'SQLSTATE', 'START', 'STOP', 'SUBTRANS', 'SUBTRANSACTION', 'SYNCHRONIZE', 'SYNTAX_ERROR', 'TABLE', 'TEMPORARY', 'THEN', 'TIME', 'TIMESTAMP', 'TINYINT', 'TO', 'TOP', 'TRAN', 'TRIGGER', 'TRUNCATE', 'TSEQUAL', 'UNBOUNDED', 'UNION', 'UNIQUE', 'UNIQUEIDENTIFIER', 'UNKNOWN', 'UNSIGNED', 'UPDATE', 'UPDATING', 'USER', 'USING', 'VALIDATE', 'VALUES', 'VARBINARY', 'VARBIT', 'VARCHAR', 'VARIABLE', 'VARYING', 'VIEW', 'WAIT', 'WAITFOR', 'WHEN', 'WHERE', 'WHILE', 'WINDOW', 'WITH', 'WITH_CUBE', 'WITH_LPAREN', 'WITH_ROLLUP', 'WITHIN', 'WORK', 'WRITETEXT', 'XML' ); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/Keywords/SQLServer2005Keywords.php000066400000000000000000000035061313473450000257030ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * Microsoft SQL Server 2005 reserved keyword dictionary. * * @license BSD http://www.opensource.org/licenses/bsd-license.php * @link www.doctrine-project.com * @since 2.3 * @author Steve Müller */ class SQLServer2005Keywords extends SQLServerKeywords { /** * {@inheritdoc} */ public function getName() { return 'SQLServer2005'; } /** * {@inheritdoc} * * @link http://msdn.microsoft.com/en-US/library/ms189822%28v=sql.90%29.aspx */ protected function getKeywords() { return array_merge(array_diff(parent::getKeywords(), array('DUMMY')), array( 'EXTERNAL', 'PIVOT', 'REVERT', 'SECURITYAUDIT', 'TABLESAMPLE', 'UNPIVOT' )); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/Keywords/SQLServer2008Keywords.php000066400000000000000000000032621313473450000257050ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * Microsoft SQL Server 2008 reserved keyword dictionary. * * @license BSD http://www.opensource.org/licenses/bsd-license.php * @link www.doctrine-project.com * @since 2.3 * @author Steve Müller */ class SQLServer2008Keywords extends SQLServer2005Keywords { /** * {@inheritdoc} */ public function getName() { return 'SQLServer2008'; } /** * {@inheritdoc} * * @link http://msdn.microsoft.com/en-us/library/ms189822%28v=sql.100%29.aspx */ protected function getKeywords() { return array_merge(parent::getKeywords(), array( 'MERGE' )); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/Keywords/SQLServer2012Keywords.php000066400000000000000000000035001313473450000256730ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * Microsoft SQL Server 2012 reserved keyword dictionary. * * @license BSD http://www.opensource.org/licenses/bsd-license.php * @link www.doctrine-project.com * @since 2.3 * @author Steve Müller */ class SQLServer2012Keywords extends SQLServer2008Keywords { /** * {@inheritdoc} */ public function getName() { return 'SQLServer2012'; } /** * {@inheritdoc} * * @link http://msdn.microsoft.com/en-us/library/ms189822.aspx */ protected function getKeywords() { return array_merge(parent::getKeywords(), array( 'SEMANTICKEYPHRASETABLE', 'SEMANTICSIMILARITYDETAILSTABLE', 'SEMANTICSIMILARITYTABLE', 'TRY_CONVERT', 'WITHIN GROUP' )); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/Keywords/SQLServerKeywords.php000066400000000000000000000131551313473450000253750ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * Microsoft SQL Server 2000 reserved keyword dictionary. * * @license BSD http://www.opensource.org/licenses/bsd-license.php * @link www.doctrine-project.com * @since 2.0 * @author Benjamin Eberlei * @author David Coallier * @author Steve Müller */ class SQLServerKeywords extends KeywordList { /** * {@inheritdoc} */ public function getName() { return 'SQLServer'; } /** * {@inheritdoc} * * @link http://msdn.microsoft.com/en-us/library/aa238507%28v=sql.80%29.aspx */ protected function getKeywords() { return array( 'ADD', 'ALL', 'ALTER', 'AND', 'ANY', 'AS', 'ASC', 'AUTHORIZATION', 'BACKUP', 'BEGIN', 'BETWEEN', 'BREAK', 'BROWSE', 'BULK', 'BY', 'CASCADE', 'CASE', 'CHECK', 'CHECKPOINT', 'CLOSE', 'CLUSTERED', 'COALESCE', 'COLLATE', 'COLUMN', 'COMMIT', 'COMPUTE', 'CONSTRAINT', 'CONTAINS', 'CONTAINSTABLE', 'CONTINUE', 'CONVERT', 'CREATE', 'CROSS', 'CURRENT', 'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURRENT_USER', 'CURSOR', 'DATABASE', 'DBCC', 'DEALLOCATE', 'DECLARE', 'DEFAULT', 'DELETE', 'DENY', 'DESC', 'DISK', 'DISTINCT', 'DISTRIBUTED', 'DOUBLE', 'DROP', 'DUMP', 'ELSE', 'END', 'ERRLVL', 'ESCAPE', 'EXCEPT', 'EXEC', 'EXECUTE', 'EXISTS', 'EXIT', 'EXTERNAL', 'FETCH', 'FILE', 'FILLFACTOR', 'FOR', 'FOREIGN', 'FREETEXT', 'FREETEXTTABLE', 'FROM', 'FULL', 'FUNCTION', 'GOTO', 'GRANT', 'GROUP', 'HAVING', 'HOLDLOCK', 'IDENTITY', 'IDENTITY_INSERT', 'IDENTITYCOL', 'IF', 'IN', 'INDEX', 'INNER', 'INSERT', 'INTERSECT', 'INTO', 'IS', 'JOIN', 'KEY', 'KILL', 'LEFT', 'LIKE', 'LINENO', 'LOAD', 'NATIONAL', 'NOCHECK ', 'NONCLUSTERED', 'NOT', 'NULL', 'NULLIF', 'OF', 'OFF', 'OFFSETS', 'ON', 'OPEN', 'OPENDATASOURCE', 'OPENQUERY', 'OPENROWSET', 'OPENXML', 'OPTION', 'OR', 'ORDER', 'OUTER', 'OVER', 'PERCENT', 'PIVOT', 'PLAN', 'PRECISION', 'PRIMARY', 'PRINT', 'PROC', 'PROCEDURE', 'PUBLIC', 'RAISERROR', 'READ', 'READTEXT', 'RECONFIGURE', 'REFERENCES', 'REPLICATION', 'RESTORE', 'RESTRICT', 'RETURN', 'REVERT', 'REVOKE', 'RIGHT', 'ROLLBACK', 'ROWCOUNT', 'ROWGUIDCOL', 'RULE', 'SAVE', 'SCHEMA', 'SECURITYAUDIT', 'SELECT', 'SESSION_USER', 'SET', 'SETUSER', 'SHUTDOWN', 'SOME', 'STATISTICS', 'SYSTEM_USER', 'TABLE', 'TABLESAMPLE', 'TEXTSIZE', 'THEN', 'TO', 'TOP', 'TRAN', 'TRANSACTION', 'TRIGGER', 'TRUNCATE', 'TSEQUAL', 'UNION', 'UNIQUE', 'UNPIVOT', 'UPDATE', 'UPDATETEXT', 'USE', 'USER', 'VALUES', 'VARYING', 'VIEW', 'WAITFOR', 'WHEN', 'WHERE', 'WHILE', 'WITH', 'WRITETEXT' ); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/Keywords/SQLiteKeywords.php000066400000000000000000000077371313473450000247210ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * SQLite Keywordlist. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ class SQLiteKeywords extends KeywordList { /** * {@inheritdoc} */ public function getName() { return 'SQLite'; } /** * {@inheritdoc} */ 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' ); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/MySQL57Platform.php000066400000000000000000000040641313473450000230350ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\TableDiff; /** * Provides the behavior, features and SQL dialect of the MySQL 5.7 database platform. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class MySQL57Platform extends MySqlPlatform { /** * {@inheritdoc} */ protected function getPreAlterTableRenameIndexForeignKeySQL(TableDiff $diff) { return array(); } /** * {@inheritdoc} */ protected function getPostAlterTableRenameIndexForeignKeySQL(TableDiff $diff) { return array(); } /** * {@inheritdoc} */ protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) { return array( 'ALTER TABLE ' . $tableName . ' RENAME INDEX ' . $oldIndexName . ' TO ' . $index->getQuotedName($this) ); } /** * {@inheritdoc} */ protected function getReservedKeywordsClass() { return 'Doctrine\DBAL\Platforms\Keywords\MySQL57Keywords'; } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php000066400000000000000000001013131313473450000227540ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\Schema\Identifier; use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Types\BlobType; use Doctrine\DBAL\Types\TextType; /** * 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 * @author Benjamin Eberlei * @todo Rename: MySQLPlatform */ class MySqlPlatform extends AbstractPlatform { const LENGTH_LIMIT_TINYTEXT = 255; const LENGTH_LIMIT_TEXT = 65535; const LENGTH_LIMIT_MEDIUMTEXT = 16777215; const LENGTH_LIMIT_TINYBLOB = 255; const LENGTH_LIMIT_BLOB = 65535; const LENGTH_LIMIT_MEDIUMBLOB = 16777215; /** * Adds MySQL-specific LIMIT clause to the query * 18446744073709551615 is 2^64-1 maximum of unsigned BIGINT the biggest limit possible */ protected function doModifyLimitQuery($query, $limit, $offset) { if ($limit !== null) { $query .= ' LIMIT ' . $limit; if ($offset !== null) { $query .= ' OFFSET ' . $offset; } } elseif ($offset !== null) { $query .= ' LIMIT 18446744073709551615 OFFSET ' . $offset; } return $query; } /** * {@inheritDoc} */ public function getIdentifierQuoteCharacter() { return '`'; } /** * {@inheritDoc} */ public function getRegexpExpression() { return 'RLIKE'; } /** * {@inheritDoc} */ public function getGuidExpression() { return 'UUID()'; } /** * {@inheritDoc} */ public function getLocateExpression($str, $substr, $startPos = false) { if ($startPos == false) { return 'LOCATE(' . $substr . ', ' . $str . ')'; } return 'LOCATE(' . $substr . ', ' . $str . ', '.$startPos.')'; } /** * {@inheritDoc} */ public function getConcatExpression() { $args = func_get_args(); return 'CONCAT(' . join(', ', (array) $args) . ')'; } /** * {@inheritdoc} */ protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) { $function = '+' === $operator ? 'DATE_ADD' : 'DATE_SUB'; return $function . '(' . $date . ', INTERVAL ' . $interval . ' ' . $unit . ')'; } /** * {@inheritDoc} */ public function getDateDiffExpression($date1, $date2) { return 'DATEDIFF(' . $date1 . ', ' . $date2 . ')'; } /** * {@inheritDoc} */ public function getListDatabasesSQL() { return 'SHOW DATABASES'; } /** * {@inheritDoc} */ public function getListTableConstraintsSQL($table) { return 'SHOW INDEX FROM ' . $table; } /** * {@inheritDoc} * * Two approaches to listing the table indexes. The information_schema is * preferred, because it doesn't cause problems with SQL keywords such as "order" or "table". */ public function getListTableIndexesSQL($table, $currentDatabase = null) { if ($currentDatabase) { $currentDatabase = $this->quoteStringLiteral($currentDatabase); $table = $this->quoteStringLiteral($table); 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; } return 'SHOW INDEX FROM ' . $table; } /** * {@inheritDoc} */ public function getListViewsSQL($database) { $database = $this->quoteStringLiteral($database); return "SELECT * FROM information_schema.VIEWS WHERE TABLE_SCHEMA = " . $database; } /** * {@inheritDoc} */ public function getListTableForeignKeysSQL($table, $database = null) { $table = $this->quoteStringLiteral($table); if (null !== $database) { $database = $this->quoteStringLiteral($database); } $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"; $databaseNameSql = null === $database ? 'DATABASE()' : $database; $sql .= " AND k.table_schema = $databaseNameSql /*!50116 AND c.constraint_schema = $databaseNameSql */"; $sql .= " AND k.`REFERENCED_COLUMN_NAME` is not NULL"; return $sql; } /** * {@inheritDoc} */ public function getCreateViewSQL($name, $sql) { return 'CREATE VIEW ' . $name . ' AS ' . $sql; } /** * {@inheritDoc} */ public function getDropViewSQL($name) { return 'DROP VIEW '. $name; } /** * {@inheritDoc} */ protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) { return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'); } /** * {@inheritdoc} */ protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) { return $fixed ? 'BINARY(' . ($length ?: 255) . ')' : 'VARBINARY(' . ($length ?: 255) . ')'; } /** * Gets the SQL snippet used to declare a CLOB column type. * TINYTEXT : 2 ^ 8 - 1 = 255 * TEXT : 2 ^ 16 - 1 = 65535 * MEDIUMTEXT : 2 ^ 24 - 1 = 16777215 * LONGTEXT : 2 ^ 32 - 1 = 4294967295 * * @param array $field * * @return string */ public function getClobTypeDeclarationSQL(array $field) { if ( ! empty($field['length']) && is_numeric($field['length'])) { $length = $field['length']; if ($length <= static::LENGTH_LIMIT_TINYTEXT) { return 'TINYTEXT'; } if ($length <= static::LENGTH_LIMIT_TEXT) { return 'TEXT'; } if ($length <= static::LENGTH_LIMIT_MEDIUMTEXT) { return 'MEDIUMTEXT'; } } return 'LONGTEXT'; } /** * {@inheritDoc} */ public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) { if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] == true) { return 'TIMESTAMP'; } return 'DATETIME'; } /** * {@inheritDoc} */ public function getDateTypeDeclarationSQL(array $fieldDeclaration) { return 'DATE'; } /** * {@inheritDoc} */ public function getTimeTypeDeclarationSQL(array $fieldDeclaration) { return 'TIME'; } /** * {@inheritDoc} */ 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. * * @deprecated Deprecated since version 2.5, Use {@link self::getColumnCollationDeclarationSQL()} instead. * * @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 $this->getColumnCollationDeclarationSQL($collation); } /** * {@inheritDoc} * * MySql prefers "autoincrement" identity columns since sequences can only * be emulated with a table. */ public function prefersIdentityColumns() { return true; } /** * {@inheritDoc} * * MySql supports this through AUTO_INCREMENT columns. */ public function supportsIdentityColumns() { return true; } /** * {@inheritDoc} */ public function supportsInlineColumnComments() { return true; } /** * {@inheritDoc} */ public function supportsColumnCollation() { return true; } public function getListTablesSQL() { return "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'"; } /** * {@inheritDoc} */ public function getListTableColumnsSQL($table, $database = null) { $table = $this->quoteStringLiteral($table); if ($database) { $database = $this->quoteStringLiteral($database); } else { $database = '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 Collation ". "FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = " . $database . " AND TABLE_NAME = " . $table; } /** * {@inheritDoc} */ public function getCreateDatabaseSQL($name) { return 'CREATE DATABASE ' . $name; } /** * {@inheritDoc} */ public function getDropDatabaseSQL($name) { return 'DROP DATABASE ' . $name; } /** * {@inheritDoc} */ 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 . ') '; $query .= $this->buildTableOptions($options); $query .= $this->buildPartitionOptions($options); $sql[] = $query; $engine = 'INNODB'; if (isset($options['engine'])) { $engine = strtoupper(trim($options['engine'])); } // Propagate foreign key constraints only for InnoDB. if (isset($options['foreignKeys']) && $engine === 'INNODB') { foreach ((array) $options['foreignKeys'] as $definition) { $sql[] = $this->getCreateForeignKeySQL($definition, $tableName); } } return $sql; } /** * {@inheritdoc} */ public function getDefaultValueDeclarationSQL($field) { // Unset the default value if the given field definition does not allow default values. if ($field['type'] instanceof TextType || $field['type'] instanceof BlobType) { $field['default'] = null; } return parent::getDefaultValueDeclarationSQL($field); } /** * Build SQL for table options * * @param array $options * * @return string */ private function buildTableOptions(array $options) { if (isset($options['table_options'])) { return $options['table_options']; } $tableOptions = array(); // Charset if ( ! isset($options['charset'])) { $options['charset'] = 'utf8'; } $tableOptions[] = sprintf('DEFAULT CHARACTER SET %s', $options['charset']); // Collate if ( ! isset($options['collate'])) { $options['collate'] = 'utf8_unicode_ci'; } $tableOptions[] = sprintf('COLLATE %s', $options['collate']); // Engine if ( ! isset($options['engine'])) { $options['engine'] = 'InnoDB'; } $tableOptions[] = sprintf('ENGINE = %s', $options['engine']); // Auto increment if (isset($options['auto_increment'])) { $tableOptions[] = sprintf('AUTO_INCREMENT = %s', $options['auto_increment']); } // Comment if (isset($options['comment'])) { $comment = trim($options['comment'], " '"); $tableOptions[] = sprintf("COMMENT = %s ", $this->quoteStringLiteral($comment)); } // Row format if (isset($options['row_format'])) { $tableOptions[] = sprintf('ROW_FORMAT = %s', $options['row_format']); } return implode(' ', $tableOptions); } /** * Build SQL for partition options. * * @param array $options * * @return string */ private function buildPartitionOptions(array $options) { return (isset($options['partition_options'])) ? ' ' . $options['partition_options'] : ''; } /** * {@inheritDoc} */ public function getAlterTableSQL(TableDiff $diff) { $columnSql = array(); $queryParts = array(); if ($diff->newName !== false) { $queryParts[] = 'RENAME TO ' . $diff->getNewName()->getQuotedName($this); } foreach ($diff->addedColumns as $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(); // Don't propagate default value changes for unsupported column types. if ($columnDiff->hasChanged('default') && count($columnDiff->changedProperties) === 1 && ($columnArray['type'] instanceof TextType || $columnArray['type'] instanceof BlobType) ) { continue; } $columnArray['comment'] = $this->getColumnComment($column); $queryParts[] = 'CHANGE ' . ($columnDiff->getOldColumnName()->getQuotedName($this)) . ' ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); } foreach ($diff->renamedColumns as $oldColumnName => $column) { if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { continue; } $oldColumnName = new Identifier($oldColumnName); $columnArray = $column->toArray(); $columnArray['comment'] = $this->getColumnComment($column); $queryParts[] = 'CHANGE ' . $oldColumnName->getQuotedName($this) . ' ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); } if (isset($diff->addedIndexes['primary'])) { $keyColumns = array_unique(array_values($diff->addedIndexes['primary']->getColumns())); $queryParts[] = 'ADD PRIMARY KEY (' . implode(', ', $keyColumns) . ')'; unset($diff->addedIndexes['primary']); } $sql = array(); $tableSql = array(); if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { if (count($queryParts) > 0) { $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . implode(", ", $queryParts); } $sql = array_merge( $this->getPreAlterTableIndexForeignKeySQL($diff), $sql, $this->getPostAlterTableIndexForeignKeySQL($diff) ); } return array_merge($sql, $tableSql, $columnSql); } /** * {@inheritDoc} */ protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) { $sql = array(); $table = $diff->getName($this)->getQuotedName($this); foreach ($diff->changedIndexes as $changedIndex) { $sql = array_merge($sql, $this->getPreAlterTableAlterPrimaryKeySQL($diff, $changedIndex)); } foreach ($diff->removedIndexes as $remKey => $remIndex) { $sql = array_merge($sql, $this->getPreAlterTableAlterPrimaryKeySQL($diff, $remIndex)); foreach ($diff->addedIndexes as $addKey => $addIndex) { if ($remIndex->getColumns() == $addIndex->getColumns()) { $indexClause = 'INDEX ' . $addIndex->getName(); if ($addIndex->isPrimary()) { $indexClause = 'PRIMARY KEY'; } elseif ($addIndex->isUnique()) { $indexClause = 'UNIQUE INDEX ' . $addIndex->getName(); } $query = 'ALTER TABLE ' . $table . ' DROP INDEX ' . $remIndex->getName() . ', '; $query .= 'ADD ' . $indexClause; $query .= ' (' . $this->getIndexFieldDeclarationListSQL($addIndex->getQuotedColumns($this)) . ')'; $sql[] = $query; unset($diff->removedIndexes[$remKey]); unset($diff->addedIndexes[$addKey]); break; } } } $engine = 'INNODB'; if ($diff->fromTable instanceof Table && $diff->fromTable->hasOption('engine')) { $engine = strtoupper(trim($diff->fromTable->getOption('engine'))); } // Suppress foreign key constraint propagation on non-supporting engines. if ('INNODB' !== $engine) { $diff->addedForeignKeys = array(); $diff->changedForeignKeys = array(); $diff->removedForeignKeys = array(); } $sql = array_merge( $sql, $this->getPreAlterTableAlterIndexForeignKeySQL($diff), parent::getPreAlterTableIndexForeignKeySQL($diff), $this->getPreAlterTableRenameIndexForeignKeySQL($diff) ); return $sql; } /** * @param TableDiff $diff * @param Index $index * * @return string[] */ private function getPreAlterTableAlterPrimaryKeySQL(TableDiff $diff, Index $index) { $sql = array(); if (! $index->isPrimary() || ! $diff->fromTable instanceof Table) { return $sql; } $tableName = $diff->getName($this)->getQuotedName($this); // Dropping primary keys requires to unset autoincrement attribute on the particular column first. foreach ($index->getColumns() as $columnName) { if (! $diff->fromTable->hasColumn($columnName)) { continue; } $column = $diff->fromTable->getColumn($columnName); if ($column->getAutoincrement() === true) { $column->setAutoincrement(false); $sql[] = 'ALTER TABLE ' . $tableName . ' MODIFY ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); // original autoincrement information might be needed later on by other parts of the table alteration $column->setAutoincrement(true); } } return $sql; } /** * @param TableDiff $diff The table diff to gather the SQL for. * * @return array */ private function getPreAlterTableAlterIndexForeignKeySQL(TableDiff $diff) { $sql = array(); $table = $diff->getName($this)->getQuotedName($this); foreach ($diff->changedIndexes as $changedIndex) { // Changed primary key if ($changedIndex->isPrimary() && $diff->fromTable instanceof Table) { foreach ($diff->fromTable->getPrimaryKeyColumns() as $columnName) { $column = $diff->fromTable->getColumn($columnName); // Check if an autoincrement column was dropped from the primary key. if ($column->getAutoincrement() && ! in_array($columnName, $changedIndex->getColumns())) { // The autoincrement attribute needs to be removed from the dropped column // before we can drop and recreate the primary key. $column->setAutoincrement(false); $sql[] = 'ALTER TABLE ' . $table . ' MODIFY ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); // Restore the autoincrement attribute as it might be needed later on // by other parts of the table alteration. $column->setAutoincrement(true); } } } } return $sql; } /** * @param TableDiff $diff The table diff to gather the SQL for. * * @return array */ protected function getPreAlterTableRenameIndexForeignKeySQL(TableDiff $diff) { $sql = array(); $tableName = $diff->getName($this)->getQuotedName($this); foreach ($this->getRemainingForeignKeyConstraintsRequiringRenamedIndexes($diff) as $foreignKey) { if (! in_array($foreignKey, $diff->changedForeignKeys, true)) { $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName); } } return $sql; } /** * Returns the remaining foreign key constraints that require one of the renamed indexes. * * "Remaining" here refers to the diff between the foreign keys currently defined in the associated * table and the foreign keys to be removed. * * @param TableDiff $diff The table diff to evaluate. * * @return array */ private function getRemainingForeignKeyConstraintsRequiringRenamedIndexes(TableDiff $diff) { if (empty($diff->renamedIndexes) || ! $diff->fromTable instanceof Table) { return array(); } $foreignKeys = array(); /** @var \Doctrine\DBAL\Schema\ForeignKeyConstraint[] $remainingForeignKeys */ $remainingForeignKeys = array_diff_key( $diff->fromTable->getForeignKeys(), $diff->removedForeignKeys ); foreach ($remainingForeignKeys as $foreignKey) { foreach ($diff->renamedIndexes as $index) { if ($foreignKey->intersectsIndexColumns($index)) { $foreignKeys[] = $foreignKey; break; } } } return $foreignKeys; } /** * {@inheritdoc} */ protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff) { return array_merge( parent::getPostAlterTableIndexForeignKeySQL($diff), $this->getPostAlterTableRenameIndexForeignKeySQL($diff) ); } /** * @param TableDiff $diff The table diff to gather the SQL for. * * @return array */ protected function getPostAlterTableRenameIndexForeignKeySQL(TableDiff $diff) { $sql = array(); $tableName = (false !== $diff->newName) ? $diff->getNewName()->getQuotedName($this) : $diff->getName($this)->getQuotedName($this); foreach ($this->getRemainingForeignKeyConstraintsRequiringRenamedIndexes($diff) as $foreignKey) { if (! in_array($foreignKey, $diff->changedForeignKeys, true)) { $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName); } } return $sql; } /** * {@inheritDoc} */ protected function getCreateIndexSQLFlags(Index $index) { $type = ''; if ($index->isUnique()) { $type .= 'UNIQUE '; } elseif ($index->hasFlag('fulltext')) { $type .= 'FULLTEXT '; } elseif ($index->hasFlag('spatial')) { $type .= 'SPATIAL '; } return $type; } /** * {@inheritDoc} */ public function getIntegerTypeDeclarationSQL(array $field) { return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field); } /** * {@inheritDoc} */ public function getBigIntTypeDeclarationSQL(array $field) { return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); } /** * {@inheritDoc} */ public function getSmallIntTypeDeclarationSQL(array $field) { return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); } /** * {@inheritDoc} */ protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) { $autoinc = ''; if ( ! empty($columnDef['autoincrement'])) { $autoinc = ' AUTO_INCREMENT'; } $unsigned = (isset($columnDef['unsigned']) && $columnDef['unsigned']) ? ' UNSIGNED' : ''; return $unsigned . $autoinc; } /** * {@inheritDoc} */ public function getAdvancedForeignKeyOptionsSQL(\Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey) { $query = ''; if ($foreignKey->hasOption('match')) { $query .= ' MATCH ' . $foreignKey->getOption('match'); } $query .= parent::getAdvancedForeignKeyOptionsSQL($foreignKey); return $query; } /** * {@inheritDoc} */ public function getDropIndexSQL($index, $table=null) { if ($index instanceof Index) { $indexName = $index->getQuotedName($this); } elseif (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); } elseif (!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 string $table * * @return string */ protected function getDropPrimaryKeySQL($table) { return 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY'; } /** * {@inheritDoc} */ public function getSetTransactionIsolationSQL($level) { return 'SET SESSION TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level); } /** * {@inheritDoc} */ public function getName() { return 'mysql'; } /** * {@inheritDoc} */ public function getReadLockSQL() { return 'LOCK IN SHARE MODE'; } /** * {@inheritDoc} */ 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', 'binary' => 'binary', 'varbinary' => 'binary', 'set' => 'simple_array', ); } /** * {@inheritDoc} */ public function getVarcharMaxLength() { return 65535; } /** * {@inheritdoc} */ public function getBinaryMaxLength() { return 65535; } /** * {@inheritDoc} */ protected function getReservedKeywordsClass() { return 'Doctrine\DBAL\Platforms\Keywords\MySQLKeywords'; } /** * {@inheritDoc} * * MySQL commits a transaction implicitly when DROP TABLE is executed, however not * if DROP TEMPORARY TABLE is executed. */ public function getDropTemporaryTableSQL($table) { if ($table instanceof Table) { $table = $table->getQuotedName($this); } elseif (!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. * TINYBLOB : 2 ^ 8 - 1 = 255 * BLOB : 2 ^ 16 - 1 = 65535 * MEDIUMBLOB : 2 ^ 24 - 1 = 16777215 * LONGBLOB : 2 ^ 32 - 1 = 4294967295 * * @param array $field * * @return string */ public function getBlobTypeDeclarationSQL(array $field) { if ( ! empty($field['length']) && is_numeric($field['length'])) { $length = $field['length']; if ($length <= static::LENGTH_LIMIT_TINYBLOB) { return 'TINYBLOB'; } if ($length <= static::LENGTH_LIMIT_BLOB) { return 'BLOB'; } if ($length <= static::LENGTH_LIMIT_MEDIUMBLOB) { return 'MEDIUMBLOB'; } } return 'LONGBLOB'; } /** * {@inheritdoc} */ public function quoteStringLiteral($str) { $str = str_replace('\\', '\\\\', $str); // MySQL requires backslashes to be escaped aswell. return parent::quoteStringLiteral($str); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/OraclePlatform.php000066400000000000000000001031261313473450000231200ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\Identifier; use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\Sequence; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Types\BinaryType; /** * OraclePlatform. * * @since 2.0 * @author Roman Borschel * @author Lukas Smith (PEAR MDB2 library) * @author Benjamin Eberlei */ class OraclePlatform extends AbstractPlatform { /** * Assertion for Oracle identifiers. * * @link http://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements008.htm * * @param string $identifier * * @throws DBALException */ static public function assertValidIdentifier($identifier) { if ( ! preg_match('(^(([a-zA-Z]{1}[a-zA-Z0-9_$#]{0,})|("[^"]+"))$)', $identifier)) { throw new DBALException("Invalid Oracle identifier"); } } /** * {@inheritDoc} */ public function getSubstringExpression($value, $position, $length = null) { if ($length !== null) { return "SUBSTR($value, $position, $length)"; } return "SUBSTR($value, $position)"; } /** * {@inheritDoc} */ 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\')'; } } /** * {@inheritDoc} */ public function getLocateExpression($str, $substr, $startPos = false) { if ($startPos == false) { return 'INSTR('.$str.', '.$substr.')'; } return 'INSTR('.$str.', '.$substr.', '.$startPos.')'; } /** * {@inheritDoc} */ public function getGuidExpression() { return 'SYS_GUID()'; } /** * {@inheritdoc} */ protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) { switch ($unit) { case self::DATE_INTERVAL_UNIT_MONTH: case self::DATE_INTERVAL_UNIT_QUARTER: case self::DATE_INTERVAL_UNIT_YEAR: switch ($unit) { case self::DATE_INTERVAL_UNIT_QUARTER: $interval *= 3; break; case self::DATE_INTERVAL_UNIT_YEAR: $interval *= 12; break; } return 'ADD_MONTHS(' . $date . ', ' . $operator . $interval . ')'; default: $calculationClause = ''; switch ($unit) { case self::DATE_INTERVAL_UNIT_SECOND: $calculationClause = '/24/60/60'; break; case self::DATE_INTERVAL_UNIT_MINUTE: $calculationClause = '/24/60'; break; case self::DATE_INTERVAL_UNIT_HOUR: $calculationClause = '/24'; break; case self::DATE_INTERVAL_UNIT_WEEK: $calculationClause = '*7'; break; } return '(' . $date . $operator . $interval . $calculationClause . ')'; } } /** * {@inheritDoc} * * 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. */ public function getDateDiffExpression($date1, $date2) { return "TRUNC(TO_NUMBER(SUBSTR((" . $date1 . "-" . $date2 . "), 1, INSTR(" . $date1 . "-" . $date2 .", ' '))))"; } /** * {@inheritDoc} */ public function getBitAndComparisonExpression($value1, $value2) { return 'BITAND('.$value1 . ', ' . $value2 . ')'; } /** * {@inheritDoc} */ public function getBitOrComparisonExpression($value1, $value2) { return '(' . $value1 . '-' . $this->getBitAndComparisonExpression($value1, $value2) . '+' . $value2 . ')'; } /** * {@inheritDoc} * * 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()} */ public function getCreateSequenceSQL(Sequence $sequence) { return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) . ' START WITH ' . $sequence->getInitialValue() . ' MINVALUE ' . $sequence->getInitialValue() . ' INCREMENT BY ' . $sequence->getAllocationSize() . $this->getSequenceCacheSQL($sequence); } /** * {@inheritDoc} */ public function getAlterSequenceSQL(Sequence $sequence) { return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) . ' INCREMENT BY ' . $sequence->getAllocationSize() . $this->getSequenceCacheSQL($sequence); } /** * Cache definition for sequences * * @param Sequence $sequence * * @return string */ private function getSequenceCacheSQL(Sequence $sequence) { if ($sequence->getCache() === 0) { return ' NOCACHE'; } else if ($sequence->getCache() === 1) { return ' NOCACHE'; } else if ($sequence->getCache() > 1) { return ' CACHE ' . $sequence->getCache(); } return ''; } /** * {@inheritDoc} */ public function getSequenceNextValSQL($sequenceName) { return 'SELECT ' . $sequenceName . '.nextval FROM DUAL'; } /** * {@inheritDoc} */ public function getSetTransactionIsolationSQL($level) { return 'SET TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level); } /** * {@inheritDoc} */ 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); } } /** * {@inheritDoc} */ public function getBooleanTypeDeclarationSQL(array $field) { return 'NUMBER(1)'; } /** * {@inheritDoc} */ public function getIntegerTypeDeclarationSQL(array $field) { return 'NUMBER(10)'; } /** * {@inheritDoc} */ public function getBigIntTypeDeclarationSQL(array $field) { return 'NUMBER(20)'; } /** * {@inheritDoc} */ public function getSmallIntTypeDeclarationSQL(array $field) { return 'NUMBER(5)'; } /** * {@inheritDoc} */ public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) { return 'TIMESTAMP(0)'; } /** * {@inheritDoc} */ public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration) { return 'TIMESTAMP(0) WITH TIME ZONE'; } /** * {@inheritDoc} */ public function getDateTypeDeclarationSQL(array $fieldDeclaration) { return 'DATE'; } /** * {@inheritDoc} */ public function getTimeTypeDeclarationSQL(array $fieldDeclaration) { return 'DATE'; } /** * {@inheritDoc} */ protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) { return ''; } /** * {@inheritDoc} */ protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) { return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(2000)') : ($length ? 'VARCHAR2(' . $length . ')' : 'VARCHAR2(4000)'); } /** * {@inheritdoc} */ protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) { return 'RAW(' . ($length ?: $this->getBinaryMaxLength()) . ')'; } /** * {@inheritdoc} */ public function getBinaryMaxLength() { return 2000; } /** * {@inheritDoc} */ public function getClobTypeDeclarationSQL(array $field) { return 'CLOB'; } /** * {@inheritDoc} */ public function getListDatabasesSQL() { return 'SELECT username FROM all_users'; } /** * {@inheritDoc} */ public function getListSequencesSQL($database) { $database = $this->normalizeIdentifier($database); $database = $this->quoteStringLiteral($database->getName()); return "SELECT sequence_name, min_value, increment_by FROM sys.all_sequences ". "WHERE SEQUENCE_OWNER = " . $database; } /** * {@inheritDoc} */ 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 $index) { $sql[] = $this->getCreateIndexSQL($index, $table); } } return $sql; } /** * {@inheritDoc} * * @license New BSD License * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaOracleReader.html */ public function getListTableIndexesSQL($table, $currentDatabase = null) { $table = $this->normalizeIdentifier($table); $table = $this->quoteStringLiteral($table->getName()); return "SELECT uind_col.index_name AS name, ( SELECT uind.index_type FROM user_indexes uind WHERE uind.index_name = uind_col.index_name ) AS type, decode( ( SELECT uind.uniqueness FROM user_indexes uind WHERE uind.index_name = uind_col.index_name ), '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.index_name = uind_col.index_name ) AS is_primary FROM user_ind_columns uind_col WHERE uind_col.table_name = " . $table . " ORDER BY uind_col.column_position ASC"; } /** * {@inheritDoc} */ public function getListTablesSQL() { return 'SELECT * FROM sys.user_tables'; } /** * {@inheritDoc} */ public function getListViewsSQL($database) { return 'SELECT view_name, text FROM sys.user_views'; } /** * {@inheritDoc} */ public function getCreateViewSQL($name, $sql) { return 'CREATE VIEW ' . $name . ' AS ' . $sql; } /** * {@inheritDoc} */ public function getDropViewSQL($name) { return 'DROP VIEW '. $name; } /** * @param string $name * @param string $table * @param integer $start * * @return array */ public function getCreateAutoincrementSql($name, $table, $start = 1) { $tableIdentifier = $this->normalizeIdentifier($table); $quotedTableName = $tableIdentifier->getQuotedName($this); $unquotedTableName = $tableIdentifier->getName(); $nameIdentifier = $this->normalizeIdentifier($name); $quotedName = $nameIdentifier->getQuotedName($this); $unquotedName = $nameIdentifier->getName(); $sql = array(); $autoincrementIdentifierName = $this->getAutoincrementIdentifierName($tableIdentifier); $idx = new Index($autoincrementIdentifierName, array($quotedName), true, true); $sql[] = 'DECLARE constraints_Count NUMBER; BEGIN SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = \'' . $unquotedTableName . '\' AND CONSTRAINT_TYPE = \'P\'; IF constraints_Count = 0 OR constraints_Count = \'\' THEN EXECUTE IMMEDIATE \''.$this->getCreateConstraintSQL($idx, $quotedTableName).'\'; END IF; END;'; $sequenceName = $this->getIdentitySequenceName( $tableIdentifier->isQuoted() ? $quotedTableName : $unquotedTableName, $nameIdentifier->isQuoted() ? $quotedName : $unquotedName ); $sequence = new Sequence($sequenceName, $start); $sql[] = $this->getCreateSequenceSQL($sequence); $sql[] = 'CREATE TRIGGER ' . $autoincrementIdentifierName . ' BEFORE INSERT ON ' . $quotedTableName . ' FOR EACH ROW DECLARE last_Sequence NUMBER; last_InsertID NUMBER; BEGIN SELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $quotedName . ' FROM DUAL; IF (:NEW.' . $quotedName . ' IS NULL OR :NEW.'.$quotedName.' = 0) THEN SELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $quotedName . ' FROM DUAL; ELSE SELECT NVL(Last_Number, 0) INTO last_Sequence FROM User_Sequences WHERE Sequence_Name = \'' . $sequence->getName() . '\'; SELECT :NEW.' . $quotedName . ' 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; } /** * Returns the SQL statements to drop the autoincrement for the given table name. * * @param string $table The table name to drop the autoincrement for. * * @return array */ public function getDropAutoincrementSql($table) { $table = $this->normalizeIdentifier($table); $autoincrementIdentifierName = $this->getAutoincrementIdentifierName($table); $identitySequenceName = $this->getIdentitySequenceName( $table->isQuoted() ? $table->getQuotedName($this) : $table->getName(), '' ); return array( 'DROP TRIGGER ' . $autoincrementIdentifierName, $this->getDropSequenceSQL($identitySequenceName), $this->getDropConstraintSQL($autoincrementIdentifierName, $table->getQuotedName($this)), ); } /** * Normalizes the given identifier. * * Uppercases the given identifier if it is not quoted by intention * to reflect Oracle's internal auto uppercasing strategy of unquoted identifiers. * * @param string $name The identifier to normalize. * * @return Identifier The normalized identifier. */ private function normalizeIdentifier($name) { $identifier = new Identifier($name); return $identifier->isQuoted() ? $identifier : new Identifier(strtoupper($name)); } /** * Returns the autoincrement primary key identifier name for the given table identifier. * * Quotes the autoincrement primary key identifier name * if the given table name is quoted by intention. * * @param Identifier $table The table identifier to return the autoincrement primary key identifier name for. * * @return string */ private function getAutoincrementIdentifierName(Identifier $table) { $identifierName = $table->getName() . '_AI_PK'; return $table->isQuoted() ? $this->quoteSingleIdentifier($identifierName) : $identifierName; } /** * {@inheritDoc} */ public function getListTableForeignKeysSQL($table) { $table = $this->normalizeIdentifier($table); $table = $this->quoteStringLiteral($table->getName()); 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 . " ORDER BY cols.constraint_name ASC, cols.position ASC"; } /** * {@inheritDoc} */ public function getListTableConstraintsSQL($table) { $table = $this->normalizeIdentifier($table); $table = $this->quoteStringLiteral($table->getName()); return "SELECT * FROM user_constraints WHERE table_name = " . $table; } /** * {@inheritDoc} */ public function getListTableColumnsSQL($table, $database = null) { $table = $this->normalizeIdentifier($table); $table = $this->quoteStringLiteral($table->getName()); $tabColumnsTableName = "user_tab_columns"; $colCommentsTableName = "user_col_comments"; $tabColumnsOwnerCondition = ''; $colCommentsOwnerCondition = ''; if (null !== $database && '/' !== $database) { $database = $this->normalizeIdentifier($database); $database = $this->quoteStringLiteral($database->getName()); $tabColumnsTableName = "all_tab_columns"; $colCommentsTableName = "all_col_comments"; $tabColumnsOwnerCondition = "AND c.owner = " . $database; $colCommentsOwnerCondition = "AND d.OWNER = c.OWNER"; } return "SELECT c.*, ( SELECT d.comments FROM $colCommentsTableName d WHERE d.TABLE_NAME = c.TABLE_NAME " . $colCommentsOwnerCondition . " AND d.COLUMN_NAME = c.COLUMN_NAME ) AS comments FROM $tabColumnsTableName c WHERE c.table_name = " . $table . " $tabColumnsOwnerCondition ORDER BY c.column_id"; } /** * {@inheritDoc} */ public function getDropSequenceSQL($sequence) { if ($sequence instanceof Sequence) { $sequence = $sequence->getQuotedName($this); } return 'DROP SEQUENCE ' . $sequence; } /** * {@inheritDoc} */ public function getDropForeignKeySQL($foreignKey, $table) { if (! $foreignKey instanceof ForeignKeyConstraint) { $foreignKey = new Identifier($foreignKey); } if (! $table instanceof Table) { $table = new Identifier($table); } $foreignKey = $foreignKey->getQuotedName($this); $table = $table->getQuotedName($this); return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $foreignKey; } /** * {@inheritdoc} */ public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey) { $referentialAction = null; if ($foreignKey->hasOption('onDelete')) { $referentialAction = $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onDelete')); } return $referentialAction ? ' ON DELETE ' . $referentialAction : ''; } /** * {@inheritdoc} */ public function getForeignKeyReferentialActionSQL($action) { $action = strtoupper($action); switch ($action) { case 'RESTRICT': // RESTRICT is not supported, therefore falling back to NO ACTION. case 'NO ACTION': // NO ACTION cannot be declared explicitly, // therefore returning empty string to indicate to OMIT the referential clause. return ''; case 'CASCADE': case 'SET NULL': return $action; default: // SET DEFAULT is not supported, throw exception instead. throw new \InvalidArgumentException('Invalid foreign key action: ' . $action); } } /** * {@inheritDoc} */ public function getDropDatabaseSQL($database) { return 'DROP USER ' . $database . ' CASCADE'; } /** * {@inheritDoc} */ 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->getName($this)->getQuotedName($this), $column->getQuotedName($this), $comment ); } } if (count($fields)) { $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ADD (' . implode(', ', $fields) . ')'; } $fields = array(); foreach ($diff->changedColumns as $columnDiff) { if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { continue; } /* @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */ $column = $columnDiff->column; // Do not generate column alteration clause if type is binary and only fixed property has changed. // Oracle only supports binary type columns with variable length. // Avoids unnecessary table alteration statements. if ($column->getType() instanceof BinaryType && $columnDiff->hasChanged('fixed') && count($columnDiff->changedProperties) === 1 ) { continue; } $columnHasChangedComment = $columnDiff->hasChanged('comment'); /** * Do not add query part if only comment has changed */ if ( ! ($columnHasChangedComment && count($columnDiff->changedProperties) === 1)) { $columnInfo = $column->toArray(); if ( ! $columnDiff->hasChanged('notnull')) { unset($columnInfo['notnull']); } $fields[] = $column->getQuotedName($this) . $this->getColumnDeclarationSQL('', $columnInfo); } if ($columnHasChangedComment) { $commentsSQL[] = $this->getCommentOnColumnSQL( $diff->getName($this)->getQuotedName($this), $column->getQuotedName($this), $this->getColumnComment($column) ); } } if (count($fields)) { $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' MODIFY (' . implode(', ', $fields) . ')'; } foreach ($diff->renamedColumns as $oldColumnName => $column) { if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { continue; } $oldColumnName = new Identifier($oldColumnName); $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' RENAME COLUMN ' . $oldColumnName->getQuotedName($this) .' 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->getName($this)->getQuotedName($this) . ' DROP (' . implode(', ', $fields).')'; } $tableSql = array(); if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { $sql = array_merge($sql, $commentsSQL); if ($diff->newName !== false) { $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' RENAME TO ' . $diff->getNewName()->getQuotedName($this); } $sql = array_merge( $this->getPreAlterTableIndexForeignKeySQL($diff), $sql, $this->getPostAlterTableIndexForeignKeySQL($diff) ); } return array_merge($sql, $tableSql, $columnSql); } /** * {@inheritdoc} */ public function getColumnDeclarationSQL($name, array $field) { if (isset($field['columnDefinition'])) { $columnDef = $this->getCustomTypeDeclarationSQL($field); } else { $default = $this->getDefaultValueDeclarationSQL($field); $notnull = ''; if (isset($field['notnull'])) { $notnull = $field['notnull'] ? ' NOT NULL' : ' NULL'; } $unique = (isset($field['unique']) && $field['unique']) ? ' ' . $this->getUniqueFieldDeclarationSQL() : ''; $check = (isset($field['check']) && $field['check']) ? ' ' . $field['check'] : ''; $typeDecl = $field['type']->getSqlDeclaration($field, $this); $columnDef = $typeDecl . $default . $notnull . $unique . $check; } return $name . ' ' . $columnDef; } /** * {@inheritdoc} */ protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) { if (strpos($tableName, '.') !== false) { list($schema) = explode('.', $tableName); $oldIndexName = $schema . '.' . $oldIndexName; } return array('ALTER INDEX ' . $oldIndexName . ' RENAME TO ' . $index->getQuotedName($this)); } /** * {@inheritDoc} */ public function prefersSequences() { return true; } /** * {@inheritdoc} */ public function usesSequenceEmulatedIdentityColumns() { return true; } /** * {@inheritdoc} */ public function getIdentitySequenceName($tableName, $columnName) { $table = new Identifier($tableName); // No usage of column name to preserve BC compatibility with <2.5 $identitySequenceName = $table->getName() . '_SEQ'; if ($table->isQuoted()) { $identitySequenceName = '"' . $identitySequenceName . '"'; } $identitySequenceIdentifier = $this->normalizeIdentifier($identitySequenceName); return $identitySequenceIdentifier->getQuotedName($this); } /** * {@inheritDoc} */ public function supportsCommentOnStatement() { return true; } /** * {@inheritDoc} */ public function getName() { return 'oracle'; } /** * {@inheritDoc} */ protected function doModifyLimitQuery($query, $limit, $offset = null) { if ($limit === null && $offset === null) { return $query; } if (preg_match('/^\s*SELECT/i', $query)) { if (!preg_match('/\sFROM\s/i', $query)) { $query .= " FROM dual"; } $columns = array('a.*'); if ($offset > 0) { $columns[] = 'ROWNUM AS doctrine_rownum'; } $query = sprintf('SELECT %s FROM (%s) a', implode(', ', $columns), $query); if ($limit !== null) { $query .= sprintf(' WHERE ROWNUM <= %d', $offset + $limit); } if ($offset > 0) { $query = sprintf('SELECT * FROM (%s) WHERE doctrine_rownum >= %d', $query, $offset + 1); } } return $query; } /** * {@inheritDoc} * * Oracle returns all column names in SQL result sets in uppercase. */ public function getSQLResultCasing($column) { return strtoupper($column); } /** * {@inheritDoc} */ public function getCreateTemporaryTableSnippetSQL() { return "CREATE GLOBAL TEMPORARY TABLE"; } /** * {@inheritDoc} */ public function getDateTimeTzFormatString() { return 'Y-m-d H:i:sP'; } /** * {@inheritDoc} */ public function getDateFormatString() { return 'Y-m-d 00:00:00'; } /** * {@inheritDoc} */ public function getTimeFormatString() { return '1900-01-01 H:i:s'; } /** * {@inheritDoc} */ public function fixSchemaElementName($schemaElementName) { if (strlen($schemaElementName) > 30) { // Trim it return substr($schemaElementName, 0, 30); } return $schemaElementName; } /** * {@inheritDoc} */ public function getMaxIdentifierLength() { return 30; } /** * {@inheritDoc} */ public function supportsSequences() { return true; } /** * {@inheritDoc} */ public function supportsForeignKeyOnUpdate() { return false; } /** * {@inheritDoc} */ public function supportsReleaseSavepoints() { return false; } /** * {@inheritDoc} */ public function getTruncateTableSQL($tableName, $cascade = false) { $tableIdentifier = new Identifier($tableName); return 'TRUNCATE TABLE ' . $tableIdentifier->getQuotedName($this); } /** * {@inheritDoc} */ public function getDummySelectSQL() { return 'SELECT 1 FROM DUAL'; } /** * {@inheritDoc} */ 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' => 'date', 'timestamp' => 'datetime', 'timestamptz' => 'datetimetz', 'float' => 'float', 'binary_float' => 'float', 'binary_double' => 'float', 'long' => 'string', 'clob' => 'text', 'nclob' => 'text', 'raw' => 'binary', 'long raw' => 'blob', 'rowid' => 'string', 'urowid' => 'string', 'blob' => 'blob', ); } /** * {@inheritDoc} */ public function releaseSavePoint($savepoint) { return ''; } /** * {@inheritDoc} */ protected function getReservedKeywordsClass() { return 'Doctrine\DBAL\Platforms\Keywords\OracleKeywords'; } /** * {@inheritDoc} */ public function getBlobTypeDeclarationSQL(array $field) { return 'BLOB'; } /** * {@inheritdoc} */ public function quoteStringLiteral($str) { $str = str_replace('\\', '\\\\', $str); // Oracle requires backslashes to be escaped aswell. return parent::quoteStringLiteral($str); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/PostgreSQL91Platform.php000066400000000000000000000041561313473450000240730ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms; /** * Provides the behavior, features and SQL dialect of the PostgreSQL 9.1 database platform. * * @author Martin Hasoň * @link www.doctrine-project.org * @since 2.5 */ class PostgreSQL91Platform extends PostgreSqlPlatform { /** * {@inheritDoc} */ public function supportsColumnCollation() { return true; } /** * {@inheritdoc} */ protected function getReservedKeywordsClass() { return 'Doctrine\DBAL\Platforms\Keywords\PostgreSQL91Keywords'; } /** * {@inheritDoc} */ public function getColumnCollationDeclarationSQL($collation) { return 'COLLATE ' . $this->quoteSingleIdentifier($collation); } /** * {@inheritDoc} */ public function getListTableColumnsSQL($table, $database = null) { $sql = parent::getListTableColumnsSQL($table, $database); $parts = explode('AS complete_type,', $sql, 2); return $parts[0].'AS complete_type, (SELECT tc.collcollate FROM pg_catalog.pg_collation tc WHERE tc.oid = a.attcollation) AS collation,'.$parts[1]; } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/PostgreSQL92Platform.php000066400000000000000000000046431313473450000240750ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms; /** * Provides the behavior, features and SQL dialect of the PostgreSQL 9.2 database platform. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class PostgreSQL92Platform extends PostgreSQL91Platform { /** * {@inheritdoc} */ public function getJsonTypeDeclarationSQL(array $field) { return 'JSON'; } /** * {@inheritdoc} */ public function getSmallIntTypeDeclarationSQL(array $field) { if ( ! empty($field['autoincrement'])) { return 'SMALLSERIAL'; } return parent::getSmallIntTypeDeclarationSQL($field); } /** * {@inheritdoc} */ public function hasNativeJsonType() { return true; } /** * {@inheritdoc} */ protected function getReservedKeywordsClass() { return 'Doctrine\DBAL\Platforms\Keywords\PostgreSQL92Keywords'; } /** * {@inheritdoc} */ protected function initializeDoctrineTypeMappings() { parent::initializeDoctrineTypeMappings(); $this->doctrineTypeMapping['json'] = 'json_array'; } /** * {@inheritdoc} */ public function getCloseActiveDatabaseConnectionsSQL($database) { $database = $this->quoteStringLiteral($database); return "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = $database"; } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php000066400000000000000000001046471313473450000240270ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\ColumnDiff; use Doctrine\DBAL\Schema\Identifier; use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\Sequence; use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\Types\BinaryType; use Doctrine\DBAL\Types\BlobType; /** * PostgreSqlPlatform. * * @since 2.0 * @author Roman Borschel * @author Lukas Smith (PEAR MDB2 library) * @author Benjamin Eberlei * @todo Rename: PostgreSQLPlatform */ class PostgreSqlPlatform extends AbstractPlatform { /** * @var bool */ private $useBooleanTrueFalseStrings = true; /** * @var array PostgreSQL booleans literals */ private $booleanLiterals = array( 'true' => array( 't', 'true', 'y', 'yes', 'on', '1' ), 'false' => array( 'f', 'false', 'n', 'no', 'off', '0' ) ); /** * PostgreSQL has different behavior with some drivers * with regard to how booleans have to be handled. * * Enables use of 'true'/'false' or otherwise 1 and 0 instead. * * @param bool $flag */ public function setUseBooleanTrueFalseStrings($flag) { $this->useBooleanTrueFalseStrings = (bool) $flag; } /** * {@inheritDoc} */ public function getSubstringExpression($value, $from, $length = null) { if ($length === null) { return 'SUBSTRING(' . $value . ' FROM ' . $from . ')'; } return 'SUBSTRING(' . $value . ' FROM ' . $from . ' FOR ' . $length . ')'; } /** * {@inheritDoc} */ public function getNowExpression() { return 'LOCALTIMESTAMP(0)'; } /** * {@inheritDoc} */ public function getRegexpExpression() { return 'SIMILAR TO'; } /** * {@inheritDoc} */ 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'; } return 'POSITION('.$substr.' IN '.$str.')'; } /** * {@inheritdoc} */ protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) { if (self::DATE_INTERVAL_UNIT_QUARTER === $unit) { $interval *= 3; $unit = self::DATE_INTERVAL_UNIT_MONTH; } return "(" . $date ." " . $operator . " (" . $interval . " || ' " . $unit . "')::interval)"; } /** * {@inheritDoc} */ public function getDateDiffExpression($date1, $date2) { return '(DATE(' . $date1 . ')-DATE(' . $date2 . '))'; } /** * {@inheritDoc} */ public function supportsSequences() { return true; } /** * {@inheritDoc} */ public function supportsSchemas() { return true; } /** * {@inheritdoc} */ public function getDefaultSchemaName() { return 'public'; } /** * {@inheritDoc} */ public function supportsIdentityColumns() { return true; } /** * {@inheritdoc} */ public function supportsPartialIndexes() { return true; } /** * {@inheritdoc} */ public function usesSequenceEmulatedIdentityColumns() { return true; } /** * {@inheritdoc} */ public function getIdentitySequenceName($tableName, $columnName) { return $tableName . '_' . $columnName . '_seq'; } /** * {@inheritDoc} */ public function supportsCommentOnStatement() { return true; } /** * {@inheritDoc} */ public function prefersSequences() { return true; } /** * {@inheritDoc} */ public function hasNativeGuidType() { return true; } /** * {@inheritDoc} */ public function getListDatabasesSQL() { return 'SELECT datname FROM pg_database'; } /** * {@inheritDoc} */ public function getListNamespacesSQL() { return "SELECT schema_name AS nspname FROM information_schema.schemata WHERE schema_name NOT LIKE 'pg\_%' AND schema_name != 'information_schema'"; } /** * {@inheritDoc} */ public function getListSequencesSQL($database) { return "SELECT sequence_name AS relname, sequence_schema AS schemaname FROM information_schema.sequences WHERE sequence_schema NOT LIKE 'pg\_%' AND sequence_schema != 'information_schema'"; } /** * {@inheritDoc} */ public function getListTablesSQL() { return "SELECT quote_ident(table_name) AS table_name, table_schema AS schema_name FROM information_schema.tables WHERE table_schema NOT LIKE 'pg\_%' AND table_schema != 'information_schema' AND table_name != 'geometry_columns' AND table_name != 'spatial_ref_sys' AND table_type != 'VIEW'"; } /** * {@inheritDoc} */ public function getListViewsSQL($database) { return 'SELECT quote_ident(table_name) AS viewname, table_schema AS schemaname, view_definition AS definition FROM information_schema.views WHERE view_definition IS NOT NULL'; } /** * {@inheritDoc} */ public function getListTableForeignKeysSQL($table, $database = null) { return "SELECT quote_ident(r.conname) as 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'"; } /** * {@inheritDoc} */ public function getCreateViewSQL($name, $sql) { return 'CREATE VIEW ' . $name . ' AS ' . $sql; } /** * {@inheritDoc} */ public function getDropViewSQL($name) { return 'DROP VIEW '. $name; } /** * {@inheritDoc} */ public function getListTableConstraintsSQL($table) { $table = new Identifier($table); $table = $this->quoteStringLiteral($table->getName()); return "SELECT quote_ident(relname) as 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') )"; } /** * {@inheritDoc} * * @license New BSD License * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html */ public function getListTableIndexesSQL($table, $currentDatabase = null) { return "SELECT quote_ident(relname) as relname, pg_index.indisunique, pg_index.indisprimary, pg_index.indkey, pg_index.indrelid, pg_get_expr(indpred, indrelid) AS where 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 = $this->quoteStringLiteral($schema); } else { $schema = "ANY(string_to_array((select replace(replace(setting,'\"\$user\"',user),' ','') from pg_catalog.pg_settings where name = 'search_path'),','))"; } $table = new Identifier($table); $table = $this->quoteStringLiteral($table->getName()); $whereClause .= "$classAlias.relname = " . $table . " AND $namespaceAlias.nspname = $schema"; return $whereClause; } /** * {@inheritDoc} */ public function getListTableColumnsSQL($table, $database = null) { return "SELECT a.attnum, quote_ident(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.oid = a.atttypid) 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_get_expr(adbin, adrelid) 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"; } /** * {@inheritDoc} */ public function getCreateDatabaseSQL($name) { return 'CREATE DATABASE ' . $name; } /** * Returns the SQL statement for disallowing new connections on the given database. * * This is useful to force DROP DATABASE operations which could fail because of active connections. * * @param string $database The name of the database to disallow new connections for. * * @return string */ public function getDisallowDatabaseConnectionsSQL($database) { return "UPDATE pg_database SET datallowconn = 'false' WHERE datname = '$database'"; } /** * Returns the SQL statement for closing currently active connections on the given database. * * This is useful to force DROP DATABASE operations which could fail because of active connections. * * @param string $database The name of the database to close currently active connections for. * * @return string */ public function getCloseActiveDatabaseConnectionsSQL($database) { $database = $this->quoteStringLiteral($database); return "SELECT pg_terminate_backend(procpid) FROM pg_stat_activity WHERE datname = $database"; } /** * {@inheritDoc} */ 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) || ($foreignKey->hasOption('deferred') && $foreignKey->getOption('deferred') !== false) ) { $query .= ' INITIALLY DEFERRED'; } else { $query .= ' INITIALLY IMMEDIATE'; } return $query; } /** * {@inheritDoc} */ 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->getName($this)->getQuotedName($this) . ' ' . $query; $comment = $this->getColumnComment($column); if (null !== $comment && '' !== $comment) { $commentsSQL[] = $this->getCommentOnColumnSQL( $diff->getName($this)->getQuotedName($this), $column->getQuotedName($this), $comment ); } } foreach ($diff->removedColumns as $column) { if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { continue; } $query = 'DROP ' . $column->getQuotedName($this); $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; } foreach ($diff->changedColumns as $columnDiff) { /** @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */ if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { continue; } if ($this->isUnchangedBinaryColumn($columnDiff)) { continue; } $oldColumnName = $columnDiff->getOldColumnName()->getQuotedName($this); $column = $columnDiff->column; if ($columnDiff->hasChanged('type') || $columnDiff->hasChanged('precision') || $columnDiff->hasChanged('scale') || $columnDiff->hasChanged('fixed')) { $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->getName($this)->getQuotedName($this) . ' ' . $query; } if ($columnDiff->hasChanged('default') || $columnDiff->hasChanged('type')) { $defaultClause = null === $column->getDefault() ? ' DROP DEFAULT' : ' SET' . $this->getDefaultValueDeclarationSQL($column->toArray()); $query = 'ALTER ' . $oldColumnName . $defaultClause; $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; } if ($columnDiff->hasChanged('notnull')) { $query = 'ALTER ' . $oldColumnName . ' ' . ($column->getNotNull() ? 'SET' : 'DROP') . ' NOT NULL'; $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; } if ($columnDiff->hasChanged('autoincrement')) { if ($column->getAutoincrement()) { // add autoincrement $seqName = $this->getIdentitySequenceName($diff->name, $oldColumnName); $sql[] = "CREATE SEQUENCE " . $seqName; $sql[] = "SELECT setval('" . $seqName . "', (SELECT MAX(" . $oldColumnName . ") FROM " . $diff->getName($this)->getQuotedName($this) . "))"; $query = "ALTER " . $oldColumnName . " SET DEFAULT nextval('" . $seqName . "')"; $sql[] = "ALTER TABLE " . $diff->getName($this)->getQuotedName($this) . " " . $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->getName($this)->getQuotedName($this) . " " . $query; } } if ($columnDiff->hasChanged('comment')) { $commentsSQL[] = $this->getCommentOnColumnSQL( $diff->getName($this)->getQuotedName($this), $column->getQuotedName($this), $this->getColumnComment($column) ); } if ($columnDiff->hasChanged('length')) { $query = 'ALTER ' . $oldColumnName . ' TYPE ' . $column->getType()->getSqlDeclaration($column->toArray(), $this); $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; } } foreach ($diff->renamedColumns as $oldColumnName => $column) { if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { continue; } $oldColumnName = new Identifier($oldColumnName); $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' RENAME COLUMN ' . $oldColumnName->getQuotedName($this) . ' TO ' . $column->getQuotedName($this); } $tableSql = array(); if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { $sql = array_merge($sql, $commentsSQL); if ($diff->newName !== false) { $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' RENAME TO ' . $diff->getNewName()->getQuotedName($this); } $sql = array_merge( $this->getPreAlterTableIndexForeignKeySQL($diff), $sql, $this->getPostAlterTableIndexForeignKeySQL($diff) ); } return array_merge($sql, $tableSql, $columnSql); } /** * Checks whether a given column diff is a logically unchanged binary type column. * * Used to determine whether a column alteration for a binary type column can be skipped. * Doctrine's {@link \Doctrine\DBAL\Types\BinaryType} and {@link \Doctrine\DBAL\Types\BlobType} * are mapped to the same database column type on this platform as this platform * does not have a native VARBINARY/BINARY column type. Therefore the {@link \Doctrine\DBAL\Schema\Comparator} * might detect differences for binary type columns which do not have to be propagated * to database as there actually is no difference at database level. * * @param ColumnDiff $columnDiff The column diff to check against. * * @return boolean True if the given column diff is an unchanged binary type column, false otherwise. */ private function isUnchangedBinaryColumn(ColumnDiff $columnDiff) { $columnType = $columnDiff->column->getType(); if ( ! $columnType instanceof BinaryType && ! $columnType instanceof BlobType) { return false; } $fromColumn = $columnDiff->fromColumn instanceof Column ? $columnDiff->fromColumn : null; if ($fromColumn) { $fromColumnType = $fromColumn->getType(); if ( ! $fromColumnType instanceof BinaryType && ! $fromColumnType instanceof BlobType) { return false; } return count(array_diff($columnDiff->changedProperties, array('type', 'length', 'fixed'))) === 0; } if ($columnDiff->hasChanged('type')) { return false; } return count(array_diff($columnDiff->changedProperties, array('length', 'fixed'))) === 0; } /** * {@inheritdoc} */ protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) { if (strpos($tableName, '.') !== false) { list($schema) = explode('.', $tableName); $oldIndexName = $schema . '.' . $oldIndexName; } return array('ALTER INDEX ' . $oldIndexName . ' RENAME TO ' . $index->getQuotedName($this)); } /** * {@inheritdoc} */ public function getCommentOnColumnSQL($tableName, $columnName, $comment) { $tableName = new Identifier($tableName); $columnName = new Identifier($columnName); $comment = $comment === null ? 'NULL' : $this->quoteStringLiteral($comment); return "COMMENT ON COLUMN " . $tableName->getQuotedName($this) . "." . $columnName->getQuotedName($this) . " IS $comment"; } /** * {@inheritDoc} */ public function getCreateSequenceSQL(Sequence $sequence) { return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) . ' INCREMENT BY ' . $sequence->getAllocationSize() . ' MINVALUE ' . $sequence->getInitialValue() . ' START ' . $sequence->getInitialValue() . $this->getSequenceCacheSQL($sequence); } /** * {@inheritDoc} */ public function getAlterSequenceSQL(Sequence $sequence) { return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) . ' INCREMENT BY ' . $sequence->getAllocationSize() . $this->getSequenceCacheSQL($sequence); } /** * Cache definition for sequences * * @param Sequence $sequence * * @return string */ private function getSequenceCacheSQL(Sequence $sequence) { if ($sequence->getCache() > 1) { return ' CACHE ' . $sequence->getCache(); } return ''; } /** * {@inheritDoc} */ public function getDropSequenceSQL($sequence) { if ($sequence instanceof Sequence) { $sequence = $sequence->getQuotedName($this); } return 'DROP SEQUENCE ' . $sequence . ' CASCADE'; } /** * {@inheritDoc} */ public function getCreateSchemaSQL($schemaName) { return 'CREATE SCHEMA ' . $schemaName; } /** * {@inheritDoc} */ public function getDropForeignKeySQL($foreignKey, $table) { return $this->getDropConstraintSQL($foreignKey, $table); } /** * {@inheritDoc} */ 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; } /** * Converts a single boolean value. * * First converts the value to its native PHP boolean type * and passes it to the given callback function to be reconverted * into any custom representation. * * @param mixed $value The value to convert. * @param callable $callback The callback function to use for converting the real boolean value. * * @return mixed * @throws \UnexpectedValueException */ private function convertSingleBooleanValue($value, $callback) { if (null === $value) { return $callback(null); } if (is_bool($value) || is_numeric($value)) { return $callback($value ? true : false); } if (!is_string($value)) { return $callback(true); } /** * Better safe than sorry: http://php.net/in_array#106319 */ if (in_array(trim(strtolower($value)), $this->booleanLiterals['false'], true)) { return $callback(false); } if (in_array(trim(strtolower($value)), $this->booleanLiterals['true'], true)) { return $callback(true); } throw new \UnexpectedValueException("Unrecognized boolean literal '${value}'"); } /** * Converts one or multiple boolean values. * * First converts the value(s) to their native PHP boolean type * and passes them to the given callback function to be reconverted * into any custom representation. * * @param mixed $item The value(s) to convert. * @param callable $callback The callback function to use for converting the real boolean value(s). * * @return mixed */ private function doConvertBooleans($item, $callback) { if (is_array($item)) { foreach ($item as $key => $value) { $item[$key] = $this->convertSingleBooleanValue($value, $callback); } return $item; } return $this->convertSingleBooleanValue($item, $callback); } /** * {@inheritDoc} * * Postgres wants boolean values converted to the strings 'true'/'false'. */ public function convertBooleans($item) { if ( ! $this->useBooleanTrueFalseStrings) { return parent::convertBooleans($item); } return $this->doConvertBooleans( $item, function ($boolean) { if (null === $boolean) { return 'NULL'; } return true === $boolean ? 'true' : 'false'; } ); } /** * {@inheritDoc} */ public function convertBooleansToDatabaseValue($item) { if ( ! $this->useBooleanTrueFalseStrings) { return parent::convertBooleansToDatabaseValue($item); } return $this->doConvertBooleans( $item, function ($boolean) { return null === $boolean ? null : (int) $boolean; } ); } /** * {@inheritDoc} */ public function convertFromBoolean($item) { if (in_array(strtolower($item), $this->booleanLiterals['false'], true)) { return false; } return parent::convertFromBoolean($item); } /** * {@inheritDoc} */ public function getSequenceNextValSQL($sequenceName) { return "SELECT NEXTVAL('" . $sequenceName . "')"; } /** * {@inheritDoc} */ public function getSetTransactionIsolationSQL($level) { return 'SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level); } /** * {@inheritDoc} */ public function getBooleanTypeDeclarationSQL(array $field) { return 'BOOLEAN'; } /** * {@inheritDoc} */ public function getIntegerTypeDeclarationSQL(array $field) { if ( ! empty($field['autoincrement'])) { return 'SERIAL'; } return 'INT'; } /** * {@inheritDoc} */ public function getBigIntTypeDeclarationSQL(array $field) { if ( ! empty($field['autoincrement'])) { return 'BIGSERIAL'; } return 'BIGINT'; } /** * {@inheritDoc} */ public function getSmallIntTypeDeclarationSQL(array $field) { return 'SMALLINT'; } /** * {@inheritDoc} */ public function getGuidTypeDeclarationSQL(array $field) { return 'UUID'; } /** * {@inheritDoc} */ public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) { return 'TIMESTAMP(0) WITHOUT TIME ZONE'; } /** * {@inheritDoc} */ public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration) { return 'TIMESTAMP(0) WITH TIME ZONE'; } /** * {@inheritDoc} */ public function getDateTypeDeclarationSQL(array $fieldDeclaration) { return 'DATE'; } /** * {@inheritDoc} */ public function getTimeTypeDeclarationSQL(array $fieldDeclaration) { return 'TIME(0) WITHOUT TIME ZONE'; } /** * {@inheritDoc} */ public function getGuidExpression() { return 'UUID_GENERATE_V4()'; } /** * {@inheritDoc} */ protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) { return ''; } /** * {@inheritDoc} */ protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) { return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'); } /** * {@inheritdoc} */ protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) { return 'BYTEA'; } /** * {@inheritDoc} */ public function getClobTypeDeclarationSQL(array $field) { return 'TEXT'; } /** * {@inheritDoc} */ public function getName() { return 'postgresql'; } /** * {@inheritDoc} * * PostgreSQL returns all column names in SQL result sets in lowercase. */ public function getSQLResultCasing($column) { return strtolower($column); } /** * {@inheritDoc} */ public function getDateTimeTzFormatString() { return 'Y-m-d H:i:sO'; } /** * {@inheritDoc} */ public function getEmptyIdentityInsertSQL($quotedTableName, $quotedIdentifierColumnName) { return 'INSERT INTO ' . $quotedTableName . ' (' . $quotedIdentifierColumnName . ') VALUES (DEFAULT)'; } /** * {@inheritDoc} */ public function getTruncateTableSQL($tableName, $cascade = false) { $tableIdentifier = new Identifier($tableName); $sql = 'TRUNCATE ' . $tableIdentifier->getQuotedName($this); if ($cascade) { $sql .= ' CASCADE'; } return $sql; } /** * {@inheritDoc} */ public function getReadLockSQL() { return 'FOR SHARE'; } /** * {@inheritDoc} */ 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', 'inet' => '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', 'uuid' => 'guid', 'bytea' => 'blob', ); } /** * {@inheritDoc} */ public function getVarcharMaxLength() { return 65535; } /** * {@inheritdoc} */ public function getBinaryMaxLength() { return 0; } /** * {@inheritdoc} */ public function getBinaryDefaultLength() { return 0; } /** * {@inheritDoc} */ protected function getReservedKeywordsClass() { return 'Doctrine\DBAL\Platforms\Keywords\PostgreSQLKeywords'; } /** * {@inheritDoc} */ public function getBlobTypeDeclarationSQL(array $field) { return 'BYTEA'; } /** * {@inheritdoc} */ public function quoteStringLiteral($str) { $str = str_replace('\\', '\\\\', $str); // PostgreSQL requires backslashes to be escaped aswell. return parent::quoteStringLiteral($str); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/SQLAnywhere11Platform.php000066400000000000000000000031251313473450000242150ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms; /** * The SQLAnywhere11Platform provides the behavior, features and SQL dialect of the * SAP Sybase SQL Anywhere 11 database platform. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class SQLAnywhere11Platform extends SQLAnywherePlatform { /** * {@inheritdoc} */ public function getRegexpExpression() { return 'REGEXP'; } /** * {@inheritdoc} */ protected function getReservedKeywordsClass() { return 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhere11Keywords'; } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/SQLAnywhere12Platform.php000066400000000000000000000073571313473450000242310ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\Sequence; /** * The SQLAnywhere12Platform provides the behavior, features and SQL dialect of the * SAP Sybase SQL Anywhere 12 database platform. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class SQLAnywhere12Platform extends SQLAnywhere11Platform { /** * {@inheritdoc} */ public function getCreateSequenceSQL(Sequence $sequence) { return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) . ' INCREMENT BY ' . $sequence->getAllocationSize() . ' START WITH ' . $sequence->getInitialValue() . ' MINVALUE ' . $sequence->getInitialValue(); } /** * {@inheritdoc} */ public function getAlterSequenceSQL(Sequence $sequence) { return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) . ' INCREMENT BY ' . $sequence->getAllocationSize(); } /** * {@inheritdoc} */ public function getDateTimeTzFormatString() { return 'Y-m-d H:i:s.uP'; } /** * {@inheritdoc} */ public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration) { return 'TIMESTAMP WITH TIME ZONE'; } /** * {@inheritdoc} */ public function getDropSequenceSQL($sequence) { if ($sequence instanceof Sequence) { $sequence = $sequence->getQuotedName($this); } return 'DROP SEQUENCE ' . $sequence; } /** * {@inheritdoc} */ public function getListSequencesSQL($database) { return 'SELECT sequence_name, increment_by, start_with, min_value FROM SYS.SYSSEQUENCE'; } /** * {@inheritdoc} */ public function getSequenceNextValSQL($sequenceName) { return 'SELECT ' . $sequenceName . '.NEXTVAL'; } /** * {@inheritdoc} */ public function supportsSequences() { return true; } /** * {@inheritdoc} */ protected function getAdvancedIndexOptionsSQL(Index $index) { if ( ! $index->isPrimary() && $index->isUnique() && $index->hasFlag('with_nulls_not_distinct')) { return ' WITH NULLS NOT DISTINCT' . parent::getAdvancedIndexOptionsSQL($index); } return parent::getAdvancedIndexOptionsSQL($index); } /** * {@inheritdoc} */ protected function getReservedKeywordsClass() { return 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhere12Keywords'; } /** * {@inheritDoc} */ protected function initializeDoctrineTypeMappings() { parent::initializeDoctrineTypeMappings(); $this->doctrineTypeMapping['timestamp with time zone'] = 'datetime'; } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/SQLAnywhere16Platform.php000066400000000000000000000043301313473450000242210ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms; use Doctrine\Common\Proxy\Exception\UnexpectedValueException; use Doctrine\DBAL\Schema\Index; /** * The SQLAnywhere16Platform provides the behavior, features and SQL dialect of the * SAP Sybase SQL Anywhere 16 database platform. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class SQLAnywhere16Platform extends SQLAnywhere12Platform { /** * {@inheritdoc} */ protected function getAdvancedIndexOptionsSQL(Index $index) { if ($index->hasFlag('with_nulls_distinct') && $index->hasFlag('with_nulls_not_distinct')) { throw new UnexpectedValueException( 'An Index can either have a "with_nulls_distinct" or "with_nulls_not_distinct" flag but not both.' ); } if ( ! $index->isPrimary() && $index->isUnique() && $index->hasFlag('with_nulls_distinct')) { return ' WITH NULLS DISTINCT' . parent::getAdvancedIndexOptionsSQL($index); } return parent::getAdvancedIndexOptionsSQL($index); } /** * {@inheritdoc} */ protected function getReservedKeywordsClass() { return 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhere16Keywords'; } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/SQLAnywherePlatform.php000066400000000000000000001305651313473450000240640ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\Connection; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\LockMode; use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\ColumnDiff; use Doctrine\DBAL\Schema\Constraint; use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\Identifier; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\TableDiff; /** * The SQLAnywherePlatform provides the behavior, features and SQL dialect of the * SAP Sybase SQL Anywhere 10 database platform. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class SQLAnywherePlatform extends AbstractPlatform { /** * @var integer */ const FOREIGN_KEY_MATCH_SIMPLE = 1; /** * @var integer */ const FOREIGN_KEY_MATCH_FULL = 2; /** * @var integer */ const FOREIGN_KEY_MATCH_SIMPLE_UNIQUE = 129; /** * @var integer */ const FOREIGN_KEY_MATCH_FULL_UNIQUE = 130; /** * {@inheritdoc} */ public function appendLockHint($fromClause, $lockMode) { switch (true) { case $lockMode === LockMode::NONE: return $fromClause . ' WITH (NOLOCK)'; case $lockMode === LockMode::PESSIMISTIC_READ: return $fromClause . ' WITH (UPDLOCK)'; case $lockMode === LockMode::PESSIMISTIC_WRITE: return $fromClause . ' WITH (XLOCK)'; default: return $fromClause; } } /** * {@inheritdoc} * * SQL Anywhere supports a maximum length of 128 bytes for identifiers. */ public function fixSchemaElementName($schemaElementName) { $maxIdentifierLength = $this->getMaxIdentifierLength(); if (strlen($schemaElementName) > $maxIdentifierLength) { return substr($schemaElementName, 0, $maxIdentifierLength); } return $schemaElementName; } /** * {@inheritdoc} */ public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey) { $query = ''; if ($foreignKey->hasOption('match')) { $query = ' MATCH ' . $this->getForeignKeyMatchClauseSQL($foreignKey->getOption('match')); } $query .= parent::getAdvancedForeignKeyOptionsSQL($foreignKey); if ($foreignKey->hasOption('check_on_commit') && (boolean) $foreignKey->getOption('check_on_commit')) { $query .= ' CHECK ON COMMIT'; } if ($foreignKey->hasOption('clustered') && (boolean) $foreignKey->getOption('clustered')) { $query .= ' CLUSTERED'; } if ($foreignKey->hasOption('for_olap_workload') && (boolean) $foreignKey->getOption('for_olap_workload')) { $query .= ' FOR OLAP WORKLOAD'; } return $query; } /** * {@inheritdoc} */ public function getAlterTableSQL(TableDiff $diff) { $sql = array(); $columnSql = array(); $commentsSQL = array(); $tableSql = array(); $alterClauses = array(); /** @var \Doctrine\DBAL\Schema\Column $column */ foreach ($diff->addedColumns as $column) { if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { continue; } $alterClauses[] = $this->getAlterTableAddColumnClause($column); $comment = $this->getColumnComment($column); if (null !== $comment && '' !== $comment) { $commentsSQL[] = $this->getCommentOnColumnSQL( $diff->getName($this)->getQuotedName($this), $column->getQuotedName($this), $comment ); } } /** @var \Doctrine\DBAL\Schema\Column $column */ foreach ($diff->removedColumns as $column) { if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { continue; } $alterClauses[] = $this->getAlterTableRemoveColumnClause($column); } /** @var \Doctrine\DBAL\Schema\ColumnDiff $columnDiff */ foreach ($diff->changedColumns as $columnDiff) { if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { continue; } $alterClause = $this->getAlterTableChangeColumnClause($columnDiff); if (null !== $alterClause) { $alterClauses[] = $alterClause; } if ($columnDiff->hasChanged('comment')) { $column = $columnDiff->column; $commentsSQL[] = $this->getCommentOnColumnSQL( $diff->getName($this)->getQuotedName($this), $column->getQuotedName($this), $this->getColumnComment($column) ); } } foreach ($diff->renamedColumns as $oldColumnName => $column) { if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { continue; } $sql[] = $this->getAlterTableClause($diff->getName($this)) . ' ' . $this->getAlterTableRenameColumnClause($oldColumnName, $column); } if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { if ( ! empty($alterClauses)) { $sql[] = $this->getAlterTableClause($diff->getName($this)) . ' ' . implode(", ", $alterClauses); } $sql = array_merge($sql, $commentsSQL); if ($diff->newName !== false) { $sql[] = $this->getAlterTableClause($diff->getName($this)) . ' ' . $this->getAlterTableRenameTableClause($diff->getNewName()); } $sql = array_merge( $this->getPreAlterTableIndexForeignKeySQL($diff), $sql, $this->getPostAlterTableIndexForeignKeySQL($diff) ); } return array_merge($sql, $tableSql, $columnSql); } /** * Returns the SQL clause for creating a column in a table alteration. * * @param Column $column The column to add. * * @return string */ protected function getAlterTableAddColumnClause(Column $column) { return 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); } /** * Returns the SQL clause for altering a table. * * @param Identifier $tableName The quoted name of the table to alter. * * @return string */ protected function getAlterTableClause(Identifier $tableName) { return 'ALTER TABLE ' . $tableName->getQuotedName($this); } /** * Returns the SQL clause for dropping a column in a table alteration. * * @param Column $column The column to drop. * * @return string */ protected function getAlterTableRemoveColumnClause(Column $column) { return 'DROP ' . $column->getQuotedName($this); } /** * Returns the SQL clause for renaming a column in a table alteration. * * @param string $oldColumnName The quoted name of the column to rename. * @param Column $column The column to rename to. * * @return string */ protected function getAlterTableRenameColumnClause($oldColumnName, Column $column) { $oldColumnName = new Identifier($oldColumnName); return 'RENAME ' . $oldColumnName->getQuotedName($this) .' TO ' . $column->getQuotedName($this); } /** * Returns the SQL clause for renaming a table in a table alteration. * * @param Identifier $newTableName The quoted name of the table to rename to. * * @return string */ protected function getAlterTableRenameTableClause(Identifier $newTableName) { return 'RENAME ' . $newTableName->getQuotedName($this); } /** * Returns the SQL clause for altering a column in a table alteration. * * This method returns null in case that only the column comment has changed. * Changes in column comments have to be handled differently. * * @param ColumnDiff $columnDiff The diff of the column to alter. * * @return string|null */ protected function getAlterTableChangeColumnClause(ColumnDiff $columnDiff) { $column = $columnDiff->column; // Do not return alter clause if only comment has changed. if ( ! ($columnDiff->hasChanged('comment') && count($columnDiff->changedProperties) === 1)) { $columnAlterationClause = 'ALTER ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); if ($columnDiff->hasChanged('default') && null === $column->getDefault()) { $columnAlterationClause .= ', ALTER ' . $column->getQuotedName($this) . ' DROP DEFAULT'; } return $columnAlterationClause; } } /** * {@inheritdoc} */ public function getBigIntTypeDeclarationSQL(array $columnDef) { $columnDef['integer_type'] = 'BIGINT'; return $this->_getCommonIntegerTypeDeclarationSQL($columnDef); } /** * {@inheritdoc} */ public function getBinaryDefaultLength() { return 1; } /** * {@inheritdoc} */ public function getBinaryMaxLength() { return 32767; } /** * {@inheritdoc} */ public function getBlobTypeDeclarationSQL(array $field) { return 'LONG BINARY'; } /** * {@inheritdoc} * * BIT type columns require an explicit NULL declaration * in SQL Anywhere if they shall be nullable. * Otherwise by just omitting the NOT NULL clause, * SQL Anywhere will declare them NOT NULL nonetheless. */ public function getBooleanTypeDeclarationSQL(array $columnDef) { $nullClause = isset($columnDef['notnull']) && (boolean) $columnDef['notnull'] === false ? ' NULL' : ''; return 'BIT' . $nullClause; } /** * {@inheritdoc} */ public function getClobTypeDeclarationSQL(array $field) { return 'TEXT'; } /** * {@inheritdoc} */ public function getCommentOnColumnSQL($tableName, $columnName, $comment) { $tableName = new Identifier($tableName); $columnName = new Identifier($columnName); $comment = $comment === null ? 'NULL' : $this->quoteStringLiteral($comment); return "COMMENT ON COLUMN " . $tableName->getQuotedName($this) . '.' . $columnName->getQuotedName($this) . " IS $comment"; } /** * {@inheritdoc} */ public function getConcatExpression() { return 'STRING(' . implode(', ', (array) func_get_args()) . ')'; } /** * {@inheritdoc} */ public function getCreateConstraintSQL(Constraint $constraint, $table) { if ($constraint instanceof ForeignKeyConstraint) { return $this->getCreateForeignKeySQL($constraint, $table); } if ($table instanceof Table) { $table = $table->getQuotedName($this); } return 'ALTER TABLE ' . $table . ' ADD ' . $this->getTableConstraintDeclarationSQL($constraint, $constraint->getQuotedName($this)); } /** * {@inheritdoc} */ public function getCreateDatabaseSQL($database) { $database = new Identifier($database); return "CREATE DATABASE '" . $database->getName() . "'"; } /** * {@inheritdoc} * * Appends SQL Anywhere specific flags if given. */ public function getCreateIndexSQL(Index $index, $table) { return parent::getCreateIndexSQL($index, $table). $this->getAdvancedIndexOptionsSQL($index); } /** * {@inheritdoc} */ public function getCreatePrimaryKeySQL(Index $index, $table) { if ($table instanceof Table) { $table = $table->getQuotedName($this); } return 'ALTER TABLE ' . $table . ' ADD ' . $this->getPrimaryKeyDeclarationSQL($index); } /** * {@inheritdoc} */ public function getCreateTemporaryTableSnippetSQL() { return 'CREATE ' . $this->getTemporaryTableSQL() . ' TABLE'; } /** * {@inheritdoc} */ public function getCreateViewSQL($name, $sql) { return 'CREATE VIEW ' . $name . ' AS ' . $sql; } /** * {@inheritdoc} */ public function getCurrentDateSQL() { return 'CURRENT DATE'; } /** * {@inheritdoc} */ public function getCurrentTimeSQL() { return 'CURRENT TIME'; } /** * {@inheritdoc} */ public function getCurrentTimestampSQL() { return 'CURRENT TIMESTAMP'; } /** * {@inheritdoc} */ protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) { $factorClause = ''; if ('-' === $operator) { $factorClause = '-1 * '; } return 'DATEADD(' . $unit . ', ' . $factorClause . $interval . ', ' . $date . ')'; } /** * {@inheritdoc} */ public function getDateDiffExpression($date1, $date2) { return 'DATEDIFF(day, ' . $date2 . ', ' . $date1 . ')'; } /** * {@inheritdoc} */ public function getDateTimeFormatString() { return 'Y-m-d H:i:s.u'; } /** * {@inheritdoc} */ public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) { return 'DATETIME'; } /** * {@inheritdoc} */ public function getDateTimeTzFormatString() { return $this->getDateTimeFormatString(); } /** * {@inheritdoc} */ public function getDateTypeDeclarationSQL(array $fieldDeclaration) { return 'DATE'; } /** * {@inheritdoc} */ public function getDefaultTransactionIsolationLevel() { return Connection::TRANSACTION_READ_UNCOMMITTED; } /** * {@inheritdoc} */ public function getDropDatabaseSQL($database) { $database = new Identifier($database); return "DROP DATABASE '" . $database->getName() . "'"; } /** * {@inheritdoc} */ public function getDropIndexSQL($index, $table = null) { if ($index instanceof Index) { $index = $index->getQuotedName($this); } if ( ! is_string($index)) { throw new \InvalidArgumentException( 'SQLAnywherePlatform::getDropIndexSQL() expects $index parameter to be string or ' . '\Doctrine\DBAL\Schema\Index.' ); } if ( ! isset($table)) { return 'DROP INDEX ' . $index; } if ($table instanceof Table) { $table = $table->getQuotedName($this); } if ( ! is_string($table)) { throw new \InvalidArgumentException( 'SQLAnywherePlatform::getDropIndexSQL() expects $table parameter to be string or ' . '\Doctrine\DBAL\Schema\Table.' ); } return 'DROP INDEX ' . $table . '.' . $index; } /** * {@inheritdoc} */ public function getDropViewSQL($name) { return 'DROP VIEW ' . $name; } /** * {@inheritdoc} */ public function getForeignKeyBaseDeclarationSQL(ForeignKeyConstraint $foreignKey) { $sql = ''; $foreignKeyName = $foreignKey->getName(); $localColumns = $foreignKey->getQuotedLocalColumns($this); $foreignColumns = $foreignKey->getQuotedForeignColumns($this); $foreignTableName = $foreignKey->getQuotedForeignTableName($this); if ( ! empty($foreignKeyName)) { $sql .= 'CONSTRAINT ' . $foreignKey->getQuotedName($this) . ' '; } if (empty($localColumns)) { throw new \InvalidArgumentException("Incomplete definition. 'local' required."); } if (empty($foreignColumns)) { throw new \InvalidArgumentException("Incomplete definition. 'foreign' required."); } if (empty($foreignTableName)) { throw new \InvalidArgumentException("Incomplete definition. 'foreignTable' required."); } if ($foreignKey->hasOption('notnull') && (boolean) $foreignKey->getOption('notnull')) { $sql .= 'NOT NULL '; } return $sql . 'FOREIGN KEY (' . $this->getIndexFieldDeclarationListSQL($localColumns) . ') ' . 'REFERENCES ' . $foreignKey->getQuotedForeignTableName($this) . ' (' . $this->getIndexFieldDeclarationListSQL($foreignColumns) . ')'; } /** * Returns foreign key MATCH clause for given type. * * @param integer $type The foreign key match type * * @return string * * @throws \InvalidArgumentException if unknown match type given */ public function getForeignKeyMatchClauseSQL($type) { switch ((int) $type) { case self::FOREIGN_KEY_MATCH_SIMPLE: return 'SIMPLE'; break; case self::FOREIGN_KEY_MATCH_FULL: return 'FULL'; break; case self::FOREIGN_KEY_MATCH_SIMPLE_UNIQUE: return 'UNIQUE SIMPLE'; break; case self::FOREIGN_KEY_MATCH_FULL_UNIQUE: return 'UNIQUE FULL'; default: throw new \InvalidArgumentException('Invalid foreign key match type: ' . $type); } } /** * {@inheritdoc} */ public function getForeignKeyReferentialActionSQL($action) { // NO ACTION is not supported, therefore falling back to RESTRICT. if (strtoupper($action) === 'NO ACTION') { return 'RESTRICT'; } return parent::getForeignKeyReferentialActionSQL($action); } /** * {@inheritdoc} */ public function getForUpdateSQL() { return ''; } /** * {@inheritdoc} */ public function getGuidExpression() { return 'NEWID()'; } /** * {@inheritdoc} */ public function getGuidTypeDeclarationSQL(array $field) { return 'UNIQUEIDENTIFIER'; } /** * {@inheritdoc} */ public function getIndexDeclarationSQL($name, Index $index) { // Index declaration in statements like CREATE TABLE is not supported. throw DBALException::notSupported(__METHOD__); } /** * {@inheritdoc} */ public function getIntegerTypeDeclarationSQL(array $columnDef) { $columnDef['integer_type'] = 'INT'; return $this->_getCommonIntegerTypeDeclarationSQL($columnDef); } /** * {@inheritdoc} */ public function getListDatabasesSQL() { return 'SELECT db_name(number) AS name FROM sa_db_list()'; } /** * {@inheritdoc} */ public function getListTableColumnsSQL($table, $database = null) { $user = 'USER_NAME()'; if (strpos($table, '.') !== false) { list($user, $table) = explode('.', $table); $user = $this->quoteStringLiteral($user); } return "SELECT col.column_name, COALESCE(def.user_type_name, def.domain_name) AS 'type', def.declared_width AS 'length', def.scale, CHARINDEX('unsigned', def.domain_name) AS 'unsigned', IF col.nulls = 'Y' THEN 0 ELSE 1 ENDIF AS 'notnull', col.\"default\", def.is_autoincrement AS 'autoincrement', rem.remarks AS 'comment' FROM sa_describe_query('SELECT * FROM \"$table\"') AS def JOIN SYS.SYSTABCOL AS col ON col.table_id = def.base_table_id AND col.column_id = def.base_column_id LEFT JOIN SYS.SYSREMARK AS rem ON col.object_id = rem.object_id WHERE def.base_owner_name = $user ORDER BY def.base_column_id ASC"; } /** * {@inheritdoc} * * @todo Where is this used? Which information should be retrieved? */ public function getListTableConstraintsSQL($table) { $user = ''; if (strpos($table, '.') !== false) { list($user, $table) = explode('.', $table); $user = $this->quoteStringLiteral($user); $table = $this->quoteStringLiteral($table); } else { $table = $this->quoteStringLiteral($table); } return "SELECT con.* FROM SYS.SYSCONSTRAINT AS con JOIN SYS.SYSTAB AS tab ON con.table_object_id = tab.object_id WHERE tab.table_name = $table AND tab.creator = USER_ID($user)"; } /** * {@inheritdoc} */ public function getListTableForeignKeysSQL($table) { $user = ''; if (strpos($table, '.') !== false) { list($user, $table) = explode('.', $table); $user = $this->quoteStringLiteral($user); $table = $this->quoteStringLiteral($table); } else { $table = $this->quoteStringLiteral($table); } return "SELECT fcol.column_name AS local_column, ptbl.table_name AS foreign_table, pcol.column_name AS foreign_column, idx.index_name, IF fk.nulls = 'N' THEN 1 ELSE NULL ENDIF AS notnull, CASE ut.referential_action WHEN 'C' THEN 'CASCADE' WHEN 'D' THEN 'SET DEFAULT' WHEN 'N' THEN 'SET NULL' WHEN 'R' THEN 'RESTRICT' ELSE NULL END AS on_update, CASE dt.referential_action WHEN 'C' THEN 'CASCADE' WHEN 'D' THEN 'SET DEFAULT' WHEN 'N' THEN 'SET NULL' WHEN 'R' THEN 'RESTRICT' ELSE NULL END AS on_delete, IF fk.check_on_commit = 'Y' THEN 1 ELSE NULL ENDIF AS check_on_commit, -- check_on_commit flag IF ftbl.clustered_index_id = idx.index_id THEN 1 ELSE NULL ENDIF AS 'clustered', -- clustered flag IF fk.match_type = 0 THEN NULL ELSE fk.match_type ENDIF AS 'match', -- match option IF pidx.max_key_distance = 1 THEN 1 ELSE NULL ENDIF AS for_olap_workload -- for_olap_workload flag FROM SYS.SYSFKEY AS fk JOIN SYS.SYSIDX AS idx ON fk.foreign_table_id = idx.table_id AND fk.foreign_index_id = idx.index_id JOIN SYS.SYSPHYSIDX pidx ON idx.table_id = pidx.table_id AND idx.phys_index_id = pidx.phys_index_id JOIN SYS.SYSTAB AS ptbl ON fk.primary_table_id = ptbl.table_id JOIN SYS.SYSTAB AS ftbl ON fk.foreign_table_id = ftbl.table_id JOIN SYS.SYSIDXCOL AS idxcol ON idx.table_id = idxcol.table_id AND idx.index_id = idxcol.index_id JOIN SYS.SYSTABCOL AS pcol ON ptbl.table_id = pcol.table_id AND idxcol.primary_column_id = pcol.column_id JOIN SYS.SYSTABCOL AS fcol ON ftbl.table_id = fcol.table_id AND idxcol.column_id = fcol.column_id LEFT JOIN SYS.SYSTRIGGER ut ON fk.foreign_table_id = ut.foreign_table_id AND fk.foreign_index_id = ut.foreign_key_id AND ut.event = 'C' LEFT JOIN SYS.SYSTRIGGER dt ON fk.foreign_table_id = dt.foreign_table_id AND fk.foreign_index_id = dt.foreign_key_id AND dt.event = 'D' WHERE ftbl.table_name = $table AND ftbl.creator = USER_ID($user) ORDER BY fk.foreign_index_id ASC, idxcol.sequence ASC"; } /** * {@inheritdoc} */ public function getListTableIndexesSQL($table, $currentDatabase = null) { $user = ''; if (strpos($table, '.') !== false) { list($user, $table) = explode('.', $table); $user = $this->quoteStringLiteral($user); $table = $this->quoteStringLiteral($table); } else { $table = $this->quoteStringLiteral($table); } return "SELECT idx.index_name AS key_name, IF idx.index_category = 1 THEN 1 ELSE 0 ENDIF AS 'primary', col.column_name, IF idx.\"unique\" IN(1, 2, 5) THEN 0 ELSE 1 ENDIF AS non_unique, IF tbl.clustered_index_id = idx.index_id THEN 1 ELSE NULL ENDIF AS 'clustered', -- clustered flag IF idx.\"unique\" = 5 THEN 1 ELSE NULL ENDIF AS with_nulls_not_distinct, -- with_nulls_not_distinct flag IF pidx.max_key_distance = 1 THEN 1 ELSE NULL ENDIF AS for_olap_workload -- for_olap_workload flag FROM SYS.SYSIDX AS idx JOIN SYS.SYSPHYSIDX pidx ON idx.table_id = pidx.table_id AND idx.phys_index_id = pidx.phys_index_id JOIN SYS.SYSIDXCOL AS idxcol ON idx.table_id = idxcol.table_id AND idx.index_id = idxcol.index_id JOIN SYS.SYSTABCOL AS col ON idxcol.table_id = col.table_id AND idxcol.column_id = col.column_id JOIN SYS.SYSTAB AS tbl ON idx.table_id = tbl.table_id WHERE tbl.table_name = $table AND tbl.creator = USER_ID($user) AND idx.index_category != 2 -- exclude indexes implicitly created by foreign key constraints ORDER BY idx.index_id ASC, idxcol.sequence ASC"; } /** * {@inheritdoc} */ public function getListTablesSQL() { return "SELECT tbl.table_name FROM SYS.SYSTAB AS tbl JOIN SYS.SYSUSER AS usr ON tbl.creator = usr.user_id JOIN dbo.SYSOBJECTS AS obj ON tbl.object_id = obj.id WHERE tbl.table_type IN(1, 3) -- 'BASE', 'GBL TEMP' AND usr.user_name NOT IN('SYS', 'dbo', 'rs_systabgroup') -- exclude system users AND obj.type = 'U' -- user created tables only ORDER BY tbl.table_name ASC"; } /** * {@inheritdoc} * * @todo Where is this used? Which information should be retrieved? */ public function getListUsersSQL() { return 'SELECT * FROM SYS.SYSUSER ORDER BY user_name ASC'; } /** * {@inheritdoc} */ public function getListViewsSQL($database) { return "SELECT tbl.table_name, v.view_def FROM SYS.SYSVIEW v JOIN SYS.SYSTAB tbl ON v.view_object_id = tbl.object_id JOIN SYS.SYSUSER usr ON tbl.creator = usr.user_id JOIN dbo.SYSOBJECTS obj ON tbl.object_id = obj.id WHERE usr.user_name NOT IN('SYS', 'dbo', 'rs_systabgroup') -- exclude system users ORDER BY tbl.table_name ASC"; } /** * {@inheritdoc} */ public function getLocateExpression($str, $substr, $startPos = false) { if ($startPos == false) { return 'LOCATE(' . $str . ', ' . $substr . ')'; } return 'LOCATE(' . $str . ', ' . $substr . ', ' . $startPos . ')'; } /** * {@inheritdoc} */ public function getMaxIdentifierLength() { return 128; } /** * {@inheritdoc} */ public function getMd5Expression($column) { return "HASH(" . $column . ", 'MD5')"; } /** * {@inheritdoc} */ public function getName() { return 'sqlanywhere'; } /** * Obtain DBMS specific SQL code portion needed to set a primary key * declaration to be used in statements like ALTER TABLE. * * @param Index $index Index definition * @param string $name Name of the primary key * * @return string DBMS specific SQL code portion needed to set a primary key * * @throws \InvalidArgumentException if the given index is not a primary key. */ public function getPrimaryKeyDeclarationSQL(Index $index, $name = null) { if ( ! $index->isPrimary()) { throw new \InvalidArgumentException( 'Can only create primary key declarations with getPrimaryKeyDeclarationSQL()' ); } return $this->getTableConstraintDeclarationSQL($index, $name); } /** * {@inheritdoc} */ public function getSetTransactionIsolationSQL($level) { return 'SET TEMPORARY OPTION isolation_level = ' . $this->_getTransactionIsolationLevelSQL($level); } /** * {@inheritdoc} */ public function getSmallIntTypeDeclarationSQL(array $columnDef) { $columnDef['integer_type'] = 'SMALLINT'; return $this->_getCommonIntegerTypeDeclarationSQL($columnDef); } /** * Returns the SQL statement for starting an existing database. * * In SQL Anywhere you can start and stop databases on a * database server instance. * This is a required statement after having created a new database * as it has to be explicitly started to be usable. * SQL Anywhere does not automatically start a database after creation! * * @param string $database Name of the database to start. * * @return string */ public function getStartDatabaseSQL($database) { $database = new Identifier($database); return "START DATABASE '" . $database->getName() . "' AUTOSTOP OFF"; } /** * Returns the SQL statement for stopping a running database. * * In SQL Anywhere you can start and stop databases on a * database server instance. * This is a required statement before dropping an existing database * as it has to be explicitly stopped before it can be dropped. * * @param string $database Name of the database to stop. * * @return string */ public function getStopDatabaseSQL($database) { $database = new Identifier($database); return 'STOP DATABASE "' . $database->getName() . '" UNCONDITIONALLY'; } /** * {@inheritdoc} */ public function getSubstringExpression($value, $from, $length = null) { if (null === $length) { return 'SUBSTRING(' . $value . ', ' . $from . ')'; } return 'SUBSTRING(' . $value . ', ' . $from . ', ' . $length . ')'; } /** * {@inheritdoc} */ public function getTemporaryTableSQL() { return 'GLOBAL TEMPORARY'; } /** * {@inheritdoc} */ public function getTimeFormatString() { return 'H:i:s.u'; } /** * {@inheritdoc} */ public function getTimeTypeDeclarationSQL(array $fieldDeclaration) { return 'TIME'; } /** * {@inheritdoc} */ public function getTrimExpression($str, $pos = self::TRIM_UNSPECIFIED, $char = false) { if ( ! $char) { switch ($pos) { case self::TRIM_LEADING: return $this->getLtrimExpression($str); case self::TRIM_TRAILING: return $this->getRtrimExpression($str); default: return 'TRIM(' . $str . ')'; } } $pattern = "'%[^' + $char + ']%'"; switch ($pos) { case self::TRIM_LEADING: return 'SUBSTR(' . $str . ', PATINDEX(' . $pattern . ', ' . $str . '))'; case self::TRIM_TRAILING: return 'REVERSE(SUBSTR(REVERSE(' . $str . '), PATINDEX(' . $pattern . ', REVERSE(' . $str . '))))'; default: return 'REVERSE(SUBSTR(REVERSE(SUBSTR(' . $str . ', PATINDEX(' . $pattern . ', ' . $str . '))), ' . 'PATINDEX(' . $pattern . ', REVERSE(SUBSTR(' . $str . ', PATINDEX(' . $pattern . ', ' . $str . '))))))'; } } /** * {@inheritdoc} */ public function getTruncateTableSQL($tableName, $cascade = false) { $tableIdentifier = new Identifier($tableName); return 'TRUNCATE TABLE ' . $tableIdentifier->getQuotedName($this); } /** * {@inheritdoc} */ public function getUniqueConstraintDeclarationSQL($name, Index $index) { if ($index->isPrimary()) { throw new \InvalidArgumentException( 'Cannot create primary key constraint declarations with getUniqueConstraintDeclarationSQL().' ); } if ( ! $index->isUnique()) { throw new \InvalidArgumentException( 'Can only create unique constraint declarations, no common index declarations with ' . 'getUniqueConstraintDeclarationSQL().' ); } return $this->getTableConstraintDeclarationSQL($index, $name); } /** * {@inheritdoc} */ public function getVarcharDefaultLength() { return 1; } /** * {@inheritdoc} */ public function getVarcharMaxLength() { return 32767; } /** * {@inheritdoc} */ public function hasNativeGuidType() { return true; } /** * {@inheritdoc} */ public function prefersIdentityColumns() { return true; } /** * {@inheritdoc} */ public function supportsCommentOnStatement() { return true; } /** * {@inheritdoc} */ public function supportsIdentityColumns() { return true; } /** * {@inheritdoc} */ protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) { $unsigned = ! empty($columnDef['unsigned']) ? 'UNSIGNED ' : ''; $autoincrement = ! empty($columnDef['autoincrement']) ? ' IDENTITY' : ''; return $unsigned . $columnDef['integer_type'] . $autoincrement; } /** * {@inheritdoc} */ protected function _getCreateTableSQL($tableName, array $columns, array $options = array()) { $columnListSql = $this->getColumnDeclarationListSQL($columns); $indexSql = array(); if ( ! empty($options['uniqueConstraints'])) { foreach ((array) $options['uniqueConstraints'] as $name => $definition) { $columnListSql .= ', ' . $this->getUniqueConstraintDeclarationSQL($name, $definition); } } if ( ! empty($options['indexes'])) { /** @var \Doctrine\DBAL\Schema\Index $index */ foreach ((array) $options['indexes'] as $index) { $indexSql[] = $this->getCreateIndexSQL($index, $tableName); } } if ( ! empty($options['primary'])) { $flags = ''; if (isset($options['primary_index']) && $options['primary_index']->hasFlag('clustered')) { $flags = ' CLUSTERED '; } $columnListSql .= ', PRIMARY KEY' . $flags . ' (' . implode(', ', array_unique(array_values((array) $options['primary']))) . ')'; } if ( ! empty($options['foreignKeys'])) { foreach ((array) $options['foreignKeys'] as $definition) { $columnListSql .= ', ' . $this->getForeignKeyDeclarationSQL($definition); } } $query = 'CREATE TABLE ' . $tableName . ' (' . $columnListSql; $check = $this->getCheckDeclarationSQL($columns); if ( ! empty($check)) { $query .= ', ' . $check; } $query .= ')'; return array_merge(array($query), $indexSql); } /** * {@inheritdoc} */ protected function _getTransactionIsolationLevelSQL($level) { switch ($level) { case Connection::TRANSACTION_READ_UNCOMMITTED: return 0; case Connection::TRANSACTION_READ_COMMITTED: return 1; case Connection::TRANSACTION_REPEATABLE_READ: return 2; case Connection::TRANSACTION_SERIALIZABLE: return 3; default: throw new \InvalidArgumentException('Invalid isolation level:' . $level); } } /** * {@inheritdoc} */ protected function doModifyLimitQuery($query, $limit, $offset) { $limitOffsetClause = ''; if ($limit > 0) { $limitOffsetClause = 'TOP ' . $limit . ' '; } if ($offset > 0) { if ($limit == 0) { $limitOffsetClause = 'TOP ALL '; } $limitOffsetClause .= 'START AT ' . ($offset + 1) . ' '; } if ($limitOffsetClause) { return preg_replace('/^\s*(SELECT\s+(DISTINCT\s+)?)/i', '\1' . $limitOffsetClause, $query); } return $query; } /** * Return the INDEX query section dealing with non-standard * SQL Anywhere options. * * @param Index $index Index definition * * @return string */ protected function getAdvancedIndexOptionsSQL(Index $index) { $sql = ''; if ( ! $index->isPrimary() && $index->hasFlag('for_olap_workload')) { $sql .= ' FOR OLAP WORKLOAD'; } return $sql; } /** * {@inheritdoc} */ protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) { return $fixed ? 'BINARY(' . ($length ?: $this->getBinaryDefaultLength()) . ')' : 'VARBINARY(' . ($length ?: $this->getBinaryDefaultLength()) . ')'; } /** * Returns the SQL snippet for creating a table constraint. * * @param Constraint $constraint The table constraint to create the SQL snippet for. * @param string|null $name The table constraint name to use if any. * * @return string * * @throws \InvalidArgumentException if the given table constraint type is not supported by this method. */ protected function getTableConstraintDeclarationSQL(Constraint $constraint, $name = null) { if ($constraint instanceof ForeignKeyConstraint) { return $this->getForeignKeyDeclarationSQL($constraint); } if ( ! $constraint instanceof Index) { throw new \InvalidArgumentException('Unsupported constraint type: ' . get_class($constraint)); } if ( ! $constraint->isPrimary() && ! $constraint->isUnique()) { throw new \InvalidArgumentException( 'Can only create primary, unique or foreign key constraint declarations, no common index declarations ' . 'with getTableConstraintDeclarationSQL().' ); } $constraintColumns = $constraint->getQuotedColumns($this); if (empty($constraintColumns)) { throw new \InvalidArgumentException("Incomplete definition. 'columns' required."); } $sql = ''; $flags = ''; if ( ! empty($name)) { $name = new Identifier($name); $sql .= 'CONSTRAINT ' . $name->getQuotedName($this) . ' '; } if ($constraint->hasFlag('clustered')) { $flags = 'CLUSTERED '; } if ($constraint->isPrimary()) { return $sql . 'PRIMARY KEY ' . $flags . '('. $this->getIndexFieldDeclarationListSQL($constraintColumns) . ')'; } return $sql . 'UNIQUE ' . $flags . '('. $this->getIndexFieldDeclarationListSQL($constraintColumns) . ')'; } /** * {@inheritdoc} */ protected function getCreateIndexSQLFlags(Index $index) { $type = ''; if ($index->hasFlag('virtual')) { $type .= 'VIRTUAL '; } if ($index->isUnique()) { $type .= 'UNIQUE '; } if ($index->hasFlag('clustered')) { $type .= 'CLUSTERED '; } return $type; } /** * {@inheritdoc} */ protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) { return array( 'ALTER INDEX ' . $oldIndexName . ' ON ' . $tableName . ' RENAME TO ' . $index->getQuotedName($this) ); } /** * {@inheritdoc} */ protected function getReservedKeywordsClass() { return 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhereKeywords'; } /** * {@inheritdoc} */ protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) { return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(' . $this->getVarcharDefaultLength() . ')') : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(' . $this->getVarcharDefaultLength() . ')'); } /** * {@inheritdoc} */ protected function initializeDoctrineTypeMappings() { $this->doctrineTypeMapping = array( 'char' => 'string', 'long nvarchar' => 'text', 'long varchar' => 'text', 'nchar' => 'string', 'ntext' => 'text', 'nvarchar' => 'string', 'text' => 'text', 'uniqueidentifierstr' => 'guid', 'varchar' => 'string', 'xml' => 'text', 'bigint' => 'bigint', 'unsigned bigint' => 'bigint', 'bit' => 'boolean', 'decimal' => 'decimal', 'double' => 'float', 'float' => 'float', 'int' => 'integer', 'integer' => 'integer', 'unsigned int' => 'integer', 'numeric' => 'decimal', 'smallint' => 'smallint', 'unsigned smallint', 'smallint', 'tinyint' => 'smallint', 'unsigned tinyint', 'smallint', 'money' => 'decimal', 'smallmoney' => 'decimal', 'long varbit' => 'text', 'varbit' => 'string', 'date' => 'date', 'datetime' => 'datetime', 'smalldatetime' => 'datetime', 'time' => 'time', 'timestamp' => 'datetime', 'binary' => 'binary', 'image' => 'blob', 'long binary' => 'blob', 'uniqueidentifier' => 'guid', 'varbinary' => 'binary', ); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/SQLAzurePlatform.php000066400000000000000000000035721313473450000233650ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\Schema\Table; /** * Platform to ensure compatibility of Doctrine with SQL Azure * * On top of SQL Server 2008 the following functionality is added: * * - Create tables with the FEDERATED ON syntax. */ class SQLAzurePlatform extends SQLServer2008Platform { /** * {@inheritDoc} */ public function getCreateTableSQL(Table $table, $createFlags=self::CREATE_INDEXES) { $sql = parent::getCreateTableSQL($table, $createFlags); if ($table->hasOption('azure.federatedOnColumnName')) { $distributionName = $table->getOption('azure.federatedOnDistributionName'); $columnName = $table->getOption('azure.federatedOnColumnName'); $stmt = ' FEDERATED ON (' . $distributionName . ' = ' . $columnName . ')'; $sql[0] = $sql[0] . $stmt; } return $sql; } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/SQLServer2005Platform.php000066400000000000000000000041641313473450000240520ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms; /** * Platform to ensure compatibility of Doctrine with Microsoft SQL Server 2005 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 { /** * {@inheritDoc} */ public function supportsLimitOffset() { return true; } /** * {@inheritDoc} */ public function getClobTypeDeclarationSQL(array $field) { return 'VARCHAR(MAX)'; } /** * {@inheritdoc} * * Returns Microsoft SQL Server 2005 specific keywords class */ protected function getReservedKeywordsClass() { return 'Doctrine\DBAL\Platforms\Keywords\SQLServer2005Keywords'; } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/SQLServer2008Platform.php000066400000000000000000000061711313473450000240550ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms; /** * Platform to ensure compatibility of Doctrine with Microsoft SQL Server 2008 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 { /** * {@inheritDoc} */ public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) { // 3 - microseconds precision length // http://msdn.microsoft.com/en-us/library/ms187819.aspx return 'DATETIME2(6)'; } /** * {@inheritDoc} */ public function getDateTypeDeclarationSQL(array $fieldDeclaration) { return 'DATE'; } /** * {@inheritDoc} */ public function getTimeTypeDeclarationSQL(array $fieldDeclaration) { return 'TIME(0)'; } /** * {@inheritDoc} */ public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration) { return 'DATETIMEOFFSET(6)'; } /** * {@inheritDoc} */ public function getDateTimeFormatString() { return 'Y-m-d H:i:s.u'; } /** * {@inheritDoc} */ public function getDateTimeTzFormatString() { return 'Y-m-d H:i:s.u P'; } /** * {@inheritDoc} */ public function getDateFormatString() { return 'Y-m-d'; } /** * {@inheritDoc} */ public function getTimeFormatString() { return 'H:i:s'; } /** * {@inheritDoc} * * Adding Datetime2 Type */ protected function initializeDoctrineTypeMappings() { parent::initializeDoctrineTypeMappings(); $this->doctrineTypeMapping['datetime2'] = 'datetime'; $this->doctrineTypeMapping['date'] = 'date'; $this->doctrineTypeMapping['time'] = 'time'; $this->doctrineTypeMapping['datetimeoffset'] = 'datetimetz'; } /** * {@inheritdoc} * * Returns Microsoft SQL Server 2008 specific keywords class */ protected function getReservedKeywordsClass() { return 'Doctrine\DBAL\Platforms\Keywords\SQLServer2008Keywords'; } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/SQLServer2012Platform.php000066400000000000000000000124361313473450000240510ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\Schema\Sequence; /** * Platform to ensure compatibility of Doctrine with Microsoft SQL Server 2012 version. * * Differences to SQL Server 2008 and before are that sequences are introduced. * * @author Steve Müller */ class SQLServer2012Platform extends SQLServer2008Platform { /** * {@inheritdoc} */ public function getAlterSequenceSQL(Sequence $sequence) { return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) . ' INCREMENT BY ' . $sequence->getAllocationSize(); } /** * {@inheritdoc} */ public function getCreateSequenceSQL(Sequence $sequence) { return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) . ' START WITH ' . $sequence->getInitialValue() . ' INCREMENT BY ' . $sequence->getAllocationSize() . ' MINVALUE ' . $sequence->getInitialValue(); } /** * {@inheritdoc} */ public function getDropSequenceSQL($sequence) { if ($sequence instanceof Sequence) { $sequence = $sequence->getQuotedName($this); } return 'DROP SEQUENCE ' . $sequence; } /** * {@inheritdoc} */ public function getListSequencesSQL($database) { return 'SELECT seq.name, CAST( seq.increment AS VARCHAR(MAX) ) AS increment, -- CAST avoids driver error for sql_variant type CAST( seq.start_value AS VARCHAR(MAX) ) AS start_value -- CAST avoids driver error for sql_variant type FROM sys.sequences AS seq'; } /** * {@inheritdoc} */ public function getSequenceNextValSQL($sequenceName) { return 'SELECT NEXT VALUE FOR ' . $sequenceName; } /** * {@inheritdoc} */ public function supportsSequences() { return true; } /** * {@inheritdoc} * * Returns Microsoft SQL Server 2012 specific keywords class */ protected function getReservedKeywordsClass() { return 'Doctrine\DBAL\Platforms\Keywords\SQLServer2012Keywords'; } /** * {@inheritdoc} */ protected function doModifyLimitQuery($query, $limit, $offset = null) { if ($limit === null && $offset === null) { return $query; } // Queries using OFFSET... FETCH MUST have an ORDER BY clause // Find the position of the last instance of ORDER BY and ensure it is not within a parenthetical statement // but can be in a newline $matches = array(); $matchesCount = preg_match_all("/[\\s]+order by /i", $query, $matches, PREG_OFFSET_CAPTURE); $orderByPos = false; if ($matchesCount > 0) { $orderByPos = $matches[0][($matchesCount - 1)][1]; } if ($orderByPos === false || substr_count($query, "(", $orderByPos) - substr_count($query, ")", $orderByPos) ) { if (stripos($query, 'SELECT DISTINCT') === 0) { // SQL Server won't let us order by a non-selected column in a DISTINCT query, // so we have to do this madness. This says, order by the first column in the // result. SQL Server's docs say that a nonordered query's result order is non- // deterministic anyway, so this won't do anything that a bunch of update and // deletes to the table wouldn't do anyway. $query .= " ORDER BY 1"; } else { // In another DBMS, we could do ORDER BY 0, but SQL Server gets angry if you // use constant expressions in the order by list. $query .= " ORDER BY (SELECT 0)"; } } if ($offset === null) { $offset = 0; } // This looks somewhat like MYSQL, but limit/offset are in inverse positions // Supposedly SQL:2008 core standard. // Per TSQL spec, FETCH NEXT n ROWS ONLY is not valid without OFFSET n ROWS. $query .= " OFFSET " . (int) $offset . " ROWS"; if ($limit !== null) { $query .= " FETCH NEXT " . (int) $limit . " ROWS ONLY"; } return $query; } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php000066400000000000000000001464761313473450000235600ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\LockMode; use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\ColumnDiff; use Doctrine\DBAL\Schema\Identifier; use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\Index; use 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 * @author Jonathan H. Wage * @author Benjamin Eberlei * @author Steve Müller */ class SQLServerPlatform extends AbstractPlatform { /** * {@inheritdoc} */ public function getCurrentDateSQL() { return $this->getConvertExpression('date', 'GETDATE()'); } /** * {@inheritdoc} */ public function getCurrentTimeSQL() { return $this->getConvertExpression('time', 'GETDATE()'); } /** * Returns an expression that converts an expression of one data type to another. * * @param string $dataType The target native data type. Alias data types cannot be used. * @param string $expression The SQL expression to convert. * * @return string */ private function getConvertExpression($dataType, $expression) { return sprintf('CONVERT(%s, %s)', $dataType, $expression); } /** * {@inheritdoc} */ protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) { $factorClause = ''; if ('-' === $operator) { $factorClause = '-1 * '; } return 'DATEADD(' . $unit . ', ' . $factorClause . $interval . ', ' . $date . ')'; } /** * {@inheritDoc} */ public function getDateDiffExpression($date1, $date2) { return 'DATEDIFF(day, ' . $date2 . ',' . $date1 . ')'; } /** * {@inheritDoc} * * Microsoft SQL Server prefers "autoincrement" identity columns * since sequences can only be emulated with a table. */ public function prefersIdentityColumns() { return true; } /** * {@inheritDoc} * * Microsoft SQL Server supports this through AUTO_INCREMENT columns. */ public function supportsIdentityColumns() { return true; } /** * {@inheritDoc} */ public function supportsReleaseSavepoints() { return false; } /** * {@inheritdoc} */ public function supportsSchemas() { return true; } /** * {@inheritdoc} */ public function getDefaultSchemaName() { return 'dbo'; } /** * {@inheritDoc} */ public function supportsColumnCollation() { return true; } /** * {@inheritDoc} */ public function hasNativeGuidType() { return true; } /** * {@inheritDoc} */ public function getCreateDatabaseSQL($name) { return 'CREATE DATABASE ' . $name; } /** * {@inheritDoc} */ public function getDropDatabaseSQL($name) { return 'DROP DATABASE ' . $name; } /** * {@inheritDoc} */ public function supportsCreateDropDatabase() { return false; } /** * {@inheritDoc} */ public function getCreateSchemaSQL($schemaName) { return 'CREATE SCHEMA ' . $schemaName; } /** * {@inheritDoc} */ public function getDropForeignKeySQL($foreignKey, $table) { if (! $foreignKey instanceof ForeignKeyConstraint) { $foreignKey = new Identifier($foreignKey); } if (! $table instanceof Table) { $table = new Identifier($table); } $foreignKey = $foreignKey->getQuotedName($this); $table = $table->getQuotedName($this); return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $foreignKey; } /** * {@inheritDoc} */ public function getDropIndexSQL($index, $table = null) { if ($index instanceof Index) { $index = $index->getQuotedName($this); } elseif (!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; } if ($table instanceof 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; } /** * {@inheritDoc} */ protected function _getCreateTableSQL($tableName, array $columns, array $options = array()) { $defaultConstraintsSql = array(); $commentsSql = array(); // @todo does other code breaks because of this? // force primary keys to be not null foreach ($columns as &$column) { if (isset($column['primary']) && $column['primary']) { $column['notnull'] = true; } // Build default constraints SQL statements. if (isset($column['default'])) { $defaultConstraintsSql[] = 'ALTER TABLE ' . $tableName . ' ADD' . $this->getDefaultConstraintDeclarationSQL($tableName, $column); } if ( ! empty($column['comment']) || is_numeric($column['comment'])) { $commentsSql[] = $this->getCreateColumnCommentSQL($tableName, $column['name'], $column['comment']); } } $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'])) { $flags = ''; if (isset($options['primary_index']) && $options['primary_index']->hasFlag('nonclustered')) { $flags = ' NONCLUSTERED'; } $columnListSql .= ', PRIMARY KEY' . $flags . ' (' . 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 array_merge($sql, $commentsSql, $defaultConstraintsSql); } /** * {@inheritDoc} */ public function getCreatePrimaryKeySQL(Index $index, $table) { $flags = ''; if ($index->hasFlag('nonclustered')) { $flags = ' NONCLUSTERED'; } return 'ALTER TABLE ' . $table . ' ADD PRIMARY KEY' . $flags . ' (' . $this->getIndexFieldDeclarationListSQL($index->getQuotedColumns($this)) . ')'; } /** * Returns the SQL statement for creating a column comment. * * SQL Server does not support native column comments, * therefore the extended properties functionality is used * as a workaround to store them. * The property name used to store column comments is "MS_Description" * which provides compatibility with SQL Server Management Studio, * as column comments are stored in the same property there when * specifying a column's "Description" attribute. * * @param string $tableName The quoted table name to which the column belongs. * @param string $columnName The quoted column name to create the comment for. * @param string $comment The column's comment. * * @return string */ protected function getCreateColumnCommentSQL($tableName, $columnName, $comment) { return $this->getAddExtendedPropertySQL( 'MS_Description', $comment, 'SCHEMA', 'dbo', 'TABLE', $tableName, 'COLUMN', $columnName ); } /** * Returns the SQL snippet for declaring a default constraint. * * @param string $table Name of the table to return the default constraint declaration for. * @param array $column Column definition. * * @return string * * @throws \InvalidArgumentException */ public function getDefaultConstraintDeclarationSQL($table, array $column) { if ( ! isset($column['default'])) { throw new \InvalidArgumentException("Incomplete column definition. 'default' required."); } $columnName = new Identifier($column['name']); return ' CONSTRAINT ' . $this->generateDefaultConstraintName($table, $column['name']) . $this->getDefaultValueDeclarationSQL($column) . ' FOR ' . $columnName->getQuotedName($this); } /** * {@inheritDoc} */ public function getUniqueConstraintDeclarationSQL($name, Index $index) { $constraint = parent::getUniqueConstraintDeclarationSQL($name, $index); $constraint = $this->_appendUniqueConstraintDefinition($constraint, $index); return $constraint; } /** * {@inheritDoc} */ public function getCreateIndexSQL(Index $index, $table) { $constraint = parent::getCreateIndexSQL($index, $table); if ($index->isUnique() && !$index->isPrimary()) { $constraint = $this->_appendUniqueConstraintDefinition($constraint, $index); } return $constraint; } /** * {@inheritDoc} */ protected function getCreateIndexSQLFlags(Index $index) { $type = ''; if ($index->isUnique()) { $type .= 'UNIQUE '; } if ($index->hasFlag('clustered')) { $type .= 'CLUSTERED '; } elseif ($index->hasFlag('nonclustered')) { $type .= 'NONCLUSTERED '; } return $type; } /** * Extend unique key constraint with required filters * * @param string $sql * @param \Doctrine\DBAL\Schema\Index $index * * @return string */ private function _appendUniqueConstraintDefinition($sql, Index $index) { $fields = array(); foreach ($index->getQuotedColumns($this) as $field) { $fields[] = $field . ' IS NOT NULL'; } return $sql . ' WHERE ' . implode(' AND ', $fields); } /** * {@inheritDoc} */ public function getAlterTableSQL(TableDiff $diff) { $queryParts = array(); $sql = array(); $columnSql = array(); $commentsSql = array(); /** @var \Doctrine\DBAL\Schema\Column $column */ foreach ($diff->addedColumns as $column) { if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { continue; } $columnDef = $column->toArray(); $queryParts[] = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnDef); if (isset($columnDef['default'])) { $queryParts[] = $this->getAlterTableAddDefaultConstraintClause($diff->name, $column); } $comment = $this->getColumnComment($column); if ( ! empty($comment) || is_numeric($comment)) { $commentsSql[] = $this->getCreateColumnCommentSQL( $diff->name, $column->getQuotedName($this), $comment ); } } foreach ($diff->removedColumns as $column) { if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { continue; } $queryParts[] = 'DROP COLUMN ' . $column->getQuotedName($this); } /* @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */ foreach ($diff->changedColumns as $columnDiff) { if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { continue; } $column = $columnDiff->column; $comment = $this->getColumnComment($column); $hasComment = ! empty ($comment) || is_numeric($comment); if ($columnDiff->fromColumn instanceof Column) { $fromComment = $this->getColumnComment($columnDiff->fromColumn); $hasFromComment = ! empty ($fromComment) || is_numeric($fromComment); if ($hasFromComment && $hasComment && $fromComment != $comment) { $commentsSql[] = $this->getAlterColumnCommentSQL( $diff->name, $column->getQuotedName($this), $comment ); } elseif ($hasFromComment && ! $hasComment) { $commentsSql[] = $this->getDropColumnCommentSQL($diff->name, $column->getQuotedName($this)); } elseif ($hasComment) { $commentsSql[] = $this->getCreateColumnCommentSQL( $diff->name, $column->getQuotedName($this), $comment ); } } else { // todo: Original comment cannot be determined. What to do? Add, update, drop or skip? } // Do not add query part if only comment has changed. if ($columnDiff->hasChanged('comment') && count($columnDiff->changedProperties) === 1) { continue; } $requireDropDefaultConstraint = $this->alterColumnRequiresDropDefaultConstraint($columnDiff); if ($requireDropDefaultConstraint) { $queryParts[] = $this->getAlterTableDropDefaultConstraintClause( $diff->name, $columnDiff->oldColumnName ); } $columnDef = $column->toArray(); $queryParts[] = 'ALTER COLUMN ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnDef); if (isset($columnDef['default']) && ($requireDropDefaultConstraint || $columnDiff->hasChanged('default'))) { $queryParts[] = $this->getAlterTableAddDefaultConstraintClause($diff->name, $column); } } foreach ($diff->renamedColumns as $oldColumnName => $column) { if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { continue; } $oldColumnName = new Identifier($oldColumnName); $sql[] = "sp_RENAME '" . $diff->getName($this)->getQuotedName($this) . "." . $oldColumnName->getQuotedName($this) . "', '" . $column->getQuotedName($this) . "', 'COLUMN'"; // Recreate default constraint with new column name if necessary (for future reference). if ($column->getDefault() !== null) { $queryParts[] = $this->getAlterTableDropDefaultConstraintClause( $diff->name, $oldColumnName->getQuotedName($this) ); $queryParts[] = $this->getAlterTableAddDefaultConstraintClause($diff->name, $column); } } $tableSql = array(); if ($this->onSchemaAlterTable($diff, $tableSql)) { return array_merge($tableSql, $columnSql); } foreach ($queryParts as $query) { $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; } $sql = array_merge($sql, $commentsSql); if ($diff->newName !== false) { $sql[] = "sp_RENAME '" . $diff->getName($this)->getQuotedName($this) . "', '" . $diff->getNewName()->getName() . "'"; /** * Rename table's default constraints names * to match the new table name. * This is necessary to ensure that the default * constraints can be referenced in future table * alterations as the table name is encoded in * default constraints' names. */ $sql[] = "DECLARE @sql NVARCHAR(MAX) = N''; " . "SELECT @sql += N'EXEC sp_rename N''' + dc.name + ''', N''' " . "+ REPLACE(dc.name, '" . $this->generateIdentifierName($diff->name) . "', " . "'" . $this->generateIdentifierName($diff->newName) . "') + ''', ''OBJECT'';' " . "FROM sys.default_constraints dc " . "JOIN sys.tables tbl ON dc.parent_object_id = tbl.object_id " . "WHERE tbl.name = '" . $diff->getNewName()->getName() . "';" . "EXEC sp_executesql @sql"; } $sql = array_merge( $this->getPreAlterTableIndexForeignKeySQL($diff), $sql, $this->getPostAlterTableIndexForeignKeySQL($diff) ); return array_merge($sql, $tableSql, $columnSql); } /** * Returns the SQL clause for adding a default constraint in an ALTER TABLE statement. * * @param string $tableName The name of the table to generate the clause for. * @param Column $column The column to generate the clause for. * * @return string */ private function getAlterTableAddDefaultConstraintClause($tableName, Column $column) { $columnDef = $column->toArray(); $columnDef['name'] = $column->getQuotedName($this); return 'ADD' . $this->getDefaultConstraintDeclarationSQL($tableName, $columnDef); } /** * Returns the SQL clause for dropping an existing default constraint in an ALTER TABLE statement. * * @param string $tableName The name of the table to generate the clause for. * @param string $columnName The name of the column to generate the clause for. * * @return string */ private function getAlterTableDropDefaultConstraintClause($tableName, $columnName) { return 'DROP CONSTRAINT ' . $this->generateDefaultConstraintName($tableName, $columnName); } /** * Checks whether a column alteration requires dropping its default constraint first. * * Different to other database vendors SQL Server implements column default values * as constraints and therefore changes in a column's default value as well as changes * in a column's type require dropping the default constraint first before being to * alter the particular column to the new definition. * * @param ColumnDiff $columnDiff The column diff to evaluate. * * @return boolean True if the column alteration requires dropping its default constraint first, false otherwise. */ private function alterColumnRequiresDropDefaultConstraint(ColumnDiff $columnDiff) { // We can only decide whether to drop an existing default constraint // if we know the original default value. if ( ! $columnDiff->fromColumn instanceof Column) { return false; } // We only need to drop an existing default constraint if we know the // column was defined with a default value before. if ($columnDiff->fromColumn->getDefault() === null) { return false; } // We need to drop an existing default constraint if the column was // defined with a default value before and it has changed. if ($columnDiff->hasChanged('default')) { return true; } // We need to drop an existing default constraint if the column was // defined with a default value before and the native column type has changed. if ($columnDiff->hasChanged('type') || $columnDiff->hasChanged('fixed')) { return true; } return false; } /** * Returns the SQL statement for altering a column comment. * * SQL Server does not support native column comments, * therefore the extended properties functionality is used * as a workaround to store them. * The property name used to store column comments is "MS_Description" * which provides compatibility with SQL Server Management Studio, * as column comments are stored in the same property there when * specifying a column's "Description" attribute. * * @param string $tableName The quoted table name to which the column belongs. * @param string $columnName The quoted column name to alter the comment for. * @param string $comment The column's comment. * * @return string */ protected function getAlterColumnCommentSQL($tableName, $columnName, $comment) { return $this->getUpdateExtendedPropertySQL( 'MS_Description', $comment, 'SCHEMA', 'dbo', 'TABLE', $tableName, 'COLUMN', $columnName ); } /** * Returns the SQL statement for dropping a column comment. * * SQL Server does not support native column comments, * therefore the extended properties functionality is used * as a workaround to store them. * The property name used to store column comments is "MS_Description" * which provides compatibility with SQL Server Management Studio, * as column comments are stored in the same property there when * specifying a column's "Description" attribute. * * @param string $tableName The quoted table name to which the column belongs. * @param string $columnName The quoted column name to drop the comment for. * * @return string */ protected function getDropColumnCommentSQL($tableName, $columnName) { return $this->getDropExtendedPropertySQL( 'MS_Description', 'SCHEMA', 'dbo', 'TABLE', $tableName, 'COLUMN', $columnName ); } /** * {@inheritdoc} */ protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) { return array( sprintf( "EXEC sp_RENAME N'%s.%s', N'%s', N'INDEX'", $tableName, $oldIndexName, $index->getQuotedName($this) ) ); } /** * Returns the SQL statement for adding an extended property to a database object. * * @param string $name The name of the property to add. * @param string|null $value The value of the property to add. * @param string|null $level0Type The type of the object at level 0 the property belongs to. * @param string|null $level0Name The name of the object at level 0 the property belongs to. * @param string|null $level1Type The type of the object at level 1 the property belongs to. * @param string|null $level1Name The name of the object at level 1 the property belongs to. * @param string|null $level2Type The type of the object at level 2 the property belongs to. * @param string|null $level2Name The name of the object at level 2 the property belongs to. * * @return string * * @link http://msdn.microsoft.com/en-us/library/ms180047%28v=sql.90%29.aspx */ public function getAddExtendedPropertySQL( $name, $value = null, $level0Type = null, $level0Name = null, $level1Type = null, $level1Name = null, $level2Type = null, $level2Name = null ) { return "EXEC sp_addextendedproperty " . "N" . $this->quoteStringLiteral($name) . ", N" . $this->quoteStringLiteral($value) . ", " . "N" . $this->quoteStringLiteral($level0Type) . ", " . $level0Name . ', ' . "N" . $this->quoteStringLiteral($level1Type) . ", " . $level1Name . ', ' . "N" . $this->quoteStringLiteral($level2Type) . ", " . $level2Name; } /** * Returns the SQL statement for dropping an extended property from a database object. * * @param string $name The name of the property to drop. * @param string|null $level0Type The type of the object at level 0 the property belongs to. * @param string|null $level0Name The name of the object at level 0 the property belongs to. * @param string|null $level1Type The type of the object at level 1 the property belongs to. * @param string|null $level1Name The name of the object at level 1 the property belongs to. * @param string|null $level2Type The type of the object at level 2 the property belongs to. * @param string|null $level2Name The name of the object at level 2 the property belongs to. * * @return string * * @link http://technet.microsoft.com/en-gb/library/ms178595%28v=sql.90%29.aspx */ public function getDropExtendedPropertySQL( $name, $level0Type = null, $level0Name = null, $level1Type = null, $level1Name = null, $level2Type = null, $level2Name = null ) { return "EXEC sp_dropextendedproperty " . "N" . $this->quoteStringLiteral($name) . ", " . "N" . $this->quoteStringLiteral($level0Type) . ", " . $level0Name . ', ' . "N" . $this->quoteStringLiteral($level1Type) . ", " . $level1Name . ', ' . "N" . $this->quoteStringLiteral($level2Type) . ", " . $level2Name; } /** * Returns the SQL statement for updating an extended property of a database object. * * @param string $name The name of the property to update. * @param string|null $value The value of the property to update. * @param string|null $level0Type The type of the object at level 0 the property belongs to. * @param string|null $level0Name The name of the object at level 0 the property belongs to. * @param string|null $level1Type The type of the object at level 1 the property belongs to. * @param string|null $level1Name The name of the object at level 1 the property belongs to. * @param string|null $level2Type The type of the object at level 2 the property belongs to. * @param string|null $level2Name The name of the object at level 2 the property belongs to. * * @return string * * @link http://msdn.microsoft.com/en-us/library/ms186885%28v=sql.90%29.aspx */ public function getUpdateExtendedPropertySQL( $name, $value = null, $level0Type = null, $level0Name = null, $level1Type = null, $level1Name = null, $level2Type = null, $level2Name = null ) { return "EXEC sp_updateextendedproperty " . "N" . $this->quoteStringLiteral($name) . ", N" . $this->quoteStringLiteral($value) . ", " . "N" . $this->quoteStringLiteral($level0Type) . ", " . $level0Name . ', ' . "N" . $this->quoteStringLiteral($level1Type) . ", " . $level1Name . ', ' . "N" . $this->quoteStringLiteral($level2Type) . ", " . $level2Name; } /** * {@inheritDoc} */ public function getEmptyIdentityInsertSQL($quotedTableName, $quotedIdentifierColumnName) { return 'INSERT INTO ' . $quotedTableName . ' DEFAULT VALUES'; } /** * {@inheritDoc} */ public function getListTablesSQL() { // "sysdiagrams" table must be ignored as it's internal SQL Server table for Database Diagrams // Category 2 must be ignored as it is "MS SQL Server 'pseudo-system' object[s]" for replication return "SELECT name FROM sysobjects WHERE type = 'U' AND name != 'sysdiagrams' AND category != 2 ORDER BY name"; } /** * {@inheritDoc} */ public function getListTableColumnsSQL($table, $database = null) { return "SELECT col.name, type.name AS type, col.max_length AS length, ~col.is_nullable AS notnull, def.definition AS [default], col.scale, col.precision, col.is_identity AS autoincrement, col.collation_name AS collation, CAST(prop.value AS NVARCHAR(MAX)) AS comment -- CAST avoids driver error for sql_variant type FROM sys.columns AS col JOIN sys.types AS type ON col.user_type_id = type.user_type_id JOIN sys.objects AS obj ON col.object_id = obj.object_id JOIN sys.schemas AS scm ON obj.schema_id = scm.schema_id LEFT JOIN sys.default_constraints def ON col.default_object_id = def.object_id AND col.object_id = def.parent_object_id LEFT JOIN sys.extended_properties AS prop ON obj.object_id = prop.major_id AND col.column_id = prop.minor_id AND prop.name = 'MS_Description' WHERE obj.type = 'U' AND " . $this->getTableWhereClause($table, 'scm.name', 'obj.name'); } /** * {@inheritDoc} */ 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 " . $this->getTableWhereClause($table, 'SCHEMA_NAME (f.schema_id)', 'OBJECT_NAME (f.parent_object_id)'); } /** * {@inheritDoc} */ public function getListTableIndexesSQL($table, $currentDatabase = null) { return "SELECT idx.name AS key_name, col.name AS column_name, ~idx.is_unique AS non_unique, idx.is_primary_key AS [primary], CASE idx.type WHEN '1' THEN 'clustered' WHEN '2' THEN 'nonclustered' ELSE NULL END AS flags FROM sys.tables AS tbl JOIN sys.schemas AS scm ON tbl.schema_id = scm.schema_id JOIN sys.indexes AS idx ON tbl.object_id = idx.object_id JOIN sys.index_columns AS idxcol ON idx.object_id = idxcol.object_id AND idx.index_id = idxcol.index_id JOIN sys.columns AS col ON idxcol.object_id = col.object_id AND idxcol.column_id = col.column_id WHERE " . $this->getTableWhereClause($table, 'scm.name', 'tbl.name') . " ORDER BY idx.index_id ASC, idxcol.key_ordinal ASC"; } /** * {@inheritDoc} */ public function getCreateViewSQL($name, $sql) { return 'CREATE VIEW ' . $name . ' AS ' . $sql; } /** * {@inheritDoc} */ public function getListViewsSQL($database) { return "SELECT name FROM sysobjects WHERE type = 'V' ORDER BY name"; } /** * Returns the where clause to filter schema and table name in a query. * * @param string $table The full qualified name of the table. * @param string $schemaColumn The name of the column to compare the schema to in the where clause. * @param string $tableColumn The name of the column to compare the table to in the where clause. * * @return string */ private function getTableWhereClause($table, $schemaColumn, $tableColumn) { if (strpos($table, ".") !== false) { list($schema, $table) = explode(".", $table); $schema = $this->quoteStringLiteral($schema); $table = $this->quoteStringLiteral($table); } else { $schema = "SCHEMA_NAME()"; $table = $this->quoteStringLiteral($table); } return "({$tableColumn} = {$table} AND {$schemaColumn} = {$schema})"; } /** * {@inheritDoc} */ public function getDropViewSQL($name) { return 'DROP VIEW ' . $name; } /** * {@inheritDoc} */ public function getGuidExpression() { return 'NEWID()'; } /** * {@inheritDoc} */ public function getLocateExpression($str, $substr, $startPos = false) { if ($startPos == false) { return 'CHARINDEX(' . $substr . ', ' . $str . ')'; } return 'CHARINDEX(' . $substr . ', ' . $str . ', ' . $startPos . ')'; } /** * {@inheritDoc} */ public function getModExpression($expression1, $expression2) { return $expression1 . ' % ' . $expression2; } /** * {@inheritDoc} */ public function getTrimExpression($str, $pos = self::TRIM_UNSPECIFIED, $char = false) { if ( ! $char) { switch ($pos) { case self::TRIM_LEADING: $trimFn = 'LTRIM'; break; case self::TRIM_TRAILING: $trimFn = 'RTRIM'; break; default: return 'LTRIM(RTRIM(' . $str . '))'; } return $trimFn . '(' . $str . ')'; } /** 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)'; } if ($pos == self::TRIM_TRAILING) { return 'reverse(stuff(reverse(' . $str . '), 1, patindex(' . $pattern . ', reverse(' . $str . ')) - 1, null))'; } 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))'; } /** * {@inheritDoc} */ public function getConcatExpression() { $args = func_get_args(); return '(' . implode(' + ', $args) . ')'; } /** * {@inheritDoc} */ public function getListDatabasesSQL() { return 'SELECT * FROM sys.databases'; } /** * {@inheritDoc} */ public function getListNamespacesSQL() { return "SELECT name FROM sys.schemas WHERE name NOT IN('guest', 'INFORMATION_SCHEMA', 'sys')"; } /** * {@inheritDoc} */ public function getSubstringExpression($value, $from, $length = null) { if (!is_null($length)) { return 'SUBSTRING(' . $value . ', ' . $from . ', ' . $length . ')'; } return 'SUBSTRING(' . $value . ', ' . $from . ', LEN(' . $value . ') - ' . $from . ' + 1)'; } /** * {@inheritDoc} */ public function getLengthExpression($column) { return 'LEN(' . $column . ')'; } /** * {@inheritDoc} */ public function getSetTransactionIsolationSQL($level) { return 'SET TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level); } /** * {@inheritDoc} */ public function getIntegerTypeDeclarationSQL(array $field) { return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field); } /** * {@inheritDoc} */ public function getBigIntTypeDeclarationSQL(array $field) { return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); } /** * {@inheritDoc} */ public function getSmallIntTypeDeclarationSQL(array $field) { return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); } /** * {@inheritDoc} */ public function getGuidTypeDeclarationSQL(array $field) { return 'UNIQUEIDENTIFIER'; } /** * {@inheritDoc} */ protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) { return $fixed ? ($length ? 'NCHAR(' . $length . ')' : 'CHAR(255)') : ($length ? 'NVARCHAR(' . $length . ')' : 'NVARCHAR(255)'); } /** * {@inheritdoc} */ protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) { return $fixed ? 'BINARY(' . ($length ?: 255) . ')' : 'VARBINARY(' . ($length ?: 255) . ')'; } /** * {@inheritdoc} */ public function getBinaryMaxLength() { return 8000; } /** * {@inheritDoc} */ public function getClobTypeDeclarationSQL(array $field) { return 'VARCHAR(MAX)'; } /** * {@inheritDoc} */ protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) { return (!empty($columnDef['autoincrement'])) ? ' IDENTITY' : ''; } /** * {@inheritDoc} */ public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) { return 'DATETIME'; } /** * {@inheritDoc} */ public function getDateTypeDeclarationSQL(array $fieldDeclaration) { return 'DATETIME'; } /** * {@inheritDoc} */ public function getTimeTypeDeclarationSQL(array $fieldDeclaration) { return 'DATETIME'; } /** * {@inheritDoc} */ public function getBooleanTypeDeclarationSQL(array $field) { return 'BIT'; } /** * {@inheritDoc} */ protected function doModifyLimitQuery($query, $limit, $offset = null) { if ($limit === null) { return $query; } $start = $offset + 1; $end = $offset + $limit; // We'll find a SELECT or SELECT distinct and prepend TOP n to it // Even if the TOP n is very large, the use of a CTE will // allow the SQL Server query planner to optimize it so it doesn't // actually scan the entire range covered by the TOP clause. $selectPattern = '/^(\s*SELECT\s+(?:DISTINCT\s+)?)(.*)$/i'; $replacePattern = sprintf('$1%s $2', "TOP $end"); $query = preg_replace($selectPattern, $replacePattern, $query); if (stristr($query, "ORDER BY")) { // Inner order by is not valid in SQL Server for our purposes // unless it's in a TOP N subquery. $query = $this->scrubInnerOrderBy($query); } // Build a new limited query around the original, using a CTE return sprintf( "WITH dctrn_cte AS (%s) " . "SELECT * FROM (" . "SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS doctrine_rownum FROM dctrn_cte" . ") AS doctrine_tbl " . "WHERE doctrine_rownum BETWEEN %d AND %d ORDER BY doctrine_rownum ASC", $query, $start, $end ); } /** * Remove ORDER BY clauses in subqueries - they're not supported by SQL Server. * Caveat: will leave ORDER BY in TOP N subqueries. * * @param $query * @return string */ private function scrubInnerOrderBy($query) { $count = substr_count(strtoupper($query), 'ORDER BY'); $offset = 0; while ($count-- > 0) { $orderByPos = stripos($query, ' ORDER BY', $offset); if ($orderByPos === false) { break; } $qLen = strlen($query); $parenCount = 0; $currentPosition = $orderByPos; while ($parenCount >= 0 && $currentPosition < $qLen) { if ($query[$currentPosition] === '(') { $parenCount++; } elseif ($query[$currentPosition] === ')') { $parenCount--; } $currentPosition++; } if ($this->isOrderByInTopNSubquery($query, $orderByPos)) { // If the order by clause is in a TOP N subquery, do not remove // it and continue iteration from the current position. $offset = $currentPosition; continue; } if ($currentPosition < $qLen - 1) { $query = substr($query, 0, $orderByPos) . substr($query, $currentPosition - 1); $offset = $orderByPos; } } return $query; } /** * Check an ORDER BY clause to see if it is in a TOP N query or subquery. * * @param string $query The query * @param int $currentPosition Start position of ORDER BY clause * @return bool true if ORDER BY is in a TOP N query, false otherwise */ private function isOrderByInTopNSubquery($query, $currentPosition) { // Grab query text on the same nesting level as the ORDER BY clause we're examining. $subQueryBuffer = ''; $parenCount = 0; // If $parenCount goes negative, we've exited the subquery we're examining. // If $currentPosition goes negative, we've reached the beginning of the query. while ($parenCount >= 0 && $currentPosition >= 0) { if ($query[$currentPosition] === '(') { $parenCount--; } elseif ($query[$currentPosition] === ')') { $parenCount++; } // Only yank query text on the same nesting level as the ORDER BY clause. $subQueryBuffer = ($parenCount === 0 ? $query[$currentPosition] : ' ') . $subQueryBuffer; $currentPosition--; } if (preg_match('/SELECT\s+(DISTINCT\s+)?TOP\s/i', $subQueryBuffer)) { return true; } return false; } /** * {@inheritDoc} */ public function supportsLimitOffset() { return false; } /** * {@inheritDoc} */ 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; } } } elseif (is_bool($item) || is_numeric($item)) { $item = ($item) ? 1 : 0; } return $item; } /** * {@inheritDoc} */ public function getCreateTemporaryTableSnippetSQL() { return "CREATE TABLE"; } /** * {@inheritDoc} */ public function getTemporaryTableName($tableName) { return '#' . $tableName; } /** * {@inheritDoc} */ public function getDateTimeFormatString() { return 'Y-m-d H:i:s.000'; } /** * {@inheritDoc} */ public function getDateFormatString() { return 'Y-m-d H:i:s.000'; } /** * {@inheritDoc} */ public function getTimeFormatString() { return 'Y-m-d H:i:s.000'; } /** * {@inheritDoc} */ public function getDateTimeTzFormatString() { return $this->getDateTimeFormatString(); } /** * {@inheritDoc} */ public function getName() { return 'mssql'; } /** * {@inheritDoc} */ 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', 'smalldatetime' => 'datetime', 'datetime' => 'datetime', 'char' => 'string', 'varchar' => 'string', 'text' => 'text', 'nchar' => 'string', 'nvarchar' => 'string', 'ntext' => 'text', 'binary' => 'binary', 'varbinary' => 'binary', 'image' => 'blob', 'uniqueidentifier' => 'guid', ); } /** * {@inheritDoc} */ public function createSavePoint($savepoint) { return 'SAVE TRANSACTION ' . $savepoint; } /** * {@inheritDoc} */ public function releaseSavePoint($savepoint) { return ''; } /** * {@inheritDoc} */ public function rollbackSavePoint($savepoint) { return 'ROLLBACK TRANSACTION ' . $savepoint; } /** * {@inheritdoc} */ public function getForeignKeyReferentialActionSQL($action) { // RESTRICT is not supported, therefore falling back to NO ACTION. if (strtoupper($action) === 'RESTRICT') { return 'NO ACTION'; } return parent::getForeignKeyReferentialActionSQL($action); } /** * {@inheritDoc} */ public function appendLockHint($fromClause, $lockMode) { switch (true) { case LockMode::NONE === $lockMode: return $fromClause . ' WITH (NOLOCK)'; case LockMode::PESSIMISTIC_READ === $lockMode: return $fromClause . ' WITH (HOLDLOCK, ROWLOCK)'; case LockMode::PESSIMISTIC_WRITE === $lockMode: return $fromClause . ' WITH (UPDLOCK, ROWLOCK)'; default: return $fromClause; } } /** * {@inheritDoc} */ public function getForUpdateSQL() { return ' '; } /** * {@inheritDoc} */ protected function getReservedKeywordsClass() { return 'Doctrine\DBAL\Platforms\Keywords\SQLServerKeywords'; } /** * {@inheritDoc} */ public function quoteSingleIdentifier($str) { return "[" . str_replace("]", "][", $str) . "]"; } /** * {@inheritDoc} */ public function getTruncateTableSQL($tableName, $cascade = false) { $tableIdentifier = new Identifier($tableName); return 'TRUNCATE TABLE ' . $tableIdentifier->getQuotedName($this); } /** * {@inheritDoc} */ public function getBlobTypeDeclarationSQL(array $field) { return 'VARBINARY(MAX)'; } /** * {@inheritDoc} */ public function getDefaultValueDeclarationSQL($field) { if ( ! isset($field['default'])) { return empty($field['notnull']) ? ' NULL' : ''; } if ( ! isset($field['type'])) { return " DEFAULT '" . $field['default'] . "'"; } if (in_array((string) $field['type'], array('Integer', 'BigInt', 'SmallInt'))) { return " DEFAULT " . $field['default']; } if (in_array((string) $field['type'], array('DateTime', 'DateTimeTz')) && $field['default'] == $this->getCurrentTimestampSQL()) { return " DEFAULT " . $this->getCurrentTimestampSQL(); } if ((string) $field['type'] == 'Boolean') { return " DEFAULT '" . $this->convertBooleans($field['default']) . "'"; } return " DEFAULT '" . $field['default'] . "'"; } /** * {@inheritdoc} * * Modifies column declaration order as it differs in Microsoft SQL Server. */ public function getColumnDeclarationSQL($name, array $field) { if (isset($field['columnDefinition'])) { $columnDef = $this->getCustomTypeDeclarationSQL($field); } else { $collation = (isset($field['collation']) && $field['collation']) ? ' ' . $this->getColumnCollationDeclarationSQL($field['collation']) : ''; $notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : ''; $unique = (isset($field['unique']) && $field['unique']) ? ' ' . $this->getUniqueFieldDeclarationSQL() : ''; $check = (isset($field['check']) && $field['check']) ? ' ' . $field['check'] : ''; $typeDecl = $field['type']->getSqlDeclaration($field, $this); $columnDef = $typeDecl . $collation . $notnull . $unique . $check; } return $name . ' ' . $columnDef; } /** * Returns a unique default constraint name for a table and column. * * @param string $table Name of the table to generate the unique default constraint name for. * @param string $column Name of the column in the table to generate the unique default constraint name for. * * @return string */ private function generateDefaultConstraintName($table, $column) { return 'DF_' . $this->generateIdentifierName($table) . '_' . $this->generateIdentifierName($column); } /** * Returns a hash value for a given identifier. * * @param string $identifier Identifier to generate a hash value for. * * @return string */ private function generateIdentifierName($identifier) { // Always generate name for unquoted identifiers to ensure consistency. $identifier = new Identifier($identifier); return strtoupper(dechex(crc32($identifier->getName()))); } } dbal-2.5.13/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php000066400000000000000000001027741313473450000231640ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\Identifier; use Doctrine\DBAL\Schema\Constraint; /** * The SqlitePlatform class describes the specifics and dialects of the SQLite * database platform. * * @since 2.0 * @author Roman Borschel * @author Benjamin Eberlei * @author Martin Hasoň * @todo Rename: SQLitePlatform */ class SqlitePlatform extends AbstractPlatform { /** * {@inheritDoc} */ public function getRegexpExpression() { return 'REGEXP'; } /** * {@inheritDoc} */ public function getGuidExpression() { return "HEX(RANDOMBLOB(4)) || '-' || HEX(RANDOMBLOB(2)) || '-4' || " . "SUBSTR(HEX(RANDOMBLOB(2)), 2) || '-' || " . "SUBSTR('89AB', 1 + (ABS(RANDOM()) % 4), 1) || " . "SUBSTR(HEX(RANDOMBLOB(2)), 2) || '-' || HEX(RANDOMBLOB(6))"; } /** * {@inheritDoc} */ public function getNowExpression($type = 'timestamp') { switch ($type) { case 'time': return 'time(\'now\')'; case 'date': return 'date(\'now\')'; case 'timestamp': default: return 'datetime(\'now\')'; } } /** * {@inheritDoc} */ public function getTrimExpression($str, $pos = self::TRIM_UNSPECIFIED, $char = false) { $trimChar = ($char != false) ? (', ' . $char) : ''; switch ($pos) { case self::TRIM_LEADING: $trimFn = 'LTRIM'; break; case self::TRIM_TRAILING: $trimFn = 'RTRIM'; break; default: $trimFn = 'TRIM'; } return $trimFn . '(' . $str . $trimChar . ')'; } /** * {@inheritDoc} * * SQLite only supports the 2 parameter variant of this function */ public function getSubstringExpression($value, $position, $length = null) { if ($length !== null) { return 'SUBSTR(' . $value . ', ' . $position . ', ' . $length . ')'; } return 'SUBSTR(' . $value . ', ' . $position . ', LENGTH(' . $value . '))'; } /** * {@inheritDoc} */ public function getLocateExpression($str, $substr, $startPos = false) { if ($startPos == false) { return 'LOCATE('.$str.', '.$substr.')'; } return 'LOCATE('.$str.', '.$substr.', '.$startPos.')'; } /** * {@inheritdoc} */ protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) { switch ($unit) { case self::DATE_INTERVAL_UNIT_SECOND: case self::DATE_INTERVAL_UNIT_MINUTE: case self::DATE_INTERVAL_UNIT_HOUR: return "DATETIME(" . $date . ",'" . $operator . $interval . " " . $unit . "')"; default: switch ($unit) { case self::DATE_INTERVAL_UNIT_WEEK: $interval *= 7; $unit = self::DATE_INTERVAL_UNIT_DAY; break; case self::DATE_INTERVAL_UNIT_QUARTER: $interval *= 3; $unit = self::DATE_INTERVAL_UNIT_MONTH; break; } return "DATE(" . $date . ",'" . $operator . $interval . " " . $unit . "')"; } } /** * {@inheritDoc} */ public function getDateDiffExpression($date1, $date2) { return 'ROUND(JULIANDAY('.$date1 . ')-JULIANDAY('.$date2.'))'; } /** * {@inheritDoc} */ 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); } } /** * {@inheritDoc} */ public function getSetTransactionIsolationSQL($level) { return 'PRAGMA read_uncommitted = ' . $this->_getTransactionIsolationLevelSQL($level); } /** * {@inheritDoc} */ public function prefersIdentityColumns() { return true; } /** * {@inheritDoc} */ public function getBooleanTypeDeclarationSQL(array $field) { return 'BOOLEAN'; } /** * {@inheritDoc} */ public function getIntegerTypeDeclarationSQL(array $field) { return 'INTEGER' . $this->_getCommonIntegerTypeDeclarationSQL($field); } /** * {@inheritDoc} */ public function getBigIntTypeDeclarationSQL(array $field) { // SQLite autoincrement is implicit for INTEGER PKs, but not for BIGINT fields. if ( ! empty($field['autoincrement'])) { return $this->getIntegerTypeDeclarationSQL($field); } return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); } /** * {@inheritDoc} */ public function getTinyIntTypeDeclarationSql(array $field) { // SQLite autoincrement is implicit for INTEGER PKs, but not for TINYINT fields. if ( ! empty($field['autoincrement'])) { return $this->getIntegerTypeDeclarationSQL($field); } return 'TINYINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); } /** * {@inheritDoc} */ public function getSmallIntTypeDeclarationSQL(array $field) { // SQLite autoincrement is implicit for INTEGER PKs, but not for SMALLINT fields. if ( ! empty($field['autoincrement'])) { return $this->getIntegerTypeDeclarationSQL($field); } return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); } /** * {@inheritDoc} */ public function getMediumIntTypeDeclarationSql(array $field) { // SQLite autoincrement is implicit for INTEGER PKs, but not for MEDIUMINT fields. if ( ! empty($field['autoincrement'])) { return $this->getIntegerTypeDeclarationSQL($field); } return 'MEDIUMINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); } /** * {@inheritDoc} */ public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) { return 'DATETIME'; } /** * {@inheritDoc} */ public function getDateTypeDeclarationSQL(array $fieldDeclaration) { return 'DATE'; } /** * {@inheritDoc} */ public function getTimeTypeDeclarationSQL(array $fieldDeclaration) { return 'TIME'; } /** * {@inheritDoc} */ protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) { // sqlite autoincrement is implicit for integer PKs, but not when the field is unsigned if ( ! empty($columnDef['autoincrement'])) { return ''; } return ! empty($columnDef['unsigned']) ? ' UNSIGNED' : ''; } /** * {@inheritDoc} */ public function getForeignKeyDeclarationSQL(ForeignKeyConstraint $foreignKey) { return parent::getForeignKeyDeclarationSQL(new ForeignKeyConstraint( $foreignKey->getQuotedLocalColumns($this), str_replace('.', '__', $foreignKey->getQuotedForeignTableName($this)), $foreignKey->getQuotedForeignColumns($this), $foreignKey->getName(), $foreignKey->getOptions() )); } /** * {@inheritDoc} */ protected function _getCreateTableSQL($name, array $columns, array $options = array()) { $name = str_replace('.', '__', $name); $queryFields = $this->getColumnDeclarationListSQL($columns); if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) { foreach ($options['uniqueConstraints'] as $name => $definition) { $queryFields .= ', ' . $this->getUniqueConstraintDeclarationSQL($name, $definition); } } if (isset($options['primary']) && ! empty($options['primary'])) { $keyColumns = array_unique(array_values($options['primary'])); $queryFields.= ', PRIMARY KEY('.implode(', ', $keyColumns).')'; } if (isset($options['foreignKeys'])) { foreach ($options['foreignKeys'] as $foreignKey) { $queryFields.= ', '.$this->getForeignKeyDeclarationSQL($foreignKey); } } $query[] = 'CREATE TABLE ' . $name . ' (' . $queryFields . ')'; if (isset($options['alter']) && true === $options['alter']) { return $query; } if (isset($options['indexes']) && ! empty($options['indexes'])) { foreach ($options['indexes'] as $indexDef) { $query[] = $this->getCreateIndexSQL($indexDef, $name); } } if (isset($options['unique']) && ! empty($options['unique'])) { foreach ($options['unique'] as $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'); } /** * {@inheritdoc} */ protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) { return 'BLOB'; } /** * {@inheritdoc} */ public function getBinaryMaxLength() { return 0; } /** * {@inheritdoc} */ public function getBinaryDefaultLength() { return 0; } /** * {@inheritDoc} */ public function getClobTypeDeclarationSQL(array $field) { return 'CLOB'; } /** * {@inheritDoc} */ public function getListTableConstraintsSQL($table) { $table = str_replace('.', '__', $table); $table = $this->quoteStringLiteral($table); return "SELECT sql FROM sqlite_master WHERE type='index' AND tbl_name = $table AND sql NOT NULL ORDER BY name"; } /** * {@inheritDoc} */ public function getListTableColumnsSQL($table, $currentDatabase = null) { $table = str_replace('.', '__', $table); $table = $this->quoteStringLiteral($table); return "PRAGMA table_info($table)"; } /** * {@inheritDoc} */ public function getListTableIndexesSQL($table, $currentDatabase = null) { $table = str_replace('.', '__', $table); $table = $this->quoteStringLiteral($table); return "PRAGMA index_list($table)"; } /** * {@inheritDoc} */ 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"; } /** * {@inheritDoc} */ public function getListViewsSQL($database) { return "SELECT name, sql FROM sqlite_master WHERE type='view' AND sql NOT NULL"; } /** * {@inheritDoc} */ public function getCreateViewSQL($name, $sql) { return 'CREATE VIEW ' . $name . ' AS ' . $sql; } /** * {@inheritDoc} */ public function getDropViewSQL($name) { return 'DROP VIEW '. $name; } /** * {@inheritDoc} */ public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey) { $query = parent::getAdvancedForeignKeyOptionsSQL($foreignKey); $query .= (($foreignKey->hasOption('deferrable') && $foreignKey->getOption('deferrable') !== false) ? ' ' : ' NOT ') . 'DEFERRABLE'; $query .= ' INITIALLY ' . (($foreignKey->hasOption('deferred') && $foreignKey->getOption('deferred') !== false) ? 'DEFERRED' : 'IMMEDIATE'); return $query; } /** * {@inheritDoc} */ public function supportsIdentityColumns() { return true; } /** * {@inheritDoc} */ public function supportsColumnCollation() { return true; } /** * {@inheritDoc} */ public function getName() { return 'sqlite'; } /** * {@inheritDoc} */ public function getTruncateTableSQL($tableName, $cascade = false) { $tableIdentifier = new Identifier($tableName); $tableName = str_replace('.', '__', $tableIdentifier->getQuotedName($this)); return 'DELETE FROM ' . $tableName; } /** * User-defined function for Sqlite that is used with PDO::sqliteCreateFunction(). * * @param integer|float $value * * @return float */ static public function udfSqrt($value) { return sqrt($value); } /** * User-defined function for Sqlite that implements MOD(a, b). * * @param integer $a * @param integer $b * * @return integer */ static public function udfMod($a, $b) { return ($a % $b); } /** * @param string $str * @param string $substr * @param integer $offset * * @return integer */ static public function udfLocate($str, $substr, $offset = 0) { // SQL's LOCATE function works on 1-based positions, while PHP's strpos works on 0-based positions. // So we have to make them compatible if an offset is given. if ($offset > 0) { $offset -= 1; } $pos = strpos($str, $substr, $offset); if ($pos !== false) { return $pos + 1; } return 0; } /** * {@inheritDoc} */ public function getForUpdateSql() { return ''; } /** * {@inheritDoc} */ 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', ); } /** * {@inheritDoc} */ protected function getReservedKeywordsClass() { return 'Doctrine\DBAL\Platforms\Keywords\SQLiteKeywords'; } /** * {@inheritDoc} */ protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) { if ( ! $diff->fromTable instanceof Table) { throw new DBALException('Sqlite platform requires for alter table the table diff with reference to original table schema'); } $sql = array(); foreach ($diff->fromTable->getIndexes() as $index) { if ( ! $index->isPrimary()) { $sql[] = $this->getDropIndexSQL($index, $diff->name); } } return $sql; } /** * {@inheritDoc} */ protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff) { if ( ! $diff->fromTable instanceof Table) { throw new DBALException('Sqlite platform requires for alter table the table diff with reference to original table schema'); } $sql = array(); $tableName = $diff->newName ? $diff->getNewName(): $diff->getName($this); foreach ($this->getIndexesInAlteredTable($diff) as $index) { if ($index->isPrimary()) { continue; } $sql[] = $this->getCreateIndexSQL($index, $tableName->getQuotedName($this)); } return $sql; } /** * {@inheritDoc} */ protected function doModifyLimitQuery($query, $limit, $offset) { if (null === $limit && null !== $offset) { return $query . ' LIMIT -1 OFFSET ' . $offset; } return parent::doModifyLimitQuery($query, $limit, $offset); } /** * {@inheritDoc} */ public function getBlobTypeDeclarationSQL(array $field) { return 'BLOB'; } /** * {@inheritDoc} */ public function getTemporaryTableName($tableName) { $tableName = str_replace('.', '__', $tableName); return $tableName; } /** * {@inheritDoc} * * 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. */ public function canEmulateSchemas() { return true; } /** * {@inheritDoc} */ public function supportsForeignKeyConstraints() { return false; } /** * {@inheritDoc} */ public function getCreatePrimaryKeySQL(Index $index, $table) { throw new DBALException('Sqlite platform does not support alter primary key.'); } /** * {@inheritdoc} */ public function getCreateForeignKeySQL(ForeignKeyConstraint $foreignKey, $table) { throw new DBALException('Sqlite platform does not support alter foreign key.'); } /** * {@inheritdoc} */ public function getDropForeignKeySQL($foreignKey, $table) { throw new DBALException('Sqlite platform does not support alter foreign key.'); } /** * {@inheritDoc} */ public function getCreateConstraintSQL(Constraint $constraint, $table) { throw new DBALException('Sqlite platform does not support alter constraint.'); } /** * {@inheritDoc} */ public function getCreateTableSQL(Table $table, $createFlags = null) { $createFlags = null === $createFlags ? self::CREATE_INDEXES | self::CREATE_FOREIGNKEYS : $createFlags; return parent::getCreateTableSQL($table, $createFlags); } /** * {@inheritDoc} */ public function getListTableForeignKeysSQL($table, $database = null) { $table = str_replace('.', '__', $table); $table = $this->quoteStringLiteral($table); return "PRAGMA foreign_key_list($table)"; } /** * {@inheritDoc} */ public function getAlterTableSQL(TableDiff $diff) { $sql = $this->getSimpleAlterTableSQL($diff); if (false !== $sql) { return $sql; } $fromTable = $diff->fromTable; if ( ! $fromTable instanceof Table) { throw new DBALException('Sqlite platform requires for alter table the table diff with reference to original table schema'); } $table = clone $fromTable; $columns = array(); $oldColumnNames = array(); $newColumnNames = array(); $columnSql = array(); foreach ($table->getColumns() as $columnName => $column) { $columnName = strtolower($columnName); $columns[$columnName] = $column; $oldColumnNames[$columnName] = $newColumnNames[$columnName] = $column->getQuotedName($this); } foreach ($diff->removedColumns as $columnName => $column) { if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { continue; } $columnName = strtolower($columnName); if (isset($columns[$columnName])) { unset($columns[$columnName]); unset($oldColumnNames[$columnName]); unset($newColumnNames[$columnName]); } } foreach ($diff->renamedColumns as $oldColumnName => $column) { if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { continue; } $oldColumnName = strtolower($oldColumnName); if (isset($columns[$oldColumnName])) { unset($columns[$oldColumnName]); } $columns[strtolower($column->getName())] = $column; if (isset($newColumnNames[$oldColumnName])) { $newColumnNames[$oldColumnName] = $column->getQuotedName($this); } } foreach ($diff->changedColumns as $oldColumnName => $columnDiff) { if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { continue; } if (isset($columns[$oldColumnName])) { unset($columns[$oldColumnName]); } $columns[strtolower($columnDiff->column->getName())] = $columnDiff->column; if (isset($newColumnNames[$oldColumnName])) { $newColumnNames[$oldColumnName] = $columnDiff->column->getQuotedName($this); } } foreach ($diff->addedColumns as $columnName => $column) { if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { continue; } $columns[strtolower($columnName)] = $column; } $sql = array(); $tableSql = array(); if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { $dataTable = new Table('__temp__'.$table->getName()); $newTable = new Table($table->getQuotedName($this), $columns, $this->getPrimaryIndexInAlteredTable($diff), $this->getForeignKeysInAlteredTable($diff), 0, $table->getOptions()); $newTable->addOption('alter', true); $sql = $this->getPreAlterTableIndexForeignKeySQL($diff); //$sql = array_merge($sql, $this->getCreateTableSQL($dataTable, 0)); $sql[] = sprintf('CREATE TEMPORARY TABLE %s AS SELECT %s FROM %s', $dataTable->getQuotedName($this), implode(', ', $oldColumnNames), $table->getQuotedName($this)); $sql[] = $this->getDropTableSQL($fromTable); $sql = array_merge($sql, $this->getCreateTableSQL($newTable)); $sql[] = sprintf('INSERT INTO %s (%s) SELECT %s FROM %s', $newTable->getQuotedName($this), implode(', ', $newColumnNames), implode(', ', $oldColumnNames), $dataTable->getQuotedName($this)); $sql[] = $this->getDropTableSQL($dataTable); if ($diff->newName && $diff->newName != $diff->name) { $renamedTable = $diff->getNewName(); $sql[] = 'ALTER TABLE '.$newTable->getQuotedName($this).' RENAME TO '.$renamedTable->getQuotedName($this); } $sql = array_merge($sql, $this->getPostAlterTableIndexForeignKeySQL($diff)); } return array_merge($sql, $tableSql, $columnSql); } /** * @param \Doctrine\DBAL\Schema\TableDiff $diff * * @return array|bool */ private function getSimpleAlterTableSQL(TableDiff $diff) { // Suppress changes on integer type autoincrement columns. foreach ($diff->changedColumns as $oldColumnName => $columnDiff) { if ( ! $columnDiff->fromColumn instanceof Column || ! $columnDiff->column instanceof Column || ! $columnDiff->column->getAutoincrement() || ! (string) $columnDiff->column->getType() === 'Integer' ) { continue; } if ( ! $columnDiff->hasChanged('type') && $columnDiff->hasChanged('unsigned')) { unset($diff->changedColumns[$oldColumnName]); continue; } $fromColumnType = (string) $columnDiff->fromColumn->getType(); if ($fromColumnType === 'SmallInt' || $fromColumnType === 'BigInt') { unset($diff->changedColumns[$oldColumnName]); } } if ( ! empty($diff->renamedColumns) || ! empty($diff->addedForeignKeys) || ! empty($diff->addedIndexes) || ! empty($diff->changedColumns) || ! empty($diff->changedForeignKeys) || ! empty($diff->changedIndexes) || ! empty($diff->removedColumns) || ! empty($diff->removedForeignKeys) || ! empty($diff->removedIndexes) || ! empty($diff->renamedIndexes) ) { return false; } $table = new Table($diff->name); $sql = array(); $tableSql = array(); $columnSql = array(); foreach ($diff->addedColumns as $column) { if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { continue; } $field = array_merge(array('unique' => null, 'autoincrement' => null, 'default' => null), $column->toArray()); $type = (string) $field['type']; switch (true) { case isset($field['columnDefinition']) || $field['autoincrement'] || $field['unique']: case $type == 'DateTime' && $field['default'] == $this->getCurrentTimestampSQL(): case $type == 'Date' && $field['default'] == $this->getCurrentDateSQL(): case $type == 'Time' && $field['default'] == $this->getCurrentTimeSQL(): return false; } $field['name'] = $column->getQuotedName($this); if (strtolower($field['type']) == 'string' && $field['length'] === null) { $field['length'] = 255; } $sql[] = 'ALTER TABLE '.$table->getQuotedName($this).' ADD COLUMN '.$this->getColumnDeclarationSQL($field['name'], $field); } if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { if ($diff->newName !== false) { $newTable = new Identifier($diff->newName); $sql[] = 'ALTER TABLE '.$table->getQuotedName($this).' RENAME TO '.$newTable->getQuotedName($this); } } return array_merge($sql, $tableSql, $columnSql); } /** * @param \Doctrine\DBAL\Schema\TableDiff $diff * * @return array */ private function getColumnNamesInAlteredTable(TableDiff $diff) { $columns = array(); foreach ($diff->fromTable->getColumns() as $columnName => $column) { $columns[strtolower($columnName)] = $column->getName(); } foreach ($diff->removedColumns as $columnName => $column) { $columnName = strtolower($columnName); if (isset($columns[$columnName])) { unset($columns[$columnName]); } } foreach ($diff->renamedColumns as $oldColumnName => $column) { $columnName = $column->getName(); $columns[strtolower($oldColumnName)] = $columnName; $columns[strtolower($columnName)] = $columnName; } foreach ($diff->changedColumns as $oldColumnName => $columnDiff) { $columnName = $columnDiff->column->getName(); $columns[strtolower($oldColumnName)] = $columnName; $columns[strtolower($columnName)] = $columnName; } foreach ($diff->addedColumns as $columnName => $column) { $columns[strtolower($columnName)] = $columnName; } return $columns; } /** * @param \Doctrine\DBAL\Schema\TableDiff $diff * * @return \Doctrine\DBAL\Schema\Index[] */ private function getIndexesInAlteredTable(TableDiff $diff) { $indexes = $diff->fromTable->getIndexes(); $columnNames = $this->getColumnNamesInAlteredTable($diff); foreach ($indexes as $key => $index) { foreach ($diff->renamedIndexes as $oldIndexName => $renamedIndex) { if (strtolower($key) === strtolower($oldIndexName)) { unset($indexes[$key]); } } $changed = false; $indexColumns = array(); foreach ($index->getColumns() as $columnName) { $normalizedColumnName = strtolower($columnName); if ( ! isset($columnNames[$normalizedColumnName])) { unset($indexes[$key]); continue 2; } else { $indexColumns[] = $columnNames[$normalizedColumnName]; if ($columnName !== $columnNames[$normalizedColumnName]) { $changed = true; } } } if ($changed) { $indexes[$key] = new Index($index->getName(), $indexColumns, $index->isUnique(), $index->isPrimary(), $index->getFlags()); } } foreach ($diff->removedIndexes as $index) { $indexName = strtolower($index->getName()); if (strlen($indexName) && isset($indexes[$indexName])) { unset($indexes[$indexName]); } } foreach (array_merge($diff->changedIndexes, $diff->addedIndexes, $diff->renamedIndexes) as $index) { $indexName = strtolower($index->getName()); if (strlen($indexName)) { $indexes[$indexName] = $index; } else { $indexes[] = $index; } } return $indexes; } /** * @param \Doctrine\DBAL\Schema\TableDiff $diff * * @return array */ private function getForeignKeysInAlteredTable(TableDiff $diff) { $foreignKeys = $diff->fromTable->getForeignKeys(); $columnNames = $this->getColumnNamesInAlteredTable($diff); foreach ($foreignKeys as $key => $constraint) { $changed = false; $localColumns = array(); foreach ($constraint->getLocalColumns() as $columnName) { $normalizedColumnName = strtolower($columnName); if ( ! isset($columnNames[$normalizedColumnName])) { unset($foreignKeys[$key]); continue 2; } else { $localColumns[] = $columnNames[$normalizedColumnName]; if ($columnName !== $columnNames[$normalizedColumnName]) { $changed = true; } } } if ($changed) { $foreignKeys[$key] = new ForeignKeyConstraint($localColumns, $constraint->getForeignTableName(), $constraint->getForeignColumns(), $constraint->getName(), $constraint->getOptions()); } } foreach ($diff->removedForeignKeys as $constraint) { $constraintName = strtolower($constraint->getName()); if (strlen($constraintName) && isset($foreignKeys[$constraintName])) { unset($foreignKeys[$constraintName]); } } foreach (array_merge($diff->changedForeignKeys, $diff->addedForeignKeys) as $constraint) { $constraintName = strtolower($constraint->getName()); if (strlen($constraintName)) { $foreignKeys[$constraintName] = $constraint; } else { $foreignKeys[] = $constraint; } } return $foreignKeys; } /** * @param \Doctrine\DBAL\Schema\TableDiff $diff * * @return array */ private function getPrimaryIndexInAlteredTable(TableDiff $diff) { $primaryIndex = array(); foreach ($this->getIndexesInAlteredTable($diff) as $index) { if ($index->isPrimary()) { $primaryIndex = array($index->getName() => $index); } } return $primaryIndex; } } dbal-2.5.13/lib/Doctrine/DBAL/Portability/000077500000000000000000000000001313473450000200255ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Portability/Connection.php000066400000000000000000000123671313473450000226460ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Portability; use Doctrine\DBAL\Cache\QueryCacheProfile; /** * Portability wrapper for a Connection. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ 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_DB2 = 13; const PORTABILITY_ORACLE = 9; const PORTABILITY_POSTGRESQL = 13; const PORTABILITY_SQLITE = 13; const PORTABILITY_OTHERVENDORS = 12; const PORTABILITY_DRIZZLE = 13; const PORTABILITY_SQLANYWHERE = 13; const PORTABILITY_SQLSRV = 13; /** * @var integer */ private $portability = self::PORTABILITY_NONE; /** * @var integer */ private $case; /** * {@inheritdoc} */ public function connect() { $ret = parent::connect(); if ($ret) { $params = $this->getParams(); if (isset($params['portability'])) { if ($this->getDatabasePlatform()->getName() === "oracle") { $params['portability'] = $params['portability'] & self::PORTABILITY_ORACLE; } elseif ($this->getDatabasePlatform()->getName() === "postgresql") { $params['portability'] = $params['portability'] & self::PORTABILITY_POSTGRESQL; } elseif ($this->getDatabasePlatform()->getName() === "sqlite") { $params['portability'] = $params['portability'] & self::PORTABILITY_SQLITE; } elseif ($this->getDatabasePlatform()->getName() === "drizzle") { $params['portability'] = $params['portability'] & self::PORTABILITY_DRIZZLE; } elseif ($this->getDatabasePlatform()->getName() === 'sqlanywhere') { $params['portability'] = $params['portability'] & self::PORTABILITY_SQLANYWHERE; } elseif ($this->getDatabasePlatform()->getName() === 'db2') { $params['portability'] = $params['portability'] & self::PORTABILITY_DB2; } elseif ($this->getDatabasePlatform()->getName() === 'mssql') { $params['portability'] = $params['portability'] & self::PORTABILITY_SQLSRV; } 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; } /** * @return integer */ public function getPortability() { return $this->portability; } /** * @return integer */ public function getFetchCase() { return $this->case; } /** * {@inheritdoc} */ public function executeQuery($query, array $params = array(), $types = array(), QueryCacheProfile $qcp = null) { $stmt = new Statement(parent::executeQuery($query, $params, $types, $qcp), $this); $stmt->setFetchMode($this->defaultFetchMode); return $stmt; } /** * {@inheritdoc} */ public function prepare($statement) { $stmt = new Statement(parent::prepare($statement), $this); $stmt->setFetchMode($this->defaultFetchMode); return $stmt; } /** * {@inheritdoc} */ public function query() { $this->connect(); $stmt = call_user_func_array(array($this->_conn, 'query'), func_get_args()); $stmt = new Statement($stmt, $this); $stmt->setFetchMode($this->defaultFetchMode); return $stmt; } } dbal-2.5.13/lib/Doctrine/DBAL/Portability/Statement.php000066400000000000000000000146601313473450000225110ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Portability; use PDO; /** * Portability wrapper for a Statement. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ class Statement implements \IteratorAggregate, \Doctrine\DBAL\Driver\Statement { /** * @var integer */ private $portability; /** * @var \Doctrine\DBAL\Driver\Statement */ private $stmt; /** * @var integer */ private $case; /** * @var integer */ private $defaultFetchMode = PDO::FETCH_BOTH; /** * Wraps Statement and applies portability measures. * * @param \Doctrine\DBAL\Driver\Statement $stmt * @param \Doctrine\DBAL\Portability\Connection $conn */ public function __construct($stmt, Connection $conn) { $this->stmt = $stmt; $this->portability = $conn->getPortability(); $this->case = $conn->getFetchCase(); } /** * {@inheritdoc} */ public function bindParam($column, &$variable, $type = null, $length = null) { return $this->stmt->bindParam($column, $variable, $type, $length); } /** * {@inheritdoc} */ public function bindValue($param, $value, $type = null) { return $this->stmt->bindValue($param, $value, $type); } /** * {@inheritdoc} */ public function closeCursor() { return $this->stmt->closeCursor(); } /** * {@inheritdoc} */ public function columnCount() { return $this->stmt->columnCount(); } /** * {@inheritdoc} */ public function errorCode() { return $this->stmt->errorCode(); } /** * {@inheritdoc} */ public function errorInfo() { return $this->stmt->errorInfo(); } /** * {@inheritdoc} */ public function execute($params = null) { return $this->stmt->execute($params); } /** * {@inheritdoc} */ public function setFetchMode($fetchMode, $arg1 = null, $arg2 = null) { $this->defaultFetchMode = $fetchMode; return $this->stmt->setFetchMode($fetchMode, $arg1, $arg2); } /** * {@inheritdoc} */ public function getIterator() { $data = $this->fetchAll(); return new \ArrayIterator($data); } /** * {@inheritdoc} */ public function fetch($fetchMode = null) { $fetchMode = $fetchMode ?: $this->defaultFetchMode; $row = $this->stmt->fetch($fetchMode); $row = $this->fixRow($row, $this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM), !is_null($this->case) && ($fetchMode == PDO::FETCH_ASSOC || $fetchMode == PDO::FETCH_BOTH) && ($this->portability & Connection::PORTABILITY_FIX_CASE) ); return $row; } /** * {@inheritdoc} */ public function fetchAll($fetchMode = null, $columnIndex = 0) { $fetchMode = $fetchMode ?: $this->defaultFetchMode; if ($columnIndex != 0) { $rows = $this->stmt->fetchAll($fetchMode, $columnIndex); } else { $rows = $this->stmt->fetchAll($fetchMode); } $iterateRow = $this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM); $fixCase = !is_null($this->case) && ($fetchMode == PDO::FETCH_ASSOC || $fetchMode == PDO::FETCH_BOTH) && ($this->portability & Connection::PORTABILITY_FIX_CASE); if ( ! $iterateRow && !$fixCase) { return $rows; } if ($fetchMode === PDO::FETCH_COLUMN) { foreach ($rows as $num => $row) { $rows[$num] = array($row); } } foreach ($rows as $num => $row) { $rows[$num] = $this->fixRow($row, $iterateRow, $fixCase); } if ($fetchMode === PDO::FETCH_COLUMN) { foreach ($rows as $num => $row) { $rows[$num] = $row[0]; } } return $rows; } /** * @param mixed $row * @param integer $iterateRow * @param boolean $fixCase * * @return array */ 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; } elseif (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($v)) { $row[$k] = rtrim($v); } } } return $row; } /** * {@inheritdoc} */ 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; } elseif (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($value)) { $value = rtrim($value); } } return $value; } /** * {@inheritdoc} */ public function rowCount() { return $this->stmt->rowCount(); } } dbal-2.5.13/lib/Doctrine/DBAL/Query/000077500000000000000000000000001313473450000166305ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Query/Expression/000077500000000000000000000000001313473450000207675ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Query/Expression/CompositeExpression.php000066400000000000000000000067441313473450000255350ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Query\Expression; /** * Composite expression is responsible to build a group of similar expression. * * @link www.doctrine-project.org * @since 2.1 * @author Guilherme Blanco * @author Benjamin Eberlei */ 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'; /** * The instance type of composite expression. * * @var string */ private $type; /** * Each expression part of the composite expression. * * @var array */ 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 $parts * * @return \Doctrine\DBAL\Query\Expression\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 \Doctrine\DBAL\Query\Expression\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); } /** * Retrieves 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) . ')'; } /** * Returns the type of this composite expression (AND/OR). * * @return string */ public function getType() { return $this->type; } } dbal-2.5.13/lib/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php000066400000000000000000000225231313473450000251520ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Query\Expression; use Doctrine\DBAL\Connection; /** * ExpressionBuilder class is responsible to dynamically create SQL query parts. * * @link www.doctrine-project.org * @since 2.1 * @author Guilherme Blanco * @author Benjamin Eberlei */ class ExpressionBuilder { const EQ = '='; const NEQ = '<>'; const LT = '<'; const LTE = '<='; const GT = '>'; const GTE = '>='; /** * The DBAL Connection. * * @var \Doctrine\DBAL\Connection */ private $connection; /** * Initializes a new ExpressionBuilder. * * @param \Doctrine\DBAL\Connection $connection The 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 \Doctrine\DBAL\Query\Expression\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 \Doctrine\DBAL\Query\Expression\CompositeExpression */ public function orX($x = null) { return new CompositeExpression(CompositeExpression::TYPE_OR, func_get_args()); } /** * Creates a comparison expression. * * @param mixed $x The left expression. * @param string $operator One of the ExpressionBuilder::* constants. * @param mixed $y The 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 = . Example: * * [php] * // u.id = ? * $expr->eq('u.id', '?'); * * @param mixed $x The left expression. * @param mixed $y The 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 <> . Example: * * [php] * // u.id <> 1 * $q->where($q->expr()->neq('u.id', '1')); * * @param mixed $x The left expression. * @param mixed $y The 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 < . Example: * * [php] * // u.id < ? * $q->where($q->expr()->lt('u.id', '?')); * * @param mixed $x The left expression. * @param mixed $y The 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 <= . Example: * * [php] * // u.id <= ? * $q->where($q->expr()->lte('u.id', '?')); * * @param mixed $x The left expression. * @param mixed $y The 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 > . Example: * * [php] * // u.id > ? * $q->where($q->expr()->gt('u.id', '?')); * * @param mixed $x The left expression. * @param mixed $y The 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 >= . Example: * * [php] * // u.id >= ? * $q->where($q->expr()->gte('u.id', '?')); * * @param mixed $x The left expression. * @param mixed $y The 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 The 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 The 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); } /** * Creates a NOT LIKE() comparison expression with the given arguments. * * @param string $x Field in string format to be inspected by NOT LIKE() comparison. * @param mixed $y Argument to be used in NOT LIKE() comparison. * * @return string */ public function notLike($x, $y) { return $this->comparison($x, 'NOT LIKE', $y); } /** * Creates a IN () comparison expression with the given arguments. * * @param string $x The field in string format to be inspected by IN() comparison. * @param string|array $y The placeholder or the array of values to be used by IN() comparison. * * @return string */ public function in($x, $y) { return $this->comparison($x, 'IN', '('.implode(', ', (array) $y).')'); } /** * Creates a NOT IN () comparison expression with the given arguments. * * @param string $x The field in string format to be inspected by NOT IN() comparison. * @param string|array $y The placeholder or the array of values to be used by NOT IN() comparison. * * @return string */ public function notIn($x, $y) { return $this->comparison($x, 'NOT IN', '('.implode(', ', (array) $y).')'); } /** * Quotes a given input parameter. * * @param mixed $input The parameter to be quoted. * @param string|null $type The type of the parameter. * * @return string */ public function literal($input, $type = null) { return $this->connection->quote($input, $type); } } dbal-2.5.13/lib/Doctrine/DBAL/Query/QueryBuilder.php000066400000000000000000001154171313473450000217660ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Query; use Doctrine\DBAL\Query\Expression\CompositeExpression; use Doctrine\DBAL\Connection; /** * QueryBuilder class is responsible to dynamically create SQL queries. * * Important: Verify that every feature you use will work with your database vendor. * SQL Query Builder does not attempt to validate the generated SQL at all. * * The query builder does no validation whatsoever if certain features even work with the * underlying database vendor. Limit queries and joins are NOT applied to UPDATE and DELETE statements * even if some vendors such as MySQL support it. * * @link www.doctrine-project.org * @since 2.1 * @author Guilherme Blanco * @author Benjamin Eberlei */ class QueryBuilder { /* * The query types. */ const SELECT = 0; const DELETE = 1; const UPDATE = 2; const INSERT = 3; /* * The builder states. */ const STATE_DIRTY = 0; const STATE_CLEAN = 1; /** * The DBAL Connection. * * @var \Doctrine\DBAL\Connection */ private $connection; /** * @var array The array of SQL parts collected. */ private $sqlParts = array( 'select' => array(), 'from' => array(), 'join' => array(), 'set' => array(), 'where' => null, 'groupBy' => array(), 'having' => null, 'orderBy' => array(), 'values' => array(), ); /** * The complete SQL string for this query. * * @var string */ private $sql; /** * The query parameters. * * @var array */ private $params = array(); /** * The parameter type map of this query. * * @var array */ private $paramTypes = array(); /** * The type of query this is. Can be select, update or delete. * * @var integer */ private $type = self::SELECT; /** * The state of the query object. Can be dirty or clean. * * @var integer */ private $state = self::STATE_CLEAN; /** * The index of the first result to retrieve. * * @var integer */ private $firstResult = null; /** * The maximum number of results to retrieve. * * @var integer */ private $maxResults = null; /** * The counter of bound parameters used with {@see bindValue). * * @var integer */ private $boundCounter = 0; /** * Initializes a new QueryBuilder. * * @param \Doctrine\DBAL\Connection $connection The DBAL Connection. */ public function __construct(Connection $connection) { $this->connection = $connection; } /** * Gets an ExpressionBuilder used for object-oriented construction of query expressions. * This producer method is intended for convenient inline usage. Example: * * * $qb = $conn->createQueryBuilder() * ->select('u') * ->from('users', 'u') * ->where($qb->expr()->eq('u.id', 1)); * * * For more complex expression construction, consider storing the expression * builder object in a local variable. * * @return \Doctrine\DBAL\Query\Expression\ExpressionBuilder */ public function expr() { return $this->connection->getExpressionBuilder(); } /** * Gets the type of the currently built query. * * @return integer */ public function getType() { return $this->type; } /** * Gets the associated DBAL Connection for this query builder. * * @return \Doctrine\DBAL\Connection */ public function getConnection() { return $this->connection; } /** * Gets the state of this query builder instance. * * @return integer Either QueryBuilder::STATE_DIRTY or QueryBuilder::STATE_CLEAN. */ public function getState() { return $this->state; } /** * Executes this query using the bound parameters and their types. * * Uses {@see Connection::executeQuery} for select statements and {@see Connection::executeUpdate} * for insert, update and delete statements. * * @return \Doctrine\DBAL\Driver\Statement|int */ public function execute() { if ($this->type == self::SELECT) { return $this->connection->executeQuery($this->getSQL(), $this->params, $this->paramTypes); } else { return $this->connection->executeUpdate($this->getSQL(), $this->params, $this->paramTypes); } } /** * Gets the complete SQL string formed by the current specifications of this QueryBuilder. * * * $qb = $em->createQueryBuilder() * ->select('u') * ->from('User', 'u') * echo $qb->getSQL(); // SELECT u FROM User u * * * @return string The SQL query string. */ public function getSQL() { if ($this->sql !== null && $this->state === self::STATE_CLEAN) { return $this->sql; } switch ($this->type) { case self::INSERT: $sql = $this->getSQLForInsert(); break; case self::DELETE: $sql = $this->getSQLForDelete(); break; case self::UPDATE: $sql = $this->getSQLForUpdate(); break; case self::SELECT: default: $sql = $this->getSQLForSelect(); break; } $this->state = self::STATE_CLEAN; $this->sql = $sql; return $sql; } /** * Sets a query parameter for the query being constructed. * * * $qb = $conn->createQueryBuilder() * ->select('u') * ->from('users', 'u') * ->where('u.id = :user_id') * ->setParameter(':user_id', 1); * * * @param string|integer $key The parameter position or name. * @param mixed $value The parameter value. * @param string|null $type One of the PDO::PARAM_* constants. * * @return $this This QueryBuilder instance. */ public function setParameter($key, $value, $type = null) { if ($type !== null) { $this->paramTypes[$key] = $type; } $this->params[$key] = $value; return $this; } /** * Sets a collection of query parameters for the query being constructed. * * * $qb = $conn->createQueryBuilder() * ->select('u') * ->from('users', 'u') * ->where('u.id = :user_id1 OR u.id = :user_id2') * ->setParameters(array( * ':user_id1' => 1, * ':user_id2' => 2 * )); * * * @param array $params The query parameters to set. * @param array $types The query parameters types to set. * * @return $this This QueryBuilder instance. */ public function setParameters(array $params, array $types = array()) { $this->paramTypes = $types; $this->params = $params; return $this; } /** * Gets all defined query parameters for the query being constructed indexed by parameter index or name. * * @return array The currently defined query parameters indexed by parameter index or name. */ public function getParameters() { return $this->params; } /** * Gets a (previously set) query parameter of the query being constructed. * * @param mixed $key The key (index or name) of the bound parameter. * * @return mixed The value of the bound parameter. */ public function getParameter($key) { return isset($this->params[$key]) ? $this->params[$key] : null; } /** * Gets all defined query parameter types for the query being constructed indexed by parameter index or name. * * @return array The currently defined query parameter types indexed by parameter index or name. */ public function getParameterTypes() { return $this->paramTypes; } /** * Gets a (previously set) query parameter type of the query being constructed. * * @param mixed $key The key (index or name) of the bound parameter type. * * @return mixed The value of the bound parameter type. */ public function getParameterType($key) { return isset($this->paramTypes[$key]) ? $this->paramTypes[$key] : null; } /** * Sets the position of the first result to retrieve (the "offset"). * * @param integer $firstResult The first result to return. * * @return $this This QueryBuilder instance. */ public function setFirstResult($firstResult) { $this->state = self::STATE_DIRTY; $this->firstResult = $firstResult; return $this; } /** * Gets the position of the first result the query object was set to retrieve (the "offset"). * Returns NULL if {@link setFirstResult} was not applied to this QueryBuilder. * * @return integer The position of the first result. */ public function getFirstResult() { return $this->firstResult; } /** * Sets the maximum number of results to retrieve (the "limit"). * * @param integer $maxResults The maximum number of results to retrieve. * * @return $this This QueryBuilder instance. */ public function setMaxResults($maxResults) { $this->state = self::STATE_DIRTY; $this->maxResults = $maxResults; return $this; } /** * Gets the maximum number of results the query object was set to retrieve (the "limit"). * Returns NULL if {@link setMaxResults} was not applied to this query builder. * * @return integer The maximum number of results. */ public function getMaxResults() { return $this->maxResults; } /** * Either appends to or replaces a single, generic query part. * * The available parts are: 'select', 'from', 'set', 'where', * 'groupBy', 'having' and 'orderBy'. * * @param string $sqlPartName * @param string $sqlPart * @param boolean $append * * @return $this This QueryBuilder instance. */ public function add($sqlPartName, $sqlPart, $append = false) { $isArray = is_array($sqlPart); $isMultiple = is_array($this->sqlParts[$sqlPartName]); if ($isMultiple && !$isArray) { $sqlPart = array($sqlPart); } $this->state = self::STATE_DIRTY; if ($append) { if ($sqlPartName == "orderBy" || $sqlPartName == "groupBy" || $sqlPartName == "select" || $sqlPartName == "set") { foreach ($sqlPart as $part) { $this->sqlParts[$sqlPartName][] = $part; } } elseif ($isArray && is_array($sqlPart[key($sqlPart)])) { $key = key($sqlPart); $this->sqlParts[$sqlPartName][$key][] = $sqlPart[$key]; } elseif ($isMultiple) { $this->sqlParts[$sqlPartName][] = $sqlPart; } else { $this->sqlParts[$sqlPartName] = $sqlPart; } return $this; } $this->sqlParts[$sqlPartName] = $sqlPart; return $this; } /** * Specifies an item that is to be returned in the query result. * Replaces any previously specified selections, if any. * * * $qb = $conn->createQueryBuilder() * ->select('u.id', 'p.id') * ->from('users', 'u') * ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id'); * * * @param mixed $select The selection expressions. * * @return $this This QueryBuilder instance. */ public function select($select = null) { $this->type = self::SELECT; if (empty($select)) { return $this; } $selects = is_array($select) ? $select : func_get_args(); return $this->add('select', $selects, false); } /** * Adds an item that is to be returned in the query result. * * * $qb = $conn->createQueryBuilder() * ->select('u.id') * ->addSelect('p.id') * ->from('users', 'u') * ->leftJoin('u', 'phonenumbers', 'u.id = p.user_id'); * * * @param mixed $select The selection expression. * * @return $this This QueryBuilder instance. */ public function addSelect($select = null) { $this->type = self::SELECT; if (empty($select)) { return $this; } $selects = is_array($select) ? $select : func_get_args(); return $this->add('select', $selects, true); } /** * Turns the query being built into a bulk delete query that ranges over * a certain table. * * * $qb = $conn->createQueryBuilder() * ->delete('users', 'u') * ->where('u.id = :user_id'); * ->setParameter(':user_id', 1); * * * @param string $delete The table whose rows are subject to the deletion. * @param string $alias The table alias used in the constructed query. * * @return $this This QueryBuilder instance. */ public function delete($delete = null, $alias = null) { $this->type = self::DELETE; if ( ! $delete) { return $this; } return $this->add('from', array( 'table' => $delete, 'alias' => $alias )); } /** * Turns the query being built into a bulk update query that ranges over * a certain table * * * $qb = $conn->createQueryBuilder() * ->update('users', 'u') * ->set('u.password', md5('password')) * ->where('u.id = ?'); * * * @param string $update The table whose rows are subject to the update. * @param string $alias The table alias used in the constructed query. * * @return $this This QueryBuilder instance. */ public function update($update = null, $alias = null) { $this->type = self::UPDATE; if ( ! $update) { return $this; } return $this->add('from', array( 'table' => $update, 'alias' => $alias )); } /** * Turns the query being built into an insert query that inserts into * a certain table * * * $qb = $conn->createQueryBuilder() * ->insert('users') * ->values( * array( * 'name' => '?', * 'password' => '?' * ) * ); * * * @param string $insert The table into which the rows should be inserted. * * @return $this This QueryBuilder instance. */ public function insert($insert = null) { $this->type = self::INSERT; if ( ! $insert) { return $this; } return $this->add('from', array( 'table' => $insert )); } /** * Creates and adds a query root corresponding to the table identified by the * given alias, forming a cartesian product with any existing query roots. * * * $qb = $conn->createQueryBuilder() * ->select('u.id') * ->from('users', 'u') * * * @param string $from The table. * @param string|null $alias The alias of the table. * * @return $this This QueryBuilder instance. */ public function from($from, $alias = null) { return $this->add('from', array( 'table' => $from, 'alias' => $alias ), true); } /** * Creates and adds a join to the query. * * * $qb = $conn->createQueryBuilder() * ->select('u.name') * ->from('users', 'u') * ->join('u', 'phonenumbers', 'p', 'p.is_primary = 1'); * * * @param string $fromAlias The alias that points to a from clause. * @param string $join The table name to join. * @param string $alias The alias of the join table. * @param string $condition The condition for the join. * * @return $this This QueryBuilder instance. */ public function join($fromAlias, $join, $alias, $condition = null) { return $this->innerJoin($fromAlias, $join, $alias, $condition); } /** * Creates and adds a join to the query. * * * $qb = $conn->createQueryBuilder() * ->select('u.name') * ->from('users', 'u') * ->innerJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1'); * * * @param string $fromAlias The alias that points to a from clause. * @param string $join The table name to join. * @param string $alias The alias of the join table. * @param string $condition The condition for the join. * * @return $this This QueryBuilder instance. */ public function innerJoin($fromAlias, $join, $alias, $condition = null) { return $this->add('join', array( $fromAlias => array( 'joinType' => 'inner', 'joinTable' => $join, 'joinAlias' => $alias, 'joinCondition' => $condition ) ), true); } /** * Creates and adds a left join to the query. * * * $qb = $conn->createQueryBuilder() * ->select('u.name') * ->from('users', 'u') * ->leftJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1'); * * * @param string $fromAlias The alias that points to a from clause. * @param string $join The table name to join. * @param string $alias The alias of the join table. * @param string $condition The condition for the join. * * @return $this This QueryBuilder instance. */ public function leftJoin($fromAlias, $join, $alias, $condition = null) { return $this->add('join', array( $fromAlias => array( 'joinType' => 'left', 'joinTable' => $join, 'joinAlias' => $alias, 'joinCondition' => $condition ) ), true); } /** * Creates and adds a right join to the query. * * * $qb = $conn->createQueryBuilder() * ->select('u.name') * ->from('users', 'u') * ->rightJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1'); * * * @param string $fromAlias The alias that points to a from clause. * @param string $join The table name to join. * @param string $alias The alias of the join table. * @param string $condition The condition for the join. * * @return $this This QueryBuilder instance. */ public function rightJoin($fromAlias, $join, $alias, $condition = null) { return $this->add('join', array( $fromAlias => array( 'joinType' => 'right', 'joinTable' => $join, 'joinAlias' => $alias, 'joinCondition' => $condition ) ), true); } /** * Sets a new value for a column in a bulk update query. * * * $qb = $conn->createQueryBuilder() * ->update('users', 'u') * ->set('u.password', md5('password')) * ->where('u.id = ?'); * * * @param string $key The column to set. * @param string $value The value, expression, placeholder, etc. * * @return $this This QueryBuilder instance. */ public function set($key, $value) { return $this->add('set', $key .' = ' . $value, true); } /** * Specifies one or more restrictions to the query result. * Replaces any previously specified restrictions, if any. * * * $qb = $conn->createQueryBuilder() * ->select('u.name') * ->from('users', 'u') * ->where('u.id = ?'); * * // You can optionally programatically build and/or expressions * $qb = $conn->createQueryBuilder(); * * $or = $qb->expr()->orx(); * $or->add($qb->expr()->eq('u.id', 1)); * $or->add($qb->expr()->eq('u.id', 2)); * * $qb->update('users', 'u') * ->set('u.password', md5('password')) * ->where($or); * * * @param mixed $predicates The restriction predicates. * * @return $this This QueryBuilder instance. */ public function where($predicates) { if ( ! (func_num_args() == 1 && $predicates instanceof CompositeExpression)) { $predicates = new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args()); } return $this->add('where', $predicates); } /** * Adds one or more restrictions to the query results, forming a logical * conjunction with any previously specified restrictions. * * * $qb = $conn->createQueryBuilder() * ->select('u') * ->from('users', 'u') * ->where('u.username LIKE ?') * ->andWhere('u.is_active = 1'); * * * @param mixed $where The query restrictions. * * @return $this This QueryBuilder instance. * * @see where() */ public function andWhere($where) { $args = func_get_args(); $where = $this->getQueryPart('where'); if ($where instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_AND) { $where->addMultiple($args); } else { array_unshift($args, $where); $where = new CompositeExpression(CompositeExpression::TYPE_AND, $args); } return $this->add('where', $where, true); } /** * Adds one or more restrictions to the query results, forming a logical * disjunction with any previously specified restrictions. * * * $qb = $em->createQueryBuilder() * ->select('u.name') * ->from('users', 'u') * ->where('u.id = 1') * ->orWhere('u.id = 2'); * * * @param mixed $where The WHERE statement. * * @return $this This QueryBuilder instance. * * @see where() */ public function orWhere($where) { $args = func_get_args(); $where = $this->getQueryPart('where'); if ($where instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_OR) { $where->addMultiple($args); } else { array_unshift($args, $where); $where = new CompositeExpression(CompositeExpression::TYPE_OR, $args); } return $this->add('where', $where, true); } /** * Specifies a grouping over the results of the query. * Replaces any previously specified groupings, if any. * * * $qb = $conn->createQueryBuilder() * ->select('u.name') * ->from('users', 'u') * ->groupBy('u.id'); * * * @param mixed $groupBy The grouping expression. * * @return $this This QueryBuilder instance. */ public function groupBy($groupBy) { if (empty($groupBy)) { return $this; } $groupBy = is_array($groupBy) ? $groupBy : func_get_args(); return $this->add('groupBy', $groupBy, false); } /** * Adds a grouping expression to the query. * * * $qb = $conn->createQueryBuilder() * ->select('u.name') * ->from('users', 'u') * ->groupBy('u.lastLogin'); * ->addGroupBy('u.createdAt') * * * @param mixed $groupBy The grouping expression. * * @return $this This QueryBuilder instance. */ public function addGroupBy($groupBy) { if (empty($groupBy)) { return $this; } $groupBy = is_array($groupBy) ? $groupBy : func_get_args(); return $this->add('groupBy', $groupBy, true); } /** * Sets a value for a column in an insert query. * * * $qb = $conn->createQueryBuilder() * ->insert('users') * ->values( * array( * 'name' => '?' * ) * ) * ->setValue('password', '?'); * * * @param string $column The column into which the value should be inserted. * @param string $value The value that should be inserted into the column. * * @return $this This QueryBuilder instance. */ public function setValue($column, $value) { $this->sqlParts['values'][$column] = $value; return $this; } /** * Specifies values for an insert query indexed by column names. * Replaces any previous values, if any. * * * $qb = $conn->createQueryBuilder() * ->insert('users') * ->values( * array( * 'name' => '?', * 'password' => '?' * ) * ); * * * @param array $values The values to specify for the insert query indexed by column names. * * @return $this This QueryBuilder instance. */ public function values(array $values) { return $this->add('values', $values); } /** * Specifies a restriction over the groups of the query. * Replaces any previous having restrictions, if any. * * @param mixed $having The restriction over the groups. * * @return $this This QueryBuilder instance. */ public function having($having) { if ( ! (func_num_args() == 1 && $having instanceof CompositeExpression)) { $having = new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args()); } return $this->add('having', $having); } /** * Adds a restriction over the groups of the query, forming a logical * conjunction with any existing having restrictions. * * @param mixed $having The restriction to append. * * @return $this This QueryBuilder instance. */ public function andHaving($having) { $args = func_get_args(); $having = $this->getQueryPart('having'); if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_AND) { $having->addMultiple($args); } else { array_unshift($args, $having); $having = new CompositeExpression(CompositeExpression::TYPE_AND, $args); } return $this->add('having', $having); } /** * Adds a restriction over the groups of the query, forming a logical * disjunction with any existing having restrictions. * * @param mixed $having The restriction to add. * * @return $this This QueryBuilder instance. */ public function orHaving($having) { $args = func_get_args(); $having = $this->getQueryPart('having'); if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_OR) { $having->addMultiple($args); } else { array_unshift($args, $having); $having = new CompositeExpression(CompositeExpression::TYPE_OR, $args); } return $this->add('having', $having); } /** * Specifies an ordering for the query results. * Replaces any previously specified orderings, if any. * * @param string $sort The ordering expression. * @param string $order The ordering direction. * * @return $this This QueryBuilder instance. */ public function orderBy($sort, $order = null) { return $this->add('orderBy', $sort . ' ' . (! $order ? 'ASC' : $order), false); } /** * Adds an ordering to the query results. * * @param string $sort The ordering expression. * @param string $order The ordering direction. * * @return $this This QueryBuilder instance. */ public function addOrderBy($sort, $order = null) { return $this->add('orderBy', $sort . ' ' . (! $order ? 'ASC' : $order), true); } /** * Gets a query part by its name. * * @param string $queryPartName * * @return mixed */ public function getQueryPart($queryPartName) { return $this->sqlParts[$queryPartName]; } /** * Gets all query parts. * * @return array */ public function getQueryParts() { return $this->sqlParts; } /** * Resets SQL parts. * * @param array|null $queryPartNames * * @return $this This QueryBuilder instance. */ public function resetQueryParts($queryPartNames = null) { if (is_null($queryPartNames)) { $queryPartNames = array_keys($this->sqlParts); } foreach ($queryPartNames as $queryPartName) { $this->resetQueryPart($queryPartName); } return $this; } /** * Resets a single SQL part. * * @param string $queryPartName * * @return $this This QueryBuilder instance. */ public function resetQueryPart($queryPartName) { $this->sqlParts[$queryPartName] = is_array($this->sqlParts[$queryPartName]) ? array() : null; $this->state = self::STATE_DIRTY; return $this; } /** * @return string * * @throws \Doctrine\DBAL\Query\QueryException */ private function getSQLForSelect() { $query = 'SELECT ' . implode(', ', $this->sqlParts['select']); $query .= ($this->sqlParts['from'] ? ' FROM ' . implode(', ', $this->getFromClauses()) : '') . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : '') . ($this->sqlParts['groupBy'] ? ' GROUP BY ' . implode(', ', $this->sqlParts['groupBy']) : '') . ($this->sqlParts['having'] !== null ? ' HAVING ' . ((string) $this->sqlParts['having']) : '') . ($this->sqlParts['orderBy'] ? ' ORDER BY ' . implode(', ', $this->sqlParts['orderBy']) : ''); if ($this->isLimitQuery()) { return $this->connection->getDatabasePlatform()->modifyLimitQuery( $query, $this->maxResults, $this->firstResult ); } return $query; } /** * @return string[] */ private function getFromClauses() { $fromClauses = array(); $knownAliases = array(); // Loop through all FROM clauses foreach ($this->sqlParts['from'] as $from) { if ($from['alias'] === null) { $tableSql = $from['table']; $tableReference = $from['table']; } else { $tableSql = $from['table'] . ' ' . $from['alias']; $tableReference = $from['alias']; } $knownAliases[$tableReference] = true; $fromClauses[$tableReference] = $tableSql . $this->getSQLForJoins($tableReference, $knownAliases); } $this->verifyAllAliasesAreKnown($knownAliases); return $fromClauses; } /** * @param array $knownAliases * * @throws QueryException */ private function verifyAllAliasesAreKnown(array $knownAliases) { foreach ($this->sqlParts['join'] as $fromAlias => $joins) { if ( ! isset($knownAliases[$fromAlias])) { throw QueryException::unknownAlias($fromAlias, array_keys($knownAliases)); } } } /** * @return bool */ private function isLimitQuery() { return $this->maxResults !== null || $this->firstResult !== null; } /** * Converts this instance into an INSERT string in SQL. * * @return string */ private function getSQLForInsert() { return 'INSERT INTO ' . $this->sqlParts['from']['table'] . ' (' . implode(', ', array_keys($this->sqlParts['values'])) . ')' . ' VALUES(' . implode(', ', $this->sqlParts['values']) . ')'; } /** * Converts this instance into an UPDATE string in SQL. * * @return string */ private function getSQLForUpdate() { $table = $this->sqlParts['from']['table'] . ($this->sqlParts['from']['alias'] ? ' ' . $this->sqlParts['from']['alias'] : ''); $query = 'UPDATE ' . $table . ' SET ' . implode(", ", $this->sqlParts['set']) . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : ''); return $query; } /** * Converts this instance into a DELETE string in SQL. * * @return string */ private function getSQLForDelete() { $table = $this->sqlParts['from']['table'] . ($this->sqlParts['from']['alias'] ? ' ' . $this->sqlParts['from']['alias'] : ''); $query = 'DELETE FROM ' . $table . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : ''); return $query; } /** * Gets a string representation of this QueryBuilder which corresponds to * the final SQL query being constructed. * * @return string The string representation of this QueryBuilder. */ public function __toString() { return $this->getSQL(); } /** * Creates a new named parameter and bind the value $value to it. * * This method provides a shortcut for PDOStatement::bindValue * when using prepared statements. * * The parameter $value specifies the value that you want to bind. If * $placeholder is not provided bindValue() will automatically create a * placeholder for you. An automatic placeholder will be of the name * ':dcValue1', ':dcValue2' etc. * * For more information see {@link http://php.net/pdostatement-bindparam} * * Example: * * $value = 2; * $q->eq( 'id', $q->bindValue( $value ) ); * $stmt = $q->executeQuery(); // executed with 'id = 2' * * * @license New BSD License * @link http://www.zetacomponents.org * * @param mixed $value * @param mixed $type * @param string $placeHolder The name to bind with. The string must start with a colon ':'. * * @return string the placeholder name used. */ public function createNamedParameter($value, $type = \PDO::PARAM_STR, $placeHolder = null) { if ($placeHolder === null) { $this->boundCounter++; $placeHolder = ":dcValue" . $this->boundCounter; } $this->setParameter(substr($placeHolder, 1), $value, $type); return $placeHolder; } /** * Creates a new positional parameter and bind the given value to it. * * Attention: If you are using positional parameters with the query builder you have * to be very careful to bind all parameters in the order they appear in the SQL * statement , otherwise they get bound in the wrong order which can lead to serious * bugs in your code. * * Example: * * $qb = $conn->createQueryBuilder(); * $qb->select('u.*') * ->from('users', 'u') * ->where('u.username = ' . $qb->createPositionalParameter('Foo', PDO::PARAM_STR)) * ->orWhere('u.username = ' . $qb->createPositionalParameter('Bar', PDO::PARAM_STR)) * * * @param mixed $value * @param integer $type * * @return string */ public function createPositionalParameter($value, $type = \PDO::PARAM_STR) { $this->boundCounter++; $this->setParameter($this->boundCounter, $value, $type); return "?"; } /** * @param string $fromAlias * @param array $knownAliases * * @return string */ private function getSQLForJoins($fromAlias, array &$knownAliases) { $sql = ''; if (isset($this->sqlParts['join'][$fromAlias])) { foreach ($this->sqlParts['join'][$fromAlias] as $join) { if (array_key_exists($join['joinAlias'], $knownAliases)) { throw QueryException::nonUniqueAlias($join['joinAlias'], array_keys($knownAliases)); } $sql .= ' ' . strtoupper($join['joinType']) . ' JOIN ' . $join['joinTable'] . ' ' . $join['joinAlias'] . ' ON ' . ((string) $join['joinCondition']); $knownAliases[$join['joinAlias']] = true; } foreach ($this->sqlParts['join'][$fromAlias] as $join) { $sql .= $this->getSQLForJoins($join['joinAlias'], $knownAliases); } } return $sql; } /** * Deep clone of all expression objects in the SQL parts. * * @return void */ public function __clone() { foreach ($this->sqlParts as $part => $elements) { if (is_array($this->sqlParts[$part])) { foreach ($this->sqlParts[$part] as $idx => $element) { if (is_object($element)) { $this->sqlParts[$part][$idx] = clone $element; } } } elseif (is_object($elements)) { $this->sqlParts[$part] = clone $elements; } } foreach ($this->params as $name => $param) { if (is_object($param)) { $this->params[$name] = clone $param; } } } } dbal-2.5.13/lib/Doctrine/DBAL/Query/QueryException.php000066400000000000000000000037401313473450000223310ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Query; use Doctrine\DBAL\DBALException; /** * @since 2.1.4 */ class QueryException extends DBALException { /** * @param string $alias * @param array $registeredAliases * * @return \Doctrine\DBAL\Query\QueryException */ static public function unknownAlias($alias, $registeredAliases) { return new self("The given alias '" . $alias . "' is not part of " . "any FROM or JOIN clause table. The currently registered " . "aliases are: " . implode(", ", $registeredAliases) . "."); } /** * @param string $alias * @param array $registeredAliases * * @return \Doctrine\DBAL\Query\QueryException */ static public function nonUniqueAlias($alias, $registeredAliases) { return new self("The given alias '" . $alias . "' is not unique " . "in FROM and JOIN clause table. The currently registered " . "aliases are: " . implode(", ", $registeredAliases) . "."); } } dbal-2.5.13/lib/Doctrine/DBAL/README.markdown000066400000000000000000000000001313473450000202120ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/SQLParserUtils.php000066400000000000000000000214341313473450000210750ustar00rootroot00000000000000. */ namespace Doctrine\DBAL; /** * Utility class that parses sql statements with regard to types and parameters. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ class SQLParserUtils { const POSITIONAL_TOKEN = '\?'; const NAMED_TOKEN = '(? integer pair (indexed from zero) for a positional statement * and a string => int[] pair for a named statement. * * @param string $statement * @param boolean $isPositional * * @return array */ static public function getPlaceholderPositions($statement, $isPositional = true) { $match = ($isPositional) ? '?' : ':'; if (strpos($statement, $match) === false) { return array(); } $token = ($isPositional) ? self::POSITIONAL_TOKEN : self::NAMED_TOKEN; $paramMap = array(); foreach (self::getUnquotedStatementFragments($statement) as $fragment) { preg_match_all("/$token/", $fragment[0], $matches, PREG_OFFSET_CAPTURE); foreach ($matches[0] as $placeholder) { if ($isPositional) { $paramMap[] = $placeholder[1] + $fragment[1]; } else { $pos = $placeholder[1] + $fragment[1]; $paramMap[$pos] = substr($placeholder[0], 1, strlen($placeholder[0])); } } } return $paramMap; } /** * For a positional query this method can rewrite the sql statement with regard to array parameters. * * @param string $query The SQL query to execute. * @param array $params The parameters to bind to the query. * @param array $types The types the previous parameters are in. * * @return array * * @throws SQLParserUtilsException */ static public function expandListParameters($query, $params, $types) { $isPositional = is_int(key($params)); $arrayPositions = array(); $bindIndex = -1; if ($isPositional) { ksort($params); ksort($types); } foreach ($types as $name => $type) { ++$bindIndex; if ($type !== Connection::PARAM_INT_ARRAY && $type !== Connection::PARAM_STR_ARRAY) { continue; } if ($isPositional) { $name = $bindIndex; } $arrayPositions[$name] = false; } if (( ! $arrayPositions && $isPositional)) { return array($query, $params, $types); } $paramPos = self::getPlaceholderPositions($query, $isPositional); if ($isPositional) { $paramOffset = 0; $queryOffset = 0; $params = array_values($params); $types = array_values($types); foreach ($paramPos as $needle => $needlePos) { if ( ! isset($arrayPositions[$needle])) { continue; } $needle += $paramOffset; $needlePos += $queryOffset; $count = 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), $count ? array_fill(0, $count, $types[$needle] - Connection::ARRAY_PARAM_OFFSET) : // array needles are at PDO::PARAM_* + 100 array(), array_slice($types, $needle + 1) ); $expandStr = $count ? implode(", ", array_fill(0, $count, "?")) : 'NULL'; $query = substr($query, 0, $needlePos) . $expandStr . substr($query, $needlePos + 1); $paramOffset += ($count - 1); // Grows larger by number of parameters minus the replaced needle. $queryOffset += (strlen($expandStr) - 1); } return array($query, $params, $types); } $queryOffset = 0; $typesOrd = array(); $paramsOrd = array(); foreach ($paramPos as $pos => $paramName) { $paramLen = strlen($paramName) + 1; $value = static::extractParam($paramName, $params, true); if ( ! isset($arrayPositions[$paramName]) && ! isset($arrayPositions[':' . $paramName])) { $pos += $queryOffset; $queryOffset -= ($paramLen - 1); $paramsOrd[] = $value; $typesOrd[] = static::extractParam($paramName, $types, false, \PDO::PARAM_STR); $query = substr($query, 0, $pos) . '?' . substr($query, ($pos + $paramLen)); continue; } $count = count($value); $expandStr = $count > 0 ? implode(', ', array_fill(0, $count, '?')) : 'NULL'; foreach ($value as $val) { $paramsOrd[] = $val; $typesOrd[] = static::extractParam($paramName, $types, false) - Connection::ARRAY_PARAM_OFFSET; } $pos += $queryOffset; $queryOffset += (strlen($expandStr) - $paramLen); $query = substr($query, 0, $pos) . $expandStr . substr($query, ($pos + $paramLen)); } return array($query, $paramsOrd, $typesOrd); } /** * Slice the SQL statement around pairs of quotes and * return string fragments of SQL outside of quoted literals. * Each fragment is captured as a 2-element array: * * 0 => matched fragment string, * 1 => offset of fragment in $statement * * @param string $statement * @return array */ static private function getUnquotedStatementFragments($statement) { $literal = self::ESCAPED_SINGLE_QUOTED_TEXT . '|' . self::ESCAPED_DOUBLE_QUOTED_TEXT . '|' . self::ESCAPED_BACKTICK_QUOTED_TEXT . '|' . self::ESCAPED_BRACKET_QUOTED_TEXT; preg_match_all("/([^'\"`\[]+)(?:$literal)?/s", $statement, $fragments, PREG_OFFSET_CAPTURE); return $fragments[1]; } /** * @param string $paramName The name of the parameter (without a colon in front) * @param array $paramsOrTypes A hash of parameters or types * @param bool $isParam * @param mixed $defaultValue An optional default value. If omitted, an exception is thrown * * @throws SQLParserUtilsException * @return mixed */ static private function extractParam($paramName, $paramsOrTypes, $isParam, $defaultValue = null) { if (array_key_exists($paramName, $paramsOrTypes)) { return $paramsOrTypes[$paramName]; } // Hash keys can be prefixed with a colon for compatibility if (array_key_exists(':' . $paramName, $paramsOrTypes)) { return $paramsOrTypes[':' . $paramName]; } if (null !== $defaultValue) { return $defaultValue; } if ($isParam) { throw SQLParserUtilsException::missingParam($paramName); } throw SQLParserUtilsException::missingType($paramName); } } dbal-2.5.13/lib/Doctrine/DBAL/SQLParserUtilsException.php000066400000000000000000000035421313473450000227540ustar00rootroot00000000000000. */ namespace Doctrine\DBAL; /** * Doctrine\DBAL\ConnectionException * * @license http://www.opensource.org/licenses/mit-license.php MIT * @link www.doctrine-project.org * @since 2.4 * @author Lars Strojny */ class SQLParserUtilsException extends DBALException { /** * @param string $paramName * * @return \Doctrine\DBAL\SQLParserUtilsException */ public static function missingParam($paramName) { return new self(sprintf('Value for :%1$s not found in params array. Params array key should be "%1$s"', $paramName)); } /** * @param string $typeName * * @return \Doctrine\DBAL\SQLParserUtilsException */ public static function missingType($typeName) { return new self(sprintf('Value for :%1$s not found in types array. Types array key should be "%1$s"', $typeName)); } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/000077500000000000000000000000001313473450000167235ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Schema/AbstractAsset.php000066400000000000000000000147341313473450000222100ustar00rootroot00000000000000. */ 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 * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ abstract class AbstractAsset { /** * @var string */ protected $_name; /** * Namespace of the asset. If none isset the default namespace is assumed. * * @var string|null */ protected $_namespace = null; /** * @var boolean */ protected $_quoted = false; /** * Sets the name of this asset. * * @param string $name * * @return void */ protected function _setName($name) { if ($this->isIdentifierQuoted($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 boolean */ public function isInDefaultNamespace($defaultNamespaceName) { return $this->_namespace == $defaultNamespaceName || $this->_namespace === null; } /** * Gets the namespace name of this asset. * * If NULL is returned this means the default namespace is used. * * @return string|null */ 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 $defaultNamespaceName * * @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. * * @param string $defaultNamespaceName * * @return string */ public function getFullQualifiedName($defaultNamespaceName) { $name = $this->getName(); if ( ! $this->_namespace) { $name = $defaultNamespaceName . "." . $name; } return strtolower($name); } /** * Checks if this asset's name is quoted. * * @return boolean */ public function isQuoted() { return $this->_quoted; } /** * Checks if this identifier is quoted. * * @param string $identifier * * @return boolean */ protected function isIdentifierQuoted($identifier) { return (isset($identifier[0]) && ($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); } /** * Returns the name of this schema asset. * * @return string */ public function getName() { if ($this->_namespace) { return $this->_namespace . "." . $this->_name; } return $this->_name; } /** * Gets the quoted representation of this asset but only if it was defined with one. Otherwise * return the plain unquoted value as inserted. * * @param \Doctrine\DBAL\Platforms\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); } /** * Generates 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 integer $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); } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php000066400000000000000000000745721313473450000236320ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Events; use Doctrine\DBAL\Event\SchemaColumnDefinitionEventArgs; use Doctrine\DBAL\Event\SchemaIndexDefinitionEventArgs; 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. * * @author Konsta Vesterinen * @author Lukas Smith (PEAR MDB2 library) * @author Roman Borschel * @author Jonathan H. Wage * @author Benjamin Eberlei * @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 * @param \Doctrine\DBAL\Platforms\AbstractPlatform|null $platform */ public function __construct(\Doctrine\DBAL\Connection $conn, AbstractPlatform $platform = null) { $this->_conn = $conn; $this->_platform = $platform ?: $this->_conn->getDatabasePlatform(); } /** * Returns the associated platform. * * @return \Doctrine\DBAL\Platforms\AbstractPlatform */ public function getDatabasePlatform() { return $this->_platform; } /** * Tries 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. * * * $result = $sm->tryMethod('dropView', 'view_name'); * * * @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; } } /** * Lists the available databases for this connection. * * @return array */ public function listDatabases() { $sql = $this->_platform->getListDatabasesSQL(); $databases = $this->_conn->fetchAll($sql); return $this->_getPortableDatabasesList($databases); } /** * Returns a list of all namespaces in the current database. * * @return array */ public function listNamespaceNames() { $sql = $this->_platform->getListNamespacesSQL(); $namespaces = $this->_conn->fetchAll($sql); return $this->getPortableNamespacesList($namespaces); } /** * Lists the available sequences for this connection. * * @param string|null $database * * @return \Doctrine\DBAL\Schema\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)); } /** * Lists 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|null $database * * @return \Doctrine\DBAL\Schema\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); } /** * Lists 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 \Doctrine\DBAL\Schema\Index[] */ public function listTableIndexes($table) { $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase()); $tableIndexes = $this->_conn->fetchAll($sql); return $this->_getPortableTableIndexesList($tableIndexes, $table); } /** * Returns true if all the given tables exist. * * @param array $tableNames * * @return boolean */ public function tablesExist($tableNames) { $tableNames = array_map('strtolower', (array) $tableNames); return count($tableNames) == count(\array_intersect($tableNames, array_map('strtolower', $this->listTableNames()))); } /** * Returns 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); } /** * Filters 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); }) ); } /** * @return string|null */ protected function getFilterSchemaAssetsExpression() { return $this->_conn->getConfiguration()->getFilterSchemaAssetsExpression(); } /** * Lists the tables for this connection. * * @return \Doctrine\DBAL\Schema\Table[] */ public function listTables() { $tableNames = $this->listTableNames(); $tables = array(); foreach ($tableNames as $tableName) { $tables[] = $this->listTableDetails($tableName); } return $tables; } /** * @param string $tableName * * @return \Doctrine\DBAL\Schema\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()); } /** * Lists the views this connection has. * * @return \Doctrine\DBAL\Schema\View[] */ public function listViews() { $database = $this->_conn->getDatabase(); $sql = $this->_platform->getListViewsSQL($database); $views = $this->_conn->fetchAll($sql); return $this->_getPortableViewsList($views); } /** * Lists the foreign keys for the given table. * * @param string $table The name of the table. * @param string|null $database * * @return \Doctrine\DBAL\Schema\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. * * @return void */ public function dropDatabase($database) { $this->_execSql($this->_platform->getDropDatabaseSQL($database)); } /** * Drops the given table. * * @param string $tableName The name of the table to drop. * * @return void */ public function dropTable($tableName) { $this->_execSql($this->_platform->getDropTableSQL($tableName)); } /** * Drops the index from the given table. * * @param \Doctrine\DBAL\Schema\Index|string $index The name of the index. * @param \Doctrine\DBAL\Schema\Table|string $table The name of the table. * * @return void */ public function dropIndex($index, $table) { if ($index instanceof Index) { $index = $index->getQuotedName($this->_platform); } $this->_execSql($this->_platform->getDropIndexSQL($index, $table)); } /** * Drops the constraint from the given table. * * @param \Doctrine\DBAL\Schema\Constraint $constraint * @param \Doctrine\DBAL\Schema\Table|string $table The name of the table. * * @return void */ public function dropConstraint(Constraint $constraint, $table) { $this->_execSql($this->_platform->getDropConstraintSQL($constraint, $table)); } /** * Drops a foreign key from a table. * * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint|string $foreignKey The name of the foreign key. * @param \Doctrine\DBAL\Schema\Table|string $table The name of the table with the foreign key. * * @return void */ 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. * * @return void */ public function dropSequence($name) { $this->_execSql($this->_platform->getDropSequenceSQL($name)); } /** * Drops a view. * * @param string $name The name of the view. * * @return void */ 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. * * @return void */ public function createDatabase($database) { $this->_execSql($this->_platform->getCreateDatabaseSQL($database)); } /** * Creates a new table. * * @param \Doctrine\DBAL\Schema\Table $table * * @return void */ public function createTable(Table $table) { $createFlags = AbstractPlatform::CREATE_INDEXES|AbstractPlatform::CREATE_FOREIGNKEYS; $this->_execSql($this->_platform->getCreateTableSQL($table, $createFlags)); } /** * Creates a new sequence. * * @param \Doctrine\DBAL\Schema\Sequence $sequence * * @return void * * @throws \Doctrine\DBAL\ConnectionException If something fails at database level. */ public function createSequence($sequence) { $this->_execSql($this->_platform->getCreateSequenceSQL($sequence)); } /** * Creates a constraint on a table. * * @param \Doctrine\DBAL\Schema\Constraint $constraint * @param \Doctrine\DBAL\Schema\Table|string $table * * @return void */ public function createConstraint(Constraint $constraint, $table) { $this->_execSql($this->_platform->getCreateConstraintSQL($constraint, $table)); } /** * Creates a new index on a table. * * @param \Doctrine\DBAL\Schema\Index $index * @param \Doctrine\DBAL\Schema\Table|string $table The name of the table on which the index is to be created. * * @return void */ public function createIndex(Index $index, $table) { $this->_execSql($this->_platform->getCreateIndexSQL($index, $table)); } /** * Creates a new foreign key. * * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey The ForeignKey instance. * @param \Doctrine\DBAL\Schema\Table|string $table The name of the table on which the foreign key is to be created. * * @return void */ public function createForeignKey(ForeignKeyConstraint $foreignKey, $table) { $this->_execSql($this->_platform->getCreateForeignKeySQL($foreignKey, $table)); } /** * Creates a new view. * * @param \Doctrine\DBAL\Schema\View $view * * @return void */ public function createView(View $view) { $this->_execSql($this->_platform->getCreateViewSQL($view->getQuotedName($this->_platform), $view->getSql())); } /* dropAndCreate*() Methods */ /** * Drops and creates a constraint. * * @see dropConstraint() * @see createConstraint() * * @param \Doctrine\DBAL\Schema\Constraint $constraint * @param \Doctrine\DBAL\Schema\Table|string $table * * @return void */ public function dropAndCreateConstraint(Constraint $constraint, $table) { $this->tryMethod('dropConstraint', $constraint, $table); $this->createConstraint($constraint, $table); } /** * Drops and creates a new index on a table. * * @param \Doctrine\DBAL\Schema\Index $index * @param \Doctrine\DBAL\Schema\Table|string $table The name of the table on which the index is to be created. * * @return void */ public function dropAndCreateIndex(Index $index, $table) { $this->tryMethod('dropIndex', $index->getQuotedName($this->_platform), $table); $this->createIndex($index, $table); } /** * Drops and creates a new foreign key. * * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey An associative array that defines properties of the foreign key to be created. * @param \Doctrine\DBAL\Schema\Table|string $table The name of the table on which the foreign key is to be created. * * @return void */ public function dropAndCreateForeignKey(ForeignKeyConstraint $foreignKey, $table) { $this->tryMethod('dropForeignKey', $foreignKey, $table); $this->createForeignKey($foreignKey, $table); } /** * Drops and create a new sequence. * * @param \Doctrine\DBAL\Schema\Sequence $sequence * * @return void * * @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); } /** * Drops and creates a new table. * * @param \Doctrine\DBAL\Schema\Table $table * * @return void */ public function dropAndCreateTable(Table $table) { $this->tryMethod('dropTable', $table->getQuotedName($this->_platform)); $this->createTable($table); } /** * Drops and creates a new database. * * @param string $database The name of the database to create. * * @return void */ public function dropAndCreateDatabase($database) { $this->tryMethod('dropDatabase', $database); $this->createDatabase($database); } /** * Drops and creates a new view. * * @param \Doctrine\DBAL\Schema\View $view * * @return void */ public function dropAndCreateView(View $view) { $this->tryMethod('dropView', $view->getQuotedName($this->_platform)); $this->createView($view); } /* alterTable() Methods */ /** * Alters an existing tables schema. * * @param \Doctrine\DBAL\Schema\TableDiff $tableDiff * * @return void */ public function alterTable(TableDiff $tableDiff) { $queries = $this->_platform->getAlterTableSQL($tableDiff); if (is_array($queries) && count($queries)) { foreach ($queries as $ddlQuery) { $this->_execSql($ddlQuery); } } } /** * Renames a given table to another name. * * @param string $name The current name of the table. * @param string $newName The new name of the table. * * @return void */ 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 */ /** * @param array $databases * * @return array */ protected function _getPortableDatabasesList($databases) { $list = array(); foreach ($databases as $value) { if ($value = $this->_getPortableDatabaseDefinition($value)) { $list[] = $value; } } return $list; } /** * Converts a list of namespace names from the native DBMS data definition to a portable Doctrine definition. * * @param array $namespaces The list of namespace names in the native DBMS data definition. * * @return array */ protected function getPortableNamespacesList(array $namespaces) { $namespacesList = array(); foreach ($namespaces as $namespace) { $namespacesList[] = $this->getPortableNamespaceDefinition($namespace); } return $namespacesList; } /** * @param array $database * * @return mixed */ protected function _getPortableDatabaseDefinition($database) { return $database; } /** * Converts a namespace definition from the native DBMS data definition to a portable Doctrine definition. * * @param array $namespace The native DBMS namespace definition. * * @return mixed */ protected function getPortableNamespaceDefinition(array $namespace) { return $namespace; } /** * @param array $functions * * @return array */ protected function _getPortableFunctionsList($functions) { $list = array(); foreach ($functions as $value) { if ($value = $this->_getPortableFunctionDefinition($value)) { $list[] = $value; } } return $list; } /** * @param array $function * * @return mixed */ protected function _getPortableFunctionDefinition($function) { return $function; } /** * @param array $triggers * * @return array */ protected function _getPortableTriggersList($triggers) { $list = array(); foreach ($triggers as $value) { if ($value = $this->_getPortableTriggerDefinition($value)) { $list[] = $value; } } return $list; } /** * @param array $trigger * * @return mixed */ protected function _getPortableTriggerDefinition($trigger) { return $trigger; } /** * @param array $sequences * * @return array */ protected function _getPortableSequencesList($sequences) { $list = array(); foreach ($sequences as $value) { if ($value = $this->_getPortableSequenceDefinition($value)) { $list[] = $value; } } return $list; } /** * @param array $sequence * * @return \Doctrine\DBAL\Schema\Sequence * * @throws \Doctrine\DBAL\DBALException */ 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 $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; } /** * Gets Table Column Definition. * * @param array $tableColumn * * @return \Doctrine\DBAL\Schema\Column */ abstract protected function _getPortableTableColumnDefinition($tableColumn); /** * Aggregates and groups the index results according to the required data result. * * @param array $tableIndexRows * @param string|null $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'], 'flags' => isset($tableIndex['flags']) ? $tableIndex['flags'] : array(), 'options' => isset($tableIndex['where']) ? array('where' => $tableIndex['where']) : array(), ); } 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'], $data['flags'], $data['options']); } if ($index) { $indexes[$indexKey] = $index; } } return $indexes; } /** * @param array $tables * * @return array */ protected function _getPortableTablesList($tables) { $list = array(); foreach ($tables as $value) { if ($value = $this->_getPortableTableDefinition($value)) { $list[] = $value; } } return $list; } /** * @param array $table * * @return array */ protected function _getPortableTableDefinition($table) { return $table; } /** * @param array $users * * @return array */ protected function _getPortableUsersList($users) { $list = array(); foreach ($users as $value) { if ($value = $this->_getPortableUserDefinition($value)) { $list[] = $value; } } return $list; } /** * @param array $user * * @return mixed */ protected function _getPortableUserDefinition($user) { return $user; } /** * @param array $views * * @return array */ protected function _getPortableViewsList($views) { $list = array(); foreach ($views as $value) { if ($view = $this->_getPortableViewDefinition($value)) { $viewName = strtolower($view->getQuotedName($this->_platform)); $list[$viewName] = $view; } } return $list; } /** * @param array $view * * @return mixed */ protected function _getPortableViewDefinition($view) { return false; } /** * @param array $tableForeignKeys * * @return array */ protected function _getPortableTableForeignKeysList($tableForeignKeys) { $list = array(); foreach ($tableForeignKeys as $value) { if ($value = $this->_getPortableTableForeignKeyDefinition($value)) { $list[] = $value; } } return $list; } /** * @param array $tableForeignKey * * @return mixed */ protected function _getPortableTableForeignKeyDefinition($tableForeignKey) { return $tableForeignKey; } /** * @param array|string $sql * * @return void */ protected function _execSql($sql) { foreach ((array) $sql as $query) { $this->_conn->executeUpdate($query); } } /** * Creates a schema instance for the current database. * * @return \Doctrine\DBAL\Schema\Schema */ public function createSchema() { $namespaces = array(); if ($this->_platform->supportsSchemas()) { $namespaces = $this->listNamespaceNames(); } $sequences = array(); if ($this->_platform->supportsSequences()) { $sequences = $this->listSequences(); } $tables = $this->listTables(); return new Schema($tables, $sequences, $this->createSchemaConfig(), $namespaces); } /** * Creates the configuration for this schema. * * @return \Doctrine\DBAL\Schema\SchemaConfig */ public function createSchemaConfig() { $schemaConfig = new SchemaConfig(); $schemaConfig->setMaxIdentifierLength($this->_platform->getMaxIdentifierLength()); $searchPaths = $this->getSchemaSearchPaths(); if (isset($searchPaths[0])) { $schemaConfig->setName($searchPaths[0]); } $params = $this->_conn->getParams(); if (isset($params['defaultTableOptions'])) { $schemaConfig->setDefaultTableOptions($params['defaultTableOptions']); } 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; } /** * @param string $comment * @param string $type * * @return string */ public function removeDoctrineTypeFromComment($comment, $type) { return str_replace('(DC2Type:'.$type.')', '', $comment); } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/Column.php000066400000000000000000000222041313473450000206710ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Types\Type; /** * Object representation of a database column. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ class Column extends AbstractAsset { /** * @var Type */ protected $_type; /** * @var integer|null */ protected $_length = null; /** * @var integer */ protected $_precision = 10; /** * @var integer */ protected $_scale = 0; /** * @var boolean */ protected $_unsigned = false; /** * @var boolean */ protected $_fixed = false; /** * @var boolean */ protected $_notnull = true; /** * @var string|null */ protected $_default = null; /** * @var boolean */ protected $_autoincrement = false; /** * @var array */ protected $_platformOptions = array(); /** * @var string|null */ protected $_columnDefinition = null; /** * @var string|null */ protected $_comment = null; /** * @var array */ protected $_customSchemaOptions = array(); /** * Creates a new Column. * * @param string $columnName * @param Type $type * @param array $options */ 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 integer|null $length * * @return Column */ public function setLength($length) { if ($length !== null) { $this->_length = (int) $length; } else { $this->_length = null; } return $this; } /** * @param integer $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 integer $scale * * @return Column */ public function setScale($scale) { if (!is_numeric($scale)) { $scale = 0; } $this->_scale = (int) $scale; return $this; } /** * @param boolean $unsigned * * @return Column */ public function setUnsigned($unsigned) { $this->_unsigned = (bool) $unsigned; return $this; } /** * @param boolean $fixed * * @return Column */ public function setFixed($fixed) { $this->_fixed = (bool) $fixed; return $this; } /** * @param boolean $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 $value * * @return Column */ public function setColumnDefinition($value) { $this->_columnDefinition = $value; return $this; } /** * @return Type */ public function getType() { return $this->_type; } /** * @return integer|null */ public function getLength() { return $this->_length; } /** * @return integer */ public function getPrecision() { return $this->_precision; } /** * @return integer */ public function getScale() { return $this->_scale; } /** * @return boolean */ public function getUnsigned() { return $this->_unsigned; } /** * @return boolean */ public function getFixed() { return $this->_fixed; } /** * @return boolean */ public function getNotnull() { return $this->_notnull; } /** * @return string|null */ public function getDefault() { return $this->_default; } /** * @return array */ public function getPlatformOptions() { return $this->_platformOptions; } /** * @param string $name * * @return boolean */ public function hasPlatformOption($name) { return isset($this->_platformOptions[$name]); } /** * @param string $name * * @return mixed */ public function getPlatformOption($name) { return $this->_platformOptions[$name]; } /** * @return string|null */ public function getColumnDefinition() { return $this->_columnDefinition; } /** * @return boolean */ public function getAutoincrement() { return $this->_autoincrement; } /** * @param boolean $flag * * @return Column */ public function setAutoincrement($flag) { $this->_autoincrement = $flag; return $this; } /** * @param string $comment * * @return Column */ public function setComment($comment) { $this->_comment = $comment; return $this; } /** * @return string|null */ 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; } /** * @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); } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/ColumnDiff.php000066400000000000000000000044641313473450000214720ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; /** * Represents the change of a column. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ class ColumnDiff { /** * @var string */ public $oldColumnName; /** * @var Column */ public $column; /** * @var array */ public $changedProperties = array(); /** * @var Column */ public $fromColumn; /** * @param string $oldColumnName * @param Column $column * @param string[] $changedProperties * @param Column $fromColumn */ public function __construct($oldColumnName, Column $column, array $changedProperties = array(), Column $fromColumn = null) { $this->oldColumnName = $oldColumnName; $this->column = $column; $this->changedProperties = $changedProperties; $this->fromColumn = $fromColumn; } /** * @param string $propertyName * * @return boolean */ public function hasChanged($propertyName) { return in_array($propertyName, $this->changedProperties); } /** * @return Identifier */ public function getOldColumnName() { $quote = $this->fromColumn && $this->fromColumn->isQuoted(); return new Identifier($this->oldColumnName, $quote); } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/Comparator.php000066400000000000000000000476041313473450000215560ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Types; /** * Compares two Schemas and return an instance of SchemaDiff. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ class Comparator { /** * @param \Doctrine\DBAL\Schema\Schema $fromSchema * @param \Doctrine\DBAL\Schema\Schema $toSchema * * @return \Doctrine\DBAL\Schema\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 differences 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 \Doctrine\DBAL\Schema\Schema $fromSchema * @param \Doctrine\DBAL\Schema\Schema $toSchema * * @return \Doctrine\DBAL\Schema\SchemaDiff */ public function compare(Schema $fromSchema, Schema $toSchema) { $diff = new SchemaDiff(); $diff->fromSchema = $fromSchema; $foreignKeysToTable = array(); foreach ($toSchema->getNamespaces() as $namespace) { if ( ! $fromSchema->hasNamespace($namespace)) { $diff->newNamespaces[$namespace] = $namespace; } } foreach ($fromSchema->getNamespaces() as $namespace) { if ( ! $toSchema->hasNamespace($namespace)) { $diff->removedNamespaces[$namespace] = $namespace; } } 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]); // deleting duplicated foreign keys present on both on the orphanedForeignKey // and the removedForeignKeys from changedTables foreach ($foreignKeysToTable[$tableName] as $foreignKey) { // strtolower the table name to make if compatible with getShortestName $localTableName = strtolower($foreignKey->getLocalTableName()); if (isset($diff->changedTables[$localTableName])) { foreach ($diff->changedTables[$localTableName]->removedForeignKeys as $key => $removedForeignKey) { // We check if the key is from the removed table if not we skip. if ($tableName !== strtolower($removedForeignKey->getForeignTableName())) { continue; } unset($diff->changedTables[$localTableName]->removedForeignKeys[$key]); } } } } } foreach ($toSchema->getSequences() as $sequence) { $sequenceName = $sequence->getShortestName($toSchema->getName()); if ( ! $fromSchema->hasSequence($sequenceName)) { if ( ! $this->isAutoIncrementSequenceInSchema($fromSchema, $sequence)) { $diff->newSequences[] = $sequence; } } else { if ($this->diffSequence($sequence, $fromSchema->getSequence($sequenceName))) { $diff->changedSequences[] = $toSchema->getSequence($sequenceName); } } } foreach ($fromSchema->getSequences() as $sequence) { if ($this->isAutoIncrementSequenceInSchema($toSchema, $sequence)) { continue; } $sequenceName = $sequence->getShortestName($fromSchema->getName()); if ( ! $toSchema->hasSequence($sequenceName)) { $diff->removedSequences[] = $sequence; } } return $diff; } /** * @param \Doctrine\DBAL\Schema\Schema $schema * @param \Doctrine\DBAL\Schema\Sequence $sequence * * @return boolean */ private function isAutoIncrementSequenceInSchema($schema, $sequence) { foreach ($schema->getTables() as $table) { if ($sequence->isAutoIncrementsFor($table)) { return true; } } return false; } /** * @param \Doctrine\DBAL\Schema\Sequence $sequence1 * @param \Doctrine\DBAL\Schema\Sequence $sequence2 * * @return boolean */ 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 \Doctrine\DBAL\Schema\Table $table1 * @param \Doctrine\DBAL\Schema\Table $table2 * * @return boolean|\Doctrine\DBAL\Schema\TableDiff */ public function diffTable(Table $table1, Table $table2) { $changes = 0; $tableDifferences = new TableDiff($table1->getName()); $tableDifferences->fromTable = $table1; $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) { // See if column is removed in table 2. if ( ! $table2->hasColumn($columnName)) { $tableDifferences->removedColumns[$columnName] = $column; $changes++; continue; } // See if column has changed properties in table 2. $changedProperties = $this->diffColumn($column, $table2->getColumn($columnName)); if ( ! empty($changedProperties)) { $columnDiff = new ColumnDiff($column->getName(), $table2->getColumn($columnName), $changedProperties); $columnDiff->fromColumn = $column; $tableDifferences->changedColumns[$column->getName()] = $columnDiff; $changes++; } } $this->detectColumnRenamings($tableDifferences); $table1Indexes = $table1->getIndexes(); $table2Indexes = $table2->getIndexes(); /* See if all the indexes in table 1 exist in table 2 */ foreach ($table2Indexes as $indexName => $index) { if (($index->isPrimary() && $table1->hasPrimaryKey()) || $table1->hasIndex($indexName)) { continue; } $tableDifferences->addedIndexes[$indexName] = $index; $changes++; } /* See if there are any removed indexes in table 2 */ foreach ($table1Indexes as $indexName => $index) { // See if index is removed in table 2. if (($index->isPrimary() && ! $table2->hasPrimaryKey()) || ! $index->isPrimary() && ! $table2->hasIndex($indexName) ) { $tableDifferences->removedIndexes[$indexName] = $index; $changes++; continue; } // See if index has changed in table 2. $table2Index = $index->isPrimary() ? $table2->getPrimaryKey() : $table2->getIndex($indexName); if ($this->diffIndex($index, $table2Index)) { $tableDifferences->changedIndexes[$indexName] = $table2Index; $changes++; } } $this->detectIndexRenamings($tableDifferences); $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 $constraint1) { $tableDifferences->removedForeignKeys[] = $constraint1; $changes++; } foreach ($toFkeys as $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 ambiguities between different possibilities should not lead to renaming at all. * * @param \Doctrine\DBAL\Schema\TableDiff $tableDifferences * * @return void */ private function detectColumnRenamings(TableDiff $tableDifferences) { $renameCandidates = array(); foreach ($tableDifferences->addedColumns as $addedColumnName => $addedColumn) { foreach ($tableDifferences->removedColumns as $removedColumn) { if (count($this->diffColumn($addedColumn, $removedColumn)) == 0) { $renameCandidates[$addedColumn->getName()][] = array($removedColumn, $addedColumn, $addedColumnName); } } } foreach ($renameCandidates as $candidateColumns) { if (count($candidateColumns) == 1) { list($removedColumn, $addedColumn) = $candidateColumns[0]; $removedColumnName = strtolower($removedColumn->getName()); $addedColumnName = strtolower($addedColumn->getName()); if ( ! isset($tableDifferences->renamedColumns[$removedColumnName])) { $tableDifferences->renamedColumns[$removedColumnName] = $addedColumn; unset($tableDifferences->addedColumns[$addedColumnName]); unset($tableDifferences->removedColumns[$removedColumnName]); } } } } /** * Try to find indexes that only changed their name, rename operations maybe cheaper than add/drop * however ambiguities between different possibilities should not lead to renaming at all. * * @param \Doctrine\DBAL\Schema\TableDiff $tableDifferences * * @return void */ private function detectIndexRenamings(TableDiff $tableDifferences) { $renameCandidates = array(); // Gather possible rename candidates by comparing each added and removed index based on semantics. foreach ($tableDifferences->addedIndexes as $addedIndexName => $addedIndex) { foreach ($tableDifferences->removedIndexes as $removedIndex) { if (! $this->diffIndex($addedIndex, $removedIndex)) { $renameCandidates[$addedIndex->getName()][] = array($removedIndex, $addedIndex, $addedIndexName); } } } foreach ($renameCandidates as $candidateIndexes) { // If the current rename candidate contains exactly one semantically equal index, // we can safely rename it. // Otherwise it is unclear if a rename action is really intended, // therefore we let those ambiguous indexes be added/dropped. if (count($candidateIndexes) === 1) { list($removedIndex, $addedIndex) = $candidateIndexes[0]; $removedIndexName = strtolower($removedIndex->getName()); $addedIndexName = strtolower($addedIndex->getName()); if (! isset($tableDifferences->renamedIndexes[$removedIndexName])) { $tableDifferences->renamedIndexes[$removedIndexName] = $addedIndex; unset($tableDifferences->addedIndexes[$addedIndexName]); unset($tableDifferences->removedIndexes[$removedIndexName]); } } } } /** * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $key1 * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $key2 * * @return boolean */ public function diffForeignKey(ForeignKeyConstraint $key1, ForeignKeyConstraint $key2) { if (array_map('strtolower', $key1->getUnquotedLocalColumns()) != array_map('strtolower', $key2->getUnquotedLocalColumns())) { return true; } if (array_map('strtolower', $key1->getUnquotedForeignColumns()) != array_map('strtolower', $key2->getUnquotedForeignColumns())) { return true; } if ($key1->getUnqualifiedForeignTableName() !== $key2->getUnqualifiedForeignTableName()) { 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 \Doctrine\DBAL\Schema\Column $column1 * @param \Doctrine\DBAL\Schema\Column $column2 * * @return array */ public function diffColumn(Column $column1, Column $column2) { $properties1 = $column1->toArray(); $properties2 = $column2->toArray(); $changedProperties = array(); foreach (array('type', 'notnull', 'unsigned', 'autoincrement') as $property) { if ($properties1[$property] != $properties2[$property]) { $changedProperties[] = $property; } } if ($properties1['default'] != $properties2['default'] || // Null values need to be checked additionally as they tell whether to create or drop a default value. // null != 0, null != false, null != '' etc. This affects platform's table alteration SQL generation. (null === $properties1['default'] && null !== $properties2['default']) || (null === $properties2['default'] && null !== $properties1['default']) ) { $changedProperties[] = 'default'; } if (($properties1['type'] instanceof Types\StringType && ! $properties1['type'] instanceof Types\GuidType) || $properties1['type'] instanceof Types\BinaryType ) { // check if value of length is set at all, default value assumed otherwise. $length1 = $properties1['length'] ?: 255; $length2 = $properties2['length'] ?: 255; if ($length1 != $length2) { $changedProperties[] = 'length'; } if ($properties1['fixed'] != $properties2['fixed']) { $changedProperties[] = 'fixed'; } } elseif ($properties1['type'] instanceof Types\DecimalType) { if (($properties1['precision'] ?: 10) != ($properties2['precision'] ?: 10)) { $changedProperties[] = 'precision'; } if ($properties1['scale'] != $properties2['scale']) { $changedProperties[] = 'scale'; } } // A null value and an empty string are actually equal for a comment so they should not trigger a change. if ($properties1['comment'] !== $properties2['comment'] && ! (null === $properties1['comment'] && '' === $properties2['comment']) && ! (null === $properties2['comment'] && '' === $properties1['comment']) ) { $changedProperties[] = 'comment'; } $customOptions1 = $column1->getCustomSchemaOptions(); $customOptions2 = $column2->getCustomSchemaOptions(); foreach (array_merge(array_keys($customOptions1), array_keys($customOptions2)) as $key) { if ( ! array_key_exists($key, $properties1) || ! array_key_exists($key, $properties2)) { $changedProperties[] = $key; } elseif ($properties1[$key] !== $properties2[$key]) { $changedProperties[] = $key; } } $platformOptions1 = $column1->getPlatformOptions(); $platformOptions2 = $column2->getPlatformOptions(); foreach (array_keys(array_intersect_key($platformOptions1, $platformOptions2)) as $key) { if ($properties1[$key] !== $properties2[$key]) { $changedProperties[] = $key; } } return array_unique($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 \Doctrine\DBAL\Schema\Index $index1 * @param \Doctrine\DBAL\Schema\Index $index2 * * @return boolean */ public function diffIndex(Index $index1, Index $index2) { if ($index1->isFullfilledBy($index2) && $index2->isFullfilledBy($index1)) { return false; } return true; } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/Constraint.php000066400000000000000000000041721313473450000215640ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Marker interface for contraints. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ interface Constraint { /** * @return string */ public function getName(); /** * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform * * @return string */ public function getQuotedName(AbstractPlatform $platform); /** * Returns the names of the referencing table columns * the constraint is associated with. * * @return array */ public function getColumns(); /** * Returns the quoted representation of the column names * the constraint is associated with. * * But only if they were defined with one or a column name * is a keyword reserved by the platform. * Otherwise the plain unquoted value as inserted is returned. * * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform The platform to use for quotation. * * @return array */ public function getQuotedColumns(AbstractPlatform $platform); } dbal-2.5.13/lib/Doctrine/DBAL/Schema/DB2SchemaManager.php000066400000000000000000000165361313473450000224320ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; /** * IBM Db2 Schema Manager. * * @link www.doctrine-project.org * @since 1.0 * @author Benjamin Eberlei */ class DB2SchemaManager extends AbstractSchemaManager { /** * {@inheritdoc} * * 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} */ public function listTableNames() { $sql = $this->_platform->getListTablesSQL(); $sql .= " AND CREATOR = UPPER('".$this->_conn->getUsername()."')"; $tables = $this->_conn->fetchAll($sql); return $this->_getPortableTablesList($tables); } /** * {@inheritdoc} */ protected function _getPortableTableColumnDefinition($tableColumn) { $tableColumn = array_change_key_case($tableColumn, \CASE_LOWER); $length = null; $fixed = null; $unsigned = false; $scale = false; $precision = false; $default = null; if (null !== $tableColumn['default'] && 'NULL' != $tableColumn['default']) { $default = trim($tableColumn['default'], "'"); } $type = $this->_platform->getDoctrineTypeMapping($tableColumn['typename']); if (isset($tableColumn['comment'])) { $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type); $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type); } 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' => $default, 'autoincrement' => (boolean) $tableColumn['autoincrement'], 'notnull' => (bool) ($tableColumn['nulls'] == 'N'), 'scale' => null, 'precision' => null, 'comment' => isset($tableColumn['comment']) && $tableColumn['comment'] !== '' ? $tableColumn['comment'] : 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); } /** * {@inheritdoc} */ protected function _getPortableTablesList($tables) { $tableNames = array(); foreach ($tables as $tableRow) { $tableRow = array_change_key_case($tableRow, \CASE_LOWER); $tableNames[] = $tableRow['name']; } return $tableNames; } /** * {@inheritdoc} */ protected function _getPortableTableIndexesList($tableIndexRows, $tableName = null) { foreach ($tableIndexRows as &$tableIndexRow) { $tableIndexRow = array_change_key_case($tableIndexRow, \CASE_LOWER); $tableIndexRow['primary'] = (boolean) $tableIndexRow['primary']; } return parent::_getPortableTableIndexesList($tableIndexRows, $tableName); } /** * {@inheritdoc} */ protected function _getPortableTableForeignKeyDefinition($tableForeignKey) { return new ForeignKeyConstraint( $tableForeignKey['local_columns'], $tableForeignKey['foreign_table'], $tableForeignKey['foreign_columns'], $tableForeignKey['name'], $tableForeignKey['options'] ); } /** * {@inheritdoc} */ protected function _getPortableTableForeignKeysList($tableForeignKeys) { $foreignKeys = array(); foreach ($tableForeignKeys as $tableForeignKey) { $tableForeignKey = array_change_key_case($tableForeignKey, \CASE_LOWER); if (!isset($foreignKeys[$tableForeignKey['index_name']])) { $foreignKeys[$tableForeignKey['index_name']] = array( 'local_columns' => array($tableForeignKey['local_column']), 'foreign_table' => $tableForeignKey['foreign_table'], 'foreign_columns' => array($tableForeignKey['foreign_column']), 'name' => $tableForeignKey['index_name'], 'options' => array( 'onUpdate' => $tableForeignKey['on_update'], 'onDelete' => $tableForeignKey['on_delete'], ) ); } else { $foreignKeys[$tableForeignKey['index_name']]['local_columns'][] = $tableForeignKey['local_column']; $foreignKeys[$tableForeignKey['index_name']]['foreign_columns'][] = $tableForeignKey['foreign_column']; } } return parent::_getPortableTableForeignKeysList($foreignKeys); } /** * {@inheritdoc} */ protected function _getPortableForeignKeyRuleDef($def) { if ($def == "C") { return "CASCADE"; } elseif ($def == "N") { return "SET NULL"; } return null; } /** * {@inheritdoc} */ 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); } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/DrizzleSchemaManager.php000066400000000000000000000100141313473450000234670ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Types\Type; /** * Schema manager for the Drizzle RDBMS. * * @author Kim Hemsø Rasmussen */ class DrizzleSchemaManager extends AbstractSchemaManager { /** * {@inheritdoc} */ protected function _getPortableTableColumnDefinition($tableColumn) { $dbType = strtolower($tableColumn['DATA_TYPE']); $type = $this->_platform->getDoctrineTypeMapping($dbType); $type = $this->extractDoctrineTypeFromComment($tableColumn['COLUMN_COMMENT'], $type); $tableColumn['COLUMN_COMMENT'] = $this->removeDoctrineTypeFromComment($tableColumn['COLUMN_COMMENT'], $type); $options = array( 'notnull' => !(bool) $tableColumn['IS_NULLABLE'], 'length' => (int) $tableColumn['CHARACTER_MAXIMUM_LENGTH'], 'default' => isset($tableColumn['COLUMN_DEFAULT']) ? $tableColumn['COLUMN_DEFAULT'] : null, 'autoincrement' => (bool) $tableColumn['IS_AUTO_INCREMENT'], 'scale' => (int) $tableColumn['NUMERIC_SCALE'], 'precision' => (int) $tableColumn['NUMERIC_PRECISION'], 'comment' => isset($tableColumn['COLUMN_COMMENT']) && '' !== $tableColumn['COLUMN_COMMENT'] ? $tableColumn['COLUMN_COMMENT'] : null, ); $column = new Column($tableColumn['COLUMN_NAME'], Type::getType($type), $options); if ( ! empty($tableColumn['COLLATION_NAME'])) { $column->setPlatformOption('collation', $tableColumn['COLLATION_NAME']); } return $column; } /** * {@inheritdoc} */ protected function _getPortableDatabaseDefinition($database) { return $database['SCHEMA_NAME']; } /** * {@inheritdoc} */ protected function _getPortableTableDefinition($table) { return $table['TABLE_NAME']; } /** * {@inheritdoc} */ public function _getPortableTableForeignKeyDefinition($tableForeignKey) { $columns = array(); foreach (explode(',', $tableForeignKey['CONSTRAINT_COLUMNS']) as $value) { $columns[] = trim($value, ' `'); } $refColumns = array(); foreach (explode(',', $tableForeignKey['REFERENCED_TABLE_COLUMNS']) as $value) { $refColumns[] = trim($value, ' `'); } return new ForeignKeyConstraint( $columns, $tableForeignKey['REFERENCED_TABLE_NAME'], $refColumns, $tableForeignKey['CONSTRAINT_NAME'], array( 'onUpdate' => $tableForeignKey['UPDATE_RULE'], 'onDelete' => $tableForeignKey['DELETE_RULE'], ) ); } /** * {@inheritdoc} */ protected function _getPortableTableIndexesList($tableIndexes, $tableName = null) { $indexes = array(); foreach ($tableIndexes as $k) { $k['primary'] = (boolean) $k['primary']; $indexes[] = $k; } return parent::_getPortableTableIndexesList($indexes, $tableName); } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/ForeignKeyConstraint.php000066400000000000000000000267311313473450000235540ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * An abstraction class for a foreign key constraint. * * @author Benjamin Eberlei * @author Steve Müller * @link www.doctrine-project.org * @since 2.0 */ class ForeignKeyConstraint extends AbstractAsset implements Constraint { /** * Instance of the referencing table the foreign key constraint is associated with. * * @var \Doctrine\DBAL\Schema\Table */ protected $_localTable; /** * Asset identifier instances of the referencing table column names the foreign key constraint is associated with. * array($columnName => Identifier) * * @var Identifier[] */ protected $_localColumnNames; /** * Table or asset identifier instance of the referenced table name the foreign key constraint is associated with. * * @var Table|Identifier */ protected $_foreignTableName; /** * Asset identifier instances of the referenced table column names the foreign key constraint is associated with. * array($columnName => Identifier) * * @var Identifier[] */ protected $_foreignColumnNames; /** * @var array Options associated with the foreign key constraint. */ protected $_options; /** * Initializes the foreign key constraint. * * @param array $localColumnNames Names of the referencing table columns. * @param Table|string $foreignTableName Referenced table. * @param array $foreignColumnNames Names of the referenced table columns. * @param string|null $name Name of the foreign key constraint. * @param array $options Options associated with the foreign key constraint. */ public function __construct(array $localColumnNames, $foreignTableName, array $foreignColumnNames, $name = null, array $options = array()) { $this->_setName($name); $identifierConstructorCallback = function ($column) { return new Identifier($column); }; $this->_localColumnNames = $localColumnNames ? array_combine($localColumnNames, array_map($identifierConstructorCallback, $localColumnNames)) : array(); if ($foreignTableName instanceof Table) { $this->_foreignTableName = $foreignTableName; } else { $this->_foreignTableName = new Identifier($foreignTableName); } $this->_foreignColumnNames = $foreignColumnNames ? array_combine($foreignColumnNames, array_map($identifierConstructorCallback, $foreignColumnNames)) : array(); $this->_options = $options; } /** * Returns the name of the referencing table * the foreign key constraint is associated with. * * @return string */ public function getLocalTableName() { return $this->_localTable->getName(); } /** * Sets the Table instance of the referencing table * the foreign key constraint is associated with. * * @param \Doctrine\DBAL\Schema\Table $table Instance of the referencing table. * * @return void */ public function setLocalTable(Table $table) { $this->_localTable = $table; } /** * @return Table */ public function getLocalTable() { return $this->_localTable; } /** * Returns the names of the referencing table columns * the foreign key constraint is associated with. * * @return array */ public function getLocalColumns() { return array_keys($this->_localColumnNames); } /** * Returns the quoted representation of the referencing table column names * the foreign key constraint is associated with. * * But only if they were defined with one or the referencing table column name * is a keyword reserved by the platform. * Otherwise the plain unquoted value as inserted is returned. * * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform The platform to use for quotation. * * @return array */ public function getQuotedLocalColumns(AbstractPlatform $platform) { $columns = array(); foreach ($this->_localColumnNames as $column) { $columns[] = $column->getQuotedName($platform); } return $columns; } /** * Returns unquoted representation of local table column names for comparison with other FK * * @return array */ public function getUnquotedLocalColumns() { return array_map(array($this, 'trimQuotes'), $this->getLocalColumns()); } /** * Returns unquoted representation of foreign table column names for comparison with other FK * * @return array */ public function getUnquotedForeignColumns() { return array_map(array($this, 'trimQuotes'), $this->getForeignColumns()); } /** * {@inheritdoc} * * @see getLocalColumns */ public function getColumns() { return $this->getLocalColumns(); } /** * Returns the quoted representation of the referencing table column names * the foreign key constraint is associated with. * * But only if they were defined with one or the referencing table column name * is a keyword reserved by the platform. * Otherwise the plain unquoted value as inserted is returned. * * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform The platform to use for quotation. * * @see getQuotedLocalColumns * * @return array */ public function getQuotedColumns(AbstractPlatform $platform) { return $this->getQuotedLocalColumns($platform); } /** * Returns the name of the referenced table * the foreign key constraint is associated with. * * @return string */ public function getForeignTableName() { return $this->_foreignTableName->getName(); } /** * Returns the non-schema qualified foreign table name. * * @return string */ public function getUnqualifiedForeignTableName() { $parts = explode(".", $this->_foreignTableName->getName()); return strtolower(end($parts)); } /** * Returns the quoted representation of the referenced table name * the foreign key constraint is associated with. * * But only if it was defined with one or the referenced table name * is a keyword reserved by the platform. * Otherwise the plain unquoted value as inserted is returned. * * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform The platform to use for quotation. * * @return string */ public function getQuotedForeignTableName(AbstractPlatform $platform) { return $this->_foreignTableName->getQuotedName($platform); } /** * Returns the names of the referenced table columns * the foreign key constraint is associated with. * * @return array */ public function getForeignColumns() { return array_keys($this->_foreignColumnNames); } /** * Returns the quoted representation of the referenced table column names * the foreign key constraint is associated with. * * But only if they were defined with one or the referenced table column name * is a keyword reserved by the platform. * Otherwise the plain unquoted value as inserted is returned. * * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform The platform to use for quotation. * * @return array */ public function getQuotedForeignColumns(AbstractPlatform $platform) { $columns = array(); foreach ($this->_foreignColumnNames as $column) { $columns[] = $column->getQuotedName($platform); } return $columns; } /** * Returns whether or not a given option * is associated with the foreign key constraint. * * @param string $name Name of the option to check. * * @return boolean */ public function hasOption($name) { return isset($this->_options[$name]); } /** * Returns an option associated with the foreign key constraint. * * @param string $name Name of the option the foreign key constraint is associated with. * * @return mixed */ public function getOption($name) { return $this->_options[$name]; } /** * Returns the options associated with the foreign key constraint. * * @return array */ public function getOptions() { return $this->_options; } /** * Returns the referential action for UPDATE operations * on the referenced table the foreign key constraint is associated with. * * @return string|null */ public function onUpdate() { return $this->onEvent('onUpdate'); } /** * Returns the referential action for DELETE operations * on the referenced table the foreign key constraint is associated with. * * @return string|null */ public function onDelete() { return $this->onEvent('onDelete'); } /** * Returns the referential action for a given database operation * on the referenced table the foreign key constraint is associated with. * * @param string $event Name of the database operation/event to return the referential action for. * * @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; } /** * Checks whether this foreign key constraint intersects the given index columns. * * Returns `true` if at least one of this foreign key's local columns * matches one of the given index's columns, `false` otherwise. * * @param Index $index The index to be checked against. * * @return boolean */ public function intersectsIndexColumns(Index $index) { foreach ($index->getColumns() as $indexColumn) { foreach ($this->_localColumnNames as $localColumn) { if (strtolower($indexColumn) === strtolower($localColumn->getName())) { return true; } } } return false; } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/Identifier.php000066400000000000000000000033441313473450000215220ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; /** * An abstraction class for an asset identifier. * * Wraps identifier names like column names in indexes / foreign keys * in an abstract class for proper quotation capabilities. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.4 */ class Identifier extends AbstractAsset { /** * Constructor. * * @param string $identifier Identifier name to wrap. * @param bool $quote Whether to force quoting the given identifier. */ public function __construct($identifier, $quote = false) { $this->_setName($identifier); if ($quote && ! $this->_quoted) { $this->_setName('"' . $this->getName() . '"'); } } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/Index.php000066400000000000000000000216241313473450000205100ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Platforms\AbstractPlatform; class Index extends AbstractAsset implements Constraint { /** * Asset identifier instances of the column names the index is associated with. * array($columnName => Identifier) * * @var Identifier[] */ protected $_columns = array(); /** * @var boolean */ protected $_isUnique = false; /** * @var boolean */ protected $_isPrimary = false; /** * Platform specific flags for indexes. * array($flagName => true) * * @var array */ protected $_flags = array(); /** * Platform specific options * * @todo $_flags should eventually be refactored into options * * @var array */ private $options = array(); /** * @param string $indexName * @param string[] $columns * @param boolean $isUnique * @param boolean $isPrimary * @param string[] $flags * @param array $options */ public function __construct($indexName, array $columns, $isUnique = false, $isPrimary = false, array $flags = array(), array $options = array()) { $isUnique = $isUnique || $isPrimary; $this->_setName($indexName); $this->_isUnique = $isUnique; $this->_isPrimary = $isPrimary; $this->options = $options; foreach ($columns as $column) { $this->_addColumn($column); } foreach ($flags as $flag) { $this->addFlag($flag); } } /** * @param string $column * * @return void * * @throws \InvalidArgumentException */ protected function _addColumn($column) { if (is_string($column)) { $this->_columns[$column] = new Identifier($column); } else { throw new \InvalidArgumentException("Expecting a string as Index Column"); } } /** * {@inheritdoc} */ public function getColumns() { return array_keys($this->_columns); } /** * {@inheritdoc} */ public function getQuotedColumns(AbstractPlatform $platform) { $columns = array(); foreach ($this->_columns as $column) { $columns[] = $column->getQuotedName($platform); } return $columns; } /** * @return string[] */ public function getUnquotedColumns() { return array_map(array($this, 'trimQuotes'), $this->getColumns()); } /** * Is the index neither unique nor primary key? * * @return boolean */ public function isSimpleIndex() { return !$this->_isPrimary && !$this->_isUnique; } /** * @return boolean */ public function isUnique() { return $this->_isUnique; } /** * @return boolean */ public function isPrimary() { return $this->_isPrimary; } /** * @param string $columnName * @param integer $pos * * @return boolean */ public function hasColumnAtPosition($columnName, $pos = 0) { $columnName = $this->trimQuotes(strtolower($columnName)); $indexColumns = array_map('strtolower', $this->getUnquotedColumns()); return array_search($columnName, $indexColumns) === $pos; } /** * Checks if this index exactly spans the given column names in the correct order. * * @param array $columnNames * * @return boolean */ public function spansColumns(array $columnNames) { $columns = $this->getColumns(); $numberOfColumns = count($columns); $sameColumns = true; for ($i = 0; $i < $numberOfColumns; $i++) { if ( ! isset($columnNames[$i]) || $this->trimQuotes(strtolower($columns[$i])) !== $this->trimQuotes(strtolower($columnNames[$i]))) { $sameColumns = false; } } return $sameColumns; } /** * Checks if the other index already fulfills all the indexing and constraint needs of the current one. * * @param Index $other * * @return boolean */ 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->samePartialIndex($other)) { return false; } 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 fulfill the requirements of just an // index that has no constraints. return true; } if ($other->isPrimary() != $this->isPrimary()) { return false; } if ($other->isUnique() != $this->isUnique()) { return false; } return true; } return false; } /** * Detects if the other index is a non-unique, non primary index that can be overwritten by this one. * * @param Index $other * * @return boolean */ public function overrules(Index $other) { if ($other->isPrimary()) { return false; } elseif ($this->isSimpleIndex() && $other->isUnique()) { return false; } if ($this->spansColumns($other->getColumns()) && ($this->isPrimary() || $this->isUnique()) && $this->samePartialIndex($other)) { return true; } return false; } /** * Returns platform specific flags for indexes. * * @return string[] */ public function getFlags() { return array_keys($this->_flags); } /** * Adds Flag for an index that translates to platform specific handling. * * @example $index->addFlag('CLUSTERED') * * @param string $flag * * @return Index */ public function addFlag($flag) { $this->_flags[strtolower($flag)] = true; return $this; } /** * Does this index have a specific flag? * * @param string $flag * * @return boolean */ public function hasFlag($flag) { return isset($this->_flags[strtolower($flag)]); } /** * Removes a flag. * * @param string $flag * * @return void */ public function removeFlag($flag) { unset($this->_flags[strtolower($flag)]); } /** * @param string $name * * @return boolean */ public function hasOption($name) { return isset($this->options[strtolower($name)]); } /** * @param string $name * * @return mixed */ public function getOption($name) { return $this->options[strtolower($name)]; } /** * @return array */ public function getOptions() { return $this->options; } /** * Return whether the two indexes have the same partial index * @param \Doctrine\DBAL\Schema\Index $other * * @return boolean */ private function samePartialIndex(Index $other) { if ($this->hasOption('where') && $other->hasOption('where') && $this->getOption('where') == $other->getOption('where')) { return true; } if ( ! $this->hasOption('where') && ! $other->hasOption('where')) { return true; } return false; } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php000066400000000000000000000204311313473450000231150ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Platforms\MySqlPlatform; use Doctrine\DBAL\Types\Type; /** * Schema manager for the MySql RDBMS. * * @author Konsta Vesterinen * @author Lukas Smith (PEAR MDB2 library) * @author Roman Borschel * @author Benjamin Eberlei * @since 2.0 */ class MySqlSchemaManager extends AbstractSchemaManager { /** * {@inheritdoc} */ protected function _getPortableViewDefinition($view) { return new View($view['TABLE_NAME'], $view['VIEW_DEFINITION']); } /** * {@inheritdoc} */ protected function _getPortableTableDefinition($table) { return array_shift($table); } /** * {@inheritdoc} */ protected function _getPortableUserDefinition($user) { return array( 'user' => $user['User'], 'password' => $user['Password'], ); } /** * {@inheritdoc} */ 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; } if (strpos($v['index_type'], 'FULLTEXT') !== false) { $v['flags'] = array('FULLTEXT'); } elseif (strpos($v['index_type'], 'SPATIAL') !== false) { $v['flags'] = array('SPATIAL'); } $tableIndexes[$k] = $v; } return parent::_getPortableTableIndexesList($tableIndexes, $tableName); } /** * {@inheritdoc} */ protected function _getPortableSequenceDefinition($sequence) { return end($sequence); } /** * {@inheritdoc} */ protected function _getPortableDatabaseDefinition($database) { return $database['Database']; } /** * {@inheritdoc} */ 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']; } else { $length = strtok('(), '); } $fixed = null; if ( ! isset($tableColumn['name'])) { $tableColumn['name'] = ''; } $scale = null; $precision = null; $type = $this->_platform->getDoctrineTypeMapping($dbType); // In cases where not connected to a database DESCRIBE $table does not return 'Comment' if (isset($tableColumn['comment'])) { $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type); $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type); } switch ($dbType) { case 'char': case 'binary': $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 'tinytext': $length = MySqlPlatform::LENGTH_LIMIT_TINYTEXT; break; case 'text': $length = MySqlPlatform::LENGTH_LIMIT_TEXT; break; case 'mediumtext': $length = MySqlPlatform::LENGTH_LIMIT_MEDIUMTEXT; break; case 'tinyblob': $length = MySqlPlatform::LENGTH_LIMIT_TINYBLOB; break; case 'blob': $length = MySqlPlatform::LENGTH_LIMIT_BLOB; break; case 'mediumblob': $length = MySqlPlatform::LENGTH_LIMIT_MEDIUMBLOB; break; case 'tinyint': case 'smallint': case 'mediumint': case 'int': case 'integer': case 'bigint': case 'year': $length = null; break; } $length = ((int) $length == 0) ? null : (int) $length; $options = array( 'length' => $length, 'unsigned' => (bool) (strpos($tableColumn['type'], 'unsigned') !== false), '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'] !== '' ? $tableColumn['comment'] : null, ); if ($scale !== null && $precision !== null) { $options['scale'] = $scale; $options['precision'] = $precision; } $column = new Column($tableColumn['field'], Type::getType($type), $options); if (isset($tableColumn['collation'])) { $column->setPlatformOption('collation', $tableColumn['collation']); } return $column; } /** * {@inheritdoc} */ protected function _getPortableTableForeignKeysList($tableForeignKeys) { $list = array(); foreach ($tableForeignKeys as $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; } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/OracleSchemaManager.php000066400000000000000000000324411313473450000232610ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver\DriverException; use Doctrine\DBAL\Types\Type; /** * Oracle Schema Manager. * * @author Konsta Vesterinen * @author Lukas Smith (PEAR MDB2 library) * @author Benjamin Eberlei * @since 2.0 */ class OracleSchemaManager extends AbstractSchemaManager { /** * {@inheritdoc} */ public function dropDatabase($database) { try { parent::dropDatabase($database); } catch (DBALException $exception) { $exception = $exception->getPrevious(); if (! $exception instanceof DriverException) { throw $exception; } // If we have a error code 1940 (ORA-01940), the drop database operation failed // because of active connections on the database. // To force dropping the database, we first have to close all active connections // on that database and issue the drop database operation again. if ($exception->getErrorCode() !== 1940) { throw $exception; } $this->killUserSessions($database); parent::dropDatabase($database); } } /** * {@inheritdoc} */ protected function _getPortableViewDefinition($view) { $view = \array_change_key_case($view, CASE_LOWER); return new View($this->getQuotedIdentifierName($view['view_name']), $view['text']); } /** * {@inheritdoc} */ protected function _getPortableUserDefinition($user) { $user = \array_change_key_case($user, CASE_LOWER); return array( 'user' => $user['username'], ); } /** * {@inheritdoc} */ protected function _getPortableTableDefinition($table) { $table = \array_change_key_case($table, CASE_LOWER); return $this->getQuotedIdentifierName($table['table_name']); } /** * {@inheritdoc} * * @license New BSD License * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html */ 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'] = $this->getQuotedIdentifierName($tableIndex['column_name']); $indexBuffer[] = $buffer; } return parent::_getPortableTableIndexesList($indexBuffer, $tableName); } /** * {@inheritdoc} */ 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"; } } $unsigned = $fixed = null; if ( ! isset($tableColumn['column_name'])) { $tableColumn['column_name'] = ''; } // Default values returned from database sometimes have trailing spaces. $tableColumn['data_default'] = trim($tableColumn['data_default']); if ($tableColumn['data_default'] === '' || $tableColumn['data_default'] === 'NULL') { $tableColumn['data_default'] = null; } if (null !== $tableColumn['data_default']) { // Default values returned from database are enclosed in single quotes. $tableColumn['data_default'] = trim($tableColumn['data_default'], "'"); } $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': case 'binary_float': case 'binary_double': $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'] ? $tableColumn['comments'] : null, 'platformDetails' => array(), ); return new Column($this->getQuotedIdentifierName($tableColumn['column_name']), Type::getType($type), $options); } /** * {@inheritdoc} */ protected function _getPortableTableForeignKeysList($tableForeignKeys) { $list = array(); foreach ($tableForeignKeys as $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' => $this->getQuotedIdentifierName($value['constraint_name']), 'local' => array(), 'foreign' => array(), 'foreignTable' => $value['references_table'], 'onDelete' => $value['delete_rule'], ); } $localColumn = $this->getQuotedIdentifierName($value['local_column']); $foreignColumn = $this->getQuotedIdentifierName($value['foreign_column']); $list[$value['constraint_name']]['local'][$value['position']] = $localColumn; $list[$value['constraint_name']]['foreign'][$value['position']] = $foreignColumn; } $result = array(); foreach ($list as $constraint) { $result[] = new ForeignKeyConstraint( array_values($constraint['local']), $this->getQuotedIdentifierName($constraint['foreignTable']), array_values($constraint['foreign']), $this->getQuotedIdentifierName($constraint['name']), array('onDelete' => $constraint['onDelete']) ); } return $result; } /** * {@inheritdoc} */ protected function _getPortableSequenceDefinition($sequence) { $sequence = \array_change_key_case($sequence, CASE_LOWER); return new Sequence( $this->getQuotedIdentifierName($sequence['sequence_name']), $sequence['increment_by'], $sequence['min_value'] ); } /** * {@inheritdoc} */ protected function _getPortableFunctionDefinition($function) { $function = \array_change_key_case($function, CASE_LOWER); return $function['name']; } /** * {@inheritdoc} */ protected function _getPortableDatabaseDefinition($database) { $database = \array_change_key_case($database, CASE_LOWER); return $database['username']; } /** * {@inheritdoc} */ 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; $this->_conn->executeUpdate($query); $query = 'GRANT DBA TO ' . $username; $this->_conn->executeUpdate($query); return true; } /** * @param string $table * * @return boolean */ public function dropAutoincrement($table) { $sql = $this->_platform->getDropAutoincrementSql($table); foreach ($sql as $query) { $this->_conn->executeUpdate($query); } return true; } /** * {@inheritdoc} */ public function dropTable($name) { $this->tryMethod('dropAutoincrement', $name); parent::dropTable($name); } /** * Returns the quoted representation of the given identifier name. * * Quotes non-uppercase identifiers explicitly to preserve case * and thus make references to the particular identifier work. * * @param string $identifier The identifier to quote. * * @return string The quoted identifier. */ private function getQuotedIdentifierName($identifier) { if (preg_match('/[a-z]/', $identifier)) { return $this->_platform->quoteIdentifier($identifier); } return $identifier; } /** * Kills sessions connected with the given user. * * This is useful to force DROP USER operations which could fail because of active user sessions. * * @param string $user The name of the user to kill sessions for. * * @return void */ private function killUserSessions($user) { $sql = <<_conn->fetchAll($sql, array(strtoupper($user))); foreach ($activeUserSessions as $activeUserSession) { $activeUserSession = array_change_key_case($activeUserSession, \CASE_LOWER); $this->_execSql( sprintf( "ALTER SYSTEM KILL SESSION '%s, %s' IMMEDIATE", $activeUserSession['sid'], $activeUserSession['serial#'] ) ); } } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php000066400000000000000000000336561313473450000241700ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Exception\DriverException; use Doctrine\DBAL\Types\Type; /** * PostgreSQL Schema Manager. * * @author Konsta Vesterinen * @author Lukas Smith (PEAR MDB2 library) * @author Benjamin Eberlei * @since 2.0 */ class PostgreSqlSchemaManager extends AbstractSchemaManager { /** * @var array */ private $existingSchemaPaths; /** * Gets 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); } /** * Returns 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 array_map('trim', $schema); } /** * Gets 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; } /** * Sets or resets the order of the existing schemas in the current search path of the user. * * This is a PostgreSQL only function. * * @return void */ public function determineExistingSchemaSearchPaths() { $names = $this->getSchemaNames(); $paths = $this->getSchemaSearchPaths(); $this->existingSchemaPaths = array_filter($paths, function ($v) use ($names) { return in_array($v, $names); }); } /** * {@inheritdoc} */ public function dropDatabase($database) { try { parent::dropDatabase($database); } catch (DriverException $exception) { // If we have a SQLSTATE 55006, the drop database operation failed // because of active connections on the database. // To force dropping the database, we first have to close all active connections // on that database and issue the drop database operation again. if ($exception->getSQLState() !== '55006') { throw $exception; } $this->_execSql( array( $this->_platform->getDisallowDatabaseConnectionsSQL($database), $this->_platform->getCloseActiveDatabaseConnectionsSQL($database), ) ); parent::dropDatabase($database); } } /** * {@inheritdoc} */ 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) ); } /** * {@inheritdoc} */ protected function _getPortableTriggerDefinition($trigger) { return $trigger['trigger_name']; } /** * {@inheritdoc} */ protected function _getPortableViewDefinition($view) { return new View($view['schemaname'].'.'.$view['viewname'], $view['definition']); } /** * {@inheritdoc} */ protected function _getPortableUserDefinition($user) { return array( 'user' => $user['usename'], 'password' => $user['passwd'] ); } /** * {@inheritdoc} */ 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']; } } /** * {@inheritdoc} * * @license New BSD License * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html */ 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'], 'where' => $row['where'], ); } } } } return parent::_getPortableTableIndexesList($buffer, $tableName); } /** * {@inheritdoc} */ protected function _getPortableDatabaseDefinition($database) { return $database['datname']; } /** * {@inheritdoc} */ protected function _getPortableSequencesList($sequences) { $sequenceDefinitions = array(); foreach ($sequences as $sequence) { if ($sequence['schemaname'] != 'public') { $sequenceName = $sequence['schemaname'] . "." . $sequence['relname']; } else { $sequenceName = $sequence['relname']; } $sequenceDefinitions[$sequenceName] = $sequence; } $list = array(); foreach ($this->filterAssetNames(array_keys($sequenceDefinitions)) as $sequenceName) { $list[] = $this->_getPortableSequenceDefinition($sequenceDefinitions[$sequenceName]); } return $list; } /** * {@inheritdoc} */ protected function getPortableNamespaceDefinition(array $namespace) { return $namespace['nspname']; } /** * {@inheritdoc} */ 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 ' . $this->_platform->quoteIdentifier($sequenceName)); return new Sequence($sequenceName, $data[0]['increment_by'], $data[0]['min_value']); } /** * {@inheritdoc} */ protected function _getPortableTableColumnDefinition($tableColumn) { $tableColumn = array_change_key_case($tableColumn, CASE_LOWER); if (strtolower($tableColumn['type']) === 'varchar' || strtolower($tableColumn['type']) === 'bpchar') { // 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 (preg_match("/^'(.*)'::.*$/", $tableColumn['default'], $matches)) { $tableColumn['default'] = $matches[1]; } 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': if ($tableColumn['default'] === 'true') { $tableColumn['default'] = true; } if ($tableColumn['default'] === 'false') { $tableColumn['default'] = false; } $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' => isset($tableColumn['comment']) && $tableColumn['comment'] !== '' ? $tableColumn['comment'] : null, ); $column = new Column($tableColumn['field'], Type::getType($type), $options); if (isset($tableColumn['collation']) && !empty($tableColumn['collation'])) { $column->setPlatformOption('collation', $tableColumn['collation']); } return $column; } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/SQLAnywhereSchemaManager.php000066400000000000000000000177061313473450000242250ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Types\Type; /** * SAP Sybase SQL Anywhere schema manager. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ class SQLAnywhereSchemaManager extends AbstractSchemaManager { /** * {@inheritdoc} * * Starts a database after creation * as SQL Anywhere needs a database to be started * before it can be used. * * @see startDatabase */ public function createDatabase($database) { parent::createDatabase($database); $this->startDatabase($database); } /** * {@inheritdoc} * * Tries stopping a database before dropping * as SQL Anywhere needs a database to be stopped * before it can be dropped. * * @see stopDatabase */ public function dropDatabase($database) { $this->tryMethod('stopDatabase', $database); parent::dropDatabase($database); } /** * Starts a database. * * @param string $database The name of the database to start. */ public function startDatabase($database) { $this->_execSql($this->_platform->getStartDatabaseSQL($database)); } /** * Stops a database. * * @param string $database The name of the database to stop. */ public function stopDatabase($database) { $this->_execSql($this->_platform->getStopDatabaseSQL($database)); } /** * {@inheritdoc} */ protected function _getPortableDatabaseDefinition($database) { return $database['name']; } /** * {@inheritdoc} */ protected function _getPortableSequenceDefinition($sequence) { return new Sequence($sequence['sequence_name'], $sequence['increment_by'], $sequence['start_with']); } /** * {@inheritdoc} */ protected function _getPortableTableColumnDefinition($tableColumn) { $type = $this->_platform->getDoctrineTypeMapping($tableColumn['type']); $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type); $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type); $precision = null; $scale = null; $fixed = false; $default = null; if (null !== $tableColumn['default']) { // Strip quotes from default value. $default = preg_replace(array("/^'(.*)'$/", "/''/"), array("$1", "'"), $tableColumn['default']); if ('autoincrement' == $default) { $default = null; } } switch ($tableColumn['type']) { case 'binary': case 'char': case 'nchar': $fixed = true; } switch ($type) { case 'decimal': case 'float': $precision = $tableColumn['length']; $scale = $tableColumn['scale']; } return new Column( $tableColumn['column_name'], Type::getType($type), array( 'length' => $type == 'string' ? $tableColumn['length'] : null, 'precision' => $precision, 'scale' => $scale, 'unsigned' => (bool) $tableColumn['unsigned'], 'fixed' => $fixed, 'notnull' => (bool) $tableColumn['notnull'], 'default' => $default, 'autoincrement' => (bool) $tableColumn['autoincrement'], 'comment' => isset($tableColumn['comment']) && '' !== $tableColumn['comment'] ? $tableColumn['comment'] : null, )); } /** * {@inheritdoc} */ protected function _getPortableTableDefinition($table) { return $table['table_name']; } /** * {@inheritdoc} */ protected function _getPortableTableForeignKeyDefinition($tableForeignKey) { return new ForeignKeyConstraint( $tableForeignKey['local_columns'], $tableForeignKey['foreign_table'], $tableForeignKey['foreign_columns'], $tableForeignKey['name'], $tableForeignKey['options'] ); } /** * {@inheritdoc} */ protected function _getPortableTableForeignKeysList($tableForeignKeys) { $foreignKeys = array(); foreach ($tableForeignKeys as $tableForeignKey) { if (!isset($foreignKeys[$tableForeignKey['index_name']])) { $foreignKeys[$tableForeignKey['index_name']] = array( 'local_columns' => array($tableForeignKey['local_column']), 'foreign_table' => $tableForeignKey['foreign_table'], 'foreign_columns' => array($tableForeignKey['foreign_column']), 'name' => $tableForeignKey['index_name'], 'options' => array( 'notnull' => $tableForeignKey['notnull'], 'match' => $tableForeignKey['match'], 'onUpdate' => $tableForeignKey['on_update'], 'onDelete' => $tableForeignKey['on_delete'], 'check_on_commit' => $tableForeignKey['check_on_commit'], 'clustered' => $tableForeignKey['clustered'], 'for_olap_workload' => $tableForeignKey['for_olap_workload'] ) ); } else { $foreignKeys[$tableForeignKey['index_name']]['local_columns'][] = $tableForeignKey['local_column']; $foreignKeys[$tableForeignKey['index_name']]['foreign_columns'][] = $tableForeignKey['foreign_column']; } } return parent::_getPortableTableForeignKeysList($foreignKeys); } /** * {@inheritdoc} */ protected function _getPortableTableIndexesList($tableIndexRows, $tableName = null) { foreach ($tableIndexRows as &$tableIndex) { $tableIndex['primary'] = (boolean) $tableIndex['primary']; $tableIndex['flags'] = array(); if ($tableIndex['clustered']) { $tableIndex['flags'][] = 'clustered'; } if ($tableIndex['with_nulls_not_distinct']) { $tableIndex['flags'][] = 'with_nulls_not_distinct'; } if ($tableIndex['for_olap_workload']) { $tableIndex['flags'][] = 'for_olap_workload'; } } return parent::_getPortableTableIndexesList($tableIndexRows, $tableName); } /** * {@inheritdoc} */ protected function _getPortableViewDefinition($view) { return new View( $view['table_name'], preg_replace('/^.*\s+as\s+SELECT(.*)/i', "SELECT$1", $view['view_def']) ); } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/SQLServerSchemaManager.php000066400000000000000000000250231313473450000237000ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver\DriverException; use Doctrine\DBAL\Types\Type; /** * SQL Server Schema Manager. * * @license http://www.opensource.org/licenses/mit-license.php MIT * @author Konsta Vesterinen * @author Lukas Smith (PEAR MDB2 library) * @author Juozas Kaziukenas * @author Steve Müller * @since 2.0 */ class SQLServerSchemaManager extends AbstractSchemaManager { /** * {@inheritdoc} */ public function dropDatabase($database) { try { parent::dropDatabase($database); } catch (DBALException $exception) { $exception = $exception->getPrevious(); if (! $exception instanceof DriverException) { throw $exception; } // If we have a error code 3702, the drop database operation failed // because of active connections on the database. // To force dropping the database, we first have to close all active connections // on that database and issue the drop database operation again. if ($exception->getErrorCode() !== 3702) { throw $exception; } $this->closeActiveDatabaseConnections($database); parent::dropDatabase($database); } } /** * {@inheritdoc} */ protected function _getPortableSequenceDefinition($sequence) { return new Sequence($sequence['name'], $sequence['increment'], $sequence['start_value']); } /** * {@inheritdoc} */ protected function _getPortableTableColumnDefinition($tableColumn) { $dbType = strtok($tableColumn['type'], '(), '); $fixed = null; $length = (int) $tableColumn['length']; $default = $tableColumn['default']; if (!isset($tableColumn['name'])) { $tableColumn['name'] = ''; } while ($default != ($default2 = preg_replace("/^\((.*)\)$/", '$1', $default))) { $default = trim($default2, "'"); if ($default == 'getdate()') { $default = $this->_platform->getCurrentTimestampSQL(); } } switch ($dbType) { case 'nchar': case 'nvarchar': case 'ntext': // Unicode data requires 2 bytes per character $length = $length / 2; break; case 'varchar': // TEXT type is returned as VARCHAR(MAX) with a length of -1 if ($length == -1) { $dbType = 'text'; } break; } if ('char' === $dbType || 'nchar' === $dbType || 'binary' === $dbType) { $fixed = true; } $type = $this->_platform->getDoctrineTypeMapping($dbType); $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type); $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type); $options = array( 'length' => ($length == 0 || !in_array($type, array('text', 'string'))) ? null : $length, 'unsigned' => false, 'fixed' => (bool) $fixed, 'default' => $default !== 'NULL' ? $default : null, 'notnull' => (bool) $tableColumn['notnull'], 'scale' => $tableColumn['scale'], 'precision' => $tableColumn['precision'], 'autoincrement' => (bool) $tableColumn['autoincrement'], 'comment' => $tableColumn['comment'] !== '' ? $tableColumn['comment'] : null, ); $column = new Column($tableColumn['name'], Type::getType($type), $options); if (isset($tableColumn['collation']) && $tableColumn['collation'] !== 'NULL') { $column->setPlatformOption('collation', $tableColumn['collation']); } return $column; } /** * {@inheritdoc} */ protected function _getPortableTableForeignKeysList($tableForeignKeys) { $foreignKeys = array(); foreach ($tableForeignKeys as $tableForeignKey) { if ( ! isset($foreignKeys[$tableForeignKey['ForeignKey']])) { $foreignKeys[$tableForeignKey['ForeignKey']] = array( 'local_columns' => array($tableForeignKey['ColumnName']), 'foreign_table' => $tableForeignKey['ReferenceTableName'], 'foreign_columns' => array($tableForeignKey['ReferenceColumnName']), 'name' => $tableForeignKey['ForeignKey'], 'options' => array( 'onUpdate' => str_replace('_', ' ', $tableForeignKey['update_referential_action_desc']), 'onDelete' => str_replace('_', ' ', $tableForeignKey['delete_referential_action_desc']) ) ); } else { $foreignKeys[$tableForeignKey['ForeignKey']]['local_columns'][] = $tableForeignKey['ColumnName']; $foreignKeys[$tableForeignKey['ForeignKey']]['foreign_columns'][] = $tableForeignKey['ReferenceColumnName']; } } return parent::_getPortableTableForeignKeysList($foreignKeys); } /** * {@inheritdoc} */ protected function _getPortableTableIndexesList($tableIndexRows, $tableName=null) { foreach ($tableIndexRows as &$tableIndex) { $tableIndex['non_unique'] = (boolean) $tableIndex['non_unique']; $tableIndex['primary'] = (boolean) $tableIndex['primary']; $tableIndex['flags'] = $tableIndex['flags'] ? array($tableIndex['flags']) : null; } return parent::_getPortableTableIndexesList($tableIndexRows, $tableName); } /** * {@inheritdoc} */ protected function _getPortableTableForeignKeyDefinition($tableForeignKey) { return new ForeignKeyConstraint( $tableForeignKey['local_columns'], $tableForeignKey['foreign_table'], $tableForeignKey['foreign_columns'], $tableForeignKey['name'], $tableForeignKey['options'] ); } /** * {@inheritdoc} */ protected function _getPortableTableDefinition($table) { return $table['name']; } /** * {@inheritdoc} */ protected function _getPortableDatabaseDefinition($database) { return $database['name']; } /** * {@inheritdoc} */ protected function getPortableNamespaceDefinition(array $namespace) { return $namespace['name']; } /** * {@inheritdoc} */ protected function _getPortableViewDefinition($view) { // @todo return new View($view['name'], null); } /** * {@inheritdoc} */ 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; } } catch (DBALException $e) { if (strpos($e->getMessage(), 'SQLSTATE [01000, 15472]') === 0) { return array(); } else { throw $e; } } return $this->_getPortableTableIndexesList($tableIndexes, $table); } /** * {@inheritdoc} */ 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']); } } } parent::alterTable($tableDiff); } /** * Returns the SQL to retrieve the constraints for a given column. * * @param string $table * @param string $column * * @return string */ 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]"; } /** * Closes currently active connections on the given database. * * This is useful to force DROP DATABASE operations which could fail because of active connections. * * @param string $database The name of the database to close currently active connections for. * * @return void */ private function closeActiveDatabaseConnections($database) { $database = new Identifier($database); $this->_execSql( sprintf( 'ALTER DATABASE %s SET SINGLE_USER WITH ROLLBACK IMMEDIATE', $database->getQuotedName($this->_platform) ) ); } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/Schema.php000066400000000000000000000336621313473450000206460ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Schema\Visitor\CreateSchemaSqlCollector; use Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector; use Doctrine\DBAL\Schema\Visitor\NamespaceVisitor; use Doctrine\DBAL\Schema\Visitor\Visitor; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * 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. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ class Schema extends AbstractAsset { /** * The namespaces in this schema. * * @var array */ private $namespaces = array(); /** * @var \Doctrine\DBAL\Schema\Table[] */ protected $_tables = array(); /** * @var \Doctrine\DBAL\Schema\Sequence[] */ protected $_sequences = array(); /** * @var \Doctrine\DBAL\Schema\SchemaConfig */ protected $_schemaConfig = false; /** * @param \Doctrine\DBAL\Schema\Table[] $tables * @param \Doctrine\DBAL\Schema\Sequence[] $sequences * @param \Doctrine\DBAL\Schema\SchemaConfig $schemaConfig * @param array $namespaces */ public function __construct( array $tables = array(), array $sequences = array(), SchemaConfig $schemaConfig = null, array $namespaces = array() ) { if ($schemaConfig == null) { $schemaConfig = new SchemaConfig(); } $this->_schemaConfig = $schemaConfig; $this->_setName($schemaConfig->getName() ?: 'public'); foreach ($namespaces as $namespace) { $this->createNamespace($namespace); } foreach ($tables as $table) { $this->_addTable($table); } foreach ($sequences as $sequence) { $this->_addSequence($sequence); } } /** * @return boolean */ public function hasExplicitForeignKeyIndexes() { return $this->_schemaConfig->hasExplicitForeignKeyIndexes(); } /** * @param \Doctrine\DBAL\Schema\Table $table * * @return void * * @throws \Doctrine\DBAL\Schema\SchemaException */ protected function _addTable(Table $table) { $namespaceName = $table->getNamespaceName(); $tableName = $table->getFullQualifiedName($this->getName()); if (isset($this->_tables[$tableName])) { throw SchemaException::tableAlreadyExists($tableName); } if ( ! $table->isInDefaultNamespace($this->getName()) && ! $this->hasNamespace($namespaceName)) { $this->createNamespace($namespaceName); } $this->_tables[$tableName] = $table; $table->setSchemaConfig($this->_schemaConfig); } /** * @param \Doctrine\DBAL\Schema\Sequence $sequence * * @return void * * @throws \Doctrine\DBAL\Schema\SchemaException */ protected function _addSequence(Sequence $sequence) { $namespaceName = $sequence->getNamespaceName(); $seqName = $sequence->getFullQualifiedName($this->getName()); if (isset($this->_sequences[$seqName])) { throw SchemaException::sequenceAlreadyExists($seqName); } if ( ! $sequence->isInDefaultNamespace($this->getName()) && ! $this->hasNamespace($namespaceName)) { $this->createNamespace($namespaceName); } $this->_sequences[$seqName] = $sequence; } /** * Returns the namespaces of this schema. * * @return array A list of namespace names. */ public function getNamespaces() { return $this->namespaces; } /** * Gets all tables of this schema. * * @return \Doctrine\DBAL\Schema\Table[] */ public function getTables() { return $this->_tables; } /** * @param string $tableName * * @return \Doctrine\DBAL\Schema\Table * * @throws \Doctrine\DBAL\Schema\SchemaException */ public function getTable($tableName) { $tableName = $this->getFullQualifiedAssetName($tableName); if (!isset($this->_tables[$tableName])) { throw SchemaException::tableDoesNotExist($tableName); } return $this->_tables[$tableName]; } /** * @param string $name * * @return string */ private function getFullQualifiedAssetName($name) { $name = $this->getUnquotedAssetName($name); if (strpos($name, ".") === false) { $name = $this->getName() . "." . $name; } return strtolower($name); } /** * Returns the unquoted representation of a given asset name. * * @param string $assetName Quoted or unquoted representation of an asset name. * * @return string */ private function getUnquotedAssetName($assetName) { if ($this->isIdentifierQuoted($assetName)) { return $this->trimQuotes($assetName); } return $assetName; } /** * Does this schema have a namespace with the given name? * * @param string $namespaceName * * @return boolean */ public function hasNamespace($namespaceName) { $namespaceName = strtolower($this->getUnquotedAssetName($namespaceName)); return isset($this->namespaces[$namespaceName]); } /** * Does this schema have a table with the given name? * * @param string $tableName * * @return boolean */ public function hasTable($tableName) { $tableName = $this->getFullQualifiedAssetName($tableName); return isset($this->_tables[$tableName]); } /** * Gets all table names, prefixed with a schema name, even the default one if present. * * @return array */ public function getTableNames() { return array_keys($this->_tables); } /** * @param string $sequenceName * * @return boolean */ public function hasSequence($sequenceName) { $sequenceName = $this->getFullQualifiedAssetName($sequenceName); return isset($this->_sequences[$sequenceName]); } /** * @param string $sequenceName * * @return \Doctrine\DBAL\Schema\Sequence * * @throws \Doctrine\DBAL\Schema\SchemaException */ 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; } /** * Creates a new namespace. * * @param string $namespaceName The name of the namespace to create. * * @return \Doctrine\DBAL\Schema\Schema This schema instance. */ public function createNamespace($namespaceName) { $unquotedNamespaceName = strtolower($this->getUnquotedAssetName($namespaceName)); if (isset($this->namespaces[$unquotedNamespaceName])) { throw SchemaException::namespaceAlreadyExists($unquotedNamespaceName); } $this->namespaces[$unquotedNamespaceName] = $namespaceName; return $this; } /** * Creates a new table. * * @param string $tableName * * @return \Doctrine\DBAL\Schema\Table */ public function createTable($tableName) { $table = new Table($tableName); $this->_addTable($table); foreach ($this->_schemaConfig->getDefaultTableOptions() as $name => $value) { $table->addOption($name, $value); } return $table; } /** * Renames a table. * * @param string $oldTableName * @param string $newTableName * * @return \Doctrine\DBAL\Schema\Schema */ public function renameTable($oldTableName, $newTableName) { $table = $this->getTable($oldTableName); $table->_setName($newTableName); $this->dropTable($oldTableName); $this->_addTable($table); return $this; } /** * Drops a table from the schema. * * @param string $tableName * * @return \Doctrine\DBAL\Schema\Schema */ public function dropTable($tableName) { $tableName = $this->getFullQualifiedAssetName($tableName); $this->getTable($tableName); unset($this->_tables[$tableName]); return $this; } /** * Creates a new sequence. * * @param string $sequenceName * @param integer $allocationSize * @param integer $initialValue * * @return \Doctrine\DBAL\Schema\Sequence */ public function createSequence($sequenceName, $allocationSize=1, $initialValue=1) { $seq = new Sequence($sequenceName, $allocationSize, $initialValue); $this->_addSequence($seq); return $seq; } /** * @param string $sequenceName * * @return \Doctrine\DBAL\Schema\Schema */ public function dropSequence($sequenceName) { $sequenceName = $this->getFullQualifiedAssetName($sequenceName); unset($this->_sequences[$sequenceName]); return $this; } /** * Returns an array of necessary SQL queries to create the schema on the given platform. * * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform * * @return array */ public function toSql(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 \Doctrine\DBAL\Platforms\AbstractPlatform $platform * * @return array */ public function toDropSql(AbstractPlatform $platform) { $dropSqlCollector = new DropSchemaSqlCollector($platform); $this->visit($dropSqlCollector); return $dropSqlCollector->getQueries(); } /** * @param \Doctrine\DBAL\Schema\Schema $toSchema * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform * * @return array */ public function getMigrateToSql(Schema $toSchema, AbstractPlatform $platform) { $comparator = new Comparator(); $schemaDiff = $comparator->compare($this, $toSchema); return $schemaDiff->toSql($platform); } /** * @param \Doctrine\DBAL\Schema\Schema $fromSchema * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform * * @return array */ public function getMigrateFromSql(Schema $fromSchema, AbstractPlatform $platform) { $comparator = new Comparator(); $schemaDiff = $comparator->compare($fromSchema, $this); return $schemaDiff->toSql($platform); } /** * @param \Doctrine\DBAL\Schema\Visitor\Visitor $visitor * * @return void */ public function visit(Visitor $visitor) { $visitor->acceptSchema($this); if ($visitor instanceof NamespaceVisitor) { foreach ($this->namespaces as $namespace) { $visitor->acceptNamespace($namespace); } } 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; } } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/SchemaConfig.php000066400000000000000000000057621313473450000217740ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; /** * Configuration for a Schema. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ class SchemaConfig { /** * @var boolean */ protected $hasExplicitForeignKeyIndexes = false; /** * @var integer */ protected $maxIdentifierLength = 63; /** * @var string */ protected $name; /** * @var array */ protected $defaultTableOptions = array(); /** * @return boolean */ public function hasExplicitForeignKeyIndexes() { return $this->hasExplicitForeignKeyIndexes; } /** * @param boolean $flag * * @return void */ public function setExplicitForeignKeyIndexes($flag) { $this->hasExplicitForeignKeyIndexes = (bool) $flag; } /** * @param integer $length * * @return void */ public function setMaxIdentifierLength($length) { $this->maxIdentifierLength = (int) $length; } /** * @return integer */ public function getMaxIdentifierLength() { return $this->maxIdentifierLength; } /** * Gets the default namespace of schema objects. * * @return string */ public function getName() { return $this->name; } /** * Sets the default namespace name of schema objects. * * @param string $name The value to set. * * @return void */ public function setName($name) { $this->name = $name; } /** * Gets the default options that are passed to Table instances created with * Schema#createTable(). * * @return array */ public function getDefaultTableOptions() { return $this->defaultTableOptions; } /** * @param array $defaultTableOptions * * @return void */ public function setDefaultTableOptions(array $defaultTableOptions) { $this->defaultTableOptions = $defaultTableOptions; } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/SchemaDiff.php000066400000000000000000000140201313473450000214220ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; use \Doctrine\DBAL\Platforms\AbstractPlatform; /** * Schema Diff. * * @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 * @author Benjamin Eberlei */ class SchemaDiff { /** * @var \Doctrine\DBAL\Schema\Schema */ public $fromSchema; /** * All added namespaces. * * @var string[] */ public $newNamespaces = array(); /** * All removed namespaces. * * @var string[] */ public $removedNamespaces = array(); /** * All added tables. * * @var \Doctrine\DBAL\Schema\Table[] */ public $newTables = array(); /** * All changed tables. * * @var \Doctrine\DBAL\Schema\TableDiff[] */ public $changedTables = array(); /** * All removed tables. * * @var \Doctrine\DBAL\Schema\Table[] */ public $removedTables = array(); /** * @var \Doctrine\DBAL\Schema\Sequence[] */ public $newSequences = array(); /** * @var \Doctrine\DBAL\Schema\Sequence[] */ public $changedSequences = array(); /** * @var \Doctrine\DBAL\Schema\Sequence[] */ public $removedSequences = array(); /** * @var \Doctrine\DBAL\Schema\ForeignKeyConstraint[] */ public $orphanedForeignKeys = array(); /** * Constructs an SchemaDiff object. * * @param \Doctrine\DBAL\Schema\Table[] $newTables * @param \Doctrine\DBAL\Schema\TableDiff[] $changedTables * @param \Doctrine\DBAL\Schema\Table[] $removedTables * @param \Doctrine\DBAL\Schema\Schema|null $fromSchema */ public function __construct($newTables = array(), $changedTables = array(), $removedTables = array(), Schema $fromSchema = null) { $this->newTables = $newTables; $this->changedTables = $changedTables; $this->removedTables = $removedTables; $this->fromSchema = $fromSchema; } /** * 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 \Doctrine\DBAL\Platforms\AbstractPlatform $platform * * @return array */ public function toSaveSql(AbstractPlatform $platform) { return $this->_toSql($platform, true); } /** * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform * * @return array */ public function toSql(AbstractPlatform $platform) { return $this->_toSql($platform, false); } /** * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform * @param boolean $saveMode * * @return array */ protected function _toSql(AbstractPlatform $platform, $saveMode = false) { $sql = array(); if ($platform->supportsSchemas()) { foreach ($this->newNamespaces as $newNamespace) { $sql[] = $platform->getCreateSchemaSQL($newNamespace); } } if ($platform->supportsForeignKeyConstraints() && $saveMode == false) { foreach ($this->orphanedForeignKeys as $orphanedForeignKey) { $sql[] = $platform->getDropForeignKeySQL($orphanedForeignKey, $orphanedForeignKey->getLocalTable()); } } 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; } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/SchemaException.php000066400000000000000000000136401313473450000225170ustar00rootroot00000000000000. */ 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; const NAMESPACE_ALREADY_EXISTS = 110; /** * @param string $tableName * * @return \Doctrine\DBAL\Schema\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 \Doctrine\DBAL\Schema\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 * @param string $table * * @return \Doctrine\DBAL\Schema\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 * @param string $table * * @return \Doctrine\DBAL\Schema\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 * @param string $table * * @return \Doctrine\DBAL\Schema\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 $namespaceName * * @return \Doctrine\DBAL\Schema\SchemaException */ static public function namespaceAlreadyExists($namespaceName) { return new self( sprintf("The namespace with name '%s' already exists.", $namespaceName), self::NAMESPACE_ALREADY_EXISTS ); } /** * @param string $tableName * * @return \Doctrine\DBAL\Schema\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 \Doctrine\DBAL\Schema\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 \Doctrine\DBAL\Schema\SchemaException */ static public function sequenceAlreadyExists($sequenceName) { return new self("The sequence '".$sequenceName."' already exists.", self::SEQUENCE_ALREADY_EXISTS); } /** * @param string $sequenceName * * @return \Doctrine\DBAL\Schema\SchemaException */ static public function sequenceDoesNotExist($sequenceName) { return new self("There exists no sequence with the name '".$sequenceName."'.", self::SEQUENCE_DOENST_EXIST); } /** * @param string $fkName * @param string $table * * @return \Doctrine\DBAL\Schema\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); } /** * @param \Doctrine\DBAL\Schema\Table $localTable * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey * * @return \Doctrine\DBAL\Schema\SchemaException */ 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." ); } /** * @param string $changeName * * @return \Doctrine\DBAL\Schema\SchemaException */ static public function alterTableChangeNotSupported($changeName) { return new self("Alter table change not supported, given '$changeName'"); } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/Sequence.php000066400000000000000000000104071313473450000212060ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Schema\Visitor\Visitor; /** * Sequence structure. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ class Sequence extends AbstractAsset { /** * @var integer */ protected $allocationSize = 1; /** * @var integer */ protected $initialValue = 1; /** * @var integer|null */ protected $cache = null; /** * @param string $name * @param integer $allocationSize * @param integer $initialValue * @param integer|null $cache */ public function __construct($name, $allocationSize = 1, $initialValue = 1, $cache = null) { $this->_setName($name); $this->allocationSize = is_numeric($allocationSize) ? $allocationSize : 1; $this->initialValue = is_numeric($initialValue) ? $initialValue : 1; $this->cache = $cache; } /** * @return integer */ public function getAllocationSize() { return $this->allocationSize; } /** * @return integer */ public function getInitialValue() { return $this->initialValue; } /** * @return integer|null */ public function getCache() { return $this->cache; } /** * @param integer $allocationSize * * @return \Doctrine\DBAL\Schema\Sequence */ public function setAllocationSize($allocationSize) { $this->allocationSize = is_numeric($allocationSize) ? $allocationSize : 1; return $this; } /** * @param integer $initialValue * * @return \Doctrine\DBAL\Schema\Sequence */ public function setInitialValue($initialValue) { $this->initialValue = is_numeric($initialValue) ? $initialValue : 1; return $this; } /** * @param integer $cache * * @return \Doctrine\DBAL\Schema\Sequence */ public function setCache($cache) { $this->cache = $cache; return $this; } /** * Checks if this sequence is an autoincrement sequence for a given table. * * This is used inside the comparator to not report sequences as missing, * when the "from" schema implicitly creates the sequences. * * @param \Doctrine\DBAL\Schema\Table $table * * @return boolean */ public function isAutoIncrementsFor(Table $table) { if ( ! $table->hasPrimaryKey()) { return false; } $pkColumns = $table->getPrimaryKey()->getColumns(); if (count($pkColumns) != 1) { return false; } $column = $table->getColumn($pkColumns[0]); if ( ! $column->getAutoincrement()) { return false; } $sequenceName = $this->getShortestName($table->getNamespaceName()); $tableName = $table->getShortestName($table->getNamespaceName()); $tableSequenceName = sprintf('%s_%s_seq', $tableName, $column->getShortestName($table->getNamespaceName())); return $tableSequenceName === $sequenceName; } /** * @param \Doctrine\DBAL\Schema\Visitor\Visitor $visitor * * @return void */ public function visit(Visitor $visitor) { $visitor->acceptSequence($this); } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php000066400000000000000000000346001313473450000233140ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Types\StringType; use Doctrine\DBAL\Types\TextType; /** * Sqlite SchemaManager. * * @author Konsta Vesterinen * @author Lukas Smith (PEAR MDB2 library) * @author Jonathan H. Wage * @author Martin Hasoň * @since 2.0 */ class SqliteSchemaManager extends AbstractSchemaManager { /** * {@inheritdoc} */ public function dropDatabase($database) { if (file_exists($database)) { unlink($database); } } /** * {@inheritdoc} */ 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(); } /** * {@inheritdoc} */ public function renameTable($name, $newName) { $tableDiff = new TableDiff($name); $tableDiff->fromTable = $this->listTableDetails($name); $tableDiff->newName = $newName; $this->alterTable($tableDiff); } /** * {@inheritdoc} */ public function createForeignKey(ForeignKeyConstraint $foreignKey, $table) { $tableDiff = $this->getTableDiffForAlterForeignKey($foreignKey, $table); $tableDiff->addedForeignKeys[] = $foreignKey; $this->alterTable($tableDiff); } /** * {@inheritdoc} */ public function dropAndCreateForeignKey(ForeignKeyConstraint $foreignKey, $table) { $tableDiff = $this->getTableDiffForAlterForeignKey($foreignKey, $table); $tableDiff->changedForeignKeys[] = $foreignKey; $this->alterTable($tableDiff); } /** * {@inheritdoc} */ public function dropForeignKey($foreignKey, $table) { $tableDiff = $this->getTableDiffForAlterForeignKey($foreignKey, $table); $tableDiff->removedForeignKeys[] = $foreignKey; $this->alterTable($tableDiff); } /** * {@inheritdoc} */ public function listTableForeignKeys($table, $database = null) { if (null === $database) { $database = $this->_conn->getDatabase(); } $sql = $this->_platform->getListTableForeignKeysSQL($table, $database); $tableForeignKeys = $this->_conn->fetchAll($sql); if ( ! empty($tableForeignKeys)) { $createSql = $this->_conn->fetchAll("SELECT sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type = 'table' AND name = '$table'"); $createSql = isset($createSql[0]['sql']) ? $createSql[0]['sql'] : ''; if (preg_match_all('# (?:CONSTRAINT\s+([^\s]+)\s+)? (?:FOREIGN\s+KEY[^\)]+\)\s*)? REFERENCES\s+[^\s]+\s+(?:\([^\)]+\))? (?: [^,]*? (NOT\s+DEFERRABLE|DEFERRABLE) (?:\s+INITIALLY\s+(DEFERRED|IMMEDIATE))? )?#isx', $createSql, $match)) { $names = array_reverse($match[1]); $deferrable = array_reverse($match[2]); $deferred = array_reverse($match[3]); } else { $names = $deferrable = $deferred = array(); } foreach ($tableForeignKeys as $key => $value) { $id = $value['id']; $tableForeignKeys[$key]['constraint_name'] = isset($names[$id]) && '' != $names[$id] ? $names[$id] : $id; $tableForeignKeys[$key]['deferrable'] = isset($deferrable[$id]) && 'deferrable' == strtolower($deferrable[$id]) ? true : false; $tableForeignKeys[$key]['deferred'] = isset($deferred[$id]) && 'deferred' == strtolower($deferred[$id]) ? true : false; } } return $this->_getPortableTableForeignKeysList($tableForeignKeys); } /** * {@inheritdoc} */ protected function _getPortableTableDefinition($table) { return $table['name']; } /** * {@inheritdoc} * * @license New BSD License * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html */ protected function _getPortableTableIndexesList($tableIndexes, $tableName=null) { $indexBuffer = array(); // fetch primary $stmt = $this->_conn->executeQuery("PRAGMA TABLE_INFO ('$tableName')"); $indexArray = $stmt->fetchAll(\PDO::FETCH_ASSOC); usort($indexArray, function($a, $b) { if ($a['pk'] == $b['pk']) { return $a['cid'] - $b['cid']; } return $a['pk'] - $b['pk']; }); foreach ($indexArray as $indexColumnRow) { if ($indexColumnRow['pk'] != "0") { $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); } /** * {@inheritdoc} */ protected function _getPortableTableIndexDefinition($tableIndex) { return array( 'name' => $tableIndex['name'], 'unique' => (bool) $tableIndex['unique'] ); } /** * {@inheritdoc} */ protected function _getPortableTableColumnList($table, $database, $tableColumns) { $list = parent::_getPortableTableColumnList($table, $database, $tableColumns); // find column with autoincrement $autoincrementColumn = null; $autoincrementCount = 0; foreach ($tableColumns as $tableColumn) { if ('0' != $tableColumn['pk']) { $autoincrementCount++; if (null === $autoincrementColumn && 'integer' == strtolower($tableColumn['type'])) { $autoincrementColumn = $tableColumn['name']; } } } if (1 == $autoincrementCount && null !== $autoincrementColumn) { foreach ($list as $column) { if ($autoincrementColumn == $column->getName()) { $column->setAutoincrement(true); } } } // inspect column collation $createSql = $this->_conn->fetchAll("SELECT sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type = 'table' AND name = '$table'"); $createSql = isset($createSql[0]['sql']) ? $createSql[0]['sql'] : ''; foreach ($list as $columnName => $column) { $type = $column->getType(); if ($type instanceof StringType || $type instanceof TextType) { $column->setPlatformOption('collation', $this->parseColumnCollationFromSQL($columnName, $createSql) ?: 'BINARY'); } } return $list; } /** * {@inheritdoc} */ protected function _getPortableTableColumnDefinition($tableColumn) { $parts = explode('(', $tableColumn['type']); $tableColumn['type'] = trim($parts[0]); if (isset($parts[1])) { $length = trim($parts[1], ')'); $tableColumn['length'] = $length; } $dbType = strtolower($tableColumn['type']); $length = isset($tableColumn['length']) ? $tableColumn['length'] : null; $unsigned = false; if (strpos($dbType, ' unsigned') !== false) { $dbType = str_replace(' unsigned', '', $dbType); $unsigned = true; } $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'])) { if (strpos($tableColumn['length'], ',') === false) { $tableColumn['length'] .= ",0"; } 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); } /** * {@inheritdoc} */ protected function _getPortableViewDefinition($view) { return new View($view['name'], $view['sql']); } /** * {@inheritdoc} */ protected function _getPortableTableForeignKeysList($tableForeignKeys) { $list = array(); foreach ($tableForeignKeys as $value) { $value = array_change_key_case($value, CASE_LOWER); $name = $value['constraint_name']; if ( ! isset($list[$name])) { if ( ! isset($value['on_delete']) || $value['on_delete'] == "RESTRICT") { $value['on_delete'] = null; } if ( ! isset($value['on_update']) || $value['on_update'] == "RESTRICT") { $value['on_update'] = null; } $list[$name] = array( 'name' => $name, 'local' => array(), 'foreign' => array(), 'foreignTable' => $value['table'], 'onDelete' => $value['on_delete'], 'onUpdate' => $value['on_update'], 'deferrable' => $value['deferrable'], 'deferred'=> $value['deferred'], ); } $list[$name]['local'][] = $value['from']; $list[$name]['foreign'][] = $value['to']; } $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'], 'deferrable' => $constraint['deferrable'], 'deferred'=> $constraint['deferred'], ) ); } return $result; } /** * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey * @param \Doctrine\DBAL\Schema\Table|string $table * * @return \Doctrine\DBAL\Schema\TableDiff * * @throws \Doctrine\DBAL\DBALException */ private function getTableDiffForAlterForeignKey(ForeignKeyConstraint $foreignKey, $table) { if ( ! $table instanceof Table) { $tableDetails = $this->tryMethod('listTableDetails', $table); if (false === $table) { throw new DBALException(sprintf('Sqlite schema manager requires to modify foreign keys table definition "%s".', $table)); } $table = $tableDetails; } $tableDiff = new TableDiff($table->getName()); $tableDiff->fromTable = $table; return $tableDiff; } private function parseColumnCollationFromSQL($column, $sql) { if (preg_match( '{(?:'.preg_quote($column).'|'.preg_quote($this->_platform->quoteSingleIdentifier($column)).') [^,(]+(?:\([^()]+\)[^,]*)? (?:(?:DEFAULT|CHECK)\s*(?:\(.*?\))?[^,]*)* COLLATE\s+["\']?([^\s,"\')]+)}isx', $sql, $match)) { return $match[1]; } return false; } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/Synchronizer/000077500000000000000000000000001313473450000214205ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Schema/Synchronizer/AbstractSchemaSynchronizer.php000066400000000000000000000035371313473450000274430ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema\Synchronizer; use Doctrine\DBAL\Connection; /** * Abstract schema synchronizer with methods for executing batches of SQL. */ abstract class AbstractSchemaSynchronizer implements SchemaSynchronizer { /** * @var \Doctrine\DBAL\Connection */ protected $conn; /** * @param \Doctrine\DBAL\Connection $conn */ public function __construct(Connection $conn) { $this->conn = $conn; } /** * @param array $sql */ protected function processSqlSafely(array $sql) { foreach ($sql as $s) { try { $this->conn->exec($s); } catch (\Exception $e) { } } } /** * @param array $sql */ protected function processSql(array $sql) { foreach ($sql as $s) { $this->conn->exec($s); } } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/Synchronizer/SchemaSynchronizer.php000066400000000000000000000056171313473450000257600ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema\Synchronizer; use Doctrine\DBAL\Schema\Schema; /** * The synchronizer knows how to synchronize a schema with the configured * database. * * @author Benjamin Eberlei */ interface SchemaSynchronizer { /** * Gets the SQL statements that can be executed to create the schema. * * @param \Doctrine\DBAL\Schema\Schema $createSchema * * @return array */ function getCreateSchema(Schema $createSchema); /** * Gets the SQL Statements to update given schema with the underlying db. * * @param \Doctrine\DBAL\Schema\Schema $toSchema * @param boolean $noDrops * * @return array */ function getUpdateSchema(Schema $toSchema, $noDrops = false); /** * Gets the SQL Statements to drop the given schema from underlying db. * * @param \Doctrine\DBAL\Schema\Schema $dropSchema * * @return array */ function getDropSchema(Schema $dropSchema); /** * Gets the SQL statements to drop all schema assets from underlying db. * * @return array */ function getDropAllSchema(); /** * Creates the Schema. * * @param \Doctrine\DBAL\Schema\Schema $createSchema * * @return void */ function createSchema(Schema $createSchema); /** * Updates the Schema to new schema version. * * @param \Doctrine\DBAL\Schema\Schema $toSchema * @param boolean $noDrops * * @return void */ function updateSchema(Schema $toSchema, $noDrops = false); /** * Drops the given database schema from the underlying db. * * @param \Doctrine\DBAL\Schema\Schema $dropSchema * * @return void */ function dropSchema(Schema $dropSchema); /** * Drops all assets from the underlying db. * * @return void */ function dropAllSchema(); } dbal-2.5.13/lib/Doctrine/DBAL/Schema/Synchronizer/SingleDatabaseSynchronizer.php000066400000000000000000000116411313473450000274200ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema\Synchronizer; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\Comparator; use Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector; /** * Schema Synchronizer for Default DBAL Connection. * * @author Benjamin Eberlei */ class SingleDatabaseSynchronizer extends AbstractSchemaSynchronizer { /** * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ private $platform; /** * @param \Doctrine\DBAL\Connection $conn */ public function __construct(Connection $conn) { parent::__construct($conn); $this->platform = $conn->getDatabasePlatform(); } /** * {@inheritdoc} */ public function getCreateSchema(Schema $createSchema) { return $createSchema->toSql($this->platform); } /** * {@inheritdoc} */ public function getUpdateSchema(Schema $toSchema, $noDrops = false) { $comparator = new Comparator(); $sm = $this->conn->getSchemaManager(); $fromSchema = $sm->createSchema(); $schemaDiff = $comparator->compare($fromSchema, $toSchema); if ($noDrops) { return $schemaDiff->toSaveSql($this->platform); } return $schemaDiff->toSql($this->platform); } /** * {@inheritdoc} */ public function getDropSchema(Schema $dropSchema) { $visitor = new DropSchemaSqlCollector($this->platform); $sm = $this->conn->getSchemaManager(); $fullSchema = $sm->createSchema(); foreach ($fullSchema->getTables() as $table) { if ($dropSchema->hasTable($table->getName())) { $visitor->acceptTable($table); } foreach ($table->getForeignKeys() as $foreignKey) { if ( ! $dropSchema->hasTable($table->getName())) { continue; } if ( ! $dropSchema->hasTable($foreignKey->getForeignTableName())) { continue; } $visitor->acceptForeignKey($table, $foreignKey); } } if ( ! $this->platform->supportsSequences()) { return $visitor->getQueries(); } foreach ($dropSchema->getSequences() as $sequence) { $visitor->acceptSequence($sequence); } foreach ($dropSchema->getTables() as $table) { if ( ! $table->hasPrimaryKey()) { continue; } $columns = $table->getPrimaryKey()->getColumns(); if (count($columns) > 1) { continue; } $checkSequence = $table->getName() . "_" . $columns[0] . "_seq"; if ($fullSchema->hasSequence($checkSequence)) { $visitor->acceptSequence($fullSchema->getSequence($checkSequence)); } } return $visitor->getQueries(); } /** * {@inheritdoc} */ public function getDropAllSchema() { $sm = $this->conn->getSchemaManager(); $visitor = new DropSchemaSqlCollector($this->platform); /* @var $schema \Doctrine\DBAL\Schema\Schema */ $schema = $sm->createSchema(); $schema->visit($visitor); return $visitor->getQueries(); } /** * {@inheritdoc} */ public function createSchema(Schema $createSchema) { $this->processSql($this->getCreateSchema($createSchema)); } /** * {@inheritdoc} */ public function updateSchema(Schema $toSchema, $noDrops = false) { $this->processSql($this->getUpdateSchema($toSchema, $noDrops)); } /** * {@inheritdoc} */ public function dropSchema(Schema $dropSchema) { $this->processSqlSafely($this->getDropSchema($dropSchema)); } /** * {@inheritdoc} */ public function dropAllSchema() { $this->processSql($this->getDropAllSchema()); } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/Table.php000066400000000000000000000573451313473450000205010ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Schema\Visitor\Visitor; use Doctrine\DBAL\DBALException; /** * Object Representation of a table. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ class Table extends AbstractAsset { /** * @var string */ protected $_name = null; /** * @var Column[] */ protected $_columns = array(); /** * @var Index[] */ private $implicitIndexes = array(); /** * @var Index[] */ protected $_indexes = array(); /** * @var string */ protected $_primaryKeyName = false; /** * @var ForeignKeyConstraint[] */ protected $_fkConstraints = array(); /** * @var array */ protected $_options = array(); /** * @var SchemaConfig */ protected $_schemaConfig = null; /** * @param string $tableName * @param Column[] $columns * @param Index[] $indexes * @param ForeignKeyConstraint[] $fkConstraints * @param integer $idGeneratorType * @param array $options * * @throws DBALException */ public function __construct($tableName, array $columns=array(), array $indexes=array(), array $fkConstraints=array(), $idGeneratorType = 0, array $options=array()) { if (strlen($tableName) == 0) { throw DBALException::invalidTableName($tableName); } $this->_setName($tableName); foreach ($columns as $column) { $this->_addColumn($column); } foreach ($indexes as $idx) { $this->_addIndex($idx); } foreach ($fkConstraints as $constraint) { $this->_addForeignKeyConstraint($constraint); } $this->_options = $options; } /** * @param SchemaConfig $schemaConfig * * @return void */ public function setSchemaConfig(SchemaConfig $schemaConfig) { $this->_schemaConfig = $schemaConfig; } /** * @return integer */ protected function _getMaxIdentifierLength() { if ($this->_schemaConfig instanceof SchemaConfig) { return $this->_schemaConfig->getMaxIdentifierLength(); } else { return 63; } } /** * Sets the Primary Key. * * @param array $columns * @param string|boolean $indexName * * @return self */ public function setPrimaryKey(array $columns, $indexName = false) { $this->_addIndex($this->_createIndex($columns, $indexName ?: "primary", true, true)); foreach ($columns as $columnName) { $column = $this->getColumn($columnName); $column->setNotnull(true); } return $this; } /** * @param array $columnNames * @param string|null $indexName * @param array $flags * @param array $options * * @return self */ public function addIndex(array $columnNames, $indexName = null, array $flags = array(), array $options = array()) { if ($indexName == null) { $indexName = $this->_generateIdentifierName( array_merge(array($this->getName()), $columnNames), "idx", $this->_getMaxIdentifierLength() ); } return $this->_addIndex($this->_createIndex($columnNames, $indexName, false, false, $flags, $options)); } /** * Drops the primary key from this table. * * @return void */ public function dropPrimaryKey() { $this->dropIndex($this->_primaryKeyName); $this->_primaryKeyName = false; } /** * Drops an index from this table. * * @param string $indexName The index name. * * @return void * * @throws SchemaException If the index does not exist. */ public function dropIndex($indexName) { $indexName = $this->normalizeIdentifier($indexName); if ( ! $this->hasIndex($indexName)) { throw SchemaException::indexDoesNotExist($indexName, $this->_name); } unset($this->_indexes[$indexName]); } /** * @param array $columnNames * @param string|null $indexName * @param array $options * * @return self */ public function addUniqueIndex(array $columnNames, $indexName = null, array $options = array()) { if ($indexName === null) { $indexName = $this->_generateIdentifierName( array_merge(array($this->getName()), $columnNames), "uniq", $this->_getMaxIdentifierLength() ); } return $this->_addIndex($this->_createIndex($columnNames, $indexName, true, false, array(), $options)); } /** * Renames an index. * * @param string $oldIndexName The name of the index to rename from. * @param string|null $newIndexName The name of the index to rename to. * If null is given, the index name will be auto-generated. * * @return self This table instance. * * @throws SchemaException if no index exists for the given current name * or if an index with the given new name already exists on this table. */ public function renameIndex($oldIndexName, $newIndexName = null) { $oldIndexName = $this->normalizeIdentifier($oldIndexName); $normalizedNewIndexName = $this->normalizeIdentifier($newIndexName); if ($oldIndexName === $normalizedNewIndexName) { return $this; } if ( ! $this->hasIndex($oldIndexName)) { throw SchemaException::indexDoesNotExist($oldIndexName, $this->_name); } if ($this->hasIndex($normalizedNewIndexName)) { throw SchemaException::indexAlreadyExists($normalizedNewIndexName, $this->_name); } $oldIndex = $this->_indexes[$oldIndexName]; if ($oldIndex->isPrimary()) { $this->dropPrimaryKey(); return $this->setPrimaryKey($oldIndex->getColumns(), $newIndexName); } unset($this->_indexes[$oldIndexName]); if ($oldIndex->isUnique()) { return $this->addUniqueIndex($oldIndex->getColumns(), $newIndexName, $oldIndex->getOptions()); } return $this->addIndex($oldIndex->getColumns(), $newIndexName, $oldIndex->getFlags(), $oldIndex->getOptions()); } /** * Checks if an index begins in the order of the given columns. * * @param array $columnsNames * * @return boolean */ public function columnsAreIndexed(array $columnsNames) { foreach ($this->getIndexes() as $index) { /* @var $index Index */ if ($index->spansColumns($columnsNames)) { return true; } } return false; } /** * @param array $columnNames * @param string $indexName * @param boolean $isUnique * @param boolean $isPrimary * @param array $flags * @param array $options * * @return Index * * @throws SchemaException */ private function _createIndex(array $columnNames, $indexName, $isUnique, $isPrimary, array $flags = array(), array $options = array()) { if (preg_match('(([^a-zA-Z0-9_]+))', $this->normalizeIdentifier($indexName))) { throw SchemaException::indexNameInvalid($indexName); } foreach ($columnNames as $columnName => $indexColOptions) { if (is_numeric($columnName) && is_string($indexColOptions)) { $columnName = $indexColOptions; } if ( ! $this->hasColumn($columnName)) { throw SchemaException::columnDoesNotExist($columnName, $this->_name); } } return new Index($indexName, $columnNames, $isUnique, $isPrimary, $flags, $options); } /** * @param string $columnName * @param string $typeName * @param array $options * * @return Column */ public function addColumn($columnName, $typeName, array $options=array()) { $column = new Column($columnName, Type::getType($typeName), $options); $this->_addColumn($column); return $column; } /** * Renames a Column. * * @param string $oldColumnName * @param string $newColumnName * * @return self * * @throws DBALException */ public function renameColumn($oldColumnName, $newColumnName) { throw new DBALException("Table#renameColumn() was removed, because it drops and recreates " . "the column instead. There is no fix available, because a schema diff cannot reliably detect if a " . "column was renamed or one column was created and another one dropped."); } /** * Change Column Details. * * @param string $columnName * @param array $options * * @return self */ public function changeColumn($columnName, array $options) { $column = $this->getColumn($columnName); $column->setOptions($options); return $this; } /** * Drops a Column from the Table. * * @param string $columnName * * @return self */ public function dropColumn($columnName) { $columnName = $this->normalizeIdentifier($columnName); unset($this->_columns[$columnName]); return $this; } /** * Adds a foreign key constraint. * * Name is inferred from the local columns. * * @param Table|string $foreignTable Table schema instance or table name * @param array $localColumnNames * @param array $foreignColumnNames * @param array $options * @param string|null $constraintName * * @return self */ public function addForeignKeyConstraint($foreignTable, array $localColumnNames, array $foreignColumnNames, array $options=array(), $constraintName = null) { $constraintName = $constraintName ?: $this->_generateIdentifierName(array_merge((array) $this->getName(), $localColumnNames), "fk", $this->_getMaxIdentifierLength()); return $this->addNamedForeignKeyConstraint($constraintName, $foreignTable, $localColumnNames, $foreignColumnNames, $options); } /** * Adds a foreign key constraint. * * Name is to be generated by the database itself. * * @deprecated Use {@link addForeignKeyConstraint} * * @param Table|string $foreignTable Table schema instance or table name * @param array $localColumnNames * @param array $foreignColumnNames * @param array $options * * @return self */ public function addUnnamedForeignKeyConstraint($foreignTable, array $localColumnNames, array $foreignColumnNames, array $options=array()) { return $this->addForeignKeyConstraint($foreignTable, $localColumnNames, $foreignColumnNames, $options); } /** * Adds a foreign key constraint with a given name. * * @deprecated Use {@link addForeignKeyConstraint} * * @param string $name * @param Table|string $foreignTable Table schema instance or table name * @param array $localColumnNames * @param array $foreignColumnNames * @param array $options * * @return self * * @throws SchemaException */ public function addNamedForeignKeyConstraint($name, $foreignTable, array $localColumnNames, array $foreignColumnNames, array $options=array()) { if ($foreignTable instanceof Table) { foreach ($foreignColumnNames as $columnName) { if ( ! $foreignTable->hasColumn($columnName)) { throw SchemaException::columnDoesNotExist($columnName, $foreignTable->getName()); } } } foreach ($localColumnNames as $columnName) { if ( ! $this->hasColumn($columnName)) { throw SchemaException::columnDoesNotExist($columnName, $this->_name); } } $constraint = new ForeignKeyConstraint( $localColumnNames, $foreignTable, $foreignColumnNames, $name, $options ); $this->_addForeignKeyConstraint($constraint); return $this; } /** * @param string $name * @param string $value * * @return self */ public function addOption($name, $value) { $this->_options[$name] = $value; return $this; } /** * @param Column $column * * @return void * * @throws SchemaException */ protected function _addColumn(Column $column) { $columnName = $column->getName(); $columnName = $this->normalizeIdentifier($columnName); if (isset($this->_columns[$columnName])) { throw SchemaException::columnAlreadyExists($this->getName(), $columnName); } $this->_columns[$columnName] = $column; } /** * Adds an index to the table. * * @param Index $indexCandidate * * @return self * * @throws SchemaException */ protected function _addIndex(Index $indexCandidate) { $indexName = $indexCandidate->getName(); $indexName = $this->normalizeIdentifier($indexName); $replacedImplicitIndexes = array(); foreach ($this->implicitIndexes as $name => $implicitIndex) { if ($implicitIndex->isFullfilledBy($indexCandidate) && isset($this->_indexes[$name])) { $replacedImplicitIndexes[] = $name; } } if ((isset($this->_indexes[$indexName]) && ! in_array($indexName, $replacedImplicitIndexes, true)) || ($this->_primaryKeyName != false && $indexCandidate->isPrimary()) ) { throw SchemaException::indexAlreadyExists($indexName, $this->_name); } foreach ($replacedImplicitIndexes as $name) { unset($this->_indexes[$name], $this->implicitIndexes[$name]); } if ($indexCandidate->isPrimary()) { $this->_primaryKeyName = $indexName; } $this->_indexes[$indexName] = $indexCandidate; return $this; } /** * @param ForeignKeyConstraint $constraint * * @return void */ protected function _addForeignKeyConstraint(ForeignKeyConstraint $constraint) { $constraint->setLocalTable($this); if (strlen($constraint->getName())) { $name = $constraint->getName(); } else { $name = $this->_generateIdentifierName( array_merge((array) $this->getName(), $constraint->getLocalColumns()), "fk", $this->_getMaxIdentifierLength() ); } $name = $this->normalizeIdentifier($name); $this->_fkConstraints[$name] = $constraint; // add an explicit index on the foreign key columns. If there is already an index that fulfils this requirements drop the request. // In the case of __construct calling this method during hydration from schema-details all the explicitly added indexes // lead to duplicates. This creates computation overhead in this case, however no duplicate indexes are ever added (based on columns). $indexName = $this->_generateIdentifierName( array_merge(array($this->getName()), $constraint->getColumns()), "idx", $this->_getMaxIdentifierLength() ); $indexCandidate = $this->_createIndex($constraint->getColumns(), $indexName, false, false); foreach ($this->_indexes as $existingIndex) { if ($indexCandidate->isFullfilledBy($existingIndex)) { return; } } $this->_addIndex($indexCandidate); $this->implicitIndexes[$this->normalizeIdentifier($indexName)] = $indexCandidate; } /** * Returns whether this table has a foreign key constraint with the given name. * * @param string $constraintName * * @return boolean */ public function hasForeignKey($constraintName) { $constraintName = $this->normalizeIdentifier($constraintName); return isset($this->_fkConstraints[$constraintName]); } /** * Returns the foreign key constraint with the given name. * * @param string $constraintName The constraint name. * * @return ForeignKeyConstraint * * @throws SchemaException If the foreign key does not exist. */ public function getForeignKey($constraintName) { $constraintName = $this->normalizeIdentifier($constraintName); if (!$this->hasForeignKey($constraintName)) { throw SchemaException::foreignKeyDoesNotExist($constraintName, $this->_name); } return $this->_fkConstraints[$constraintName]; } /** * Removes the foreign key constraint with the given name. * * @param string $constraintName The constraint name. * * @return void * * @throws SchemaException */ public function removeForeignKey($constraintName) { $constraintName = $this->normalizeIdentifier($constraintName); if (!$this->hasForeignKey($constraintName)) { throw SchemaException::foreignKeyDoesNotExist($constraintName, $this->_name); } unset($this->_fkConstraints[$constraintName]); } /** * @return Column[] */ public function getColumns() { $columns = $this->_columns; $pkCols = array(); $fkCols = array(); if ($this->hasPrimaryKey()) { $pkCols = $this->getPrimaryKey()->getColumns(); } foreach ($this->getForeignKeys() as $fk) { /* @var $fk ForeignKeyConstraint */ $fkCols = array_merge($fkCols, $fk->getColumns()); } $colNames = array_unique(array_merge($pkCols, $fkCols, array_keys($columns))); uksort($columns, function ($a, $b) use ($colNames) { return (array_search($a, $colNames) >= array_search($b, $colNames)); }); return $columns; } /** * Returns whether this table has a Column with the given name. * * @param string $columnName The column name. * * @return boolean */ public function hasColumn($columnName) { $columnName = $this->normalizeIdentifier($columnName); return isset($this->_columns[$columnName]); } /** * Returns the Column with the given name. * * @param string $columnName The column name. * * @return Column * * @throws SchemaException If the column does not exist. */ public function getColumn($columnName) { $columnName = $this->normalizeIdentifier($columnName); if ( ! $this->hasColumn($columnName)) { throw SchemaException::columnDoesNotExist($columnName, $this->_name); } return $this->_columns[$columnName]; } /** * Returns the primary key. * * @return Index|null The primary key, or null if this Table has no primary key. */ public function getPrimaryKey() { if ( ! $this->hasPrimaryKey()) { return null; } return $this->getIndex($this->_primaryKeyName); } /** * Returns the primary key columns. * * @return array * * @throws DBALException */ public function getPrimaryKeyColumns() { if ( ! $this->hasPrimaryKey()) { throw new DBALException("Table " . $this->getName() . " has no primary key."); } return $this->getPrimaryKey()->getColumns(); } /** * Returns whether this table has a primary key. * * @return boolean */ public function hasPrimaryKey() { return ($this->_primaryKeyName && $this->hasIndex($this->_primaryKeyName)); } /** * Returns whether this table has an Index with the given name. * * @param string $indexName The index name. * * @return boolean */ public function hasIndex($indexName) { $indexName = $this->normalizeIdentifier($indexName); return (isset($this->_indexes[$indexName])); } /** * Returns the Index with the given name. * * @param string $indexName The index name. * * @return Index * * @throws SchemaException If the index does not exist. */ public function getIndex($indexName) { $indexName = $this->normalizeIdentifier($indexName); if ( ! $this->hasIndex($indexName)) { throw SchemaException::indexDoesNotExist($indexName, $this->_name); } return $this->_indexes[$indexName]; } /** * @return Index[] */ public function getIndexes() { return $this->_indexes; } /** * Returns the foreign key constraints. * * @return ForeignKeyConstraint[] */ public function getForeignKeys() { return $this->_fkConstraints; } /** * @param string $name * * @return boolean */ public function hasOption($name) { return isset($this->_options[$name]); } /** * @param string $name * * @return mixed */ public function getOption($name) { return $this->_options[$name]; } /** * @return array */ public function getOptions() { return $this->_options; } /** * @param Visitor $visitor * * @return void */ public function visit(Visitor $visitor) { $visitor->acceptTable($this); foreach ($this->getColumns() as $column) { $visitor->acceptColumn($this, $column); } foreach ($this->getIndexes() as $index) { $visitor->acceptIndex($this, $index); } foreach ($this->getForeignKeys() as $constraint) { $visitor->acceptForeignKey($this, $constraint); } } /** * Clone of a Table triggers a deep clone of all affected assets. * * @return void */ public function __clone() { foreach ($this->_columns as $k => $column) { $this->_columns[$k] = clone $column; } foreach ($this->_indexes as $k => $index) { $this->_indexes[$k] = clone $index; } foreach ($this->_fkConstraints as $k => $fk) { $this->_fkConstraints[$k] = clone $fk; $this->_fkConstraints[$k]->setLocalTable($this); } } /** * Normalizes a given identifier. * * Trims quotes and lowercases the given identifier. * * @param string $identifier The identifier to normalize. * * @return string The normalized identifier. */ private function normalizeIdentifier($identifier) { return $this->trimQuotes(strtolower($identifier)); } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/TableDiff.php000066400000000000000000000112711313473450000212560ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Table Diff. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ class TableDiff { /** * @var string */ public $name = null; /** * @var string|boolean */ public $newName = false; /** * All added fields. * * @var \Doctrine\DBAL\Schema\Column[] */ public $addedColumns; /** * All changed fields. * * @var \Doctrine\DBAL\Schema\ColumnDiff[] */ public $changedColumns = array(); /** * All removed fields. * * @var \Doctrine\DBAL\Schema\Column[] */ public $removedColumns = array(); /** * Columns that are only renamed from key to column instance name. * * @var \Doctrine\DBAL\Schema\Column[] */ public $renamedColumns = array(); /** * All added indexes. * * @var \Doctrine\DBAL\Schema\Index[] */ public $addedIndexes = array(); /** * All changed indexes. * * @var \Doctrine\DBAL\Schema\Index[] */ public $changedIndexes = array(); /** * All removed indexes * * @var \Doctrine\DBAL\Schema\Index[] */ public $removedIndexes = array(); /** * Indexes that are only renamed but are identical otherwise. * * @var \Doctrine\DBAL\Schema\Index[] */ public $renamedIndexes = array(); /** * All added foreign key definitions * * @var \Doctrine\DBAL\Schema\ForeignKeyConstraint[] */ public $addedForeignKeys = array(); /** * All changed foreign keys * * @var \Doctrine\DBAL\Schema\ForeignKeyConstraint[] */ public $changedForeignKeys = array(); /** * All removed foreign keys * * @var \Doctrine\DBAL\Schema\ForeignKeyConstraint[] */ public $removedForeignKeys = array(); /** * @var \Doctrine\DBAL\Schema\Table */ public $fromTable; /** * Constructs an TableDiff object. * * @param string $tableName * @param \Doctrine\DBAL\Schema\Column[] $addedColumns * @param \Doctrine\DBAL\Schema\ColumnDiff[] $changedColumns * @param \Doctrine\DBAL\Schema\Column[] $removedColumns * @param \Doctrine\DBAL\Schema\Index[] $addedIndexes * @param \Doctrine\DBAL\Schema\Index[] $changedIndexes * @param \Doctrine\DBAL\Schema\Index[] $removedIndexes * @param \Doctrine\DBAL\Schema\Table|null $fromTable */ public function __construct($tableName, $addedColumns = array(), $changedColumns = array(), $removedColumns = array(), $addedIndexes = array(), $changedIndexes = array(), $removedIndexes = array(), Table $fromTable = null) { $this->name = $tableName; $this->addedColumns = $addedColumns; $this->changedColumns = $changedColumns; $this->removedColumns = $removedColumns; $this->addedIndexes = $addedIndexes; $this->changedIndexes = $changedIndexes; $this->removedIndexes = $removedIndexes; $this->fromTable = $fromTable; } /** * @param AbstractPlatform $platform The platform to use for retrieving this table diff's name. * * @return \Doctrine\DBAL\Schema\Identifier */ public function getName(AbstractPlatform $platform) { return new Identifier( $this->fromTable instanceof Table ? $this->fromTable->getQuotedName($platform) : $this->name ); } /** * @return \Doctrine\DBAL\Schema\Identifier|boolean */ public function getNewName() { return $this->newName ? new Identifier($this->newName) : $this->newName; } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/View.php000066400000000000000000000030261313473450000203470ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema; /** * Representation of a Database View. * * @link www.doctrine-project.org * @since 1.0 * @author Benjamin Eberlei */ class View extends AbstractAsset { /** * @var string */ private $_sql; /** * @param string $name * @param string $sql */ public function __construct($name, $sql) { $this->_setName($name); $this->_sql = $sql; } /** * @return string */ public function getSql() { return $this->_sql; } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/Visitor/000077500000000000000000000000001313473450000203625ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Schema/Visitor/AbstractVisitor.php000066400000000000000000000047131313473450000242230ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema\Visitor; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\Sequence; use Doctrine\DBAL\Schema\Index; /** * Abstract Visitor with empty methods for easy extension. */ class AbstractVisitor implements Visitor, NamespaceVisitor { /** * @param \Doctrine\DBAL\Schema\Schema $schema */ public function acceptSchema(Schema $schema) { } /** * {@inheritdoc} */ public function acceptNamespace($namespaceName) { } /** * @param \Doctrine\DBAL\Schema\Table $table */ public function acceptTable(Table $table) { } /** * @param \Doctrine\DBAL\Schema\Table $table * @param \Doctrine\DBAL\Schema\Column $column */ public function acceptColumn(Table $table, Column $column) { } /** * @param \Doctrine\DBAL\Schema\Table $localTable * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $fkConstraint */ public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) { } /** * @param \Doctrine\DBAL\Schema\Table $table * @param \Doctrine\DBAL\Schema\Index $index */ public function acceptIndex(Table $table, Index $index) { } /** * @param \Doctrine\DBAL\Schema\Sequence $sequence */ public function acceptSequence(Sequence $sequence) { } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/Visitor/CreateSchemaSqlCollector.php000066400000000000000000000101071313473450000257450ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema\Visitor; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\Sequence; class CreateSchemaSqlCollector extends AbstractVisitor { /** * @var array */ private $createNamespaceQueries = array(); /** * @var array */ private $createTableQueries = array(); /** * @var array */ private $createSequenceQueries = array(); /** * @var array */ private $createFkConstraintQueries = array(); /** * * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ private $platform = null; /** * @param AbstractPlatform $platform */ public function __construct(AbstractPlatform $platform) { $this->platform = $platform; } /** * {@inheritdoc} */ public function acceptNamespace($namespaceName) { if ($this->platform->supportsSchemas()) { $this->createNamespaceQueries = array_merge( $this->createNamespaceQueries, (array) $this->platform->getCreateSchemaSQL($namespaceName) ); } } /** * {@inheritdoc} */ public function acceptTable(Table $table) { $this->createTableQueries = array_merge($this->createTableQueries, (array) $this->platform->getCreateTableSQL($table)); } /** * {@inheritdoc} */ public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) { if ($this->platform->supportsForeignKeyConstraints()) { $this->createFkConstraintQueries = array_merge( $this->createFkConstraintQueries, (array) $this->platform->getCreateForeignKeySQL( $fkConstraint, $localTable ) ); } } /** * {@inheritdoc} */ public function acceptSequence(Sequence $sequence) { $this->createSequenceQueries = array_merge( $this->createSequenceQueries, (array) $this->platform->getCreateSequenceSQL($sequence) ); } /** * @return void */ public function resetQueries() { $this->createNamespaceQueries = array(); $this->createTableQueries = array(); $this->createSequenceQueries = array(); $this->createFkConstraintQueries = array(); } /** * Gets all queries collected so far. * * @return array */ public function getQueries() { $sql = array(); foreach ($this->createNamespaceQueries as $schemaSql) { $sql = array_merge($sql, (array) $schemaSql); } foreach ($this->createTableQueries as $schemaSql) { $sql = array_merge($sql, (array) $schemaSql); } foreach ($this->createSequenceQueries as $schemaSql) { $sql = array_merge($sql, (array) $schemaSql); } foreach ($this->createFkConstraintQueries as $schemaSql) { $sql = array_merge($sql, (array) $schemaSql); } return $sql; } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/Visitor/DropSchemaSqlCollector.php000066400000000000000000000065471313473450000254630ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema\Visitor; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\Sequence; use Doctrine\DBAL\Schema\SchemaException; /** * Gathers SQL statements that allow to completely drop the current schema. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ class DropSchemaSqlCollector extends AbstractVisitor { /** * @var \SplObjectStorage */ private $constraints; /** * @var \SplObjectStorage */ private $sequences; /** * @var \SplObjectStorage */ private $tables; /** * @var AbstractPlatform */ private $platform; /** * @param AbstractPlatform $platform */ public function __construct(AbstractPlatform $platform) { $this->platform = $platform; $this->clearQueries(); } /** * {@inheritdoc} */ public function acceptTable(Table $table) { $this->tables->attach($table); } /** * {@inheritdoc} */ public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) { if (strlen($fkConstraint->getName()) == 0) { throw SchemaException::namedForeignKeyRequired($localTable, $fkConstraint); } $this->constraints->attach($fkConstraint, $localTable); } /** * {@inheritdoc} */ public function acceptSequence(Sequence $sequence) { $this->sequences->attach($sequence); } /** * @return void */ public function clearQueries() { $this->constraints = new \SplObjectStorage(); $this->sequences = new \SplObjectStorage(); $this->tables = new \SplObjectStorage(); } /** * @return array */ public function getQueries() { $sql = array(); foreach ($this->constraints as $fkConstraint) { $localTable = $this->constraints[$fkConstraint]; $sql[] = $this->platform->getDropForeignKeySQL($fkConstraint, $localTable); } foreach ($this->sequences as $sequence) { $sql[] = $this->platform->getDropSequenceSQL($sequence); } foreach ($this->tables as $table) { $sql[] = $this->platform->getDropTableSQL($table); } return $sql; } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/Visitor/Graphviz.php000066400000000000000000000123711313473450000226710ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema\Visitor; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\ForeignKeyConstraint; /** * Create a Graphviz output of a Schema. */ class Graphviz extends AbstractVisitor { /** * @var string */ private $output = ''; /** * {@inheritdoc} */ public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) { $this->output .= $this->createNodeRelation( $fkConstraint->getLocalTableName() . ":col" . current($fkConstraint->getLocalColumns()).":se", $fkConstraint->getForeignTableName() . ":col" . current($fkConstraint->getForeignColumns()).":se", array( 'dir' => 'back', 'arrowtail' => 'dot', 'arrowhead' => 'normal', ) ); } /** * {@inheritdoc} */ public function acceptSchema(Schema $schema) { $this->output = 'digraph "' . sha1(mt_rand()) . '" {' . "\n"; $this->output .= 'splines = true;' . "\n"; $this->output .= 'overlap = false;' . "\n"; $this->output .= 'outputorder=edgesfirst;'."\n"; $this->output .= 'mindist = 0.6;' . "\n"; $this->output .= 'sep = .2;' . "\n"; } /** * {@inheritdoc} */ public function acceptTable(Table $table) { $this->output .= $this->createNode( $table->getName(), array( 'label' => $this->createTableLabel($table), 'shape' => 'plaintext', ) ); } /** * @param \Doctrine\DBAL\Schema\Table $table * * @return string */ private function createTableLabel(Table $table) { // Start the table $label = '<'; // The title $label .= ''; // The attributes block foreach ($table->getColumns() as $column) { $columnLabel = $column->getName(); $label .= ''; $label .= ''; $label .= ''; } // End the table $label .= '
' . $table->getName() . '
'; $label .= '' . $columnLabel . ''; $label .= '' . strtolower($column->getType()) . ''; if ($table->hasPrimaryKey() && in_array($column->getName(), $table->getPrimaryKey()->getColumns())) { $label .= "\xe2\x9c\xb7"; } $label .= '
>'; return $label; } /** * @param string $name * @param array $options * * @return string */ private function createNode($name, $options) { $node = $name . " ["; foreach ($options as $key => $value) { $node .= $key . '=' . $value . ' '; } $node .= "]\n"; return $node; } /** * @param string $node1 * @param string $node2 * @param array $options * * @return string */ private function createNodeRelation($node1, $node2, $options) { $relation = $node1 . ' -> ' . $node2 . ' ['; foreach ($options as $key => $value) { $relation .= $key . '=' . $value . ' '; } $relation .= "]\n"; return $relation; } /** * Get Graphviz Output * * @return string */ public function getOutput() { return $this->output . "}"; } /** * Writes dot language output to a file. This should usually be a *.dot file. * * You have to convert the output into a viewable format. For example use "neato" on linux systems * and execute: * * neato -Tpng -o er.png er.dot * * @param string $filename * * @return void */ public function write($filename) { file_put_contents($filename, $this->getOutput()); } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/Visitor/NamespaceVisitor.php000066400000000000000000000026011313473450000243460ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema\Visitor; /** * Visitor that can visit schema namespaces. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ interface NamespaceVisitor { /** * Accepts a schema namespace name. * * @param string $namespaceName The schema namespace name to accept. */ public function acceptNamespace($namespaceName); } dbal-2.5.13/lib/Doctrine/DBAL/Schema/Visitor/RemoveNamespacedAssets.php000066400000000000000000000061731313473450000255030ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema\Visitor; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\Sequence; /** * Removes assets from a schema that are not in the default namespace. * * Some databases such as MySQL support cross databases joins, but don't * allow to call DDLs to a database from another connected database. * Before a schema is serialized into SQL this visitor can cleanup schemas with * non default namespaces. * * This visitor filters all these non-default namespaced tables and sequences * and removes them from the SChema instance. * * @author Benjamin Eberlei * @since 2.2 */ class RemoveNamespacedAssets extends AbstractVisitor { /** * @var \Doctrine\DBAL\Schema\Schema */ private $schema; /** * {@inheritdoc} */ public function acceptSchema(Schema $schema) { $this->schema = $schema; } /** * {@inheritdoc} */ public function acceptTable(Table $table) { if ( ! $table->isInDefaultNamespace($this->schema->getName())) { $this->schema->dropTable($table->getName()); } } /** * {@inheritdoc} */ public function acceptSequence(Sequence $sequence) { if ( ! $sequence->isInDefaultNamespace($this->schema->getName())) { $this->schema->dropSequence($sequence->getName()); } } /** * {@inheritdoc} */ public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) { // The table may already be deleted in a previous // RemoveNamespacedAssets#acceptTable call. Removing Foreign keys that // point to nowhere. if ( ! $this->schema->hasTable($fkConstraint->getForeignTableName())) { $localTable->removeForeignKey($fkConstraint->getName()); return; } $foreignTable = $this->schema->getTable($fkConstraint->getForeignTableName()); if ( ! $foreignTable->isInDefaultNamespace($this->schema->getName())) { $localTable->removeForeignKey($fkConstraint->getName()); } } } dbal-2.5.13/lib/Doctrine/DBAL/Schema/Visitor/SchemaDiffVisitor.php000066400000000000000000000051211313473450000244430ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema\Visitor; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\Sequence; /** * Visit a SchemaDiff. * * @link www.doctrine-project.org * @since 2.4 * @author Benjamin Eberlei */ interface SchemaDiffVisitor { /** * Visit an orphaned foreign key whose table was deleted. * * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey */ function visitOrphanedForeignKey(ForeignKeyConstraint $foreignKey); /** * Visit a sequence that has changed. * * @param \Doctrine\DBAL\Schema\Sequence $sequence */ function visitChangedSequence(Sequence $sequence); /** * Visit a sequence that has been removed. * * @param \Doctrine\DBAL\Schema\Sequence $sequence */ function visitRemovedSequence(Sequence $sequence); /** * @param \Doctrine\DBAL\Schema\Sequence $sequence */ function visitNewSequence(Sequence $sequence); /** * @param \Doctrine\DBAL\Schema\Table $table */ function visitNewTable(Table $table); /** * @param \Doctrine\DBAL\Schema\Table $table * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey */ function visitNewTableForeignKey(Table $table, ForeignKeyConstraint $foreignKey); /** * @param \Doctrine\DBAL\Schema\Table $table */ function visitRemovedTable(Table $table); /** * @param \Doctrine\DBAL\Schema\TableDiff $tableDiff */ function visitChangedTable(TableDiff $tableDiff); } dbal-2.5.13/lib/Doctrine/DBAL/Schema/Visitor/Visitor.php000066400000000000000000000050071313473450000225340ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Schema\Visitor; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\Sequence; use Doctrine\DBAL\Schema\Index; /** * Schema Visitor used for Validation or Generation purposes. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ interface Visitor { /** * @param \Doctrine\DBAL\Schema\Schema $schema * * @return void */ public function acceptSchema(Schema $schema); /** * @param \Doctrine\DBAL\Schema\Table $table * * @return void */ public function acceptTable(Table $table); /** * @param \Doctrine\DBAL\Schema\Table $table * @param \Doctrine\DBAL\Schema\Column $column * * @return void */ public function acceptColumn(Table $table, Column $column); /** * @param \Doctrine\DBAL\Schema\Table $localTable * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $fkConstraint * * @return void */ public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint); /** * @param \Doctrine\DBAL\Schema\Table $table * @param \Doctrine\DBAL\Schema\Index $index * * @return void */ public function acceptIndex(Table $table, Index $index); /** * @param \Doctrine\DBAL\Schema\Sequence $sequence * * @return void */ public function acceptSequence(Sequence $sequence); } dbal-2.5.13/lib/Doctrine/DBAL/Sharding/000077500000000000000000000000001313473450000172625ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Sharding/PoolingShardConnection.php000066400000000000000000000203071313473450000244060ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Sharding; use Doctrine\Common\EventManager; use Doctrine\DBAL\Configuration; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Driver; use Doctrine\DBAL\Event\ConnectionEventArgs; use Doctrine\DBAL\Events; use Doctrine\DBAL\Sharding\ShardChoser\ShardChoser; /** * Sharding implementation that pools many different connections * internally and serves data from the currently active connection. * * The internals of this class are: * * - All sharding clients are specified and given a shard-id during * configuration. * - By default, the global shard is selected. If no global shard is configured * an exception is thrown on access. * - Selecting a shard by distribution value delegates the mapping * "distributionValue" => "client" to the ShardChooser interface. * - An exception is thrown if trying to switch shards during an open * transaction. * * Instantiation through the DriverManager looks like: * * @example * * $conn = DriverManager::getConnection(array( * 'wrapperClass' => 'Doctrine\DBAL\Sharding\PoolingShardConnection', * 'driver' => 'pdo_mysql', * 'global' => array('user' => '', 'password' => '', 'host' => '', 'dbname' => ''), * 'shards' => array( * array('id' => 1, 'user' => 'slave1', 'password', 'host' => '', 'dbname' => ''), * array('id' => 2, 'user' => 'slave2', 'password', 'host' => '', 'dbname' => ''), * ), * 'shardChoser' => 'Doctrine\DBAL\Sharding\ShardChoser\MultiTenantShardChoser', * )); * $shardManager = $conn->getShardManager(); * $shardManager->selectGlobal(); * $shardManager->selectShard($value); * * @author Benjamin Eberlei */ class PoolingShardConnection extends Connection { /** * @var array */ private $activeConnections; /** * @var integer */ private $activeShardId; /** * @var array */ private $connections; /** * @param array $params * @param \Doctrine\DBAL\Driver $driver * @param \Doctrine\DBAL\Configuration $config * @param \Doctrine\Common\EventManager $eventManager * * @throws \InvalidArgumentException */ public function __construct(array $params, Driver $driver, Configuration $config = null, EventManager $eventManager = null) { if ( !isset($params['global']) || !isset($params['shards'])) { throw new \InvalidArgumentException("Connection Parameters require 'global' and 'shards' configurations."); } if ( !isset($params['shardChoser'])) { throw new \InvalidArgumentException("Missing Shard Choser configuration 'shardChoser'"); } if (is_string($params['shardChoser'])) { $params['shardChoser'] = new $params['shardChoser']; } if ( ! ($params['shardChoser'] instanceof ShardChoser)) { throw new \InvalidArgumentException("The 'shardChoser' configuration is not a valid instance of Doctrine\DBAL\Sharding\ShardChoser\ShardChoser"); } $this->connections[0] = array_merge($params, $params['global']); foreach ($params['shards'] as $shard) { if ( ! isset($shard['id'])) { throw new \InvalidArgumentException("Missing 'id' for one configured shard. Please specify a unique shard-id."); } if ( !is_numeric($shard['id']) || $shard['id'] < 1) { throw new \InvalidArgumentException("Shard Id has to be a non-negative number."); } if (isset($this->connections[$shard['id']])) { throw new \InvalidArgumentException("Shard " . $shard['id'] . " is duplicated in the configuration."); } $this->connections[$shard['id']] = array_merge($params, $shard); } parent::__construct($params, $driver, $config, $eventManager); } /** * Get active shard id. * * @return integer */ public function getActiveShardId() { return $this->activeShardId; } /** * {@inheritdoc} */ public function getParams() { return $this->activeShardId ? $this->connections[$this->activeShardId] : $this->connections[0]; } /** * {@inheritdoc} */ public function getHost() { $params = $this->getParams(); return isset($params['host']) ? $params['host'] : parent::getHost(); } /** * {@inheritdoc} */ public function getPort() { $params = $this->getParams(); return isset($params['port']) ? $params['port'] : parent::getPort(); } /** * {@inheritdoc} */ public function getUsername() { $params = $this->getParams(); return isset($params['user']) ? $params['user'] : parent::getUsername(); } /** * {@inheritdoc} */ public function getPassword() { $params = $this->getParams(); return isset($params['password']) ? $params['password'] : parent::getPassword(); } /** * Connects to a given shard. * * @param mixed $shardId * * @return boolean * * @throws \Doctrine\DBAL\Sharding\ShardingException */ public function connect($shardId = null) { if ($shardId === null && $this->_conn) { return false; } if ($shardId !== null && $shardId === $this->activeShardId) { return false; } if ($this->getTransactionNestingLevel() > 0) { throw new ShardingException("Cannot switch shard when transaction is active."); } $this->activeShardId = (int)$shardId; if (isset($this->activeConnections[$this->activeShardId])) { $this->_conn = $this->activeConnections[$this->activeShardId]; return false; } $this->_conn = $this->activeConnections[$this->activeShardId] = $this->connectTo($this->activeShardId); if ($this->_eventManager->hasListeners(Events::postConnect)) { $eventArgs = new ConnectionEventArgs($this); $this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs); } return true; } /** * Connects to a specific connection. * * @param string $shardId * * @return \Doctrine\DBAL\Driver\Connection */ protected function connectTo($shardId) { $params = $this->getParams(); $driverOptions = isset($params['driverOptions']) ? $params['driverOptions'] : array(); $connectionParams = $this->connections[$shardId]; $user = isset($connectionParams['user']) ? $connectionParams['user'] : null; $password = isset($connectionParams['password']) ? $connectionParams['password'] : null; return $this->_driver->connect($connectionParams, $user, $password, $driverOptions); } /** * @param string|null $shardId * * @return boolean */ public function isConnected($shardId = null) { if ($shardId === null) { return $this->_conn !== null; } return isset($this->activeConnections[$shardId]); } /** * @return void */ public function close() { $this->_conn = null; $this->activeConnections = null; $this->activeShardId = null; } } dbal-2.5.13/lib/Doctrine/DBAL/Sharding/PoolingShardManager.php000066400000000000000000000067101313473450000236630ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Sharding; use Doctrine\DBAL\Sharding\ShardChoser\ShardChoser; /** * Shard Manager for the Connection Pooling Shard Strategy * * @author Benjamin Eberlei */ class PoolingShardManager implements ShardManager { /** * @var PoolingShardConnection */ private $conn; /** * @var ShardChoser */ private $choser; /** * @var string|null */ private $currentDistributionValue; /** * @param PoolingShardConnection $conn */ public function __construct(PoolingShardConnection $conn) { $params = $conn->getParams(); $this->conn = $conn; $this->choser = $params['shardChoser']; } /** * @return void */ public function selectGlobal() { $this->conn->connect(0); $this->currentDistributionValue = null; } /** * @param string $distributionValue * * @return void */ public function selectShard($distributionValue) { $shardId = $this->choser->pickShard($distributionValue, $this->conn); $this->conn->connect($shardId); $this->currentDistributionValue = $distributionValue; } /** * @return string|null */ public function getCurrentDistributionValue() { return $this->currentDistributionValue; } /** * @return array */ public function getShards() { $params = $this->conn->getParams(); $shards = array(); foreach ($params['shards'] as $shard) { $shards[] = array('id' => $shard['id']); } return $shards; } /** * @param string $sql * @param array $params * @param array $types * * @return array * * @throws \RuntimeException */ public function queryAll($sql, array $params, array $types) { $shards = $this->getShards(); if (!$shards) { throw new \RuntimeException("No shards found."); } $result = array(); $oldDistribution = $this->getCurrentDistributionValue(); foreach ($shards as $shard) { $this->conn->connect($shard['id']); foreach ($this->conn->fetchAll($sql, $params, $types) as $row) { $result[] = $row; } } if ($oldDistribution === null) { $this->selectGlobal(); } else { $this->selectShard($oldDistribution); } return $result; } } dbal-2.5.13/lib/Doctrine/DBAL/Sharding/SQLAzure/000077500000000000000000000000001313473450000207305ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php000066400000000000000000000237171313473450000277230ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Sharding\SQLAzure; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Schema\Synchronizer\AbstractSchemaSynchronizer; use Doctrine\DBAL\Schema\Synchronizer\SingleDatabaseSynchronizer; use Doctrine\DBAL\Schema\Synchronizer\SchemaSynchronizer; /** * SQL Azure Schema Synchronizer. * * Will iterate over all shards when performing schema operations. This is done * by partitioning the passed schema into subschemas for the federation and the * global database and then applying the operations step by step using the * {@see \Doctrine\DBAL\Schema\Synchronizer\SingleDatabaseSynchronizer}. * * @author Benjamin Eberlei */ class SQLAzureFederationsSynchronizer extends AbstractSchemaSynchronizer { const FEDERATION_TABLE_FEDERATED = 'azure.federated'; const FEDERATION_DISTRIBUTION_NAME = 'azure.federatedOnDistributionName'; /** * @var \Doctrine\DBAL\Sharding\SQLAzure\SQLAzureShardManager */ private $shardManager; /** * @var \Doctrine\DBAL\Schema\Synchronizer\SchemaSynchronizer */ private $synchronizer; /** * @param \Doctrine\DBAL\Connection $conn * @param \Doctrine\DBAL\Sharding\SQLAzure\SQLAzureShardManager $shardManager * @param \Doctrine\DBAL\Schema\Synchronizer\SchemaSynchronizer|null $sync */ public function __construct(Connection $conn, SQLAzureShardManager $shardManager, SchemaSynchronizer $sync = null) { parent::__construct($conn); $this->shardManager = $shardManager; $this->synchronizer = $sync ?: new SingleDatabaseSynchronizer($conn); } /** * {@inheritdoc} */ public function getCreateSchema(Schema $createSchema) { $sql = array(); list($global, $federation) = $this->partitionSchema($createSchema); $globalSql = $this->synchronizer->getCreateSchema($global); if ($globalSql) { $sql[] = "-- Create Root Federation\n" . "USE FEDERATION ROOT WITH RESET;"; $sql = array_merge($sql, $globalSql); } $federationSql = $this->synchronizer->getCreateSchema($federation); if ($federationSql) { $defaultValue = $this->getFederationTypeDefaultValue(); $sql[] = $this->getCreateFederationStatement(); $sql[] = "USE FEDERATION " . $this->shardManager->getFederationName() . " (" . $this->shardManager->getDistributionKey() . " = " . $defaultValue . ") WITH RESET, FILTERING = OFF;"; $sql = array_merge($sql, $federationSql); } return $sql; } /** * {@inheritdoc} */ public function getUpdateSchema(Schema $toSchema, $noDrops = false) { return $this->work($toSchema, function ($synchronizer, $schema) use ($noDrops) { return $synchronizer->getUpdateSchema($schema, $noDrops); }); } /** * {@inheritdoc} */ public function getDropSchema(Schema $dropSchema) { return $this->work($dropSchema, function ($synchronizer, $schema) { return $synchronizer->getDropSchema($schema); }); } /** * {@inheritdoc} */ public function createSchema(Schema $createSchema) { $this->processSql($this->getCreateSchema($createSchema)); } /** * {@inheritdoc} */ public function updateSchema(Schema $toSchema, $noDrops = false) { $this->processSql($this->getUpdateSchema($toSchema, $noDrops)); } /** * {@inheritdoc} */ public function dropSchema(Schema $dropSchema) { $this->processSqlSafely($this->getDropSchema($dropSchema)); } /** * {@inheritdoc} */ public function getDropAllSchema() { $this->shardManager->selectGlobal(); $globalSql = $this->synchronizer->getDropAllSchema(); if ($globalSql) { $sql[] = "-- Work on Root Federation\nUSE FEDERATION ROOT WITH RESET;"; $sql = array_merge($sql, $globalSql); } $shards = $this->shardManager->getShards(); foreach ($shards as $shard) { $this->shardManager->selectShard($shard['rangeLow']); $federationSql = $this->synchronizer->getDropAllSchema(); if ($federationSql) { $sql[] = "-- Work on Federation ID " . $shard['id'] . "\n" . "USE FEDERATION " . $this->shardManager->getFederationName() . " (" . $this->shardManager->getDistributionKey() . " = " . $shard['rangeLow'].") WITH RESET, FILTERING = OFF;"; $sql = array_merge($sql, $federationSql); } } $sql[] = "USE FEDERATION ROOT WITH RESET;"; $sql[] = "DROP FEDERATION " . $this->shardManager->getFederationName(); return $sql; } /** * {@inheritdoc} */ public function dropAllSchema() { $this->processSqlSafely($this->getDropAllSchema()); } /** * @param \Doctrine\DBAL\Schema\Schema $schema * * @return array */ private function partitionSchema(Schema $schema) { return array( $this->extractSchemaFederation($schema, false), $this->extractSchemaFederation($schema, true), ); } /** * @param \Doctrine\DBAL\Schema\Schema $schema * @param boolean $isFederation * * @return \Doctrine\DBAL\Schema\Schema * * @throws \RuntimeException */ private function extractSchemaFederation(Schema $schema, $isFederation) { $partitionedSchema = clone $schema; foreach ($partitionedSchema->getTables() as $table) { if ($isFederation) { $table->addOption(self::FEDERATION_DISTRIBUTION_NAME, $this->shardManager->getDistributionKey()); } if ($table->hasOption(self::FEDERATION_TABLE_FEDERATED) !== $isFederation) { $partitionedSchema->dropTable($table->getName()); } else { foreach ($table->getForeignKeys() as $fk) { $foreignTable = $schema->getTable($fk->getForeignTableName()); if ($foreignTable->hasOption(self::FEDERATION_TABLE_FEDERATED) !== $isFederation) { throw new \RuntimeException("Cannot have foreign key between global/federation."); } } } } return $partitionedSchema; } /** * Work on the Global/Federation based on currently existing shards and * perform the given operation on the underlying schema synchronizer given * the different partitioned schema instances. * * @param \Doctrine\DBAL\Schema\Schema $schema * @param \Closure $operation * * @return array */ private function work(Schema $schema, \Closure $operation) { list($global, $federation) = $this->partitionSchema($schema); $sql = array(); $this->shardManager->selectGlobal(); $globalSql = $operation($this->synchronizer, $global); if ($globalSql) { $sql[] = "-- Work on Root Federation\nUSE FEDERATION ROOT WITH RESET;"; $sql = array_merge($sql, $globalSql); } $shards = $this->shardManager->getShards(); foreach ($shards as $shard) { $this->shardManager->selectShard($shard['rangeLow']); $federationSql = $operation($this->synchronizer, $federation); if ($federationSql) { $sql[] = "-- Work on Federation ID " . $shard['id'] . "\n" . "USE FEDERATION " . $this->shardManager->getFederationName() . " (" . $this->shardManager->getDistributionKey() . " = " . $shard['rangeLow'].") WITH RESET, FILTERING = OFF;"; $sql = array_merge($sql, $federationSql); } } return $sql; } /** * @return string */ private function getFederationTypeDefaultValue() { $federationType = Type::getType($this->shardManager->getDistributionType()); switch ($federationType->getName()) { case Type::GUID: $defaultValue = '00000000-0000-0000-0000-000000000000'; break; case Type::INTEGER: case Type::SMALLINT: case Type::BIGINT: $defaultValue = '0'; break; default: $defaultValue = ''; break; } return $defaultValue; } /** * @return string */ private function getCreateFederationStatement() { $federationType = Type::getType($this->shardManager->getDistributionType()); $federationTypeSql = $federationType->getSqlDeclaration(array(), $this->conn->getDatabasePlatform()); return "--Create Federation\n" . "CREATE FEDERATION " . $this->shardManager->getFederationName() . " (" . $this->shardManager->getDistributionKey() . " " . $federationTypeSql ." RANGE)"; } } dbal-2.5.13/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php000066400000000000000000000153611313473450000253720ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Sharding\SQLAzure; use Doctrine\DBAL\Sharding\ShardManager; use Doctrine\DBAL\Sharding\ShardingException; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Types\Type; /** * Sharding using the SQL Azure Federations support. * * @author Benjamin Eberlei */ class SQLAzureShardManager implements ShardManager { /** * @var string */ private $federationName; /** * @var boolean */ private $filteringEnabled; /** * @var string */ private $distributionKey; /** * @var string */ private $distributionType; /** * @var \Doctrine\DBAL\Connection */ private $conn; /** * @var string */ private $currentDistributionValue; /** * @param \Doctrine\DBAL\Connection $conn * * @throws \Doctrine\DBAL\Sharding\ShardingException */ public function __construct(Connection $conn) { $this->conn = $conn; $params = $conn->getParams(); if ( ! isset($params['sharding']['federationName'])) { throw ShardingException::missingDefaultFederationName(); } if ( ! isset($params['sharding']['distributionKey'])) { throw ShardingException::missingDefaultDistributionKey(); } if ( ! isset($params['sharding']['distributionType'])) { throw ShardingException::missingDistributionType(); } $this->federationName = $params['sharding']['federationName']; $this->distributionKey = $params['sharding']['distributionKey']; $this->distributionType = $params['sharding']['distributionType']; $this->filteringEnabled = (isset($params['sharding']['filteringEnabled'])) ? (bool) $params['sharding']['filteringEnabled'] : false; } /** * Gets the name of the federation. * * @return string */ public function getFederationName() { return $this->federationName; } /** * Gets the distribution key. * * @return string */ public function getDistributionKey() { return $this->distributionKey; } /** * Gets the Doctrine Type name used for the distribution. * * @return string */ public function getDistributionType() { return $this->distributionType; } /** * Sets Enabled/Disable filtering on the fly. * * @param boolean $flag * * @return void */ public function setFilteringEnabled($flag) { $this->filteringEnabled = (bool) $flag; } /** * {@inheritDoc} */ public function selectGlobal() { if ($this->conn->isTransactionActive()) { throw ShardingException::activeTransaction(); } $sql = "USE FEDERATION ROOT WITH RESET"; $this->conn->exec($sql); $this->currentDistributionValue = null; } /** * {@inheritDoc} */ public function selectShard($distributionValue) { if ($this->conn->isTransactionActive()) { throw ShardingException::activeTransaction(); } if ($distributionValue === null || is_bool($distributionValue) || !is_scalar($distributionValue)) { throw ShardingException::noShardDistributionValue(); } $platform = $this->conn->getDatabasePlatform(); $sql = sprintf( "USE FEDERATION %s (%s = %s) WITH RESET, FILTERING = %s;", $platform->quoteIdentifier($this->federationName), $platform->quoteIdentifier($this->distributionKey), $this->conn->quote($distributionValue), ($this->filteringEnabled ? 'ON' : 'OFF') ); $this->conn->exec($sql); $this->currentDistributionValue = $distributionValue; } /** * {@inheritDoc} */ public function getCurrentDistributionValue() { return $this->currentDistributionValue; } /** * {@inheritDoc} */ public function getShards() { $sql = "SELECT member_id as id, distribution_name as distribution_key, CAST(range_low AS CHAR) AS rangeLow, CAST(range_high AS CHAR) AS rangeHigh FROM sys.federation_member_distributions d INNER JOIN sys.federations f ON f.federation_id = d.federation_id WHERE f.name = " . $this->conn->quote($this->federationName); return $this->conn->fetchAll($sql); } /** * {@inheritDoc} */ public function queryAll($sql, array $params = array(), array $types = array()) { $shards = $this->getShards(); if (!$shards) { throw new \RuntimeException("No shards found for " . $this->federationName); } $result = array(); $oldDistribution = $this->getCurrentDistributionValue(); foreach ($shards as $shard) { $this->selectShard($shard['rangeLow']); foreach ($this->conn->fetchAll($sql, $params, $types) as $row) { $result[] = $row; } } if ($oldDistribution === null) { $this->selectGlobal(); } else { $this->selectShard($oldDistribution); } return $result; } /** * Splits Federation at a given distribution value. * * @param mixed $splitDistributionValue * * @return void */ public function splitFederation($splitDistributionValue) { $type = Type::getType($this->distributionType); $sql = "ALTER FEDERATION " . $this->getFederationName() . " " . "SPLIT AT (" . $this->getDistributionKey() . " = " . $this->conn->quote($splitDistributionValue, $type->getBindingType()) . ")"; $this->conn->exec($sql); } } dbal-2.5.13/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/000077500000000000000000000000001313473450000221305ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php000066400000000000000000000123421313473450000264670ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Sharding\SQLAzure\Schema; use Doctrine\DBAL\Schema\Visitor\Visitor; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\Sequence; use Doctrine\DBAL\Schema\Index; /** * Converts a single tenant schema into a multi-tenant schema for SQL Azure * Federations under the following assumptions: * * - Every table is part of the multi-tenant application, only explicitly * excluded tables are non-federated. The behavior of the tables being in * global or federated database is undefined. It depends on you selecting a * federation before DDL statements or not. * - Every Primary key of a federated table is extended by another column * 'tenant_id' with a default value of the SQLAzure function * `federation_filtering_value('tenant_id')`. * - You always have to work with `filtering=On` when using federations with this * multi-tenant approach. * - Primary keys are either using globally unique ids (GUID, Table Generator) * or you explicitly add the tenent_id in every UPDATE or DELETE statement * (otherwise they will affect the same-id rows from other tenents as well). * SQLAzure throws errors when you try to create IDENTIY columns on federated * tables. * * @author Benjamin Eberlei */ class MultiTenantVisitor implements Visitor { /** * @var array */ private $excludedTables = array(); /** * @var string */ private $tenantColumnName; /** * @var string */ private $tenantColumnType = 'integer'; /** * Name of the federation distribution, defaulting to the tenantColumnName * if not specified. * * @var string */ private $distributionName; /** * @param array $excludedTables * @param string $tenantColumnName * @param string|null $distributionName */ public function __construct(array $excludedTables = array(), $tenantColumnName = 'tenant_id', $distributionName = null) { $this->excludedTables = $excludedTables; $this->tenantColumnName = $tenantColumnName; $this->distributionName = $distributionName ?: $tenantColumnName; } /** * {@inheritdoc} */ public function acceptTable(Table $table) { if (in_array($table->getName(), $this->excludedTables)) { return; } $table->addColumn($this->tenantColumnName, $this->tenantColumnType, array( 'default' => "federation_filtering_value('". $this->distributionName ."')", )); $clusteredIndex = $this->getClusteredIndex($table); $indexColumns = $clusteredIndex->getColumns(); $indexColumns[] = $this->tenantColumnName; if ($clusteredIndex->isPrimary()) { $table->dropPrimaryKey(); $table->setPrimaryKey($indexColumns); } else { $table->dropIndex($clusteredIndex->getName()); $table->addIndex($indexColumns, $clusteredIndex->getName()); $table->getIndex($clusteredIndex->getName())->addFlag('clustered'); } } /** * @param \Doctrine\DBAL\Schema\Table $table * * @return \Doctrine\DBAL\Schema\Index * * @throws \RuntimeException */ private function getClusteredIndex($table) { foreach ($table->getIndexes() as $index) { if ($index->isPrimary() && ! $index->hasFlag('nonclustered')) { return $index; } elseif ($index->hasFlag('clustered')) { return $index; } } throw new \RuntimeException("No clustered index found on table " . $table->getName()); } /** * {@inheritdoc} */ public function acceptSchema(Schema $schema) { } /** * {@inheritdoc} */ public function acceptColumn(Table $table, Column $column) { } /** * {@inheritdoc} */ public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) { } /** * {@inheritdoc} */ public function acceptIndex(Table $table, Index $index) { } /** * {@inheritdoc} */ public function acceptSequence(Sequence $sequence) { } } dbal-2.5.13/lib/Doctrine/DBAL/Sharding/ShardChoser/000077500000000000000000000000001313473450000214675ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Sharding/ShardChoser/MultiTenantShardChoser.php000066400000000000000000000026771313473450000266060ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Sharding\ShardChoser; use Doctrine\DBAL\Sharding\PoolingShardConnection; /** * The MultiTenant Shard choser assumes that the distribution value directly * maps to the shard id. * * @author Benjamin Eberlei */ class MultiTenantShardChoser implements ShardChoser { /** * {@inheritdoc} */ public function pickShard($distributionValue, PoolingShardConnection $conn) { return $distributionValue; } } dbal-2.5.13/lib/Doctrine/DBAL/Sharding/ShardChoser/ShardChoser.php000066400000000000000000000031571313473450000244130ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Sharding\ShardChoser; use Doctrine\DBAL\Sharding\PoolingShardConnection; /** * Given a distribution value this shard-choser strategy will pick the shard to * connect to for retrieving rows with the distribution value. * * @author Benjamin Eberlei */ interface ShardChoser { /** * Picks a shard for the given distribution value. * * @param string $distributionValue * @param \Doctrine\DBAL\Sharding\PoolingShardConnection $conn * * @return integer */ function pickShard($distributionValue, PoolingShardConnection $conn); } dbal-2.5.13/lib/Doctrine/DBAL/Sharding/ShardManager.php000066400000000000000000000063241313473450000223340ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Sharding; /** * Sharding Manager gives access to APIs to implementing sharding on top of * Doctrine\DBAL\Connection instances. * * For simplicity and developer ease-of-use (and understanding) the sharding * API only covers single shard queries, no fan-out support. It is primarily * suited for multi-tenant applications. * * The assumption about sharding here * is that a distribution value can be found that gives access to all the * necessary data for all use-cases. Switching between shards should be done with * caution, especially if lazy loading is implemented. Any query is always * executed against the last shard that was selected. If a query is created for * a shard Y but then a shard X is selected when its actually executed you * will hit the wrong shard. * * @author Benjamin Eberlei */ interface ShardManager { /** * Selects global database with global data. * * This is the default database that is connected when no shard is * selected. * * @return void */ function selectGlobal(); /** * Selects the shard against which the queries after this statement will be issued. * * @param string $distributionValue * * @return void * * @throws \Doctrine\DBAL\Sharding\ShardingException If no value is passed as shard identifier. */ function selectShard($distributionValue); /** * Gets the distribution value currently used for sharding. * * @return string */ function getCurrentDistributionValue(); /** * Gets information about the amount of shards and other details. * * Format is implementation specific, each shard is one element and has an * 'id' attribute at least. * * @return array */ function getShards(); /** * Queries all shards in undefined order and return the results appended to * each other. Restore the previous distribution value after execution. * * Using {@link \Doctrine\DBAL\Connection::fetchAll} to retrieve rows internally. * * @param string $sql * @param array $params * @param array $types * * @return array */ function queryAll($sql, array $params, array $types); } dbal-2.5.13/lib/Doctrine/DBAL/Sharding/ShardingException.php000066400000000000000000000051311313473450000234110ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Sharding; use Doctrine\DBAL\DBALException; /** * Sharding related Exceptions * * @since 2.3 */ class ShardingException extends DBALException { /** * @return \Doctrine\DBAL\Sharding\ShardingException */ static public function notImplemented() { return new self("This functionality is not implemented with this sharding provider.", 1331557937); } /** * @return \Doctrine\DBAL\Sharding\ShardingException */ static public function missingDefaultFederationName() { return new self("SQLAzure requires a federation name to be set during sharding configuration.", 1332141280); } /** * @return \Doctrine\DBAL\Sharding\ShardingException */ static public function missingDefaultDistributionKey() { return new self("SQLAzure requires a distribution key to be set during sharding configuration.", 1332141329); } /** * @return \Doctrine\DBAL\Sharding\ShardingException */ static public function activeTransaction() { return new self("Cannot switch shard during an active transaction.", 1332141766); } /** * @return \Doctrine\DBAL\Sharding\ShardingException */ static public function noShardDistributionValue() { return new self("You have to specify a string or integer as shard distribution value.", 1332142103); } /** * @return \Doctrine\DBAL\Sharding\ShardingException */ static public function missingDistributionType() { return new self("You have to specify a sharding distribution type such as 'integer', 'string', 'guid'."); } } dbal-2.5.13/lib/Doctrine/DBAL/Statement.php000066400000000000000000000215531313473450000202060ustar00rootroot00000000000000. */ namespace Doctrine\DBAL; use PDO; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Driver\Statement as DriverStatement; /** * A thin wrapper around a Doctrine\DBAL\Driver\Statement that adds support * for logging, DBAL mapping types, etc. * * @author Roman Borschel * @since 2.0 */ class Statement implements \IteratorAggregate, DriverStatement { /** * The SQL statement. * * @var string */ protected $sql; /** * The bound parameters. * * @var array */ protected $params = array(); /** * The parameter types. * * @var array */ protected $types = array(); /** * The underlying driver statement. * * @var \Doctrine\DBAL\Driver\Statement */ protected $stmt; /** * The underlying database platform. * * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ protected $platform; /** * The connection this statement is bound to and executed on. * * @var \Doctrine\DBAL\Connection */ protected $conn; /** * Creates a new Statement for the given SQL and Connection. * * @param string $sql The SQL of the statement. * @param \Doctrine\DBAL\Connection $conn The connection on which the statement should be executed. */ public function __construct($sql, Connection $conn) { $this->sql = $sql; $this->stmt = $conn->getWrappedConnection()->prepare($sql); $this->conn = $conn; $this->platform = $conn->getDatabasePlatform(); } /** * Binds a parameter value to the statement. * * The value can optionally be bound with a PDO binding type or a DBAL mapping type. * If bound with a DBAL mapping type, the binding type is derived from the mapping * type and the value undergoes the conversion routines of the mapping type before * being bound. * * @param string $name The name or position of the parameter. * @param mixed $value The value of the parameter. * @param mixed $type Either a PDO binding type or a DBAL mapping type name or instance. * * @return boolean TRUE on success, FALSE on failure. */ public function bindValue($name, $value, $type = null) { $this->params[$name] = $value; $this->types[$name] = $type; if ($type !== null) { if (is_string($type)) { $type = Type::getType($type); } if ($type instanceof Type) { $value = $type->convertToDatabaseValue($value, $this->platform); $bindingType = $type->getBindingType(); } else { $bindingType = $type; // PDO::PARAM_* constants } return $this->stmt->bindValue($name, $value, $bindingType); } else { return $this->stmt->bindValue($name, $value); } } /** * Binds a parameter to a value by reference. * * Binding a parameter by reference does not support DBAL mapping types. * * @param string $name The name or position of the parameter. * @param mixed $var The reference to the variable to bind. * @param integer $type The PDO binding type. * @param integer|null $length Must be specified when using an OUT bind * so that PHP allocates enough memory to hold the returned value. * * @return boolean TRUE on success, FALSE on failure. */ public function bindParam($name, &$var, $type = PDO::PARAM_STR, $length = null) { $this->params[$name] = $var; $this->types[$name] = $type; return $this->stmt->bindParam($name, $var, $type, $length); } /** * Executes the statement with the currently bound parameters. * * @param array|null $params * * @return boolean TRUE on success, FALSE on failure. * * @throws \Doctrine\DBAL\DBALException */ public function execute($params = null) { if (is_array($params)) { $this->params = $params; } $logger = $this->conn->getConfiguration()->getSQLLogger(); if ($logger) { $logger->startQuery($this->sql, $this->params, $this->types); } try { $stmt = $this->stmt->execute($params); } catch (\Exception $ex) { if ($logger) { $logger->stopQuery(); } throw DBALException::driverExceptionDuringQuery( $this->conn->getDriver(), $ex, $this->sql, $this->conn->resolveParams($this->params, $this->types) ); } if ($logger) { $logger->stopQuery(); } $this->params = array(); $this->types = array(); return $stmt; } /** * Closes the cursor, freeing the database resources used by this statement. * * @return boolean TRUE on success, FALSE on failure. */ public function closeCursor() { return $this->stmt->closeCursor(); } /** * Returns the number of columns in the result set. * * @return integer */ public function columnCount() { return $this->stmt->columnCount(); } /** * Fetches the SQLSTATE associated with the last operation on the statement. * * @return string */ public function errorCode() { return $this->stmt->errorCode(); } /** * Fetches extended error information associated with the last operation on the statement. * * @return array */ public function errorInfo() { return $this->stmt->errorInfo(); } /** * {@inheritdoc} */ public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) { if ($arg2 === null) { return $this->stmt->setFetchMode($fetchMode); } elseif ($arg3 === null) { return $this->stmt->setFetchMode($fetchMode, $arg2); } return $this->stmt->setFetchMode($fetchMode, $arg2, $arg3); } /** * Required by interface IteratorAggregate. * * {@inheritdoc} */ public function getIterator() { return $this->stmt; } /** * Fetches the next row from a result set. * * @param integer|null $fetchMode * * @return mixed The return value of this function on success depends on the fetch type. * In all cases, FALSE is returned on failure. */ public function fetch($fetchMode = null) { return $this->stmt->fetch($fetchMode); } /** * Returns an array containing all of the result set rows. * * @param integer|null $fetchMode * @param mixed $fetchArgument * * @return array An array containing all of the remaining rows in the result set. */ public function fetchAll($fetchMode = null, $fetchArgument = 0) { if ($fetchArgument !== 0) { return $this->stmt->fetchAll($fetchMode, $fetchArgument); } return $this->stmt->fetchAll($fetchMode); } /** * Returns a single column from the next row of a result set. * * @param integer $columnIndex * * @return mixed A single column from the next row of a result set or FALSE if there are no more rows. */ public function fetchColumn($columnIndex = 0) { return $this->stmt->fetchColumn($columnIndex); } /** * Returns the number of rows affected by the last execution of this statement. * * @return integer The number of affected rows. */ public function rowCount() { return $this->stmt->rowCount(); } /** * Gets the wrapped driver statement. * * @return \Doctrine\DBAL\Driver\Statement */ public function getWrappedStatement() { return $this->stmt; } } dbal-2.5.13/lib/Doctrine/DBAL/Tools/000077500000000000000000000000001313473450000166235ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Tools/Console/000077500000000000000000000000001313473450000202255ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Tools/Console/Command/000077500000000000000000000000001313473450000216035ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php000066400000000000000000000111731313473450000250700ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Tools\Console\Command; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * Task for executing arbitrary SQL that can come from a file or directly from * the command line. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel */ class ImportCommand extends Command { /** * {@inheritdoc} */ protected function configure() { $this ->setName('dbal:import') ->setDescription('Import SQL file(s) directly to Database.') ->setDefinition(array( new InputArgument( 'file', InputArgument::REQUIRED | InputArgument::IS_ARRAY, 'File path(s) of SQL to be executed.' ) )) ->setHelp(<<getHelper('db')->getConnection(); if (($fileNames = $input->getArgument('file')) !== null) { foreach ((array) $fileNames as $fileName) { $filePath = realpath($fileName); // Phar compatibility. if (false === $filePath) { $filePath = $fileName; } if ( ! file_exists($filePath)) { throw new \InvalidArgumentException( sprintf("SQL file '%s' does not exist.", $filePath) ); } elseif ( ! is_readable($filePath)) { throw new \InvalidArgumentException( sprintf("SQL file '%s' does not have read permissions.", $filePath) ); } $output->write(sprintf("Processing file '%s'... ", $filePath)); $sql = file_get_contents($filePath); if ($conn instanceof \Doctrine\DBAL\Driver\PDOConnection) { // PDO Drivers try { $lines = 0; $stmt = $conn->prepare($sql); $stmt->execute(); do { // Required due to "MySQL has gone away!" issue $stmt->fetch(); $stmt->closeCursor(); $lines++; } while ($stmt->nextRowset()); $output->write(sprintf('%d statements executed!', $lines) . PHP_EOL); } catch (\PDOException $e) { $output->write('error!' . PHP_EOL); throw new \RuntimeException($e->getMessage(), $e->getCode(), $e); } } else { // Non-PDO Drivers (ie. OCI8 driver) $stmt = $conn->prepare($sql); $rs = $stmt->execute(); if ($rs) { $output->writeln('OK!' . PHP_EOL); } else { $error = $stmt->errorInfo(); $output->write('error!' . PHP_EOL); throw new \RuntimeException($error[2], $error[0]); } $stmt->closeCursor(); } } } } } dbal-2.5.13/lib/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php000066400000000000000000000144101313473450000264110ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Tools\Console\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Doctrine\DBAL\Platforms\Keywords\ReservedKeywordsValidator; class ReservedWordsCommand extends Command { /** * @var array */ private $keywordListClasses = array( 'mysql' => 'Doctrine\DBAL\Platforms\Keywords\MySQLKeywords', 'mysql57' => 'Doctrine\DBAL\Platforms\Keywords\MySQL57Keywords', 'sqlserver' => 'Doctrine\DBAL\Platforms\Keywords\SQLServerKeywords', 'sqlserver2005' => 'Doctrine\DBAL\Platforms\Keywords\SQLServer2005Keywords', 'sqlserver2008' => 'Doctrine\DBAL\Platforms\Keywords\SQLServer2008Keywords', 'sqlserver2012' => 'Doctrine\DBAL\Platforms\Keywords\SQLServer2012Keywords', 'sqlite' => 'Doctrine\DBAL\Platforms\Keywords\SQLiteKeywords', 'pgsql' => 'Doctrine\DBAL\Platforms\Keywords\PostgreSQLKeywords', 'pgsql91' => 'Doctrine\DBAL\Platforms\Keywords\PostgreSQL91Keywords', 'pgsql92' => 'Doctrine\DBAL\Platforms\Keywords\PostgreSQL92Keywords', 'oracle' => 'Doctrine\DBAL\Platforms\Keywords\OracleKeywords', 'db2' => 'Doctrine\DBAL\Platforms\Keywords\DB2Keywords', 'sqlanywhere' => 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhereKeywords', 'sqlanywhere11' => 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhere11Keywords', 'sqlanywhere12' => 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhere12Keywords', 'sqlanywhere16' => 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhere16Keywords', ); /** * If you want to add or replace a keywords list use this command. * * @param string $name * @param string $class * * @return void */ public function setKeywordListClass($name, $class) { $this->keywordListClasses[$name] = $class; } /** * {@inheritdoc} */ protected function configure() { $this ->setName('dbal:reserved-words') ->setDescription('Checks if the current database contains identifiers that are reserved.') ->setDefinition(array( new InputOption( 'list', 'l', InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Keyword-List name.' ) )) ->setHelp(<<%command.full_name% If you want to check against specific dialects you can pass them to the command: %command.full_name% mysql pgsql The following keyword lists are currently shipped with Doctrine: * mysql * mysql57 * pgsql * pgsql92 * sqlite * oracle * sqlserver * sqlserver2005 * sqlserver2008 * sqlserver2012 * sqlanywhere * sqlanywhere11 * sqlanywhere12 * sqlanywhere16 * db2 (Not checked by default) EOT ); } /** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { /* @var $conn \Doctrine\DBAL\Connection */ $conn = $this->getHelper('db')->getConnection(); $keywordLists = (array) $input->getOption('list'); if ( ! $keywordLists) { $keywordLists = array( 'mysql', 'mysql57', 'pgsql', 'pgsql92', 'sqlite', 'oracle', 'sqlserver', 'sqlserver2005', 'sqlserver2008', 'sqlserver2012', 'sqlanywhere', 'sqlanywhere11', 'sqlanywhere12', 'sqlanywhere16', ); } $keywords = array(); foreach ($keywordLists as $keywordList) { if (!isset($this->keywordListClasses[$keywordList])) { throw new \InvalidArgumentException( "There exists no keyword list with name '" . $keywordList . "'. ". "Known lists: " . implode(", ", array_keys($this->keywordListClasses)) ); } $class = $this->keywordListClasses[$keywordList]; $keywords[] = new $class; } $output->write('Checking keyword violations for ' . implode(", ", $keywordLists) . "...", true); /* @var $schema \Doctrine\DBAL\Schema\Schema */ $schema = $conn->getSchemaManager()->createSchema(); $visitor = new ReservedKeywordsValidator($keywords); $schema->visit($visitor); $violations = $visitor->getViolations(); if (count($violations) == 0) { $output->write("No reserved keywords violations have been found!", true); } else { $output->write('There are ' . count($violations) . ' reserved keyword violations in your database schema:', true); foreach ($violations as $violation) { $output->write(' - ' . $violation, true); } return 1; } } } dbal-2.5.13/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php000066400000000000000000000061041313473450000250400ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Tools\Console\Command; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputOption; /** * Task for executing arbitrary SQL that can come from a file or directly from * the command line. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel */ class RunSqlCommand extends Command { /** * {@inheritdoc} */ protected function configure() { $this ->setName('dbal:run-sql') ->setDescription('Executes arbitrary SQL directly from the command line.') ->setDefinition(array( new InputArgument('sql', InputArgument::REQUIRED, 'The SQL statement to execute.'), new InputOption('depth', null, InputOption::VALUE_REQUIRED, 'Dumping depth of result set.', 7) )) ->setHelp(<<getHelper('db')->getConnection(); if (($sql = $input->getArgument('sql')) === null) { throw new \RuntimeException("Argument 'SQL' is required in order to execute this command correctly."); } $depth = $input->getOption('depth'); if ( ! is_numeric($depth)) { throw new \LogicException("Option 'depth' must contains an integer value"); } if (stripos($sql, 'select') === 0) { $resultSet = $conn->fetchAll($sql); } else { $resultSet = $conn->executeUpdate($sql); } ob_start(); \Doctrine\Common\Util\Debug::dump($resultSet, (int) $depth); $message = ob_get_clean(); $output->write($message); } } dbal-2.5.13/lib/Doctrine/DBAL/Tools/Console/ConsoleRunner.php000066400000000000000000000064141313473450000235370ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Tools\Console; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Tools\Console\Command\ImportCommand; use Doctrine\DBAL\Tools\Console\Command\ReservedWordsCommand; use Doctrine\DBAL\Tools\Console\Command\RunSqlCommand; use Symfony\Component\Console\Helper\HelperSet; use Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper; use Symfony\Component\Console\Application; use Doctrine\DBAL\Version; /** * Handles running the Console Tools inside Symfony Console context. */ class ConsoleRunner { /** * Create a Symfony Console HelperSet * * @param Connection $connection * * @return HelperSet */ static public function createHelperSet(Connection $connection) { return new HelperSet(array( 'db' => new ConnectionHelper($connection) )); } /** * Runs console with the given helperset. * * @param \Symfony\Component\Console\Helper\HelperSet $helperSet * @param \Symfony\Component\Console\Command\Command[] $commands * * @return void */ static public function run(HelperSet $helperSet, $commands = array()) { $cli = new Application('Doctrine Command Line Interface', Version::VERSION); $cli->setCatchExceptions(true); $cli->setHelperSet($helperSet); self::addCommands($cli); $cli->addCommands($commands); $cli->run(); } /** * @param Application $cli * * @return void */ static public function addCommands(Application $cli) { $cli->addCommands(array( new RunSqlCommand(), new ImportCommand(), new ReservedWordsCommand(), )); } /** * Prints the instructions to create a configuration file */ static public function printCliConfigTemplate() { echo <<<'HELP' You are missing a "cli-config.php" or "config/cli-config.php" file in your project, which is required to get the Doctrine-DBAL Console working. You can use the following sample as a template: . */ namespace Doctrine\DBAL\Tools\Console\Helper; use Symfony\Component\Console\Helper\Helper; use Doctrine\DBAL\Connection; /** * Doctrine CLI Connection Helper. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel */ class ConnectionHelper extends Helper { /** * The Doctrine database Connection. * * @var \Doctrine\DBAL\Connection */ protected $_connection; /** * Constructor. * * @param \Doctrine\DBAL\Connection $connection The Doctrine database Connection. */ public function __construct(Connection $connection) { $this->_connection = $connection; } /** * Retrieves the Doctrine database Connection. * * @return \Doctrine\DBAL\Connection */ public function getConnection() { return $this->_connection; } /** * {@inheritdoc} */ public function getName() { return 'connection'; } } dbal-2.5.13/lib/Doctrine/DBAL/Types/000077500000000000000000000000001313473450000166275ustar00rootroot00000000000000dbal-2.5.13/lib/Doctrine/DBAL/Types/ArrayType.php000066400000000000000000000044541313473450000212670ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Type that maps a PHP array to a clob SQL type. * * @since 2.0 */ class ArrayType extends Type { /** * {@inheritdoc} */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getClobTypeDeclarationSQL($fieldDeclaration); } /** * {@inheritdoc} */ public function convertToDatabaseValue($value, AbstractPlatform $platform) { // @todo 3.0 - $value === null check to save real NULL in database return serialize($value); } /** * {@inheritdoc} */ public function convertToPHPValue($value, AbstractPlatform $platform) { if ($value === null) { return null; } $value = (is_resource($value)) ? stream_get_contents($value) : $value; $val = unserialize($value); if ($val === false && $value != 'b:0;') { throw ConversionException::conversionFailed($value, $this->getName()); } return $val; } /** * {@inheritdoc} */ public function getName() { return Type::TARRAY; } /** * {@inheritdoc} */ public function requiresSQLCommentHint(AbstractPlatform $platform) { return true; } } dbal-2.5.13/lib/Doctrine/DBAL/Types/BigIntType.php000066400000000000000000000034351313473450000213630ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Type that maps a database BIGINT to a PHP string. * * @author robo * @since 2.0 */ class BigIntType extends Type { /** * {@inheritdoc} */ public function getName() { return Type::BIGINT; } /** * {@inheritdoc} */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getBigIntTypeDeclarationSQL($fieldDeclaration); } /** * {@inheritdoc} */ public function getBindingType() { return \PDO::PARAM_STR; } /** * {@inheritdoc} */ public function convertToPHPValue($value, AbstractPlatform $platform) { return (null === $value) ? null : (string) $value; } } dbal-2.5.13/lib/Doctrine/DBAL/Types/BinaryType.php000066400000000000000000000042401313473450000214260ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Type that maps ab SQL BINARY/VARBINARY to a PHP resource stream. * * @author Steve Müller * @since 2.5 */ class BinaryType extends Type { /** * {@inheritdoc} */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getBinaryTypeDeclarationSQL($fieldDeclaration); } /** * {@inheritdoc} */ public function convertToPHPValue($value, AbstractPlatform $platform) { if (null === $value) { return null; } if (is_string($value)) { $fp = fopen('php://temp', 'rb+'); fwrite($fp, $value); fseek($fp, 0); $value = $fp; } if ( ! is_resource($value)) { throw ConversionException::conversionFailed($value, self::BINARY); } return $value; } /** * {@inheritdoc} */ public function getName() { return Type::BINARY; } /** * {@inheritdoc} */ public function getBindingType() { return \PDO::PARAM_LOB; } } dbal-2.5.13/lib/Doctrine/DBAL/Types/BlobType.php000066400000000000000000000041271313473450000210640ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Type that maps an SQL BLOB to a PHP resource stream. * * @since 2.2 */ class BlobType extends Type { /** * {@inheritdoc} */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getBlobTypeDeclarationSQL($fieldDeclaration); } /** * {@inheritdoc} */ public function convertToPHPValue($value, AbstractPlatform $platform) { if (null === $value) { return null; } if (is_string($value)) { $fp = fopen('php://temp', 'rb+'); fwrite($fp, $value); fseek($fp, 0); $value = $fp; } if ( ! is_resource($value)) { throw ConversionException::conversionFailed($value, self::BLOB); } return $value; } /** * {@inheritdoc} */ public function getName() { return Type::BLOB; } /** * {@inheritdoc} */ public function getBindingType() { return \PDO::PARAM_LOB; } } dbal-2.5.13/lib/Doctrine/DBAL/Types/BooleanType.php000066400000000000000000000037151313473450000215670ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Type that maps an SQL boolean to a PHP boolean. * * @since 2.0 */ class BooleanType extends Type { /** * {@inheritdoc} */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getBooleanTypeDeclarationSQL($fieldDeclaration); } /** * {@inheritdoc} */ public function convertToDatabaseValue($value, AbstractPlatform $platform) { return $platform->convertBooleansToDatabaseValue($value); } /** * {@inheritdoc} */ public function convertToPHPValue($value, AbstractPlatform $platform) { return $platform->convertFromBoolean($value); } /** * {@inheritdoc} */ public function getName() { return Type::BOOLEAN; } /** * {@inheritdoc} */ public function getBindingType() { return \PDO::PARAM_BOOL; } } dbal-2.5.13/lib/Doctrine/DBAL/Types/ConversionException.php000066400000000000000000000050071313473450000233460ustar00rootroot00000000000000. */ /** * Conversion Exception is thrown when the database to PHP conversion fails. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel */ namespace Doctrine\DBAL\Types; class ConversionException extends \Doctrine\DBAL\DBALException { /** * Thrown when a Database to Doctrine Type Conversion fails. * * @param string $value * @param string $toType * * @return \Doctrine\DBAL\Types\ConversionException */ static public function conversionFailed($value, $toType) { $value = (strlen($value) > 32) ? substr($value, 0, 20) . "..." : $value; return new self('Could not convert database value "' . $value . '" to Doctrine Type ' . $toType); } /** * Thrown when a Database to Doctrine Type Conversion fails and we can make a statement * about the expected format. * * @param string $value * @param string $toType * @param string $expectedFormat * * @return \Doctrine\DBAL\Types\ConversionException */ static public function conversionFailedFormat($value, $toType, $expectedFormat) { $value = (strlen($value) > 32) ? substr($value, 0, 20) . "..." : $value; return new self( 'Could not convert database value "' . $value . '" to Doctrine Type ' . $toType . '. Expected format: ' . $expectedFormat ); } } dbal-2.5.13/lib/Doctrine/DBAL/Types/DateTimeType.php000066400000000000000000000044361313473450000217050ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Type that maps an SQL DATETIME/TIMESTAMP to a PHP DateTime object. * * @since 2.0 */ class DateTimeType extends Type { /** * {@inheritdoc} */ public function getName() { return Type::DATETIME; } /** * {@inheritdoc} */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getDateTimeTypeDeclarationSQL($fieldDeclaration); } /** * {@inheritdoc} */ public function convertToDatabaseValue($value, AbstractPlatform $platform) { return ($value !== null) ? $value->format($platform->getDateTimeFormatString()) : null; } /** * {@inheritdoc} */ public function convertToPHPValue($value, AbstractPlatform $platform) { if ($value === null || $value instanceof \DateTime) { return $value; } $val = \DateTime::createFromFormat($platform->getDateTimeFormatString(), $value); if ( ! $val) { $val = date_create($value); } if ( ! $val) { throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getDateTimeFormatString()); } return $val; } } dbal-2.5.13/lib/Doctrine/DBAL/Types/DateTimeTzType.php000066400000000000000000000064011313473450000222150ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * DateTime type saving additional timezone information. * * Caution: Databases are not necessarily experts at storing timezone related * data of dates. First, of all the supported vendors only PostgreSQL and Oracle * support storing Timezone data. But those two don't save the actual timezone * attached to a DateTime instance (for example "Europe/Berlin" or "America/Montreal") * but the current offset of them related to UTC. That means depending on daylight saving times * or not you may get different offsets. * * This datatype makes only sense to use, if your application works with an offset, not * with an actual timezone that uses transitions. Otherwise your DateTime instance * attached with a timezone such as Europe/Berlin gets saved into the database with * the offset and re-created from persistence with only the offset, not the original timezone * attached. * * @link www.doctrine-project.org * @since 1.0 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel */ class DateTimeTzType extends Type { /** * {@inheritdoc} */ public function getName() { return Type::DATETIMETZ; } /** * {@inheritdoc} */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getDateTimeTzTypeDeclarationSQL($fieldDeclaration); } /** * {@inheritdoc} */ public function convertToDatabaseValue($value, AbstractPlatform $platform) { return ($value !== null) ? $value->format($platform->getDateTimeTzFormatString()) : null; } /** * {@inheritdoc} */ public function convertToPHPValue($value, AbstractPlatform $platform) { if ($value === null || $value instanceof \DateTime) { return $value; } $val = \DateTime::createFromFormat($platform->getDateTimeTzFormatString(), $value); if ( ! $val) { throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getDateTimeTzFormatString()); } return $val; } } dbal-2.5.13/lib/Doctrine/DBAL/Types/DateType.php000066400000000000000000000042551313473450000210650ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Type that maps an SQL DATE to a PHP Date object. * * @since 2.0 */ class DateType extends Type { /** * {@inheritdoc} */ public function getName() { return Type::DATE; } /** * {@inheritdoc} */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getDateTypeDeclarationSQL($fieldDeclaration); } /** * {@inheritdoc} */ public function convertToDatabaseValue($value, AbstractPlatform $platform) { return ($value !== null) ? $value->format($platform->getDateFormatString()) : null; } /** * {@inheritdoc} */ public function convertToPHPValue($value, AbstractPlatform $platform) { if ($value === null || $value instanceof \DateTime) { return $value; } $val = \DateTime::createFromFormat('!'.$platform->getDateFormatString(), $value); if ( ! $val) { throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getDateFormatString()); } return $val; } } dbal-2.5.13/lib/Doctrine/DBAL/Types/DecimalType.php000066400000000000000000000032151313473450000215410ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Type that maps an SQL DECIMAL to a PHP string. * * @since 2.0 */ class DecimalType extends Type { /** * {@inheritdoc} */ public function getName() { return Type::DECIMAL; } /** * {@inheritdoc} */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getDecimalTypeDeclarationSQL($fieldDeclaration); } /** * {@inheritdoc} */ public function convertToPHPValue($value, AbstractPlatform $platform) { return (null === $value) ? null : $value; } } dbal-2.5.13/lib/Doctrine/DBAL/Types/FloatType.php000066400000000000000000000031011313473450000212420ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; class FloatType extends Type { /** * {@inheritdoc} */ public function getName() { return Type::FLOAT; } /** * {@inheritdoc} */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getFloatDeclarationSQL($fieldDeclaration); } /** * {@inheritdoc} */ public function convertToPHPValue($value, AbstractPlatform $platform) { return (null === $value) ? null : (double) $value; } } dbal-2.5.13/lib/Doctrine/DBAL/Types/GuidType.php000066400000000000000000000033271313473450000210770ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Represents a GUID/UUID datatype (both are actually synonyms) in the database. * * @author Benjamin Eberlei * @since 2.3 */ class GuidType extends StringType { /** * {@inheritdoc} */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getGuidTypeDeclarationSQL($fieldDeclaration); } /** * {@inheritdoc} */ public function getName() { return Type::GUID; } /** * {@inheritdoc} */ public function requiresSQLCommentHint(AbstractPlatform $platform) { return !$platform->hasNativeGuidType(); } } dbal-2.5.13/lib/Doctrine/DBAL/Types/IntegerType.php000066400000000000000000000034721313473450000216050ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Type that maps an SQL INT to a PHP integer. * * @author Roman Borschel * @since 2.0 */ class IntegerType extends Type { /** * {@inheritdoc} */ public function getName() { return Type::INTEGER; } /** * {@inheritdoc} */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getIntegerTypeDeclarationSQL($fieldDeclaration); } /** * {@inheritdoc} */ public function convertToPHPValue($value, AbstractPlatform $platform) { return (null === $value) ? null : (int) $value; } /** * {@inheritdoc} */ public function getBindingType() { return \PDO::PARAM_INT; } } dbal-2.5.13/lib/Doctrine/DBAL/Types/JsonArrayType.php000066400000000000000000000043761313473450000221240ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Array Type which can be used to generate json arrays. * * @since 2.3 * @author Johannes M. Schmitt */ class JsonArrayType extends Type { /** * {@inheritdoc} */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getJsonTypeDeclarationSQL($fieldDeclaration); } /** * {@inheritdoc} */ public function convertToDatabaseValue($value, AbstractPlatform $platform) { if (null === $value) { return null; } return json_encode($value); } /** * {@inheritdoc} */ public function convertToPHPValue($value, AbstractPlatform $platform) { if ($value === null || $value === '') { return array(); } $value = (is_resource($value)) ? stream_get_contents($value) : $value; return json_decode($value, true); } /** * {@inheritdoc} */ public function getName() { return Type::JSON_ARRAY; } /** * {@inheritdoc} */ public function requiresSQLCommentHint(AbstractPlatform $platform) { return ! $platform->hasNativeJsonType(); } } dbal-2.5.13/lib/Doctrine/DBAL/Types/ObjectType.php000066400000000000000000000043441313473450000214150ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Type that maps a PHP object to a clob SQL type. * * @since 2.0 */ class ObjectType extends Type { /** * {@inheritdoc} */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getClobTypeDeclarationSQL($fieldDeclaration); } /** * {@inheritdoc} */ public function convertToDatabaseValue($value, AbstractPlatform $platform) { return serialize($value); } /** * {@inheritdoc} */ public function convertToPHPValue($value, AbstractPlatform $platform) { if ($value === null) { return null; } $value = (is_resource($value)) ? stream_get_contents($value) : $value; $val = unserialize($value); if ($val === false && $value !== 'b:0;') { throw ConversionException::conversionFailed($value, $this->getName()); } return $val; } /** * {@inheritdoc} */ public function getName() { return Type::OBJECT; } /** * {@inheritdoc} */ public function requiresSQLCommentHint(AbstractPlatform $platform) { return true; } } dbal-2.5.13/lib/Doctrine/DBAL/Types/SimpleArrayType.php000066400000000000000000000044231313473450000224350ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Array Type which can be used for simple values. * * Only use this type if you are sure that your values cannot contain a ",". * * @since 2.3 * @author Johannes M. Schmitt */ class SimpleArrayType extends Type { /** * {@inheritdoc} */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getClobTypeDeclarationSQL($fieldDeclaration); } /** * {@inheritdoc} */ public function convertToDatabaseValue($value, AbstractPlatform $platform) { if (!$value) { return null; } return implode(',', $value); } /** * {@inheritdoc} */ public function convertToPHPValue($value, AbstractPlatform $platform) { if ($value === null) { return array(); } $value = (is_resource($value)) ? stream_get_contents($value) : $value; return explode(',', $value); } /** * {@inheritdoc} */ public function getName() { return Type::SIMPLE_ARRAY; } /** * {@inheritdoc} */ public function requiresSQLCommentHint(AbstractPlatform $platform) { return true; } } dbal-2.5.13/lib/Doctrine/DBAL/Types/SmallIntType.php000066400000000000000000000034251313473450000217310ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Type that maps a database SMALLINT to a PHP integer. * * @author robo */ class SmallIntType extends Type { /** * {@inheritdoc} */ public function getName() { return Type::SMALLINT; } /** * {@inheritdoc} */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getSmallIntTypeDeclarationSQL($fieldDeclaration); } /** * {@inheritdoc} */ public function convertToPHPValue($value, AbstractPlatform $platform) { return (null === $value) ? null : (int) $value; } /** * {@inheritdoc} */ public function getBindingType() { return \PDO::PARAM_INT; } } dbal-2.5.13/lib/Doctrine/DBAL/Types/StringType.php000066400000000000000000000032051313473450000214500ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Type that maps an SQL VARCHAR to a PHP string. * * @since 2.0 */ class StringType extends Type { /** * {@inheritdoc} */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getVarcharTypeDeclarationSQL($fieldDeclaration); } /** * {@inheritdoc} */ public function getDefaultLength(AbstractPlatform $platform) { return $platform->getVarcharDefaultLength(); } /** * {@inheritdoc} */ public function getName() { return Type::STRING; } } dbal-2.5.13/lib/Doctrine/DBAL/Types/TextType.php000066400000000000000000000032341313473450000211300ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Type that maps an SQL CLOB to a PHP string. * * @since 2.0 */ class TextType extends Type { /** * {@inheritdoc} */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getClobTypeDeclarationSQL($fieldDeclaration); } /** * {@inheritdoc} */ public function convertToPHPValue($value, AbstractPlatform $platform) { return (is_resource($value)) ? stream_get_contents($value) : $value; } /** * {@inheritdoc} */ public function getName() { return Type::TEXT; } } dbal-2.5.13/lib/Doctrine/DBAL/Types/TimeType.php000066400000000000000000000042631313473450000211050ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Type that maps an SQL TIME to a PHP DateTime object. * * @since 2.0 */ class TimeType extends Type { /** * {@inheritdoc} */ public function getName() { return Type::TIME; } /** * {@inheritdoc} */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getTimeTypeDeclarationSQL($fieldDeclaration); } /** * {@inheritdoc} */ public function convertToDatabaseValue($value, AbstractPlatform $platform) { return ($value !== null) ? $value->format($platform->getTimeFormatString()) : null; } /** * {@inheritdoc} */ public function convertToPHPValue($value, AbstractPlatform $platform) { if ($value === null || $value instanceof \DateTime) { return $value; } $val = \DateTime::createFromFormat('!' . $platform->getTimeFormatString(), $value); if ( ! $val) { throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getTimeFormatString()); } return $val; } } dbal-2.5.13/lib/Doctrine/DBAL/Types/Type.php000066400000000000000000000242401313473450000202630ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\DBALException; /** * The base class for so-called Doctrine mapping types. * * A Type object is obtained by calling the static {@link getType()} method. * * @author Roman Borschel * @author Benjamin Eberlei * @since 2.0 */ abstract class Type { const TARRAY = 'array'; const SIMPLE_ARRAY = 'simple_array'; const JSON_ARRAY = 'json_array'; const BIGINT = 'bigint'; const BOOLEAN = 'boolean'; const DATETIME = 'datetime'; const DATETIMETZ = 'datetimetz'; const DATE = 'date'; const TIME = 'time'; const DECIMAL = 'decimal'; const INTEGER = 'integer'; const OBJECT = 'object'; const SMALLINT = 'smallint'; const STRING = 'string'; const TEXT = 'text'; const BINARY = 'binary'; const BLOB = 'blob'; const FLOAT = 'float'; const GUID = 'guid'; /** * Map of already instantiated type objects. One instance per type (flyweight). * * @var array */ private static $_typeObjects = array(); /** * The map of supported doctrine mapping types. * * @var array */ private static $_typesMap = array( self::TARRAY => 'Doctrine\DBAL\Types\ArrayType', self::SIMPLE_ARRAY => 'Doctrine\DBAL\Types\SimpleArrayType', self::JSON_ARRAY => 'Doctrine\DBAL\Types\JsonArrayType', self::OBJECT => 'Doctrine\DBAL\Types\ObjectType', self::BOOLEAN => 'Doctrine\DBAL\Types\BooleanType', self::INTEGER => 'Doctrine\DBAL\Types\IntegerType', self::SMALLINT => 'Doctrine\DBAL\Types\SmallIntType', self::BIGINT => 'Doctrine\DBAL\Types\BigIntType', self::STRING => 'Doctrine\DBAL\Types\StringType', self::TEXT => 'Doctrine\DBAL\Types\TextType', self::DATETIME => 'Doctrine\DBAL\Types\DateTimeType', self::DATETIMETZ => 'Doctrine\DBAL\Types\DateTimeTzType', self::DATE => 'Doctrine\DBAL\Types\DateType', self::TIME => 'Doctrine\DBAL\Types\TimeType', self::DECIMAL => 'Doctrine\DBAL\Types\DecimalType', self::FLOAT => 'Doctrine\DBAL\Types\FloatType', self::BINARY => 'Doctrine\DBAL\Types\BinaryType', self::BLOB => 'Doctrine\DBAL\Types\BlobType', self::GUID => 'Doctrine\DBAL\Types\GuidType', ); /** * Prevents instantiation and forces use of the factory method. */ final private function __construct() { } /** * Converts a value from its PHP representation to its database representation * of this type. * * @param mixed $value The value to convert. * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform The currently used database platform. * * @return mixed The database representation of the value. */ public function convertToDatabaseValue($value, AbstractPlatform $platform) { return $value; } /** * Converts a value from its database representation to its PHP representation * of this type. * * @param mixed $value The value to convert. * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform The currently used database platform. * * @return mixed The PHP representation of the value. */ public function convertToPHPValue($value, AbstractPlatform $platform) { return $value; } /** * Gets the default length of this type. * * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform * * @return integer|null * * @todo Needed? */ public function getDefaultLength(AbstractPlatform $platform) { return null; } /** * Gets the SQL declaration snippet for a field of this type. * * @param array $fieldDeclaration The field declaration. * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform The currently used database platform. * * @return string */ abstract public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform); /** * Gets the name of this type. * * @return string * * @todo Needed? */ abstract public function getName(); /** * Factory method to create type instances. * Type instances are implemented as flyweights. * * @param string $name The name of the type (as returned by getName()). * * @return \Doctrine\DBAL\Types\Type * * @throws \Doctrine\DBAL\DBALException */ public static function getType($name) { if ( ! isset(self::$_typeObjects[$name])) { if ( ! isset(self::$_typesMap[$name])) { throw DBALException::unknownColumnType($name); } self::$_typeObjects[$name] = new self::$_typesMap[$name](); } return self::$_typeObjects[$name]; } /** * Adds a custom type to the type map. * * @param string $name The name of the type. This should correspond to what getName() returns. * @param string $className The class name of the custom type. * * @return void * * @throws \Doctrine\DBAL\DBALException */ public static function addType($name, $className) { if (isset(self::$_typesMap[$name])) { throw DBALException::typeExists($name); } self::$_typesMap[$name] = $className; } /** * Checks if exists support for a type. * * @param string $name The name of the type. * * @return boolean TRUE if type is supported; FALSE otherwise. */ public static function hasType($name) { return isset(self::$_typesMap[$name]); } /** * Overrides an already defined type to use a different implementation. * * @param string $name * @param string $className * * @return void * * @throws \Doctrine\DBAL\DBALException */ public static function overrideType($name, $className) { if ( ! isset(self::$_typesMap[$name])) { throw DBALException::typeNotFound($name); } if (isset(self::$_typeObjects[$name])) { unset(self::$_typeObjects[$name]); } self::$_typesMap[$name] = $className; } /** * Gets the (preferred) binding type for values of this type that * can be used when binding parameters to prepared statements. * * This method should return one of the PDO::PARAM_* constants, that is, one of: * * PDO::PARAM_BOOL * PDO::PARAM_NULL * PDO::PARAM_INT * PDO::PARAM_STR * PDO::PARAM_LOB * * @return integer */ public function getBindingType() { return \PDO::PARAM_STR; } /** * Gets the types array map which holds all registered types and the corresponding * type class * * @return array */ public static function getTypesMap() { return self::$_typesMap; } /** * @return string */ public function __toString() { $e = explode('\\', get_class($this)); return str_replace('Type', '', end($e)); } /** * Does working with this column require SQL conversion functions? * * This is a metadata function that is required for example in the ORM. * Usage of {@link convertToDatabaseValueSQL} and * {@link convertToPHPValueSQL} works for any type and mostly * does nothing. This method can additionally be used for optimization purposes. * * @return boolean */ public function canRequireSQLConversion() { return false; } /** * Modifies the SQL expression (identifier, parameter) to convert to a database value. * * @param string $sqlExpr * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform * * @return string */ public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform) { return $sqlExpr; } /** * Modifies the SQL expression (identifier, parameter) to convert to a PHP value. * * @param string $sqlExpr * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform * * @return string */ public function convertToPHPValueSQL($sqlExpr, $platform) { return $sqlExpr; } /** * Gets an array of database types that map to this Doctrine type. * * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform * * @return array */ public function getMappedDatabaseTypes(AbstractPlatform $platform) { return array(); } /** * If this Doctrine Type maps to an already mapped database type, * reverse schema engineering can't take them apart. You need to mark * one of those types as commented, which will have Doctrine use an SQL * comment to typehint the actual Doctrine Type. * * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform * * @return boolean */ public function requiresSQLCommentHint(AbstractPlatform $platform) { return false; } } dbal-2.5.13/lib/Doctrine/DBAL/Types/VarDateTimeType.php000066400000000000000000000040561313473450000223540ustar00rootroot00000000000000. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Variable DateTime Type using date_create() instead of DateTime::createFromFormat(). * * This type has performance implications as it runs twice as long as the regular * {@see DateTimeType}, however in certain PostgreSQL configurations with * TIMESTAMP(n) columns where n > 0 it is necessary to use this type. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel */ class VarDateTimeType extends DateTimeType { /** * {@inheritdoc} */ public function convertToPHPValue($value, AbstractPlatform $platform) { if ($value === null || $value instanceof \DateTime) { return $value; } $val = date_create($value); if ( ! $val) { throw ConversionException::conversionFailed($value, $this->getName()); } return $val; } } dbal-2.5.13/lib/Doctrine/DBAL/Version.php000066400000000000000000000036121313473450000176630ustar00rootroot00000000000000. */ namespace Doctrine\DBAL; /** * Class to store and retrieve the version of Doctrine. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel */ class Version { /** * Current Doctrine Version. */ const VERSION = '2.5.13'; /** * Compares a Doctrine version with the current one. * * @param string $version The Doctrine version to compare to. * * @return integer -1 if older, 0 if it is the same, 1 if version passed as argument is newer. */ public static function compare($version) { $currentVersion = str_replace(' ', '', strtolower(self::VERSION)); $version = str_replace(' ', '', $version); return version_compare($version, $currentVersion); } } dbal-2.5.13/lib/Doctrine/DBAL/VersionAwarePlatformDriver.php000066400000000000000000000037211313473450000235250ustar00rootroot00000000000000. */ namespace Doctrine\DBAL; /** * Contract for a driver that is able to create platform instances by version. * * Doctrine uses different platform classes for different vendor versions to * support the correct features and SQL syntax of each version. * This interface should be implemented by drivers that are capable to do this * distinction. * * @author Steve Müller * @link www.doctrine-project.org * @since 2.5 */ interface VersionAwarePlatformDriver { /** * Factory method for creating the appropriate platform instance for the given version. * * @param string $version The platform/server version string to evaluate. This should be given in the notation * the underlying database vendor uses. * * @return \Doctrine\DBAL\Platforms\AbstractPlatform * * @throws DBALException if the given version string could not be evaluated. */ public function createDatabasePlatformForVersion($version); } dbal-2.5.13/lib/vendor/000077500000000000000000000000001313473450000145475ustar00rootroot00000000000000dbal-2.5.13/lib/vendor/Symfony/000077500000000000000000000000001313473450000162135ustar00rootroot00000000000000dbal-2.5.13/lib/vendor/Symfony/Component/000077500000000000000000000000001313473450000201555ustar00rootroot00000000000000dbal-2.5.13/lib/vendor/Symfony/Component/Console/000077500000000000000000000000001313473450000215575ustar00rootroot00000000000000dbal-2.5.13/lib/vendor/doctrine-build-common/000077500000000000000000000000001313473450000207415ustar00rootroot00000000000000dbal-2.5.13/lib/vendor/doctrine-common/000077500000000000000000000000001313473450000176445ustar00rootroot00000000000000