package.xml0000644000175100017510000005771612143374463013330 0ustar beberleibeberlei DoctrineDBAL pear.doctrine-project.org Doctrine Database Abstraction Layer The Doctrine DBAL package is the database abstraction layer used to power the ORM package. Jonathan H. Wage jwage jonwage@gmail.com yes Guilherme Blanco guilhermeblanco guilhermeblanco@gmail.com yes Roman Borschel romanb roman@code-factory.org yes Benjamin Eberlei beberlei kontakt@beberlei.de yes 2013-05-11 2.3.4 2.3.4 stable stable LGPL - 5.3.2 1.6.0 1.6.1 DoctrineCommon pear.doctrine-project.org 2.0.1 Console pear.symfony.com 2.0.0 2.3.4 2.3.4 stable stable 2013-05-11 LGPL - DoctrineDBAL-2.3.4/bin/doctrine-dbal0000644000175100017510000000006712143374463017234 0ustar beberleibeberlei#!/usr/bin/env php register(); $classLoader = new \Doctrine\Common\ClassLoader('Symfony'); $classLoader->register(); $configFile = getcwd() . DIRECTORY_SEPARATOR . 'cli-config.php'; $helperSet = null; if (file_exists($configFile)) { if ( ! is_readable($configFile)) { trigger_error( 'Configuration file [' . $configFile . '] does not have read permission.', E_ERROR ); } require $configFile; foreach ($GLOBALS as $helperSetCandidate) { if ($helperSetCandidate instanceof \Symfony\Component\Console\Helper\HelperSet) { $helperSet = $helperSetCandidate; break; } } } $helperSet = ($helperSet) ?: new \Symfony\Component\Console\Helper\HelperSet(); $cli = new \Symfony\Component\Console\Application('Doctrine Command Line Interface', Doctrine\DBAL\Version::VERSION); $cli->setCatchExceptions(true); $cli->setHelperSet($helperSet); $cli->addCommands(array( // DBAL Commands new \Doctrine\DBAL\Tools\Console\Command\RunSqlCommand(), new \Doctrine\DBAL\Tools\Console\Command\ImportCommand(), new \Doctrine\DBAL\Tools\Console\Command\ReservedWordsCommand(), )); $cli->run(); DoctrineDBAL-2.3.4/Doctrine/DBAL/Configuration.php0000644000175100017510000000706212143374463021625 0ustar beberleibeberlei. */ 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 SQLLogger $logger */ public function setSQLLogger(SQLLogger $logger = null) { $this->_attributes['sqlLogger'] = $logger; } /** * Gets the SQL logger that is used. * * @return SQLLogger */ public function getSQLLogger() { return isset($this->_attributes['sqlLogger']) ? $this->_attributes['sqlLogger'] : null; } /** * Gets the cache driver implementation that is used for query result caching. * * @return \Doctrine\Common\Cache\Cache */ public function getResultCacheImpl() { return isset($this->_attributes['resultCacheImpl']) ? $this->_attributes['resultCacheImpl'] : null; } /** * Sets the cache driver implementation that is used for query result caching. * * @param \Doctrine\Common\Cache\Cache $cacheImpl */ public function setResultCacheImpl(Cache $cacheImpl) { $this->_attributes['resultCacheImpl'] = $cacheImpl; } /** * Filter schema assets expression. * * Only include tables/sequences matching the filter expression regexp in * schema instances generated for the active connection when calling * {AbstractSchemaManager#createSchema()}. * * @param string $filterExpression */ public function setFilterSchemaAssetsExpression($filterExpression) { $this->_attributes['filterSchemaAssetsExpression'] = $filterExpression; } /** * Return filter schema assets expression. * * @return string|null */ public function getFilterSchemaAssetsExpression() { if (isset($this->_attributes['filterSchemaAssetsExpression'])) { return $this->_attributes['filterSchemaAssetsExpression']; } return null; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Connection.php0000644000175100017510000011462512143374463021121 0ustar beberleibeberlei. */ namespace Doctrine\DBAL; use PDO, Closure, Exception, Doctrine\DBAL\Types\Type, Doctrine\DBAL\Driver\Connection as DriverConnection, Doctrine\Common\EventManager, Doctrine\DBAL\DBALException, Doctrine\DBAL\Cache\ResultCacheStatement, Doctrine\DBAL\Cache\QueryCacheProfile, Doctrine\DBAL\Cache\ArrayStatement, Doctrine\DBAL\Cache\CacheException; /** * 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 int */ const PARAM_INT_ARRAY = 101; /** * Represents an array of strings to be expanded by Doctrine SQL parsing. * * @var int */ const PARAM_STR_ARRAY = 102; /** * Offset by which PARAM_* constants are detected as arrays of the param type. * * @var int */ 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 transaction nesting level. * * @var integer */ private $_transactionNestingLevel = 0; /** * The currently active transaction isolation level. * * @var integer */ private $_transactionIsolationLevel; /** * If nested transations should use savepoints * * @var integer */ private $_nestTransactionsWithSavepoints; /** * 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 */ protected $_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; private $_defaultFetchMode = PDO::FETCH_ASSOC; /** * Initializes a new instance of the Connection class. * * @param array $params The connection parameters. * @param Driver $driver * @param Configuration $config * @param EventManager $eventManager */ 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; } // 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); if ( ! isset($params['platform'])) { $this->_platform = $driver->getDatabasePlatform(); } else if ($params['platform'] instanceof Platforms\AbstractPlatform) { $this->_platform = $params['platform']; } else { throw DBALException::invalidPlatformSpecified(); } $this->_platform->setEventManager($eventManager); $this->_transactionIsolationLevel = $this->_platform->getDefaultTransactionIsolationLevel(); } /** * Gets the parameters used during instantiation. * * @return array $params */ public function getParams() { return $this->_params; } /** * Gets the name of the database this Connection is connected to. * * @return string $database */ public function getDatabase() { return $this->_driver->getDatabase($this); } /** * Gets the hostname of the currently connected database. * * @return string */ 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 */ public function getUsername() { return isset($this->_params['user']) ? $this->_params['user'] : null; } /** * Gets the password used by this connection. * * @return string */ 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() { 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 ($this->_eventManager->hasListeners(Events::postConnect)) { $eventArgs = new Event\ConnectionEventArgs($this); $this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs); } return true; } /** * setFetchMode * * @param integer $fetchMode */ 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. * @return array */ public function fetchAssoc($statement, array $params = array()) { return $this->executeQuery($statement, $params)->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 sql query to be executed * @param array $params prepared statement params * @return array */ public function fetchArray($statement, array $params = array()) { return $this->executeQuery($statement, $params)->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 sql query to be executed * @param array $params prepared statement params * @param int $colnum 0-indexed column number to retrieve * @return mixed */ public function fetchColumn($statement, array $params = array(), $colnum = 0) { return $this->executeQuery($statement, $params)->fetchColumn($colnum); } /** * 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. * * @param string $tableName The name of the table on which to delete. * @param array $identifier The deletion criteria. An associative array containing column-value pairs. * @return integer The number of affected rows. */ public function delete($tableName, array $identifier) { $this->connect(); $criteria = array(); foreach (array_keys($identifier) as $columnName) { $criteria[] = $columnName . ' = ?'; } $query = 'DELETE FROM ' . $tableName . ' WHERE ' . implode(' AND ', $criteria); return $this->executeUpdate($query, array_values($identifier)); } /** * Closes the connection. * * @return void */ public function close() { unset($this->_conn); $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->_platform->getSetTransactionIsolationSQL($level)); } /** * Gets the currently active transaction isolation level. * * @return integer The current transaction isolation level. */ public function getTransactionIsolation() { return $this->_transactionIsolationLevel; } /** * Executes an SQL UPDATE statement on a table. * * @param string $tableName The name of the table to update. * @param array $data * @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($tableName, array $data, array $identifier, array $types = array()) { $this->connect(); $set = array(); foreach ($data as $columnName => $value) { $set[] = $columnName . ' = ?'; } $params = array_merge(array_values($data), array_values($identifier)); $sql = 'UPDATE ' . $tableName . ' SET ' . implode(', ', $set) . ' WHERE ' . implode(' = ? AND ', array_keys($identifier)) . ' = ?'; return $this->executeUpdate($sql, $params, $types); } /** * Inserts a table row with specified data. * * @param string $tableName The name of the table to insert data into. * @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($tableName, array $data, array $types = array()) { $this->connect(); // column names are specified as array keys $cols = array(); $placeholders = array(); foreach ($data as $columnName => $value) { $cols[] = $columnName; $placeholders[] = '?'; } $query = 'INSERT INTO ' . $tableName . ' (' . implode(', ', $cols) . ')' . ' VALUES (' . implode(', ', $placeholders) . ')'; return $this->executeUpdate($query, array_values($data), $types); } /** * Quote 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->_platform->quoteIdentifier($str); } /** * Quotes a given input parameter. * * @param mixed $input Parameter to be quoted. * @param string $type 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. * @return array */ public function fetchAll($sql, array $params = array()) { return $this->executeQuery($sql, $params)->fetchAll(); } /** * Prepares an SQL statement. * * @param string $statement The SQL statement to prepare. * @return \Doctrine\DBAL\Driver\Statement The prepared statement. */ public function prepare($statement) { $this->connect(); try { $stmt = new Statement($statement, $this); } catch (\Exception $ex) { throw DBALException::driverExceptionDuringQuery($ex, $statement); } $stmt->setFetchMode($this->_defaultFetchMode); return $stmt; } /** * Executes an, optionally parameterized, SQL query. * * If the query is parameterized, 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 QueryCacheProfile $qcp * @return \Doctrine\DBAL\Driver\Statement The executed statement. * @internal PERF: Directly prepares a driver statement, not a wrapper. */ 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($ex, $query, $this->resolveParams($params, $types)); } $stmt->setFetchMode($this->_defaultFetchMode); if ($logger) { $logger->stopQuery(); } return $stmt; } /** * Execute a caching query and * * @param string $query * @param array $params * @param array $types * @param QueryCacheProfile $qcp * @return \Doctrine\DBAL\Driver\ResultStatement */ 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]); } else if (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 parameterized, 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 $mapper The transformation function that is applied on each row. * The function receives a single paramater, an array, that * represents a row of the result set. * @return mixed The projected result of the query. */ public function project($query, array $params, Closure $function) { $result = array(); $stmt = $this->executeQuery($query, $params ?: array()); while ($row = $stmt->fetch()) { $result[] = $function($row); } $stmt->closeCursor(); return $result; } /** * Executes an SQL statement, returning a result set as a Statement object. * * @param string $statement * @param integer $fetchType * @return \Doctrine\DBAL\Driver\Statement */ public function query() { $this->connect(); $args = func_get_args(); $logger = $this->_config->getSQLLogger(); if ($logger) { $logger->startQuery($args[0]); } try { $statement = call_user_func_array(array($this->_conn, 'query'), $args); } catch (\Exception $ex) { throw DBALException::driverExceptionDuringQuery($ex, func_get_arg(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. * @internal PERF: Directly prepares a driver statement, not a wrapper. */ 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($ex, $query, $this->resolveParams($params, $types)); } if ($logger) { $logger->stopQuery(); } return $result; } /** * Execute an SQL statement and return the number of affected rows. * * @param string $statement * @return integer The number of affected rows. */ 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($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; } /** * Fetch the SQLSTATE associated with the last database operation. * * @return integer The last error code. */ public function errorCode() { $this->connect(); return $this->_conn->errorCode(); } /** * Fetch 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 $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. */ public function transactional(Closure $func) { $this->beginTransaction(); try { $func($this); $this->commit(); } catch (Exception $e) { $this->rollback(); throw $e; } } /** * Set if nested transactions should use savepoints * * @param boolean $nestTransactionsWithSavepoints * @return void */ public function setNestTransactionsWithSavepoints($nestTransactionsWithSavepoints) { if ($this->_transactionNestingLevel > 0) { throw ConnectionException::mayNotAlterNestedTransactionWithSavepointsInTransaction(); } if ( ! $this->_platform->supportsSavepoints()) { throw ConnectionException::savepointsNotSupported(); } $this->_nestTransactionsWithSavepoints = $nestTransactionsWithSavepoints; } /** * Get 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(); } } else if ($this->_nestTransactionsWithSavepoints) { if ($logger) { $logger->startQuery('"SAVEPOINT"'); } $this->createSavepoint($this->_getNestedTransactionSavePointName()); if ($logger) { $logger->stopQuery(); } } } /** * Commits the current transaction. * * @return void * @throws 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(); } } else if ($this->_nestTransactionsWithSavepoints) { if ($logger) { $logger->startQuery('"RELEASE SAVEPOINT"'); } $this->releaseSavepoint($this->_getNestedTransactionSavePointName()); if ($logger) { $logger->stopQuery(); } } --$this->_transactionNestingLevel; } /** * Cancel any database changes done during the current transaction. * * this method can be listened with onPreTransactionRollback and onTransactionRollback * eventlistener methods * * @throws 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(); } } else if ($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; } } /** * createSavepoint * creates a new savepoint * * @param string $savepoint name of a savepoint to set * @return void */ public function createSavepoint($savepoint) { if ( ! $this->_platform->supportsSavepoints()) { throw ConnectionException::savepointsNotSupported(); } $this->_conn->exec($this->_platform->createSavePoint($savepoint)); } /** * releaseSavePoint * releases given savepoint * * @param string $savepoint name of a savepoint to release * @return void */ public function releaseSavepoint($savepoint) { if ( ! $this->_platform->supportsSavepoints()) { throw ConnectionException::savepointsNotSupported(); } if ($this->_platform->supportsReleaseSavepoints()) { $this->_conn->exec($this->_platform->releaseSavePoint($savepoint)); } } /** * rollbackSavePoint * releases given savepoint * * @param string $savepoint name of a savepoint to rollback to * @return void */ public function rollbackSavepoint($savepoint) { if ( ! $this->_platform->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. * * @throws ConnectionException If no transaction is active. */ public function setRollbackOnly() { if ($this->_transactionNestingLevel == 0) { throw ConnectionException::noActiveTransaction(); } $this->_isRollbackOnly = true; } /** * Check whether the current transaction is marked for rollback only. * * @return boolean * @throws 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->_platform); } /** * 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->_platform); } /** * 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 string $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). * @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->_platform); $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; } /** * Create a new instance of a SQL query builder. * * @return \Doctrine\DBAL\Query\QueryBuilder */ public function createQueryBuilder() { return new Query\QueryBuilder($this); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/ConnectionException.php0000644000175100017510000000400412143374463022765 0ustar beberleibeberlei. */ namespace Doctrine\DBAL; /** * Doctrine\DBAL\ConnectionException * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.org * @since 2.0 * @version $Revision: 4628 $ * @author Jonathan H. Wage getMessage(); 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)) . ']'; } public static function invalidWrapperClass($wrapperClass) { return new self("The given 'wrapperClass' ".$wrapperClass." has to be a ". "subtype of \Doctrine\DBAL\Connection."); } public static function invalidDriverClass($driverClass) { return new self("The given 'driverClass' ".$driverClass." has to implement the ". "\Doctrine\DBAL\Driver interface."); } /** * @param string $tableName * @return DBALException */ public static function invalidTableName($tableName) { return new self("Invalid table name specified: ".$tableName); } /** * @param string $tableName * @return DBALException */ public static function noColumnsSpecifiedForTable($tableName) { return new self("No columns specified for table ".$tableName); } public static function limitOffsetInvalid() { return new self("Invalid Offset in Limit Query, it has to be larger or equal to 0."); } public static function typeExists($name) { return new self('Type '.$name.' already exists.'); } public static function unknownColumnType($name) { return new self('Unknown column type "'.$name.'" requested. 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::getTypeMap(). 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.' ); } public static function typeNotFound($name) { return new self('Type to be overwritten '.$name.' does not exist.'); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver.php0000644000175100017510000000513112143374463020244 0ustar beberleibeberlei. */ namespace Doctrine\DBAL; /** * Driver interface. * Interface that all DBAL drivers must implement. * * @since 2.0 */ interface Driver { /** * Attempts to create a connection with the database. * * @param array $params All connection parameters passed by the user. * @param string $username The username to use when connecting. * @param string $password The password to use when connecting. * @param array $driverOptions The driver options to use when connecting. * @return \Doctrine\DBAL\Driver\Connection The database connection. */ public function connect(array $params, $username = null, $password = null, array $driverOptions = array()); /** * Gets the DatabasePlatform instance that provides all the metadata about * the platform this driver connects to. * * @return \Doctrine\DBAL\Platforms\AbstractPlatform The database platform. */ public function getDatabasePlatform(); /** * Gets the SchemaManager that can be used to inspect and change the underlying * database schema of the platform this driver connects to. * * @param \Doctrine\DBAL\Connection $conn * @return \Doctrine\DBAL\Schema\AbstractSchemaManager */ public function getSchemaManager(Connection $conn); /** * Gets the name of the driver. * * @return string The name of the driver. */ public function getName(); /** * Get the name of the database connected to for this driver. * * @param \Doctrine\DBAL\Connection $conn * @return string $database */ public function getDatabase(Connection $conn); } DoctrineDBAL-2.3.4/Doctrine/DBAL/DriverManager.php0000644000175100017510000001445412143374463021547 0ustar beberleibeberlei. */ 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_ibm' => 'Doctrine\DBAL\Driver\PDOIbm\Driver', 'pdo_sqlsrv' => 'Doctrine\DBAL\Driver\PDOSqlsrv\Driver', 'mysqli' => 'Doctrine\DBAL\Driver\Mysqli\Driver', 'drizzle_pdo_mysql' => 'Doctrine\DBAL\Driver\DrizzlePDOMySql\Driver', 'sqlsrv' => 'Doctrine\DBAL\Driver\SQLSrv\Driver', ); /** Private constructor. This class cannot be instantiated. */ private function __construct() { } /** * Creates a connection object based on the specified parameters. * This method returns a Doctrine\DBAL\Connection which wraps the underlying * driver connection. * * $params must contain at least one of the following. * * Either 'driver' with one of the following values: * * pdo_mysql * pdo_sqlite * pdo_pgsql * pdo_oci (unstable) * pdo_sqlsrv * pdo_ibm (unstable) * pdo_sqlsrv * mysqli * 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 The configuration to use. * @param \Doctrine\Common\EventManager The event manager to use. * @return \Doctrine\DBAL\Connection */ public static function getConnection( array $params, Configuration $config = null, EventManager $eventManager = null) { // create default config and event manager, if not set if ( ! $config) { $config = new Configuration(); } if ( ! $eventManager) { $eventManager = new EventManager(); } // check for existing pdo object if (isset($params['pdo']) && ! $params['pdo'] instanceof \PDO) { throw DBALException::invalidPdoInstance(); } else if (isset($params['pdo'])) { $params['pdo']->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $params['driver'] = 'pdo_' . $params['pdo']->getAttribute(\PDO::ATTR_DRIVER_NAME); } else { self::_checkParams($params); } if (isset($params['driverClass'])) { $className = $params['driverClass']; } else { $className = self::$_driverMap[$params['driver']]; } $driver = new $className(); $wrapperClass = 'Doctrine\DBAL\Connection'; if (isset($params['wrapperClass'])) { if (is_subclass_of($params['wrapperClass'], $wrapperClass)) { $wrapperClass = $params['wrapperClass']; } else { throw DBALException::invalidWrapperClass($params['wrapperClass']); } } return new $wrapperClass($params, $driver, $config, $eventManager); } /** * Checks the list of parameters. * * @param array $params */ private static function _checkParams(array $params) { // check existance of mandatory parameters // driver if ( ! isset($params['driver']) && ! isset($params['driverClass'])) { throw DBALException::driverRequired(); } // check validity of parameters // driver if ( isset($params['driver']) && ! isset(self::$_driverMap[$params['driver']])) { throw DBALException::unknownDriver($params['driver'], array_keys(self::$_driverMap)); } if (isset($params['driverClass']) && ! in_array('Doctrine\DBAL\Driver', class_implements($params['driverClass'], true))) { throw DBALException::invalidDriverClass($params['driverClass']); } } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Events.php0000644000175100017510000000372312143374463020262 0ustar beberleibeberlei. */ namespace Doctrine\DBAL; /** * Container for all DBAL events. * * This class cannot be instantiated. * * @author Roman Borschel * @since 2.0 */ final class Events { private function __construct() {} const postConnect = 'postConnect'; const onSchemaCreateTable = 'onSchemaCreateTable'; const onSchemaCreateTableColumn = 'onSchemaCreateTableColumn'; const onSchemaDropTable = 'onSchemaDropTable'; const onSchemaAlterTable = 'onSchemaAlterTable'; const onSchemaAlterTableAddColumn = 'onSchemaAlterTableAddColumn'; const onSchemaAlterTableRemoveColumn = 'onSchemaAlterTableRemoveColumn'; const onSchemaAlterTableChangeColumn = 'onSchemaAlterTableChangeColumn'; const onSchemaAlterTableRenameColumn = 'onSchemaAlterTableRenameColumn'; const onSchemaColumnDefinition = 'onSchemaColumnDefinition'; const onSchemaIndexDefinition = 'onSchemaIndexDefinition'; } DoctrineDBAL-2.3.4/Doctrine/DBAL/LockMode.php0000644000175100017510000000275412143374463020516 0ustar beberleibeberlei. */ namespace Doctrine\DBAL; /** * Contains all DBAL LockModes * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 1.0 * @version $Revision$ * @author Benjamin Eberlei * @author Roman Borschel */ class LockMode { const NONE = 0; const OPTIMISTIC = 1; const PESSIMISTIC_READ = 2; const PESSIMISTIC_WRITE = 4; final private function __construct() { } } DoctrineDBAL-2.3.4/Doctrine/DBAL/README.markdown0000644000175100017510000000000012143374463020767 0ustar beberleibeberleiDoctrineDBAL-2.3.4/Doctrine/DBAL/SQLParserUtils.php0000644000175100017510000002052512143374463021652 0ustar beberleibeberlei. */ namespace Doctrine\DBAL; use Doctrine\DBAL\Connection; /** * Utility class that parses sql statements with regard to types and parameters. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 2.0 * @author Benjamin Eberlei */ 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 bool $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. * * @throws SQLParserUtilsException * @return array */ static public function expandListParameters($query, $params, $types) { $isPositional = is_int(key($params)); $arrayPositions = array(); $bindIndex = -1; foreach ($types as $name => $type) { ++$bindIndex; if ($type !== Connection::PARAM_INT_ARRAY && $type !== Connection::PARAM_STR_ARRAY) { 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; 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 = implode(", ", array_fill(0, $count, "?")); $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, '?')) : '?'; 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; 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 (isset($paramsOrTypes[$paramName])) { return $paramsOrTypes[$paramName]; } // Hash keys can be prefixed with a colon for compatibility if (isset($paramsOrTypes[':' . $paramName])) { return $paramsOrTypes[':' . $paramName]; } if (null !== $defaultValue) { return $defaultValue; } if ($isParam) { throw SQLParserUtilsException::missingParam($paramName); } throw SQLParserUtilsException::missingType($paramName); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/SQLParserUtilsException.php0000644000175100017510000000323312143374463023526 0ustar beberleibeberlei. */ namespace Doctrine\DBAL; /** * Doctrine\DBAL\ConnectionException * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.org * @since 2.4 * @author Lars Strojny */ class SQLParserUtilsException extends DBALException { 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)); } 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)); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Statement.php0000644000175100017510000001775612143374463020775 0ustar beberleibeberlei. */ namespace Doctrine\DBAL; use PDO, Doctrine\DBAL\Types\Type, 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 { /** * @var string The SQL statement. */ protected $sql; /** * @var array The bound parameters. */ protected $params = array(); /** * @var array The parameter types */ protected $types = array(); /** * @var \Doctrine\DBAL\Driver\Statement The underlying driver statement. */ protected $stmt; /** * @var \Doctrine\DBAL\Platforms\AbstractPlatform The underlying database platform. */ protected $platform; /** * @var \Doctrine\DBAL\Connection The connection this statement is bound to and executed on. */ protected $conn; /** * Creates a new Statement for the given SQL and Connection. * * @param string $sql The SQL of the statement. * @param \Doctrine\DBAL\Connection 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. * @return boolean TRUE on success, FALSE on failure. */ public function bindParam($name, &$var, $type = PDO::PARAM_STR, $length = null) { return $this->stmt->bindParam($name, $var, $type, $length ); } /** * Executes the statement with the currently bound parameters. * * @param array $params * @return boolean TRUE on success, FALSE on failure. */ public function execute($params = null) { $logger = $this->conn->getConfiguration()->getSQLLogger(); if ($logger) { $logger->startQuery($this->sql, $this->params, $this->types); } try { $stmt = $this->stmt->execute($params); } catch (\Exception $ex) { throw DBALException::driverExceptionDuringQuery($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(); } public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) { if ($arg2 === null) { return $this->stmt->setFetchMode($fetchMode); } else if ($arg3 === null) { return $this->stmt->setFetchMode($fetchMode, $arg2); } return $this->stmt->setFetchMode($fetchMode, $arg2, $arg3); } public function getIterator() { return $this->stmt; } /** * Fetches the next row from a result set. * * @param integer $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 $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; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Version.php0000644000175100017510000000366112143374463020444 0ustar beberleibeberlei. */ namespace Doctrine\DBAL; /** * Class to store and retrieve the version of Doctrine * * * @link www.doctrine-project.org * @since 2.0 * @version $Revision$ * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel */ class Version { /** * Current Doctrine Version */ const VERSION = '2.3.4'; /** * Compares a Doctrine version with the current one. * * @param string $version Doctrine version to compare. * @return int Returns -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); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Cache/ArrayStatement.php0000644000175100017510000000631612143374463022765 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Cache; use Doctrine\DBAL\Driver\ResultStatement; use PDO; class ArrayStatement implements \IteratorAggregate, ResultStatement { private $data; private $columnCount = 0; private $num = 0; private $defaultFetchMode = PDO::FETCH_BOTH; public function __construct(array $data) { $this->data = $data; if (count($data)) { $this->columnCount = count($data[0]); } } public function closeCursor() { unset ($this->data); } public function columnCount() { return $this->columnCount; } public function setFetchMode($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; } public function getIterator() { $data = $this->fetchAll(); return new \ArrayIterator($data); } 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; } else if ($fetchMode === PDO::FETCH_NUM) { return array_values($row); } else if ($fetchMode === PDO::FETCH_BOTH) { return array_merge($row, array_values($row)); } else if ($fetchMode === PDO::FETCH_COLUMN) { return reset($row); } else { throw new \InvalidArgumentException("Invalid fetch-style given for fetching result."); } } return false; } public function fetchAll($fetchMode = null) { $rows = array(); while ($row = $this->fetch($fetchMode)) { $rows[] = $row; } return $rows; } public function fetchColumn($columnIndex = 0) { $row = $this->fetch(PDO::FETCH_NUM); if (!isset($row[$columnIndex])) { // TODO: verify this is correct behavior return false; } return $row[$columnIndex]; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Cache/CacheException.php0000644000175100017510000000260412143374463022700 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Cache; /** * @author Benjamin Eberlei * @since 2.2 */ class CacheException extends \Doctrine\DBAL\DBALException { static public function noCacheKey() { return new self("No cache key was set."); } static public function noResultDriverConfigured() { return new self("Trying to cache a query but no result driver is configured."); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Cache/QueryCacheProfile.php0000644000175100017510000000700712143374463023372 0ustar beberleibeberlei. */ 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 Cache */ private $resultCacheDriver; /** * @var int */ private $lifetime = 0; /** * @var string */ private $cacheKey; /** * @param int $lifetime * @param string $cacheKey * @param Cache $resultCache */ public function __construct($lifetime = 0, $cacheKey = null, Cache $resultCache = null) { $this->lifetime = $lifetime; $this->cacheKey = $cacheKey; $this->resultCacheDriver = $resultCache; } /** * @return Cache */ public function getResultCacheDriver() { return $this->resultCacheDriver; } /** * @return int */ public function getLifetime() { return $this->lifetime; } /** * @return string */ public function getCacheKey() { if ($this->cacheKey === null) { throw CacheException::noCacheKey(); } return $this->cacheKey; } /** * Generate the real cache key from query, params and types. * * @param string $query * @param array $params * @param array $types * @return array */ public function generateCacheKeys($query, $params, $types) { $realCacheKey = $query . "-" . serialize($params) . "-" . serialize($types); // should the key be automatically generated using the inputs or is the cache key set? if ($this->cacheKey === null) { $cacheKey = sha1($realCacheKey); } else { $cacheKey = $this->cacheKey; } return array($cacheKey, $realCacheKey); } /** * @param Cache $cache * @return QueryCacheProfile */ public function setResultCacheDriver(Cache $cache) { return new QueryCacheProfile($this->lifetime, $this->cacheKey, $cache); } /** * @param string|null $cacheKey * @return QueryCacheProfile */ public function setCacheKey($cacheKey) { return new QueryCacheProfile($this->lifetime, $cacheKey, $this->resultCacheDriver); } /** * @param int $lifetime * @return QueryCacheProfile */ public function setLifetime($lifetime) { return new QueryCacheProfile($lifetime, $this->cacheKey, $this->resultCacheDriver); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Cache/ResultCacheStatement.php0000644000175100017510000001665312143374463024116 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Cache; use Doctrine\DBAL\Driver\Statement; use Doctrine\DBAL\Driver\ResultStatement; use Doctrine\DBAL\Connection; use Doctrine\Common\Cache\Cache; use PDO; /** * Cache statement for SQL results. * * A result is saved in multiple cache keys, there is the originally specified * cache key which is just pointing to result rows by key. The following things * have to be ensured: * * 1. lifetime of the original key has to be longer than that of all the individual rows keys * 2. if any one row key is missing the query has to be re-executed. * * Also you have to realize that the cache will load the whole result into memory at once to ensure 2. * This means that the memory usage for cached results might increase by using this feature. */ class ResultCacheStatement implements \IteratorAggregate, ResultStatement { /** * @var \Doctrine\Common\Cache\Cache */ private $resultCache; /** * * @var string */ private $cacheKey; /** * @var string */ private $realKey; /** * @var int */ private $lifetime; /** * @var Doctrine\DBAL\Driver\Statement */ private $statement; /** * Did we reach the end of the statement? * * @var bool */ private $emptied = false; /** * @var array */ private $data; /** * @var int */ private $defaultFetchMode = PDO::FETCH_BOTH; /** * @param Statement $stmt * @param Cache $resultCache * @param string $cacheKey * @param string $realKey * @param int $lifetime */ public function __construct(Statement $stmt, Cache $resultCache, $cacheKey, $realKey, $lifetime) { $this->statement = $stmt; $this->resultCache = $resultCache; $this->cacheKey = $cacheKey; $this->realKey = $realKey; $this->lifetime = $lifetime; } /** * Closes the cursor, enabling the statement to be executed again. * * @return boolean Returns TRUE on success or FALSE on failure. */ public function closeCursor() { $this->statement->closeCursor(); if ($this->emptied && $this->data !== null) { $data = $this->resultCache->fetch($this->cacheKey); if ( ! $data) { $data = array(); } $data[$this->realKey] = $this->data; $this->resultCache->save($this->cacheKey, $data, $this->lifetime); unset($this->data); } } /** * columnCount * Returns the number of columns in the result set * * @return integer Returns the number of columns in the result set represented * by the PDOStatement object. If there is no result set, * this method should return 0. */ public function columnCount() { return $this->statement->columnCount(); } public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) { $this->defaultFetchMode = $fetchMode; } public function getIterator() { $data = $this->fetchAll(); return new \ArrayIterator($data); } /** * fetch * * @see Query::HYDRATE_* constants * @param integer $fetchMode Controls how the next row will be returned to the caller. * This value must be one of the Query::HYDRATE_* constants, * defaulting to Query::HYDRATE_BOTH * * @return mixed */ 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; } else if ($fetchMode == PDO::FETCH_NUM) { return array_values($row); } else if ($fetchMode == PDO::FETCH_BOTH) { return array_merge($row, array_values($row)); } else if ($fetchMode == PDO::FETCH_COLUMN) { return reset($row); } else { throw new \InvalidArgumentException("Invalid fetch-style given for caching result."); } } $this->emptied = true; return false; } /** * Returns an array containing all of the result set rows * * @param integer $fetchMode Controls how the next row will be returned to the caller. * This value must be one of the Query::HYDRATE_* constants, * defaulting to Query::HYDRATE_BOTH * * @return array */ public function fetchAll($fetchMode = null) { $rows = array(); while ($row = $this->fetch($fetchMode)) { $rows[] = $row; } return $rows; } /** * fetchColumn * Returns a single column from the next row of a * result set or FALSE if there are no more rows. * * @param integer $columnIndex 0-indexed number of the column you wish to retrieve from the row. If no * value is supplied, PDOStatement->fetchColumn() * fetches the first column. * * @return string returns a single column in the next row of a result set. */ public function fetchColumn($columnIndex = 0) { $row = $this->fetch(PDO::FETCH_NUM); if (!isset($row[$columnIndex])) { // TODO: verify this is correct behavior return false; } return $row[$columnIndex]; } /** * rowCount * rowCount() returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement * executed by the corresponding object. * * If the last SQL statement executed by the associated Statement object was a SELECT statement, * some databases may return the number of rows returned by that statement. However, * this behaviour is not guaranteed for all databases and should not be * relied on for portable applications. * * @return integer Returns the number of rows. */ public function rowCount() { return $this->statement->rowCount(); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Connections/MasterSlaveConnection.php0000644000175100017510000002521112143374463025542 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Connections; use Doctrine\DBAL\Connection, Doctrine\DBAL\Driver, Doctrine\DBAL\Configuration, Doctrine\Common\EventManager, Doctrine\DBAL\Event\ConnectionEventArgs, Doctrine\DBAL\Events; /** * Master-Slave Connection * * Connection can be used with master-slave setups. * * Important for the understanding of this connection should be how and when * it picks the slave or master. * * 1. Slave if master was never picked before and ONLY if 'getWrappedConnection' * or 'executeQuery' is used. * 2. Master picked when 'exec', 'executeUpdate', 'insert', 'delete', 'update', 'createSavepoint', * 'releaseSavepoint', 'beginTransaction', 'rollback', 'commit', 'query' or * 'prepare' is called. * 3. If master was picked once during the lifetime of the connection it will always get picked afterwards. * 4. One slave connection is randomly picked ONCE during a request. * * ATTENTION: You can write to the slave with this connection if you execute a write query without * opening up a transaction. For example: * * $conn = DriverManager::getConnection(...); * $conn->executeQuery("DELETE FROM table"); * * Be aware that Connection#executeQuery is a method specifically for READ * operations only. * * This connection is limited to slave operations using the * Connection#executeQuery operation only, because it wouldn't be compatible * with the ORM or SchemaManager code otherwise. Both use all the other * operations in a context where writes could happen to a slave, which makes * this restricted approach necessary. * * You can manually connect to the master at any time by calling: * * $conn->connect('master'); * * Instantiation through the DriverManager looks like: * * @example * * $conn = DriverManager::getConnection(array( * 'wrapperClass' => 'Doctrine\DBAL\Connections\MasterSlaveConnection', * 'driver' => 'pdo_mysql', * 'master' => array('user' => '', 'password' => '', 'host' => '', 'dbname' => ''), * 'slaves' => array( * array('user' => 'slave1', 'password', 'host' => '', 'dbname' => ''), * array('user' => 'slave2', 'password', 'host' => '', 'dbname' => ''), * ) * )); * * You can also pass 'driverOptions' and any other documented option to each of this drivers to pass additional information. * * @author Lars Strojny * @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 bool */ protected $keepSlave = false; /** * Create Master Slave Connection * * @param array $params * @param Driver $driver * @param Configuration $config * @param EventManager $eventManager */ public function __construct(array $params, Driver $driver, Configuration $config = null, EventManager $eventManager = null) { if ( !isset($params['slaves']) || !isset($params['master']) ) { throw new \InvalidArgumentException('master or slaves configuration missing'); } if ( count($params['slaves']) == 0 ) { throw new \InvalidArgumentException('You have to configure at least one slaves.'); } $params['master']['driver'] = $params['driver']; foreach ($params['slaves'] as $slaveKey => $slave) { $params['slaves'][$slaveKey]['driver'] = $params['driver']; } $this->keepSlave = isset($params['keepSlave']) ? (bool)$params['keepSlave'] : false; parent::__construct($params, $driver, $config, $eventManager); } /** * Check if the connection is currently towards the master or not. * * @return bool */ public function isConnectedToMaster() { return $this->_conn !== null && $this->_conn === $this->connections['master']; } /** * {@inheritDoc} */ public function connect($connectionName = 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]) { if ($forceMasterAsSlave) { $this->connections['slave'] = $this->_conn = $this->connections['master']; } else { $this->_conn = $this->connections[$connectionName]; } return false; } if ($connectionName === 'master') { // Set slave connection to master to avoid invalid reads if ($this->connections['slave'] && ! $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; } /** * Connect to a specific connection * * @param string $connectionName * @return Driver */ protected function connectTo($connectionName) { $params = $this->getParams(); $driverOptions = isset($params['driverOptions']) ? $params['driverOptions'] : array(); $connectionParams = $this->chooseConnectionConfiguration($connectionName, $params); $user = isset($connectionParams['user']) ? $connectionParams['user'] : null; $password = isset($connectionParams['password']) ? $connectionParams['password'] : null; return $this->_driver->connect($connectionParams, $user, $password, $driverOptions); } protected function chooseConnectionConfiguration($connectionName, $params) { if ($connectionName === 'master') { return $params['master']; } return $params['slaves'][array_rand($params['slaves'])]; } /** * {@inheritDoc} */ public function executeUpdate($query, array $params = array(), array $types = array()) { $this->connect('master'); return parent::executeUpdate($query, $params, $types); } /** * {@inheritDoc} */ public function beginTransaction() { $this->connect('master'); return parent::beginTransaction(); } /** * {@inheritDoc} */ public function commit() { $this->connect('master'); return parent::commit(); } /** * {@inheritDoc} */ public function rollBack() { $this->connect('master'); return parent::rollBack(); } /** * {@inheritDoc} */ public function delete($tableName, array $identifier) { $this->connect('master'); return parent::delete($tableName, $identifier); } /** * {@inheritDoc} */ public function update($tableName, array $data, array $identifier, array $types = array()) { $this->connect('master'); return parent::update($tableName, $data, $identifier, $types); } /** * {@inheritDoc} */ public function insert($tableName, array $data, array $types = array()) { $this->connect('master'); return parent::insert($tableName, $data, $types); } /** * {@inheritDoc} */ public function exec($statement) { $this->connect('master'); return parent::exec($statement); } /** * {@inheritDoc} */ public function createSavepoint($savepoint) { $this->connect('master'); return parent::createSavepoint($savepoint); } /** * {@inheritDoc} */ public function releaseSavepoint($savepoint) { $this->connect('master'); return parent::releaseSavepoint($savepoint); } /** * {@inheritDoc} */ public function rollbackSavepoint($savepoint) { $this->connect('master'); return parent::rollbackSavepoint($savepoint); } public function query() { $this->connect('master'); $args = func_get_args(); $logger = $this->getConfiguration()->getSQLLogger(); if ($logger) { $logger->startQuery($args[0]); } $statement = call_user_func_array(array($this->_conn, 'query'), $args); if ($logger) { $logger->stopQuery(); } return $statement; } public function prepare($statement) { $this->connect('master'); return parent::prepare($statement); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/Connection.php0000644000175100017510000000276012143374463022350 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver; /** * Connection interface. * Driver connections must implement this interface. * * This resembles (a subset of) the PDO interface. * * @since 2.0 */ interface Connection { function prepare($prepareString); function query(); function quote($input, $type=\PDO::PARAM_STR); function exec($statement); function lastInsertId($name = null); function beginTransaction(); function commit(); function rollBack(); function errorCode(); function errorInfo(); } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/PDOConnection.php0000644000175100017510000000303212143374463022704 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver; use \PDO; /** * PDO implementation of the Connection interface. * Used by all PDO-based drivers. * * @since 2.0 */ class PDOConnection extends PDO implements Connection { public function __construct($dsn, $user = null, $password = null, array $options = null) { parent::__construct($dsn, $user, $password, $options); $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('Doctrine\DBAL\Driver\PDOStatement', array())); $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/PDOStatement.php0000644000175100017510000000357212143374463022562 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver; /** * The PDO implementation of the Statement interface. * Used by all PDO-based drivers. * * @since 2.0 */ class PDOStatement extends \PDOStatement implements Statement { private function __construct() {} public function setFetchMode($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. if ($arg2 === null && $arg3 === null) { return parent::setFetchMode($fetchMode); } if ($arg3 === null) { return parent::setFetchMode($fetchMode, $arg2); } return parent::setFetchMode($fetchMode, $arg2, $arg3); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/ResultStatement.php0000644000175100017510000000656212143374463023420 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver; use PDO; /** * 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 Returns TRUE on success or FALSE on failure. */ function closeCursor(); /** * columnCount * Returns the number of columns in the result set * * @return integer Returns the number of columns in the result set represented * by the PDOStatement object. If there is no result set, * this method should return 0. */ function columnCount(); /** * setFetchMode * Set the fetch mode to use while iterating this statement. * * @param integer $fetchMode */ function setFetchMode($fetchMode, $arg2 = null, $arg3 = null); /** * fetch * * @see Query::HYDRATE_* constants * @param integer $fetchMode Controls how the next row will be returned to the caller. * This value must be one of the Query::HYDRATE_* constants, * defaulting to Query::HYDRATE_BOTH * * @return mixed */ function fetch($fetchMode = null); /** * Returns an array containing all of the result set rows * * @param integer $fetchMode Controls how the next row will be returned to the caller. * This value must be one of the Query::HYDRATE_* constants, * defaulting to Query::HYDRATE_BOTH * * @return array */ function fetchAll($fetchMode = null); /** * fetchColumn * Returns a single column from the next row of a * result set or FALSE if there are no more rows. * * @param integer $columnIndex 0-indexed number of the column you wish to retrieve from the row. If no * value is supplied, PDOStatement->fetchColumn() * fetches the first column. * * @return string returns a single column in the next row of a result set. */ function fetchColumn($columnIndex = 0); } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/Statement.php0000644000175100017510000001343712143374463022220 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver; use \PDO; /** * Statement interface. * Drivers must implement this interface. * * This resembles (a subset of) the PDOStatement interface. * * @author Konsta Vesterinen * @author Roman Borschel * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.org * @since 2.0 */ interface Statement extends ResultStatement { /** * Binds a value to a corresponding named or positional * placeholder in the SQL statement that was used to prepare the statement. * * @param mixed $param Parameter identifier. For a prepared statement using named placeholders, * this will be a parameter name of the form :name. For a prepared statement * using question mark placeholders, this will be the 1-indexed position of the parameter * * @param mixed $value The value to bind to the parameter. * @param integer $type Explicit data type for the parameter using the PDO::PARAM_* constants. * * @return boolean Returns TRUE on success or FALSE on failure. */ function bindValue($param, $value, $type = null); /** * Binds a PHP variable to a corresponding named or question mark placeholder in the * SQL statement that was use to prepare the statement. Unlike PDOStatement->bindValue(), * the variable is bound as a reference and will only be evaluated at the time * that PDOStatement->execute() is called. * * Most parameters are input parameters, that is, parameters that are * used in a read-only fashion to build up the query. Some drivers support the invocation * of stored procedures that return data as output parameters, and some also as input/output * parameters that both send in data and are updated to receive it. * * @param mixed $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 $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 $length You must specify maxlength when using an OUT bind so that PHP allocates enough memory to hold the returned value. * @return boolean Returns TRUE on success or FALSE on failure. */ function bindParam($column, &$variable, $type = null, $length = null); /** * errorCode * Fetch the SQLSTATE associated with the last operation on the statement handle * * @see Doctrine_Adapter_Interface::errorCode() * @return string error code string */ function errorCode(); /** * errorInfo * Fetch extended error information associated with the last operation on the statement handle * * @see Doctrine_Adapter_Interface::errorInfo() * @return array error info array */ function errorInfo(); /** * Executes a prepared statement * * If the prepared statement included parameter markers, you must either: * call PDOStatement->bindParam() to bind PHP variables to the parameter markers: * bound variables pass their value as input and receive the output value, * if any, of their associated parameter markers or pass an array of input-only * parameter values * * * @param array $params An array of values with as many elements as there are * bound parameters in the SQL statement being executed. * @return boolean Returns TRUE on success or FALSE on failure. */ function execute($params = null); /** * rowCount * rowCount() returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement * executed by the corresponding object. * * If the last SQL statement executed by the associated Statement object was a SELECT statement, * some databases may return the number of rows returned by that statement. However, * this behaviour is not guaranteed for all databases and should not be * relied on for portable applications. * * @return integer Returns the number of rows. */ function rowCount(); } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/DrizzlePDOMySql/Connection.php0000644000175100017510000000272412143374463025324 0ustar beberleibeberlei. */ 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); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/DrizzlePDOMySql/Driver.php0000644000175100017510000000544112143374463024457 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\DrizzlePDOMySql; /** * Drizzle driver using PDO MySql. * * @author Kim Hemsø Rasmussen */ class Driver implements \Doctrine\DBAL\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; } /** * Constructs the Drizzle MySql PDO DSN. * * @return string The DSN. */ private function _constructPdoDsn(array $params) { $dsn = 'mysql:'; if (isset($params['host']) && $params['host'] != '') { $dsn .= 'host=' . $params['host'] . ';'; } if (isset($params['port'])) { $dsn .= 'port=' . $params['port'] . ';'; } if (isset($params['dbname'])) { $dsn .= 'dbname=' . $params['dbname'] . ';'; } if (isset($params['unix_socket'])) { $dsn .= 'unix_socket=' . $params['unix_socket'] . ';'; } return $dsn; } /** * {@inheritdoc} */ public function getDatabasePlatform() { return new \Doctrine\DBAL\Platforms\DrizzlePlatform(); } /** * {@inheritdoc} */ public function getSchemaManager(\Doctrine\DBAL\Connection $conn) { return new \Doctrine\DBAL\Schema\DrizzleSchemaManager($conn); } /** * {@inheritdoc} */ public function getName() { return 'drizzle_pdo_mysql'; } /** * {@inheritdoc} */ public function getDatabase(\Doctrine\DBAL\Connection $conn) { $params = $conn->getParams(); return $params['dbname']; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php0000644000175100017510000000652112143374463023536 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\IBMDB2; class DB2Connection implements \Doctrine\DBAL\Driver\Connection { private $_conn = null; public function __construct(array $params, $username, $password, $driverOptions = array()) { $isPersistant = (isset($params['persistent']) && $params['persistent'] == true); if ($isPersistant) { $this->_conn = db2_pconnect($params['dbname'], $username, $password, $driverOptions); } else { $this->_conn = db2_connect($params['dbname'], $username, $password, $driverOptions); } if ( ! $this->_conn) { throw new DB2Exception(db2_conn_errormsg()); } } public function prepare($sql) { $stmt = @db2_prepare($this->_conn, $sql); if ( ! $stmt) { throw new DB2Exception(db2_stmt_errormsg()); } return new DB2Statement($stmt); } public function query() { $args = func_get_args(); $sql = $args[0]; $stmt = $this->prepare($sql); $stmt->execute(); return $stmt; } public function quote($input, $type=\PDO::PARAM_STR) { $input = db2_escape_string($input); if ($type == \PDO::PARAM_INT ) { return $input; } else { return "'".$input."'"; } } public function exec($statement) { $stmt = $this->prepare($statement); $stmt->execute(); return $stmt->rowCount(); } public function lastInsertId($name = null) { return db2_last_insert_id($this->_conn); } public function beginTransaction() { db2_autocommit($this->_conn, DB2_AUTOCOMMIT_OFF); } public function commit() { if (!db2_commit($this->_conn)) { throw new DB2Exception(db2_conn_errormsg($this->_conn)); } db2_autocommit($this->_conn, DB2_AUTOCOMMIT_ON); } public function rollBack() { if (!db2_rollback($this->_conn)) { throw new DB2Exception(db2_conn_errormsg($this->_conn)); } db2_autocommit($this->_conn, DB2_AUTOCOMMIT_ON); } public function errorCode() { return db2_conn_error($this->_conn); } public function errorInfo() { return array( 0 => db2_conn_errormsg($this->_conn), 1 => $this->errorCode(), ); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php0000644000175100017510000000744712143374463022702 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\IBMDB2; use Doctrine\DBAL\Driver, Doctrine\DBAL\Connection; /** * IBM DB2 Driver * * @since 2.0 * @author Benjamin Eberlei */ class DB2Driver implements Driver { /** * Attempts to create a connection with the database. * * @param array $params All connection parameters passed by the user. * @param string $username The username to use when connecting. * @param string $password The password to use when connecting. * @param array $driverOptions The driver options to use when connecting. * @return \Doctrine\DBAL\Driver\Connection The database connection. */ public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { if ( ! isset($params['protocol'])) { $params['protocol'] = 'TCPIP'; } if ($params['host'] !== 'localhost' && $params['host'] != '127.0.0.1') { // if the host isn't localhost, use extended connection params $params['dbname'] = 'DRIVER={IBM DB2 ODBC DRIVER}' . ';DATABASE=' . $params['dbname'] . ';HOSTNAME=' . $params['host'] . ';PROTOCOL=' . $params['protocol'] . ';UID=' . $username . ';PWD=' . $password .';'; if (isset($params['port'])) { $params['dbname'] .= 'PORT=' . $params['port']; } $username = null; $password = null; } return new DB2Connection($params, $username, $password, $driverOptions); } /** * Gets the DatabasePlatform instance that provides all the metadata about * the platform this driver connects to. * * @return \Doctrine\DBAL\Platforms\AbstractPlatform The database platform. */ public function getDatabasePlatform() { return new \Doctrine\DBAL\Platforms\DB2Platform; } /** * Gets the SchemaManager that can be used to inspect and change the underlying * database schema of the platform this driver connects to. * * @param \Doctrine\DBAL\Connection $conn * @return \Doctrine\DBAL\Schema\DB2SchemaManager */ public function getSchemaManager(Connection $conn) { return new \Doctrine\DBAL\Schema\DB2SchemaManager($conn); } /** * Gets the name of the driver. * * @return string The name of the driver. */ public function getName() { return 'ibm_db2'; } /** * Get the name of the database connected to for this driver. * * @param \Doctrine\DBAL\Connection $conn * @return string $database */ public function getDatabase(\Doctrine\DBAL\Connection $conn) { $params = $conn->getParams(); return $params['dbname']; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/IBMDB2/DB2Exception.php0000644000175100017510000000207312143374463023373 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\IBMDB2; class DB2Exception extends \Exception { } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php0000644000175100017510000001221412143374463023377 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\IBMDB2; use \Doctrine\DBAL\Driver\Statement; class DB2Statement implements \IteratorAggregate, Statement { private $_stmt = null; private $_bindParam = array(); private $_defaultFetchMode = \PDO::FETCH_BOTH; /** * DB2_BINARY, DB2_CHAR, DB2_DOUBLE, or DB2_LONG * @var array */ static private $_typeMap = array( \PDO::PARAM_INT => DB2_LONG, \PDO::PARAM_STR => DB2_CHAR, ); public function __construct($stmt) { $this->_stmt = $stmt; } /** * {@inheritdoc} */ public function bindValue($param, $value, $type = null) { return $this->bindParam($param, $value, $type); } /** * {@inheritdoc} */ public function bindParam($column, &$variable, $type = null, $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(); db2_free_result($this->_stmt); $ret = db2_free_stmt($this->_stmt); $this->_stmt = false; return $ret; } /** * {@inheritdoc} */ public function columnCount() { if ( ! $this->_stmt) { return false; } return db2_num_fields($this->_stmt); } /** * {@inheritdoc} */ public function errorCode() { return db2_stmt_error(); } /** * {@inheritdoc} */ public function errorInfo() { return array( 0 => db2_stmt_errormsg(), 1 => db2_stmt_error(), ); } /** * {@inheritdoc} */ public function execute($params = null) { if ( ! $this->_stmt) { return false; } /*$retval = true; if ($params !== null) { $retval = @db2_execute($this->_stmt, $params); } else { $retval = @db2_execute($this->_stmt); }*/ if ($params === null) { ksort($this->_bindParam); $params = array_values($this->_bindParam); } $retval = @db2_execute($this->_stmt, $params); if ($retval === false) { throw new DB2Exception(db2_stmt_errormsg()); } return $retval; } /** * {@inheritdoc} */ public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) { $this->_defaultFetchMode = $fetchMode; } /** * {@inheritdoc} */ public function getIterator() { $data = $this->fetchAll(); return new \ArrayIterator($data); } /** * {@inheritdoc} */ public function fetch($fetchMode = null) { $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_NUM: return db2_fetch_array($this->_stmt); default: throw new DB2Exception("Given Fetch-Style " . $fetchMode . " is not supported."); } } /** * {@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 ($row && isset($row[$columnIndex])) { return $row[$columnIndex]; } return false; } /** * {@inheritdoc} */ public function rowCount() { return (@db2_num_rows($this->_stmt))?:0; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/Mysqli/Driver.php0000644000175100017510000000401212143374463022752 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\Mysqli; use Doctrine\DBAL\Driver as DriverInterface; /** * @author Kim Hemsø Rasmussen */ class Driver implements DriverInterface { /** * {@inheritdoc} */ public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { return new MysqliConnection($params, $username, $password, $driverOptions); } /** * {@inheritdoc} */ public function getName() { return 'mysqli'; } /** * {@inheritdoc} */ public function getSchemaManager(\Doctrine\DBAL\Connection $conn) { return new \Doctrine\DBAL\Schema\MySqlSchemaManager($conn); } /** * {@inheritdoc} */ public function getDatabasePlatform() { return new \Doctrine\DBAL\Platforms\MySqlPlatform(); } /** * {@inheritdoc} */ public function getDatabase(\Doctrine\DBAL\Connection $conn) { $params = $conn->getParams(); return $params['dbname']; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php0000644000175100017510000000716512143374463025031 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\Mysqli; use Doctrine\DBAL\Driver\Connection as Connection; /** * @author Kim Hemsø Rasmussen */ class MysqliConnection implements Connection { /** * @var \mysqli */ private $_conn; public function __construct(array $params, $username, $password, array $driverOptions = array()) { $port = isset($params['port']) ? $params['port'] : ini_get('mysqli.default_port'); $socket = isset($params['unix_socket']) ? $params['unix_socket'] : ini_get('mysqli.default_socket'); $this->_conn = mysqli_init(); if ( ! $this->_conn->real_connect($params['host'], $username, $password, $params['dbname'], $port, $socket)) { throw new MysqliException($this->_conn->connect_error, $this->_conn->connect_errno); } if (isset($params['charset'])) { $this->_conn->set_charset($params['charset']); } } /** * Retrieve mysqli native resource handle. * * Could be used if part of your application is not using DBAL * * @return \mysqli */ public function getWrappedResourceHandle() { return $this->_conn; } /** * {@inheritdoc} */ public function prepare($prepareString) { return new MysqliStatement($this->_conn, $prepareString); } /** * {@inheritdoc} */ public function query() { $args = func_get_args(); $sql = $args[0]; $stmt = $this->prepare($sql); $stmt->execute(); return $stmt; } /** * {@inheritdoc} */ public function quote($input, $type=\PDO::PARAM_STR) { return "'". $this->_conn->escape_string($input) ."'"; } /** * {@inheritdoc} */ public function exec($statement) { $this->_conn->query($statement); return $this->_conn->affected_rows; } /** * {@inheritdoc} */ public function lastInsertId($name = null) { return $this->_conn->insert_id; } /** * {@inheritdoc} */ public function beginTransaction() { $this->_conn->query('START TRANSACTION'); return true; } /** * {@inheritdoc} */ public function commit() { return $this->_conn->commit(); } /** * {@inheritdoc}non-PHPdoc) */ public function rollBack() { return $this->_conn->rollback(); } /** * {@inheritdoc} */ public function errorCode() { return $this->_conn->errno; } /** * {@inheritdoc} */ public function errorInfo() { return $this->_conn->error; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/Mysqli/MysqliException.php0000644000175100017510000000215612143374463024663 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\Mysqli; /** * @author Kim Hemsø Rasmussen */ class MysqliException extends \Exception {} DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php0000644000175100017510000002165212143374463024673 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\Mysqli; use Doctrine\DBAL\Driver\Statement; use PDO; /** * @author Kim Hemsø Rasmussen */ class MysqliStatement implements \IteratorAggregate, Statement { protected static $_paramTypeMap = array( PDO::PARAM_STR => 's', PDO::PARAM_BOOL => 'i', PDO::PARAM_NULL => 's', PDO::PARAM_INT => 'i', PDO::PARAM_LOB => 's' // TODO Support LOB bigger then max package size. ); protected $_conn; protected $_stmt; /** * @var null|false|array */ protected $_columnNames; /** * @var null|array */ protected $_rowBindedValues; /** * @var array */ protected $_bindedValues; /** * Contains ref values for bindValue() * * @var array */ protected $_values = array(); protected $_defaultFetchMode = PDO::FETCH_BOTH; public function __construct(\mysqli $conn, $prepareString) { $this->_conn = $conn; $this->_stmt = $conn->prepare($prepareString); if (false === $this->_stmt) { throw new MysqliException($this->_conn->error, $this->_conn->errno); } $paramCount = $this->_stmt->param_count; if (0 < $paramCount) { // Index 0 is types // Need to init the string else php think we are trying to access it as a array. $bindedValues = array(0 => str_repeat('s', $paramCount)); $null = null; for ($i = 1; $i < $paramCount; $i++) { $bindedValues[] =& $null; } $this->_bindedValues = $bindedValues; } } /** * {@inheritdoc} */ public function bindParam($column, &$variable, $type = null, $length = null) { if (null === $type) { $type = 's'; } else { if (isset(self::$_paramTypeMap[$type])) { $type = self::$_paramTypeMap[$type]; } else { throw new MysqliException("Unkown type: '{$type}'"); } } $this->_bindedValues[$column] =& $variable; $this->_bindedValues[0][$column - 1] = $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->_bindedValues[0][$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'), $this->_bindedValues)) { throw new MysqliException($this->_stmt->error, $this->_stmt->errno); } } } if ( ! $this->_stmt->execute()) { throw new MysqliException($this->_stmt->error, $this->_stmt->errno); } if (null === $this->_columnNames) { $meta = $this->_stmt->result_metadata(); if (false !== $meta) { $columnNames = array(); foreach ($meta->fetch_fields() as $col) { $columnNames[] = $col->name; } $meta->free(); $this->_columnNames = $columnNames; $this->_rowBindedValues = array_fill(0, count($columnNames), NULL); $refs = array(); foreach ($this->_rowBindedValues as $key => &$value) { $refs[$key] =& $value; } if (!call_user_func_array(array($this->_stmt, 'bind_result'), $refs)) { throw new MysqliException($this->_stmt->error, $this->_stmt->errno); } } else { $this->_columnNames = false; } } // We have a result. if (false !== $this->_columnNames) { $this->_stmt->store_result(); } return true; } /** * Bind a array of values to bound parameters * * @param array $values * @return boolean */ private function _bindValues($values) { $params = array(); $types = str_repeat('s', count($values)); $params[0] = $types; foreach ($values as &$v) { $params[] =& $v; } return call_user_func_array(array($this->_stmt, 'bind_param'), $params); } /** * @return boolean|array */ private function _fetch() { $ret = $this->_stmt->fetch(); if (true === $ret) { $values = array(); foreach ($this->_rowBindedValues as $v) { // Mysqli converts them to a scalar type it can fit in. $values[] = null === $v ? null : (string)$v; } return $values; } return $ret; } /** * {@inheritdoc} */ public function fetch($fetchMode = null) { $values = $this->_fetch(); if (null === $values) { return null; } if (false === $values) { throw new MysqliException($this->_stmt->error, $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)) !== null) { $rows[] = $row; } } return $rows; } /** * {@inheritdoc} */ public function fetchColumn($columnIndex = 0) { $row = $this->fetch(PDO::FETCH_NUM); if (null === $row) { return false; } return $row[$columnIndex]; } /** * {@inheritdoc} */ public function errorCode() { return $this->_stmt->errno; } /** * {@inheritdoc} */ public function errorInfo() { return $this->_stmt->error; } /** * {@inheritdoc} */ public function closeCursor() { $this->_stmt->free_result(); return true; } /** * {@inheritdoc} */ public function rowCount() { if (false === $this->_columnNames) { return $this->_stmt->affected_rows; } return $this->_stmt->num_rows; } /** * {@inheritdoc} */ public function columnCount() { return $this->_stmt->field_count; } /** * {@inheritdoc} */ public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) { $this->_defaultFetchMode = $fetchMode; } /** * {@inheritdoc} */ public function getIterator() { $data = $this->fetchAll(); return new \ArrayIterator($data); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/OCI8/Driver.php0000644000175100017510000000631012143374463022201 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\OCI8; use Doctrine\DBAL\Platforms; /** * A Doctrine DBAL driver for the Oracle OCI8 PHP extensions. * * @author Roman Borschel * @since 2.0 */ class Driver implements \Doctrine\DBAL\Driver { public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { return new OCI8Connection( $username, $password, $this->_constructDsn($params), isset($params['charset']) ? $params['charset'] : null, isset($params['sessionMode']) ? $params['sessionMode'] : OCI_DEFAULT, isset($params['persistent']) ? $params['persistent'] : false ); } /** * Constructs the Oracle DSN. * * @return string The DSN. */ protected function _constructDsn(array $params) { $dsn = ''; if (isset($params['host']) && $params['host'] != '') { $dsn .= '(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)' . '(HOST=' . $params['host'] . ')'; if (isset($params['port'])) { $dsn .= '(PORT=' . $params['port'] . ')'; } else { $dsn .= '(PORT=1521)'; } if (isset($params['service']) && $params['service'] == true) { $dsn .= '))(CONNECT_DATA=(SERVICE_NAME=' . $params['dbname'] . '))'; } else { $dsn .= '))(CONNECT_DATA=(SID=' . $params['dbname'] . '))'; } if (isset($params['pooled']) && $params['pooled'] == true) { $dsn .= '(SERVER=POOLED)'; } $dsn .= ')'; } else { $dsn .= $params['dbname']; } return $dsn; } public function getDatabasePlatform() { return new \Doctrine\DBAL\Platforms\OraclePlatform(); } public function getSchemaManager(\Doctrine\DBAL\Connection $conn) { return new \Doctrine\DBAL\Schema\OracleSchemaManager($conn); } public function getName() { return 'oci8'; } public function getDatabase(\Doctrine\DBAL\Connection $conn) { $params = $conn->getParams(); return $params['user']; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php0000644000175100017510000001217312143374463023474 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\OCI8; use Doctrine\DBAL\Platforms\OraclePlatform; /** * OCI8 implementation of the Connection interface. * * @since 2.0 */ class OCI8Connection implements \Doctrine\DBAL\Driver\Connection { /** * @var resource */ protected $dbh; /** * @var int */ protected $executeMode = OCI_COMMIT_ON_SUCCESS; /** * Create a Connection to an Oracle Database using oci8 extension. * * @param string $username * @param string $password * @param string $db */ public function __construct($username, $password, $db, $charset = null, $sessionMode = OCI_DEFAULT, $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()); } } /** * Create a non-executed prepared statement. * * @param string $prepareString * @return OCI8Statement */ public function prepare($prepareString) { return new OCI8Statement($this->dbh, $prepareString, $this); } /** * @param string $sql * @return OCI8Statement */ public function query() { $args = func_get_args(); $sql = $args[0]; //$fetchMode = $args[1]; $stmt = $this->prepare($sql); $stmt->execute(); return $stmt; } /** * Quote input value. * * @param mixed $input * @param int $type PDO::PARAM* * @return mixed */ public function quote($value, $type=\PDO::PARAM_STR) { if (is_int($value) || is_float($value)) { return $value; } $value = str_replace("'", "''", $value); return "'" . addcslashes($value, "\000\n\r\\\032") . "'"; } /** * * @param string $statement * @return int */ public function exec($statement) { $stmt = $this->prepare($statement); $stmt->execute(); return $stmt->rowCount(); } /** * {@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']; } /** * Return the current execution mode. */ public function getExecuteMode() { return $this->executeMode; } /** * Start a transactiom * * Oracle has to explicitly set the autocommit mode off. That means * after connection, a commit or rollback there is always automatically * opened a new transaction. * * @return bool */ public function beginTransaction() { $this->executeMode = OCI_NO_AUTO_COMMIT; return true; } /** * @throws OCI8Exception * @return bool */ public function commit() { if (!oci_commit($this->dbh)) { throw OCI8Exception::fromErrorInfo($this->errorInfo()); } $this->executeMode = OCI_COMMIT_ON_SUCCESS; return true; } /** * @throws OCI8Exception * @return bool */ public function rollBack() { if (!oci_rollback($this->dbh)) { throw OCI8Exception::fromErrorInfo($this->errorInfo()); } $this->executeMode = OCI_COMMIT_ON_SUCCESS; return true; } public function errorCode() { $error = oci_error($this->dbh); if ($error !== false) { $error = $error['code']; } return $error; } public function errorInfo() { return oci_error($this->dbh); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/OCI8/OCI8Exception.php0000644000175100017510000000226212143374463023331 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\OCI8; class OCI8Exception extends \Exception { static public function fromErrorInfo($error) { return new self($error['message'], $error['code']); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php0000644000175100017510000002041312143374463023335 0ustar beberleibeberlei. */ 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 { /** Statement handle. */ protected $_dbh; protected $_sth; protected $_conn; protected static $_PARAM = ':param'; protected static $fetchModeMap = array( PDO::FETCH_BOTH => OCI_BOTH, PDO::FETCH_ASSOC => OCI_ASSOC, PDO::FETCH_NUM => OCI_NUM, PDO::PARAM_LOB => OCI_B_BLOB, PDO::FETCH_COLUMN => OCI_NUM, ); protected $_defaultFetchMode = PDO::FETCH_BOTH; protected $_paramMap = array(); /** * Creates a new OCI8Statement that uses the given connection handle and SQL statement. * * @param resource $dbh The connection handle. * @param string $statement The SQL statement. */ public function __construct($dbh, $statement, OCI8Connection $conn) { list($statement, $paramMap) = self::convertPositionalToNamedPlaceholders($statement); $this->_sth = oci_parse($dbh, $statement); $this->_dbh = $dbh; $this->_paramMap = $paramMap; $this->_conn = $conn; } /** * Convert positional (?) into named placeholders (:param) * * Oracle does not support positional parameters, hence this method converts all * positional parameters into artificially named parameters. Note that this conversion * is not perfect. All question marks (?) in the original statement are treated as * placeholders and converted to a named parameter. * * The algorithm uses a state machine with two possible states: InLiteral and NotInLiteral. * Question marks inside literal strings are therefore handled correctly by this method. * This comes at a cost, the whole sql statement has to be looped over. * * @todo extract into utility class in Doctrine\DBAL\Util namespace * @todo review and test for lost spaces. we experienced missing spaces with oci8 in some sql statements. * @param string $statement The SQL statement to convert. * @return string */ static public function convertPositionalToNamedPlaceholders($statement) { $count = 1; $inLiteral = false; // a valid query never starts with quotes $stmtLen = strlen($statement); $paramMap = array(); for ($i = 0; $i < $stmtLen; $i++) { if ($statement[$i] == '?' && !$inLiteral) { // real positional parameter detected $paramMap[$count] = ":param$count"; $len = strlen($paramMap[$count]); $statement = substr_replace($statement, ":param$count", $i, 1); $i += $len-1; // jump ahead $stmtLen = strlen($statement); // adjust statement length ++$count; } else if ($statement[$i] == "'" || $statement[$i] == '"') { $inLiteral = ! $inLiteral; // switch state! } } return array($statement, $paramMap); } /** * {@inheritdoc} */ public function bindValue($param, $value, $type = null) { return $this->bindParam($param, $value, $type, 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); return oci_bind_by_name($this->_sth, $column, $lob, -1, OCI_B_BLOB); } else { return oci_bind_by_name($this->_sth, $column, $variable); } } /** * Closes the cursor, enabling the statement to be executed again. * * @return boolean Returns TRUE on success or FALSE on failure. */ public function closeCursor() { return oci_free_statement($this->_sth); } /** * {@inheritdoc} */ public function columnCount() { return oci_num_fields($this->_sth); } /** * {@inheritdoc} */ public function errorCode() { $error = oci_error($this->_sth); if ($error !== false) { $error = $error['code']; } return $error; } /** * {@inheritdoc} */ public function errorInfo() { return oci_error($this->_sth); } /** * {@inheritdoc} */ public function execute($params = null) { if ($params) { $hasZeroIndex = array_key_exists(0, $params); foreach ($params as $key => $val) { if ($hasZeroIndex && is_numeric($key)) { $this->bindValue($key + 1, $val); } else { $this->bindValue($key, $val); } } } $ret = @oci_execute($this->_sth, $this->_conn->getExecuteMode()); if ( ! $ret) { throw OCI8Exception::fromErrorInfo($this->errorInfo()); } return $ret; } /** * {@inheritdoc} */ public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) { $this->_defaultFetchMode = $fetchMode; } /** * {@inheritdoc} */ public function getIterator() { $data = $this->fetchAll(); return new \ArrayIterator($data); } /** * {@inheritdoc} */ public function fetch($fetchMode = null) { $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; } 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) { $row = oci_fetch_array($this->_sth, OCI_NUM | OCI_RETURN_NULLS | OCI_RETURN_LOBS); return isset($row[$columnIndex]) ? $row[$columnIndex] : false; } /** * {@inheritdoc} */ public function rowCount() { return oci_num_rows($this->_sth); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/PDOIbm/Driver.php0000644000175100017510000000754512143374463022564 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\PDOIbm; use Doctrine\DBAL\Connection; /** * Driver for the PDO IBM extension * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 1.0 * @version $Revision$ * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel */ class Driver implements \Doctrine\DBAL\Driver { /** * Attempts to establish a connection with the underlying driver. * * @param array $params * @param string $username * @param string $password * @param array $driverOptions * @return \Doctrine\DBAL\Driver\Connection */ public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { $conn = new \Doctrine\DBAL\Driver\PDOConnection( $this->_constructPdoDsn($params), $username, $password, $driverOptions ); return $conn; } /** * Constructs the MySql PDO DSN. * * @return string The DSN. */ private function _constructPdoDsn(array $params) { $dsn = 'ibm:'; if (isset($params['host'])) { $dsn .= 'HOSTNAME=' . $params['host'] . ';'; } if (isset($params['port'])) { $dsn .= 'PORT=' . $params['port'] . ';'; } $dsn .= 'PROTOCOL=TCPIP;'; if (isset($params['dbname'])) { $dsn .= 'DATABASE=' . $params['dbname'] . ';'; } return $dsn; } /** * Gets the DatabasePlatform instance that provides all the metadata about * the platform this driver connects to. * * @return \Doctrine\DBAL\Platforms\AbstractPlatform The database platform. */ public function getDatabasePlatform() { return new \Doctrine\DBAL\Platforms\DB2Platform; } /** * Gets the SchemaManager that can be used to inspect and change the underlying * database schema of the platform this driver connects to. * * @param \Doctrine\DBAL\Connection $conn * @return \Doctrine\DBAL\Schema\DB2SchemaManager */ public function getSchemaManager(Connection $conn) { return new \Doctrine\DBAL\Schema\DB2SchemaManager($conn); } /** * Gets the name of the driver. * * @return string The name of the driver. */ public function getName() { return 'pdo_ibm'; } /** * Get the name of the database connected to for this driver. * * @param \Doctrine\DBAL\Connection $conn * @return string $database */ public function getDatabase(\Doctrine\DBAL\Connection $conn) { $params = $conn->getParams(); return $params['dbname']; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/PDOMySql/Driver.php0000644000175100017510000000607712143374463023121 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\PDOMySql; use Doctrine\DBAL\Connection; /** * PDO MySql driver. * * @since 2.0 */ class Driver implements \Doctrine\DBAL\Driver { /** * Attempts to establish a connection with the underlying driver. * * @param array $params * @param string $username * @param string $password * @param array $driverOptions * @return \Doctrine\DBAL\Driver\Connection */ public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { $conn = new \Doctrine\DBAL\Driver\PDOConnection( $this->_constructPdoDsn($params), $username, $password, $driverOptions ); return $conn; } /** * Constructs the MySql PDO DSN. * * @return string The DSN. */ private function _constructPdoDsn(array $params) { $dsn = 'mysql:'; if (isset($params['host']) && $params['host'] != '') { $dsn .= 'host=' . $params['host'] . ';'; } if (isset($params['port'])) { $dsn .= 'port=' . $params['port'] . ';'; } if (isset($params['dbname'])) { $dsn .= 'dbname=' . $params['dbname'] . ';'; } if (isset($params['unix_socket'])) { $dsn .= 'unix_socket=' . $params['unix_socket'] . ';'; } if (isset($params['charset'])) { $dsn .= 'charset=' . $params['charset'] . ';'; } return $dsn; } public function getDatabasePlatform() { return new \Doctrine\DBAL\Platforms\MySqlPlatform(); } public function getSchemaManager(\Doctrine\DBAL\Connection $conn) { return new \Doctrine\DBAL\Schema\MySqlSchemaManager($conn); } public function getName() { return 'pdo_mysql'; } public function getDatabase(\Doctrine\DBAL\Connection $conn) { $params = $conn->getParams(); if (isset($params['dbname'])) { return $params['dbname']; } return $conn->query('SELECT DATABASE()')->fetchColumn(); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/PDOOracle/Driver.php0000644000175100017510000000624212143374463023253 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\PDOOracle; use Doctrine\DBAL\Platforms; /** * PDO Oracle driver * * WARNING: This driver gives us segfauls in our testsuites on CLOB and other * stuff. PDO Oracle is not maintained by Oracle or anyone in the PHP community, * which leads us to the recommendation to use the "oci8" driver to connect * to Oracle instead. */ class Driver implements \Doctrine\DBAL\Driver { public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { return new \Doctrine\DBAL\Driver\PDOConnection( $this->_constructPdoDsn($params), $username, $password, $driverOptions ); } /** * Constructs the Oracle PDO DSN. * * @return string The DSN. */ private function _constructPdoDsn(array $params) { $dsn = 'oci:'; if (isset($params['host']) && $params['host'] != '') { $dsn .= 'dbname=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)' . '(HOST=' . $params['host'] . ')'; if (isset($params['port'])) { $dsn .= '(PORT=' . $params['port'] . ')'; } else { $dsn .= '(PORT=1521)'; } if (isset($params['service']) && $params['service'] == true) { $dsn .= '))(CONNECT_DATA=(SERVICE_NAME=' . $params['dbname'] . ')))'; } else { $dsn .= '))(CONNECT_DATA=(SID=' . $params['dbname'] . ')))'; } } else { $dsn .= 'dbname=' . $params['dbname']; } if (isset($params['charset'])) { $dsn .= ';charset=' . $params['charset']; } return $dsn; } public function getDatabasePlatform() { return new \Doctrine\DBAL\Platforms\OraclePlatform(); } public function getSchemaManager(\Doctrine\DBAL\Connection $conn) { return new \Doctrine\DBAL\Schema\OracleSchemaManager($conn); } public function getName() { return 'pdo_oracle'; } public function getDatabase(\Doctrine\DBAL\Connection $conn) { $params = $conn->getParams(); return $params['user']; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/PDOPgSql/Driver.php0000644000175100017510000000330012143374463023064 0ustar beberleibeberlei_constructPdoDsn($params), $username, $password, $driverOptions ); } /** * Constructs the Postgres PDO DSN. * * @return string The DSN. */ private function _constructPdoDsn(array $params) { $dsn = 'pgsql:'; if (isset($params['host']) && $params['host'] != '') { $dsn .= 'host=' . $params['host'] . ' '; } if (isset($params['port']) && $params['port'] != '') { $dsn .= 'port=' . $params['port'] . ' '; } if (isset($params['dbname'])) { $dsn .= 'dbname=' . $params['dbname'] . ' '; } return $dsn; } public function getDatabasePlatform() { return new \Doctrine\DBAL\Platforms\PostgreSqlPlatform(); } public function getSchemaManager(\Doctrine\DBAL\Connection $conn) { return new \Doctrine\DBAL\Schema\PostgreSqlSchemaManager($conn); } public function getName() { return 'pdo_pgsql'; } public function getDatabase(\Doctrine\DBAL\Connection $conn) { $params = $conn->getParams(); return $params['dbname']; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/PDOSqlite/Driver.php0000644000175100017510000000730212143374463023305 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\PDOSqlite; /** * The PDO Sqlite driver. * * @since 2.0 */ class Driver implements \Doctrine\DBAL\Driver { /** * @var array */ protected $_userDefinedFunctions = array( 'sqrt' => array('callback' => array('Doctrine\DBAL\Platforms\SqlitePlatform', 'udfSqrt'), 'numArgs' => 1), 'mod' => array('callback' => array('Doctrine\DBAL\Platforms\SqlitePlatform', 'udfMod'), 'numArgs' => 2), 'locate' => array('callback' => array('Doctrine\DBAL\Platforms\SqlitePlatform', 'udfLocate'), 'numArgs' => -1), ); /** * Tries to establish a database connection to SQLite. * * @param array $params * @param string $username * @param string $password * @param array $driverOptions * @return \Doctrine\DBAL\Driver\PDOConnection */ public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { if (isset($driverOptions['userDefinedFunctions'])) { $this->_userDefinedFunctions = array_merge( $this->_userDefinedFunctions, $driverOptions['userDefinedFunctions']); unset($driverOptions['userDefinedFunctions']); } $pdo = new \Doctrine\DBAL\Driver\PDOConnection( $this->_constructPdoDsn($params), $username, $password, $driverOptions ); foreach ($this->_userDefinedFunctions as $fn => $data) { $pdo->sqliteCreateFunction($fn, $data['callback'], $data['numArgs']); } return $pdo; } /** * Constructs the Sqlite PDO DSN. * * @return string The DSN. * @override */ protected function _constructPdoDsn(array $params) { $dsn = 'sqlite:'; if (isset($params['path'])) { $dsn .= $params['path']; } else if (isset($params['memory'])) { $dsn .= ':memory:'; } return $dsn; } /** * Gets the database platform that is relevant for this driver. */ public function getDatabasePlatform() { return new \Doctrine\DBAL\Platforms\SqlitePlatform(); } /** * Gets the schema manager that is relevant for this driver. * * @param \Doctrine\DBAL\Connection $conn * @return \Doctrine\DBAL\Schema\SqliteSchemaManager */ public function getSchemaManager(\Doctrine\DBAL\Connection $conn) { return new \Doctrine\DBAL\Schema\SqliteSchemaManager($conn); } public function getName() { return 'pdo_sqlite'; } public function getDatabase(\Doctrine\DBAL\Connection $conn) { $params = $conn->getParams(); return isset($params['path']) ? $params['path'] : null; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php0000644000175100017510000000276012143374463024205 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\PDOSqlsrv; /** * Sqlsrv Connection implementation. * * @since 2.0 */ class Connection extends \Doctrine\DBAL\Driver\PDOConnection implements \Doctrine\DBAL\Driver\Connection { /** * @override */ public function quote($value, $type=\PDO::PARAM_STR) { $val = parent::quote($value, $type); // Fix for a driver version terminating all values with null byte if (strpos($val, "\0") !== false) { $val = substr($val, 0, -1); } return $val; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php0000644000175100017510000000510512143374463023335 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\PDOSqlsrv; /** * The PDO-based Sqlsrv driver. * * @since 2.0 */ class Driver implements \Doctrine\DBAL\Driver { public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { return new Connection( $this->_constructPdoDsn($params), $username, $password, $driverOptions ); } /** * Constructs the Sqlsrv PDO DSN. * * @return string The DSN. */ private function _constructPdoDsn(array $params) { $dsn = 'sqlsrv:server='; if (isset($params['host'])) { $dsn .= $params['host']; } if (isset($params['port']) && !empty($params['port'])) { $dsn .= ',' . $params['port']; } if (isset($params['dbname'])) {; $dsn .= ';Database=' . $params['dbname']; } if (isset($params['MultipleActiveResultSets'])) { $dsn .= '; MultipleActiveResultSets=' . ($params['MultipleActiveResultSets'] ? 'true' : 'false'); } return $dsn; } public function getDatabasePlatform() { return new \Doctrine\DBAL\Platforms\SQLServer2008Platform(); } public function getSchemaManager(\Doctrine\DBAL\Connection $conn) { return new \Doctrine\DBAL\Schema\SQLServerSchemaManager($conn); } public function getName() { return 'pdo_sqlsrv'; } public function getDatabase(\Doctrine\DBAL\Connection $conn) { $params = $conn->getParams(); return $params['dbname']; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/SQLSrv/Driver.php0000644000175100017510000000470212143374463022634 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\SQLSrv; /** * Driver for ext/sqlsrv */ class Driver implements \Doctrine\DBAL\Driver { 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."); } if (!isset($params['dbname'])) { throw new SQLSrvException("Missing 'dbname' in configuration for sqlsrv driver."); } $serverName = $params['host']; if (isset($params['port'])) { $serverName .= ', ' . $params['port']; } $driverOptions['Database'] = $params['dbname']; $driverOptions['UID'] = $username; $driverOptions['PWD'] = $password; if (!isset($driverOptions['ReturnDatesAsStrings'])) { $driverOptions['ReturnDatesAsStrings'] = 1; } return new SQLSrvConnection($serverName, $driverOptions); } public function getDatabasePlatform() { return new \Doctrine\DBAL\Platforms\SQLServer2008Platform(); } public function getSchemaManager(\Doctrine\DBAL\Connection $conn) { return new \Doctrine\DBAL\Schema\SQLServerSchemaManager($conn); } public function getName() { return 'sqlsrv'; } public function getDatabase(\Doctrine\DBAL\Connection $conn) { $params = $conn->getParams(); return $params['dbname']; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/SQLSrv/LastInsertId.php0000644000175100017510000000243312143374463023745 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\SQLSrv; /** * Last Id Data Container * * @since 2.3 * @author Benjamin Eberlei */ class LastInsertId { private $id; public function setId($id) { $this->id = $id; } public function getId() { return $this->id; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php0000644000175100017510000000753112143374463024556 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\SQLSrv; /** * SQL Server implementation for the Connection interface. * * @since 2.3 * @author Benjamin Eberlei */ class SQLSrvConnection implements \Doctrine\DBAL\Driver\Connection { /** * @var resource */ protected $conn; /** * @var LastInsertId */ protected $lastInsertId; public function __construct($serverName, $connectionOptions) { $this->conn = sqlsrv_connect($serverName, $connectionOptions); if ( ! $this->conn) { throw SQLSrvException::fromSqlSrvErrors(); } $this->lastInsertId = new LastInsertId(); } /** * {@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; } else if (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) { $sql = "SELECT IDENT_CURRENT(".$this->quote($name).") AS LastInsertId"; $stmt = $this->prepare($sql); $stmt->execute(); 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); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/SQLSrv/SQLSrvException.php0000644000175100017510000000321512143374463024410 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Driver\SQLSrv; class SQLSrvException extends \Doctrine\DBAL\DBALException { /** * Helper method to turn sql server errors into exception. * * @return SQLSrvException */ static public function fromSqlSrvErrors() { $errors = sqlsrv_errors(SQLSRV_ERR_ERRORS); $message = ""; foreach ($errors as $error) { $message .= "SQLSTATE [".$error['SQLSTATE'].", ".$error['code']."]: ". $error['message']."\n"; } if ( ! $message) { $message = "SQL Server error occured but no error message was retrieved from driver."; } return new self(rtrim($message)); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php0000644000175100017510000001445112143374463024422 0ustar beberleibeberlei. */ 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 { /** * SQLSRV Resource * * @var resource */ private $conn; /** * SQL Statement to execute * * @var string */ private $sql; /** * SQLSRV Statement Resource * * @var resource */ private $stmt; /** * Parameters to bind * * @var array */ private $params = 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, ); /** * Fetch Style * * @param int */ private $defaultFetchMode = PDO::FETCH_BOTH; /** * @var int|null */ private $lastInsertId; /** * Append to any INSERT query to retrieve the last insert id. * * @var string */ const LAST_INSERT_ID_SQL = ';SELECT SCOPE_IDENTITY() AS LastInsertId;'; public function __construct($conn, $sql, $lastInsertId = null) { $this->conn = $conn; $this->sql = $sql; if (stripos($sql, 'INSERT INTO ') === 0) { $this->sql .= self::LAST_INSERT_ID_SQL; $this->lastInsertId = $lastInsertId; } } public function bindValue($param, $value, $type = null) { return $this->bindParam($param, $value, $type,null); } /** * {@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."); } if ($type === \PDO::PARAM_LOB) { $this->params[$column-1] = array($variable, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY), SQLSRV_SQLTYPE_VARBINARY('max')); } else { $this->params[$column-1] = $variable; } } public function closeCursor() { if ($this->stmt) { sqlsrv_free_stmt($this->stmt); } } 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); } 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); } } $this->stmt = sqlsrv_query($this->conn, $this->sql, $this->params); if ( ! $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) ); } } public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) { $this->defaultFetchMode = $fetchMode; } /** * {@inheritdoc} */ public function getIterator() { $data = $this->fetchAll(); return new \ArrayIterator($data); } /** * {@inheritdoc} */ public function fetch($fetchMode = null) { $fetchMode = $fetchMode ?: $this->defaultFetchMode; if (isset(self::$fetchMap[$fetchMode])) { return sqlsrv_fetch_array($this->stmt, self::$fetchMap[$fetchMode]); } else if ($fetchMode == PDO::FETCH_OBJ || $fetchMode == PDO::FETCH_CLASS) { $className = null; $ctorArgs = null; if (func_num_args() >= 2) { $args = func_get_args(); $className = $args[1]; $ctorArgs = (isset($args[2])) ? $args[2] : array(); } return sqlsrv_fetch_object($this->stmt, $className, $ctorArgs); } throw new SQLSrvException("Fetch mode is not supported!"); } /** * {@inheritdoc} */ public function fetchAll($fetchMode = null) { $className = null; $ctorArgs = null; if (func_num_args() >= 2) { $args = func_get_args(); $className = $args[1]; $ctorArgs = (isset($args[2])) ? $args[2] : array(); } $rows = array(); while ($row = $this->fetch($fetchMode, $className, $ctorArgs)) { $rows[] = $row; } return $rows; } /** * {@inheritdoc} */ public function fetchColumn($columnIndex = 0) { $row = $this->fetch(PDO::FETCH_NUM); return $row[$columnIndex]; } /** * {@inheritdoc} */ public function rowCount() { return sqlsrv_rows_affected($this->stmt); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Event/ConnectionEventArgs.php0000644000175100017510000000440012143374463024006 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Event; use Doctrine\Common\EventArgs, Doctrine\DBAL\Connection; /** * Event Arguments used when a Driver connection is established inside Doctrine\DBAL\Connection. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 1.0 * @version $Revision$ * @author Benjamin Eberlei */ class ConnectionEventArgs extends EventArgs { /** * @var Connection */ private $_connection = null; public function __construct(Connection $connection) { $this->_connection = $connection; } /** * @return \Doctrine\DBAL\Connection */ public function getConnection() { return $this->_connection; } /** * @return \Doctrine\DBAL\Driver */ public function getDriver() { return $this->_connection->getDriver(); } /** * @return \Doctrine\DBAL\Platforms\AbstractPlatform */ public function getDatabasePlatform() { return $this->_connection->getDatabasePlatform(); } /** * @return \Doctrine\DBAL\Schema\AbstractSchemaManager */ public function getSchemaManager() { return $this->_connection->getSchemaManager(); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Event/SchemaAlterTableAddColumnEventArgs.php0000644000175100017510000000613712143374463026647 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Event; use Doctrine\DBAL\Platforms\AbstractPlatform, Doctrine\DBAL\Schema\Column, Doctrine\DBAL\Schema\TableDiff; /** * Event Arguments used when SQL queries for adding table columns are generated inside Doctrine\DBAL\Platform\*Platform. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 2.2 * @author Jan Sorgalla */ class SchemaAlterTableAddColumnEventArgs extends SchemaEventArgs { /** * @var \Doctrine\DBAL\Schema\Column */ private $_column = null; /** * @var \Doctrine\DBAL\Schema\TableDiff */ private $_tableDiff = null; /** * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ private $_platform = null; /** * @var array */ private $_sql = array(); /** * @param \Doctrine\DBAL\Schema\Column $column * @param \Doctrine\DBAL\Schema\TableDiff $tableDiff * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform */ public function __construct(Column $column, TableDiff $tableDiff, AbstractPlatform $platform) { $this->_column = $column; $this->_tableDiff = $tableDiff; $this->_platform = $platform; } /** * @return \Doctrine\DBAL\Schema\Column */ public function getColumn() { return $this->_column; } /** * @return \Doctrine\DBAL\Schema\TableDiff */ public function getTableDiff() { return $this->_tableDiff; } /** * @return \Doctrine\DBAL\Platforms\AbstractPlatform */ public function getPlatform() { return $this->_platform; } /** * @param string|array $sql * @return \Doctrine\DBAL\Event\SchemaAlterTableAddColumnEventArgs */ public function addSql($sql) { if (is_array($sql)) { $this->_sql = array_merge($this->_sql, $sql); } else { $this->_sql[] = $sql; } return $this; } /** * @return array */ public function getSql() { return $this->_sql; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Event/SchemaAlterTableChangeColumnEventArgs.php0000644000175100017510000000622612143374463027343 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Event; use Doctrine\DBAL\Platforms\AbstractPlatform, Doctrine\DBAL\Schema\ColumnDiff, Doctrine\DBAL\Schema\TableDiff; /** * Event Arguments used when SQL queries for changing table columns are generated inside Doctrine\DBAL\Platform\*Platform. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 2.2 * @author Jan Sorgalla */ class SchemaAlterTableChangeColumnEventArgs extends SchemaEventArgs { /** * @var \Doctrine\DBAL\Schema\ColumnDiff */ private $_columnDiff = null; /** * @var \Doctrine\DBAL\Schema\TableDiff */ private $_tableDiff = null; /** * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ private $_platform = null; /** * @var array */ private $_sql = array(); /** * @param \Doctrine\DBAL\Schema\ColumnDiff $columnDiff * @param \Doctrine\DBAL\Schema\TableDiff $tableDiff * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform */ public function __construct(ColumnDiff $columnDiff, TableDiff $tableDiff, AbstractPlatform $platform) { $this->_columnDiff = $columnDiff; $this->_tableDiff = $tableDiff; $this->_platform = $platform; } /** * @return \Doctrine\DBAL\Schema\ColumnDiff */ public function getColumnDiff() { return $this->_columnDiff; } /** * @return \Doctrine\DBAL\Schema\TableDiff */ public function getTableDiff() { return $this->_tableDiff; } /** * @return \Doctrine\DBAL\Platforms\AbstractPlatform */ public function getPlatform() { return $this->_platform; } /** * @param string|array $sql * @return \Doctrine\DBAL\Event\SchemaAlterTableChangeColumnEventArgs */ public function addSql($sql) { if (is_array($sql)) { $this->_sql = array_merge($this->_sql, $sql); } else { $this->_sql[] = $sql; } return $this; } /** * @return array */ public function getSql() { return $this->_sql; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Event/SchemaAlterTableEventArgs.php0000644000175100017510000000540112143374463025051 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Event; use Doctrine\DBAL\Platforms\AbstractPlatform, Doctrine\DBAL\Schema\Column, Doctrine\DBAL\Schema\TableDiff; /** * Event Arguments used when SQL queries for creating tables are generated inside Doctrine\DBAL\Platform\*Platform. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 2.2 * @author Jan Sorgalla */ class SchemaAlterTableEventArgs extends SchemaEventArgs { /** * @var \Doctrine\DBAL\Schema\TableDiff */ private $_tableDiff = null; /** * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ private $_platform = null; /** * @var array */ private $_sql = array(); /** * @param \Doctrine\DBAL\Schema\TableDiff $tableDiff * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform */ public function __construct(TableDiff $tableDiff, AbstractPlatform $platform) { $this->_tableDiff = $tableDiff; $this->_platform = $platform; } /** * @return \Doctrine\DBAL\Schema\TableDiff */ public function getTableDiff() { return $this->_tableDiff; } /** * @return \Doctrine\DBAL\Platforms\AbstractPlatform */ public function getPlatform() { return $this->_platform; } /** * @param string|array $sql * @return \Doctrine\DBAL\Event\SchemaAlterTableEventArgs */ public function addSql($sql) { if (is_array($sql)) { $this->_sql = array_merge($this->_sql, $sql); } else { $this->_sql[] = $sql; } return $this; } /** * @return array */ public function getSql() { return $this->_sql; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Event/SchemaAlterTableRemoveColumnEventArgs.php0000644000175100017510000000614712143374463027415 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Event; use Doctrine\DBAL\Platforms\AbstractPlatform, Doctrine\DBAL\Schema\Column, Doctrine\DBAL\Schema\TableDiff; /** * Event Arguments used when SQL queries for removing table columns are generated inside Doctrine\DBAL\Platform\*Platform. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 2.2 * @author Jan Sorgalla */ class SchemaAlterTableRemoveColumnEventArgs extends SchemaEventArgs { /** * @var \Doctrine\DBAL\Schema\Column */ private $_column = null; /** * @var \Doctrine\DBAL\Schema\TableDiff */ private $_tableDiff = null; /** * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ private $_platform = null; /** * @var array */ private $_sql = array(); /** * @param \Doctrine\DBAL\Schema\Column $column * @param \Doctrine\DBAL\Schema\TableDiff $tableDiff * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform */ public function __construct(Column $column, TableDiff $tableDiff, AbstractPlatform $platform) { $this->_column = $column; $this->_tableDiff = $tableDiff; $this->_platform = $platform; } /** * @return \Doctrine\DBAL\Schema\Column */ public function getColumn() { return $this->_column; } /** * @return \Doctrine\DBAL\Schema\TableDiff */ public function getTableDiff() { return $this->_tableDiff; } /** * @return \Doctrine\DBAL\Platforms\AbstractPlatform */ public function getPlatform() { return $this->_platform; } /** * @param string|array $sql * @return \Doctrine\DBAL\Event\SchemaAlterTableRemoveColumnEventArgs */ public function addSql($sql) { if (is_array($sql)) { $this->_sql = array_merge($this->_sql, $sql); } else { $this->_sql[] = $sql; } return $this; } /** * @return array */ public function getSql() { return $this->_sql; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Event/SchemaAlterTableRenameColumnEventArgs.php0000644000175100017510000000663712143374463027373 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Event; use Doctrine\DBAL\Platforms\AbstractPlatform, Doctrine\DBAL\Schema\Column, Doctrine\DBAL\Schema\TableDiff; /** * Event Arguments used when SQL queries for renaming table columns are generated inside Doctrine\DBAL\Platform\*Platform. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 2.2 * @author Jan Sorgalla */ class SchemaAlterTableRenameColumnEventArgs extends SchemaEventArgs { /** * @var string */ private $_oldColumnName = null; /** * @var \Doctrine\DBAL\Schema\Column */ private $_column = null; /** * @var \Doctrine\DBAL\Schema\TableDiff */ private $_tableDiff = null; /** * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ private $_platform = null; /** * @var array */ private $_sql = array(); /** * @param string $oldColumnName * @param \Doctrine\DBAL\Schema\Column $column * @param \Doctrine\DBAL\Schema\TableDiff $tableDiff * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform */ public function __construct($oldColumnName, Column $column, TableDiff $tableDiff, AbstractPlatform $platform) { $this->_oldColumnName = $oldColumnName; $this->_column = $column; $this->_tableDiff = $tableDiff; $this->_platform = $platform; } /** * @return string */ public function getOldColumnName() { return $this->_oldColumnName; } /** * @return \Doctrine\DBAL\Schema\Column */ public function getColumn() { return $this->_column; } /** * @return \Doctrine\DBAL\Schema\TableDiff */ public function getTableDiff() { return $this->_tableDiff; } /** * @return \Doctrine\DBAL\Platforms\AbstractPlatform */ public function getPlatform() { return $this->_platform; } /** * @param string|array $sql * @return \Doctrine\DBAL\Event\SchemaAlterTableRenameColumnEventArgs */ public function addSql($sql) { if (is_array($sql)) { $this->_sql = array_merge($this->_sql, $sql); } else { $this->_sql[] = $sql; } return $this; } /** * @return array */ public function getSql() { return $this->_sql; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Event/SchemaColumnDefinitionEventArgs.php0000644000175100017510000000666412143374463026314 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Event; use Doctrine\DBAL\Connection, Doctrine\DBAL\Schema\Column; /** * Event Arguments used when the portable column definition is generated inside Doctrine\DBAL\Schema\AbstractSchemaManager. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 2.2 * @author Jan Sorgalla */ class SchemaColumnDefinitionEventArgs extends SchemaEventArgs { /** * @var \Doctrine\DBAL\Schema\Column */ private $_column = null; /** * Raw column data as fetched from the database * * @var array */ private $_tableColumn = null; /** * @var string */ private $_table = null; /** * @var string */ private $_database = null; /** * @var \Doctrine\DBAL\Connection */ private $_connection = null; /** * @param array $tableColumn * @param string $table * @param string $database * @param \Doctrine\DBAL\Connection $conn */ public function __construct(array $tableColumn, $table, $database, Connection $connection) { $this->_tableColumn = $tableColumn; $this->_table = $table; $this->_database = $database; $this->_connection = $connection; } /** * Allows to clear the column which means the column will be excluded from * tables column list. * * @param null|\Doctrine\DBAL\Schema\Column $column * @return SchemaColumnDefinitionEventArgs */ public function setColumn(Column $column = null) { $this->_column = $column; return $this; } /** * @return \Doctrine\DBAL\Schema\Column */ public function getColumn() { return $this->_column; } /** * @return array */ public function getTableColumn() { return $this->_tableColumn; } /** * @return string */ public function getTable() { return $this->_table; } /** * @return string */ public function getDatabase() { return $this->_database; } /** * @return \Doctrine\DBAL\Connection */ public function getConnection() { return $this->_connection; } /** * @return \Doctrine\DBAL\Platforms\AbstractPlatform */ public function getDatabasePlatform() { return $this->_connection->getDatabasePlatform(); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Event/SchemaCreateTableColumnEventArgs.php0000644000175100017510000000606512143374463026372 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Event; use Doctrine\DBAL\Platforms\AbstractPlatform, Doctrine\DBAL\Schema\Column, Doctrine\DBAL\Schema\Table; /** * Event Arguments used when SQL queries for creating table columns are generated inside Doctrine\DBAL\Platform\AbstractPlatform. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 2.2 * @author Jan Sorgalla */ class SchemaCreateTableColumnEventArgs extends SchemaEventArgs { /** * @var \Doctrine\DBAL\Schema\Column */ private $_column = null; /** * @var \Doctrine\DBAL\Schema\Table */ private $_table = null; /** * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ private $_platform = null; /** * @var array */ private $_sql = array(); /** * @param \Doctrine\DBAL\Schema\Column $column * @param \Doctrine\DBAL\Schema\Table $table * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform */ public function __construct(Column $column, Table $table, AbstractPlatform $platform) { $this->_column = $column; $this->_table = $table; $this->_platform = $platform; } /** * @return \Doctrine\DBAL\Schema\Column */ public function getColumn() { return $this->_column; } /** * @return \Doctrine\DBAL\Schema\Table */ public function getTable() { return $this->_table; } /** * @return \Doctrine\DBAL\Platforms\AbstractPlatform */ public function getPlatform() { return $this->_platform; } /** * @param string|array $sql * @return \Doctrine\DBAL\Event\SchemaCreateTableColumnEventArgs */ public function addSql($sql) { if (is_array($sql)) { $this->_sql = array_merge($this->_sql, $sql); } else { $this->_sql[] = $sql; } return $this; } /** * @return array */ public function getSql() { return $this->_sql; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Event/SchemaCreateTableEventArgs.php0000644000175100017510000000630712143374463025213 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Event; use Doctrine\DBAL\Platforms\AbstractPlatform, Doctrine\DBAL\Schema\Table; /** * Event Arguments used when SQL queries for creating tables are generated inside Doctrine\DBAL\Platform\AbstractPlatform. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 2.2 * @author Jan Sorgalla */ class SchemaCreateTableEventArgs extends SchemaEventArgs { /** * @var \Doctrine\DBAL\Schema\Table */ private $_table = null; /** * @var array */ private $_columns = null; /** * @var array */ private $_options = null; /** * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ private $_platform = null; /** * @var array */ private $_sql = array(); /** * @param \Doctrine\DBAL\Schema\Table $table * @param array $columns * @param array $options * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform */ public function __construct(Table $table, array $columns, array $options, AbstractPlatform $platform) { $this->_table = $table; $this->_columns = $columns; $this->_options = $options; $this->_platform = $platform; } /** * @return \Doctrine\DBAL\Schema\Table */ public function getTable() { return $this->_table; } /** * @return array */ public function getColumns() { return $this->_columns; } /** * @return array */ public function getOptions() { return $this->_options; } /** * @return \Doctrine\DBAL\Platforms\AbstractPlatform */ public function getPlatform() { return $this->_platform; } /** * @param string|array $sql * @return \Doctrine\DBAL\Event\SchemaCreateTableEventArgs */ public function addSql($sql) { if (is_array($sql)) { $this->_sql = array_merge($this->_sql, $sql); } else { $this->_sql[] = $sql; } return $this; } /** * @return array */ public function getSql() { return $this->_sql; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Event/SchemaDropTableEventArgs.php0000644000175100017510000000545012143374463024712 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Event; use Doctrine\DBAL\Platforms\AbstractPlatform, Doctrine\DBAL\Schema\Table; /** * Event Arguments used when the SQL query for dropping tables are generated inside Doctrine\DBAL\Platform\AbstractPlatform. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 2.2 * @author Jan Sorgalla */ class SchemaDropTableEventArgs extends SchemaEventArgs { /** * @var string|\Doctrine\DBAL\Schema\Table */ private $_table = null; /** * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ private $_platform = null; /** * @var string */ private $_sql = null; /** * @param string|\Doctrine\DBAL\Schema\Table $table * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform */ public function __construct($table, AbstractPlatform $platform) { if ( ! $table instanceof Table && !is_string($table)) { throw new \InvalidArgumentException('SchemaCreateTableEventArgs expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); } $this->_table = $table; $this->_platform = $platform; } /** * @return string|\Doctrine\DBAL\Schema\Table */ public function getTable() { return $this->_table; } /** * @return \Doctrine\DBAL\Platforms\AbstractPlatform */ public function getPlatform() { return $this->_platform; } /** * @param string $sql * @return \Doctrine\DBAL\Event\SchemaDropTableEventArgs */ public function setSql($sql) { $this->_sql = $sql; return $this; } /** * @return string */ public function getSql() { return $this->_sql; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Event/SchemaEventArgs.php0000644000175100017510000000327412143374463023117 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Event; use Doctrine\Common\EventArgs; /** * Base class for schema related events. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 2.2 * @author Jan Sorgalla */ 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; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Event/SchemaIndexDefinitionEventArgs.php0000644000175100017510000000621312143374463026114 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Event; use Doctrine\DBAL\Connection, Doctrine\DBAL\Schema\Index; /** * Event Arguments used when the portable index definition is generated inside Doctrine\DBAL\Schema\AbstractSchemaManager. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 2.2 * @author Jan Sorgalla */ class SchemaIndexDefinitionEventArgs extends SchemaEventArgs { /** * @var \Doctrine\DBAL\Schema\Index */ private $_index = null; /** * Raw index data as fetched from the database * * @var array */ private $_tableIndex = null; /** * @var string */ private $_table = null; /** * @var \Doctrine\DBAL\Connection */ private $_connection = null; /** * @param array $tableIndex * @param string $table * @param \Doctrine\DBAL\Connection $conn */ public function __construct(array $tableIndex, $table, Connection $connection) { $this->_tableIndex = $tableIndex; $this->_table = $table; $this->_connection = $connection; } /** * Allows to clear the index which means the index will be excluded from * tables index list. * * @param null|\Doctrine\DBAL\Schema\Index $index * @return SchemaIndexDefinitionEventArgs */ public function setIndex(Index $index = null) { $this->_index = $index; return $this; } /** * @return \Doctrine\DBAL\Schema\Index */ public function getIndex() { return $this->_index; } /** * @return array */ public function getTableIndex() { return $this->_tableIndex; } /** * @return string */ public function getTable() { return $this->_table; } /** * @return \Doctrine\DBAL\Connection */ public function getConnection() { return $this->_connection; } /** * @return \Doctrine\DBAL\Platforms\AbstractPlatform */ public function getDatabasePlatform() { return $this->_connection->getDatabasePlatform(); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Event/Listeners/MysqlSessionInit.php0000644000175100017510000000462112143374463025342 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Event\Listeners; use Doctrine\DBAL\Event\ConnectionEventArgs; use Doctrine\DBAL\Events; use Doctrine\Common\EventSubscriber; /** * MySQL Session Init Event Subscriber which allows to set the Client Encoding of the Connection * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 1.0 * @version $Revision$ * @author Benjamin Eberlei * @deprecated Use "charset" option to PDO MySQL Connection instead. */ class MysqlSessionInit implements EventSubscriber { /** * @var string */ private $_charset; /** * @var string */ private $_collation; /** * Configure Charset and Collation options of MySQL Client for each Connection * * @param string $charset * @param string $collation */ public function __construct($charset = 'utf8', $collation = false) { $this->_charset = $charset; $this->_collation = $collation; } /** * @param ConnectionEventArgs $args * @return void */ public function postConnect(ConnectionEventArgs $args) { $collation = ($this->_collation) ? " COLLATE ".$this->_collation : ""; $args->getConnection()->executeUpdate("SET NAMES ".$this->_charset . $collation); } public function getSubscribedEvents() { return array(Events::postConnect); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Event/Listeners/OracleSessionInit.php0000644000175100017510000000565512143374463025452 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Event\Listeners; use Doctrine\DBAL\Event\ConnectionEventArgs; use Doctrine\DBAL\Events; use Doctrine\Common\EventSubscriber; /** * Should be used when Oracle Server default enviroment does not match the Doctrine requirements. * * The following enviroment variables are required for the Doctrine default date format: * * NLS_TIME_FORMAT="HH24:MI:SS" * NLS_DATE_FORMAT="YYYY-MM-DD HH24:MI:SS" * NLS_TIMESTAMP_FORMAT="YYYY-MM-DD HH24:MI:SS" * NLS_TIMESTAMP_TZ_FORMAT="YYYY-MM-DD HH24:MI:SS TZH:TZM" * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 2.0 * @author Benjamin Eberlei */ class OracleSessionInit implements EventSubscriber { protected $_defaultSessionVars = array( 'NLS_TIME_FORMAT' => "HH24:MI:SS", 'NLS_DATE_FORMAT' => "YYYY-MM-DD HH24:MI:SS", 'NLS_TIMESTAMP_FORMAT' => "YYYY-MM-DD HH24:MI:SS", 'NLS_TIMESTAMP_TZ_FORMAT' => "YYYY-MM-DD HH24:MI:SS TZH:TZM", 'NLS_NUMERIC_CHARACTERS' => ".,", ); /** * @param array $oracleSessionVars */ public function __construct(array $oracleSessionVars = array()) { $this->_defaultSessionVars = array_merge($this->_defaultSessionVars, $oracleSessionVars); } /** * @param ConnectionEventArgs $args * @return void */ public function postConnect(ConnectionEventArgs $args) { if (count($this->_defaultSessionVars)) { array_change_key_case($this->_defaultSessionVars, \CASE_UPPER); $vars = array(); foreach ($this->_defaultSessionVars as $option => $value) { $vars[] = $option." = '".$value."'"; } $sql = "ALTER SESSION SET ".implode(" ", $vars); $args->getConnection()->executeUpdate($sql); } } public function getSubscribedEvents() { return array(Events::postConnect); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Event/Listeners/SQLSessionInit.php0000644000175100017510000000367712143374463024706 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Event\Listeners; use Doctrine\DBAL\Event\ConnectionEventArgs; use Doctrine\DBAL\Events; use Doctrine\Common\EventSubscriber; /** * Session init listener for executing a single SQL statement right after a connection is opened. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 2.2 * @author Benjamin Eberlei */ class SQLSessionInit implements EventSubscriber { /** * @var string */ protected $sql; /** * @param string $sql */ public function __construct($sql) { $this->sql = $sql; } /** * @param ConnectionEventArgs $args * @return void */ public function postConnect(ConnectionEventArgs $args) { $conn = $args->getConnection(); $conn->exec($this->sql); } public function getSubscribedEvents() { return array(Events::postConnect); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Id/TableGenerator.php0000644000175100017510000001371112143374463022246 0ustar beberleibeberlei. */ 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 Connection $conn * @param string $generatorTableName */ 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; } /** * Generate the next unused value for the given sequence name * * @param string * @return int */ 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 occured while generating ID with TableGenerator, aborted generation: " . $e->getMessage(), 0, $e); } return $value; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Id/TableGeneratorSchemaVisitor.php0000644000175100017510000000511612143374463024747 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Id; use Doctrine\DBAL\Schema\Table, Doctrine\DBAL\Schema\Schema, Doctrine\DBAL\Schema\Column, Doctrine\DBAL\Schema\ForeignKeyConstraint, Doctrine\DBAL\Schema\Constraint, Doctrine\DBAL\Schema\Sequence, Doctrine\DBAL\Schema\Index; class TableGeneratorSchemaVisitor implements \Doctrine\DBAL\Schema\Visitor\Visitor { /** * @var string */ private $generatorTableName; public function __construct($generatorTableName = 'sequences') { $this->generatorTableName = $generatorTableName; } /** * @param Schema $schema */ 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)); } /** * @param Table $table */ public function acceptTable(Table $table) { } /** * @param Column $column */ public function acceptColumn(Table $table, Column $column) { } /** * @param Table $localTable * @param ForeignKeyConstraint $fkConstraint */ public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) { } /** * @param Table $table * @param Index $index */ public function acceptIndex(Table $table, Index $index) { } /** * @param Sequence $sequence */ public function acceptSequence(Sequence $sequence) { } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Logging/DebugStack.php0000644000175100017510000000427712143374463022425 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Logging; /** * Includes executed SQLs in a Debug Stack * * * @link www.doctrine-project.org * @since 2.0 * @version $Revision$ * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel */ class DebugStack implements SQLLogger { /** @var array $queries Executed SQL queries. */ public $queries = array(); /** @var boolean $enabled If Debug Stack is enabled (log queries) or not. */ public $enabled = true; public $start = null; public $currentQuery = 0; /** * {@inheritdoc} */ public function startQuery($sql, array $params = null, array $types = null) { if ($this->enabled) { $this->start = microtime(true); $this->queries[++$this->currentQuery] = array('sql' => $sql, 'params' => $params, 'types' => $types, 'executionMS' => 0); } } /** * {@inheritdoc} */ public function stopQuery() { if ($this->enabled) { $this->queries[$this->currentQuery]['executionMS'] = microtime(true) - $this->start; } } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Logging/EchoSQLLogger.php0000644000175100017510000000342412143374463023000 0ustar beberleibeberlei. */ 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 * @version $Revision$ * @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() { } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Logging/LoggerChain.php0000644000175100017510000000346412143374463022570 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Logging; /** * Chains multiple SQLLogger * * * @link www.doctrine-project.org * @since 2.2 * @author Christophe Coevoet */ class LoggerChain implements SQLLogger { private $loggers = array(); /** * Adds a logger in the chain * * @param SQLLogger $logger */ public function addLogger(SQLLogger $logger) { $this->loggers[] = $logger; } /** * {@inheritdoc} */ public function startQuery($sql, array $params = null, array $types = null) { foreach ($this->loggers as $logger) { $logger->startQuery($sql, $params, $types); } } /** * {@inheritdoc} */ public function stopQuery() { foreach ($this->loggers as $logger) { $logger->stopQuery(); } } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Logging/SQLLogger.php0000644000175100017510000000351112143374463022176 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Logging; /** * Interface for SQL loggers. * * * @link www.doctrine-project.org * @since 2.0 * @version $Revision$ * @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 $params The SQL parameters. * @param array $types The SQL parameter types. * @return void */ public function startQuery($sql, array $params = null, array $types = null); /** * Mark the last started query as stopped. This can be used for timing of queries. * * @return void */ public function stopQuery(); } DoctrineDBAL-2.3.4/Doctrine/DBAL/Platforms/AbstractPlatform.php0000644000175100017510000023750112143374463024240 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\DBALException, Doctrine\DBAL\Connection, Doctrine\DBAL\Types, Doctrine\DBAL\Schema\Constraint, Doctrine\DBAL\Schema\Sequence, Doctrine\DBAL\Schema\Table, Doctrine\DBAL\Schema\Index, Doctrine\DBAL\Schema\ForeignKeyConstraint, Doctrine\DBAL\Schema\TableDiff, Doctrine\DBAL\Schema\Column, Doctrine\DBAL\Schema\ColumnDiff, Doctrine\DBAL\Types\Type, Doctrine\DBAL\Events, Doctrine\Common\EventManager, Doctrine\DBAL\Event\SchemaCreateTableEventArgs, Doctrine\DBAL\Event\SchemaCreateTableColumnEventArgs, Doctrine\DBAL\Event\SchemaDropTableEventArgs, Doctrine\DBAL\Event\SchemaAlterTableEventArgs, Doctrine\DBAL\Event\SchemaAlterTableAddColumnEventArgs, Doctrine\DBAL\Event\SchemaAlterTableRemoveColumnEventArgs, Doctrine\DBAL\Event\SchemaAlterTableChangeColumnEventArgs, 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 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 */ protected $doctrineTypeMapping = null; /** * Contains a list of all columns that should generate parseable column comments for type-detection * in reverse engineering scenarios. * * @var array */ 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 */ 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; } /** * Gets the SQL snippet that declares a boolean column. * * @param array $columnDef * * @return string */ abstract public function getBooleanTypeDeclarationSQL(array $columnDef); /** * Gets the SQL snippet that declares a 4 byte integer column. * * @param array $columnDef * * @return string */ abstract public function getIntegerTypeDeclarationSQL(array $columnDef); /** * Gets the SQL snippet that declares an 8 byte integer column. * * @param array $columnDef * * @return string */ abstract public function getBigIntTypeDeclarationSQL(array $columnDef); /** * Gets the SQL snippet that declares a 2 byte integer column. * * @param array $columnDef * * @return string */ abstract public function getSmallIntTypeDeclarationSQL(array $columnDef); /** * Gets 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(); /** * Initialize Doctrine Type Mappings with the platform defaults * and with all additional type mappings. */ private function initializeAllDoctrineTypeMappings() { $this->initializeDoctrineTypeMappings(); foreach (Type::getTypesMap() as $typeName => $className) { foreach (Type::getType($typeName)->getMappedDatabaseTypes($this) as $dbType) { $this->doctrineTypeMapping[$dbType] = $typeName; } } } /** * Gets 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); } /** * Get the SQL Snippet to create a GUID/UUID field. * * By default this maps directly to a VARCHAR and only maps to more * special datatypes when the underlying databases support this datatype. * * @param array $field * * @return string */ public function getGuidTypeDeclarationSQL(array $field) { return $this->getVarcharTypeDeclarationSQL($field); } /** * @param integer $length * @param boolean $fixed * * @return string * * @throws \Doctrine\DBAL\DBALException */ protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) { throw DBALException::notSupported('VARCHARs not supported by Platform.'); } /** * Gets the SQL snippet used to declare a CLOB column type. * * @param array $field * * @return string */ abstract public function getClobTypeDeclarationSQL(array $field); /** * Gets 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(); /** * Register 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; } /** * Get the Doctrine type that is mapped for the given database column type. * * @param string $dbType * * @return string */ 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]; } /** * Check 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]); } /** * Initialize 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 Type $doctrineType * * @return boolean */ public function isCommentedDoctrineType(Type $doctrineType) { if ($this->doctrineTypeComments === null) { $this->initializeCommentedDoctrineTypes(); } return in_array($doctrineType->getName(), $this->doctrineTypeComments); } /** * Mark this type as to be commented in ALTER TABLE and CREATE TABLE statements. * * @param string|Type $doctrineType * * @return void */ public function markDoctrineTypeCommented($doctrineType) { if ($this->doctrineTypeComments === null) { $this->initializeCommentedDoctrineTypes(); } $this->doctrineTypeComments[] = $doctrineType instanceof Type ? $doctrineType->getName() : $doctrineType; } /** * Get the comment to append to a column comment that helps parsing this type in reverse engineering. * * @param Type $doctrineType * @return string */ public function getDoctrineTypeComment(Type $doctrineType) { return '(DC2Type:' . $doctrineType->getName() . ')'; } /** * Return the comment of a passed column modified by potential doctrine type comment hints. * * @param 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 all SQL wildcard characters of the platform. * * @return array */ public function getWildcards() { return array('%', '_'); } /** * Returns the regular expression operator. * * @return string */ public function getRegexpExpression() { throw DBALException::notSupported(__METHOD__); } /** * Returns global unique identifier * * @return string to get global unique identifier */ public function getGuidExpression() { throw DBALException::notSupported(__METHOD__); } /** * Returns 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 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 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 lowest value of a column * * @param string $column the column to use * @return string */ public function getMinExpression($column) { return 'MIN(' . $column . ')'; } /** * Returns the total sum of a column * * @param string $column the column to use * @return string */ public function getSumExpression($column) { return 'SUM(' . $column . ')'; } // scalar functions /** * Returns 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 length of a text field. * * @param string $column * * @return string */ public function getLengthExpression($column) { return 'LENGTH(' . $column . ')'; } /** * Returns 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 . ')'; } /** * Rounds 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 remainder of the division operation * $expression1 / $expression2. * * @param string $expression1 * @param string $expression2 * * @return string */ public function getModExpression($expression1, $expression2) { return 'MOD(' . $expression1 . ', ' . $expression2 . ')'; } /** * Trim a string, leading/trailing/both and with a given char which defaults to space. * * @param string $str * @param integer $pos * @param string $char has to be quoted already * * @return string */ public function getTrimExpression($str, $pos = self::TRIM_UNSPECIFIED, $char = false) { $posStr = ''; $trimChar = ($char != false) ? $char . ' FROM ' : ''; switch ($pos) { case self::TRIM_LEADING: $posStr = 'LEADING '.$trimChar; break; case self::TRIM_TRAILING: $posStr = 'TRAILING '.$trimChar; break; case self::TRIM_BOTH: $posStr = 'BOTH '.$trimChar; break; } return 'TRIM(' . $posStr . $str . ')'; } /** * rtrim * returns the string $str with proceeding space characters removed * * @param string $str literal string or column name * * @return string */ public function getRtrimExpression($str) { return 'RTRIM(' . $str . ')'; } /** * ltrim * returns the string $str with leading space characters removed * * @param string $str literal string or column name * * @return string */ public function getLtrimExpression($str) { return 'LTRIM(' . $str . ')'; } /** * upper * Returns the string $str with all characters changed 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 . ')'; } /** * lower * Returns the string $str with all characters changed 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 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 $startPos position to start at, beginning of string by default * * @return string */ public function getLocateExpression($str, $substr, $startPos = false) { throw DBALException::notSupported(__METHOD__); } /** * Returns the current system date. * * @return string */ public function getNowExpression() { return 'NOW()'; } /** * return string to call a function to get a substring inside an SQL statement * * Note: Not SQL92, but common functionality. * * SQLite only supports the 2 parameter variant of this function * * @param string $value an sql string literal or column name/alias * @param integer $from where to start the substring portion * @param integer $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 series of strings concatinated * * concat() accepts an arbitrary number of parameters. Each parameter * must contain an expression * * @param string $arg1, $arg2 ... $argN strings that will be concatenated. * * @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 a logical expression */ public function getNotExpression($expression) { return 'NOT(' . $expression . ')'; } /** * Returns the SQL to check if a value is one in a set of * given values. * * in() accepts an arbitrary number of parameters. The first parameter * must always specify the value that should be matched against. Successive * must contain a logical expression or an array with logical expressions. * These expressions will be matched against the first parameter. * * @param string $column the value that should be matched against * @param string|array $values values that will be matched against $column * * @return string logical expression */ public function getInExpression($column, $values) { if ( ! is_array($values)) { $values = array($values); } // TODO: fix this code: the method does not exist $values = $this->getIdentifiers($values); if (count($values) == 0) { throw new \InvalidArgumentException('Values must not be empty.'); } return $column . ' IN (' . implode(', ', $values) . ')'; } /** * Returns SQL that checks if a expression is null. * * @param string $expression the expression that should be compared to null * * @return string logical expression */ public function getIsNullExpression($expression) { return $expression . ' IS NULL'; } /** * Returns SQL that checks if a expression is not null. * * @param string $expression the expression that should be compared to null * * @return string logical expression */ public function getIsNotNullExpression($expression) { return $expression . ' IS NOT NULL'; } /** * Returns 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 logical expression */ public function getBetweenExpression($expression, $value1, $value2) { return $expression . ' BETWEEN ' .$value1 . ' AND ' . $value2; } public function getAcosExpression($value) { return 'ACOS(' . $value . ')'; } public function getSinExpression($value) { return 'SIN(' . $value . ')'; } public function getPiExpression() { return 'PI()'; } public function getCosExpression($value) { return 'COS(' . $value . ')'; } /** * Calculate the difference in days between the two passed dates. * * Computes diff = date1 - date2 * * @param string $date1 * @param string $date2 * * @return string */ public function getDateDiffExpression($date1, $date2) { throw DBALException::notSupported(__METHOD__); } /** * Add the number of given days to a date. * * @param string $date * @param integer $days * * @return string */ public function getDateAddDaysExpression($date, $days) { throw DBALException::notSupported(__METHOD__); } /** * Substract the number of given days to a date. * * @param string $date * @param integer $days * * @return string */ public function getDateSubDaysExpression($date, $days) { throw DBALException::notSupported(__METHOD__); } /** * Add the number of given months to a date. * * @param string $date * @param integer $months * * @return string */ public function getDateAddMonthExpression($date, $months) { throw DBALException::notSupported(__METHOD__); } /** * Substract the number of given months to a date. * * @param string $date * @param integer $months * * @return string */ public function getDateSubMonthExpression($date, $months) { throw DBALException::notSupported(__METHOD__); } /** * Gets SQL bit AND comparison expression * * @param string $value1 * @param string $value2 * * @return string */ public function getBitAndComparisonExpression($value1, $value2) { return '(' . $value1 . ' & ' . $value2 . ')'; } /** * Gets SQL bit OR comparison expression * * @param string $value1 * @param string $value2 * * @return string */ public function getBitOrComparisonExpression($value1, $value2) { return '(' . $value1 . ' | ' . $value2 . ')'; } 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 * @param integer $lockMode * * @return string */ public function appendLockHint($fromClause, $lockMode) { return $fromClause; } /** * Get the sql snippet to append to any SELECT statement which locks rows in shared read lock. * * This defaults to the ASNI 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(); } /** * Get 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 ASNI SQL standard. * * @return string */ public function getWriteLockSQL() { return $this->getForUpdateSQL(); } /** * Get the SQL snippet to drop an existing database * * @param string $database name of the database that should be dropped * * @return string */ public function getDropDatabaseSQL($database) { return 'DROP DATABASE ' . $database; } /** * Drop a Table * * @throws \InvalidArgumentException * * @param Table|string $table * * @return string */ public function getDropTableSQL($table) { $tableArg = $table; if ($table instanceof Table) { $table = $table->getQuotedName($this); } else if(!is_string($table)) { throw new \InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); } 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; } /** * Get SQL to safely drop a temporary table WITHOUT implicitly committing an open transaction. * * @param Table|string $table * * @return string */ public function getDropTemporaryTableSQL($table) { return $this->getDropTableSQL($table); } /** * Drop index from a table * * @param Index|string $name * @param string|Table $table * * @return string */ public function getDropIndexSQL($index, $table = null) { if ($index instanceof Index) { $index = $index->getQuotedName($this); } else if(!is_string($index)) { throw new \InvalidArgumentException('AbstractPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.'); } return 'DROP INDEX ' . $index; } /** * Get drop constraint sql * * @param \Doctrine\DBAL\Schema\Constraint $constraint * @param string|Table $table * * @return string */ public function getDropConstraintSQL($constraint, $table) { if ($constraint instanceof Constraint) { $constraint = $constraint->getQuotedName($this); } if ($table instanceof Table) { $table = $table->getQuotedName($this); } return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $constraint; } /** * @param ForeignKeyConstraint|string $foreignKey * @param Table|string $table * * @return string */ public function getDropForeignKeySQL($foreignKey, $table) { if ($foreignKey instanceof ForeignKeyConstraint) { $foreignKey = $foreignKey->getQuotedName($this); } if ($table instanceof Table) { $table = $table->getQuotedName($this); } return 'ALTER TABLE ' . $table . ' DROP FOREIGN KEY ' . $foreignKey; } /** * Gets the SQL statement(s) to create a table with the specified name, columns and constraints * on this platform. * * @param string $table The name of the table. * @param integer $createFlags * * @return array The sequence of SQL statements. */ 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()) { $platform = $this; $options['primary'] = array_map(function ($columnName) use ($table, $platform) { return $table->getColumn($columnName)->getQuotedName($platform); }, $index->getColumns()); $options['primary_index'] = $index; } else { $options['indexes'][$index->getName()] = $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 = array(); $columnData['name'] = $column->getQuotedName($this); $columnData['type'] = $column->getType(); $columnData['length'] = $column->getLength(); $columnData['notnull'] = $column->getNotNull(); $columnData['fixed'] = $column->getFixed(); $columnData['unique'] = false; // TODO: what do we do about this? $columnData['version'] = $column->hasPlatformOption("version") ? $column->getPlatformOption('version') : false; if (strtolower($columnData['type']) == "string" && $columnData['length'] === null) { $columnData['length'] = 255; } $columnData['unsigned'] = $column->getUnsigned(); $columnData['precision'] = $column->getPrecision(); $columnData['scale'] = $column->getScale(); $columnData['default'] = $column->getDefault(); $columnData['columnDefinition'] = $column->getColumnDefinition(); $columnData['autoincrement'] = $column->getAutoincrement(); $columnData['comment'] = $this->getColumnComment($column); 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) { if ($this->getColumnComment($column)) { $sql[] = $this->getCommentOnColumnSQL($tableName, $column->getName(), $this->getColumnComment($column)); } } } return array_merge($sql, $columnSql); } public function getCommentOnColumnSQL($tableName, $columnName, $comment) { return "COMMENT ON COLUMN " . $tableName . "." . $columnName . " IS '" . $comment . "'"; } /** * Gets 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; } public function getCreateTemporaryTableSnippetSQL() { return "CREATE TEMPORARY TABLE"; } /** * Gets the SQL to create a sequence on this platform. * * @param \Doctrine\DBAL\Schema\Sequence $sequence * * @return string * * @throws DBALException */ public function getCreateSequenceSQL(Sequence $sequence) { throw DBALException::notSupported(__METHOD__); } /** * Gets the SQL statement to change a sequence on this platform. * * @param \Doctrine\DBAL\Schema\Sequence $sequence * * @return string */ public function getAlterSequenceSQL(Sequence $sequence) { throw DBALException::notSupported(__METHOD__); } /** * Gets the SQL to create a constraint on a table on this platform. * * @param \Doctrine\DBAL\Schema\Constraint $constraint * @param string|Table $table * * @return string */ public function getCreateConstraintSQL(Constraint $constraint, $table) { if ($table instanceof Table) { $table = $table->getQuotedName($this); } $query = 'ALTER TABLE ' . $table . ' ADD CONSTRAINT ' . $constraint->getQuotedName($this); $columns = array(); foreach ($constraint->getColumns() as $column) { $columns[] = $column; } $columnList = '('. implode(', ', $columns) . ')'; $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().' ); } } else if ($constraint instanceof ForeignKeyConstraint) { $query .= ' FOREIGN KEY'; $foreignColumns = array(); foreach ($constraint->getForeignColumns() as $column) { $foreignColumns[] = $column; } $referencesClause = ' REFERENCES '.$constraint->getForeignTableName(). ' ('.implode(', ', $foreignColumns).')'; } $query .= ' '.$columnList.$referencesClause; return $query; } /** * Gets the SQL to create an index on a table on this platform. * * @param Index $index * @param string|Table $table name of the table on which the index is to be created * * @return string */ public function getCreateIndexSQL(Index $index, $table) { if ($table instanceof Table) { $table = $table->getQuotedName($this); } $name = $index->getQuotedName($this); $columns = $index->getColumns(); 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) . ')'; return $query; } /** * Adds additional flags for index generation * * @param Index $index * * @return string */ protected function getCreateIndexSQLFlags(Index $index) { return $index->isUnique() ? 'UNIQUE ' : ''; } /** * Get SQL to create an unnamed primary key constraint. * * @param Index $index * @param string|Table $table * * @return string */ public function getCreatePrimaryKeySQL(Index $index, $table) { return 'ALTER TABLE ' . $table . ' ADD PRIMARY KEY (' . $this->getIndexFieldDeclarationListSQL($index->getColumns()) . ')'; } /** * 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 identifier name to be quoted * * @return string quoted identifier string */ public function quoteIdentifier($str) { if (strpos($str, ".") !== false) { $parts = array_map(array($this, "quoteIdentifier"), explode(".", $str)); return implode(".", $parts); } return $this->quoteSingleIdentifier($str); } /** * Quote a single identifier (no dot chain separation) * * @param string $str * * @return string */ public function quoteSingleIdentifier($str) { $c = $this->getIdentifierQuoteCharacter(); return $c . str_replace($c, $c.$c, $str) . $c; } /** * Create a new foreign key * * @param ForeignKeyConstraint $foreignKey ForeignKey instance * @param string|Table $table name of the table on which the foreign key is to be created * * @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. * * The method returns an array of sql statements, since some platforms need several statements. * * @param TableDiff $diff * * @return array */ public function getAlterTableSQL(TableDiff $diff) { throw DBALException::notSupported(__METHOD__); } /** * @param Column $column * @param 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 Column $column * @param 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 ColumnDiff $columnDiff * @param 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 Column $column * @param 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 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(); } protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) { $tableName = $diff->name; $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; } protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff) { $tableName = false !== $diff->newName ? $diff->newName : $diff->name; $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); } return $sql; } /** * Common code for alter table statement generation that updates the changed Index and Foreign Key definitions. * * @param TableDiff $diff * * @return array */ protected function _getAlterTableIndexForeignKeySQL(TableDiff $diff) { return array_merge($this->getPreAlterTableIndexForeignKeySQL($diff), $this->getPostAlterTableIndexForeignKeySQL($diff)); } /** * Get 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); } /** * Obtain DBMS specific SQL code portion needed to declare a generic type * field to be used in statements like CREATE TABLE. * * @param string $name name the field to be declared. * @param array $field associative array with the name of the properties * of the field being declared as array indexes. Currently, the types * of supported field properties are as follows: * * 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 '" . $field['comment'] . "'"; } return $name . ' ' . $columnDef; } /** * Gets 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'] . ')'; } /** * Obtain DBMS specific SQL code portion needed to set a default value * declaration to be used in statements like CREATE TABLE. * * @param array $field 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", "BigInteger", "SmallInteger"))) { $default = " DEFAULT ".$field['default']; } else if ((string)$field['type'] == 'DateTime' && $field['default'] == $this->getCurrentTimestampSQL()) { $default = " DEFAULT ".$this->getCurrentTimestampSQL(); } else if ((string) $field['type'] == 'Boolean') { $default = " DEFAULT '" . $this->convertBooleans($field['default']) . "'"; } } } return $default; } /** * Obtain DBMS specific SQL code portion needed to set a CHECK constraint * declaration to be used in statements like CREATE TABLE. * * @param array $definition 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); } /** * Obtain DBMS specific SQL code portion needed to set a unique * constraint declaration to be used in statements like CREATE TABLE. * * @param string $name name of the unique constraint * @param Index $index index definition * * @return string DBMS specific SQL code portion needed * to set a constraint */ public function getUniqueConstraintDeclarationSQL($name, Index $index) { if (count($index->getColumns()) === 0) { throw new \InvalidArgumentException("Incomplete definition. 'columns' required."); } return 'CONSTRAINT ' . $name . ' UNIQUE (' . $this->getIndexFieldDeclarationListSQL($index->getColumns()) . ')'; } /** * Obtain DBMS specific SQL code portion needed to set an index * declaration to be used in statements like CREATE TABLE. * * @param string $name name of the index * @param Index $index index definition * * @return string DBMS specific SQL code portion needed to set an index */ public function getIndexDeclarationSQL($name, Index $index) { $type = ''; if ($index->isUnique()) { $type = 'UNIQUE '; } if (count($index->getColumns()) === 0) { throw new \InvalidArgumentException("Incomplete definition. 'columns' required."); } return $type . 'INDEX ' . $name . ' (' . $this->getIndexFieldDeclarationListSQL($index->getColumns()) . ')'; } /** * getCustomTypeDeclarationSql * Obtail 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']; } /** * getIndexFieldDeclarationList * Obtain 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); } /** * A method to return 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; } /** * Get sql query to show a list of database. * * @return string */ public function getShowDatabasesSQL() { throw DBALException::notSupported(__METHOD__); } /** * 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; } /** * Return the FOREIGN KEY query section dealing with non-standard options * as MATCH, INITIALLY DEFERRED, ON UPDATE, ... * * @param ForeignKeyConstraint $foreignKey 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 given referential action in uppercase if valid, otherwise throws * an exception * * @throws \InvalidArgumentException if unknown referential action given * * @param string $action foreign key referential action * * @return string */ 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); } } /** * 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 ForeignKeyConstraint $foreignKey * * @return string */ 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->getLocalColumns()) . ') REFERENCES ' . $foreignKey->getQuotedForeignTableName($this) . ' (' . implode(', ', $foreignKey->getForeignColumns()) . ')'; return $sql; } /** * Obtain 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'; } /** * Obtain 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 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 ''; } /** * Obtain DBMS specific SQL code portion needed to set the COLLATION * of a field declaration to be used in statements like CREATE TABLE. * * @param string $collation name of the collation * * @return string DBMS specific SQL code portion needed to set the COLLATION * of a field declaration. */ public function getColumnCollationDeclarationSQL($collation) { return ''; } /** * 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). * * @param mixed $item * * @return mixed */ public function convertBooleans($item) { if (is_array($item)) { foreach ($item as $k => $value) { if (is_bool($value)) { $item[$k] = (int) $value; } } } else if (is_bool($item)) { $item = (int) $item; } return $item; } /** * Gets the SQL specific for the platform to get the current date. * * @return string */ public function getCurrentDateSQL() { return 'CURRENT_DATE'; } /** * Gets the SQL specific for the platform to get the current time. * * @return string */ public function getCurrentTimeSQL() { return 'CURRENT_TIME'; } /** * Gets the SQL specific for the platform to get the current timestamp * * @return string */ public function getCurrentTimestampSQL() { return 'CURRENT_TIMESTAMP'; } /** * Get sql for transaction isolation level Connection constant * * @param integer $level * * @return string */ 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); } } public function getListDatabasesSQL() { throw DBALException::notSupported(__METHOD__); } public function getListSequencesSQL($database) { throw DBALException::notSupported(__METHOD__); } public function getListTableConstraintsSQL($table) { throw DBALException::notSupported(__METHOD__); } public function getListTableColumnsSQL($table, $database = null) { throw DBALException::notSupported(__METHOD__); } public function getListTablesSQL() { throw DBALException::notSupported(__METHOD__); } public function getListUsersSQL() { throw DBALException::notSupported(__METHOD__); } /** * Get the SQL to list all views of a database or user. * * @param string $database * * @return string */ public function getListViewsSQL($database) { throw DBALException::notSupported(__METHOD__); } /** * Get 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 */ public function getListTableIndexesSQL($table, $currentDatabase = null) { throw DBALException::notSupported(__METHOD__); } public function getListTableForeignKeysSQL($table) { throw DBALException::notSupported(__METHOD__); } public function getCreateViewSQL($name, $sql) { throw DBALException::notSupported(__METHOD__); } public function getDropViewSQL($name) { throw DBALException::notSupported(__METHOD__); } /** * Get the SQL snippet to drop an existing sequence * * @param \Doctrine\DBAL\Schema\Sequence $sequence * * @return string */ public function getDropSequenceSQL($sequence) { throw DBALException::notSupported(__METHOD__); } public function getSequenceNextValSQL($sequenceName) { throw DBALException::notSupported(__METHOD__); } /** * create a new database * * @param string $database name of the database that should be created * * @return string */ public function getCreateDatabaseSQL($database) { throw DBALException::notSupported(__METHOD__); } /** * Get sql to set the transaction isolation level * * @param integer $level * * @return string */ public function getSetTransactionIsolationSQL($level) { throw DBALException::notSupported(__METHOD__); } /** * Obtain DBMS specific SQL to be used to create datetime fields in * statements like CREATE TABLE * * @param array $fieldDeclaration * * @return string */ public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) { throw DBALException::notSupported(__METHOD__); } /** * Obtain 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); } /** * Obtain DBMS specific SQL to be used to create date fields in statements * like CREATE TABLE. * * @param array $fieldDeclaration * * @return string */ public function getDateTypeDeclarationSQL(array $fieldDeclaration) { throw DBALException::notSupported(__METHOD__); } /** * Obtain DBMS specific SQL to be used to create time fields in statements * like CREATE TABLE. * * @param array $fieldDeclaration * * @return string */ public function getTimeTypeDeclarationSQL(array $fieldDeclaration) { throw DBALException::notSupported(__METHOD__); } 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 recieve an auto-generated value from the * database on insert of a row. * * @return boolean */ public function supportsIdentityColumns() { return false; } /** * Whether the platform supports indexes. * * @return boolean */ public function supportsIndexes() { return true; } /** * 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; } /** * Does the platform supports foreign key constraints? * * @return boolean */ public function supportsForeignKeyConstraints() { return true; } /** * Does 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; } /** * Can this platform 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; } /** * 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; } /** * Does this plaform support to add inline column comments as postfix. * * @return boolean */ public function supportsInlineColumnComments() { return false; } /** * Does this platform support the propriortary synatx "COMMENT ON asset" * * @return boolean */ public function supportsCommentOnStatement() { return false; } public function getIdentityColumnNullInsertSQL() { return ""; } /** * Does this platform views ? * * @return boolean */ public function supportsViews() { return true; } /** * 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'; } /** * Modify limit query * * @param string $query * @param integer $limit * @param integer $offset * * @return string */ 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 $limit * @param integer $offset * * @return string */ protected function doModifyLimitQuery($query, $limit, $offset) { if ($limit !== null) { $query .= ' LIMIT ' . $limit; } if ($offset !== null) { $query .= ' OFFSET ' . $offset; } return $query; } /** * Does 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 databse identifier, like tables or column names. * * @return integer */ public function getMaxIdentifierLength() { return 63; } /** * Get the insert sql for an empty insert statement * * @param string $tableName * @param string $identifierColumnName * * @return string $sql */ public function getEmptyIdentityInsertSQL($tableName, $identifierColumnName) { return 'INSERT INTO ' . $tableName . ' (' . $identifierColumnName . ') VALUES (null)'; } /** * Generate 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) { return 'TRUNCATE '.$tableName; } /** * This is for test reasons, many vendors have special requirements for dummy statements. * * @return string */ public function getDummySelectSQL() { return 'SELECT 1'; } /** * Generate SQL to create a new savepoint * * @param string $savepoint * * @return string */ public function createSavePoint($savepoint) { return 'SAVEPOINT ' . $savepoint; } /** * Generate SQL to release a savepoint * * @param string $savepoint * * @return string */ public function releaseSavePoint($savepoint) { return 'RELEASE SAVEPOINT ' . $savepoint; } /** * Generate SQL to rollback a savepoint * * @param string $savepoint * * @return string */ public function rollbackSavePoint($savepoint) { return 'ROLLBACK TO SAVEPOINT ' . $savepoint; } /** * Return the keyword list instance of this platform. * * Throws exception if no keyword list is specified. * * @throws DBALException * * @return \Doctrine\DBAL\Platforms\Keywords\KeywordList */ 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; } /** * The class name of the reserved keywords list. * * @return string */ protected function getReservedKeywordsClass() { throw DBALException::notSupported(__METHOD__); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Platforms/DB2Platform.php0000644000175100017510000003417512143374463023046 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\TableDiff; class DB2Platform extends AbstractPlatform { /** * {@inheritDoc} */ public function getBlobTypeDeclarationSQL(array $field) { throw DBALException::notSupported(__METHOD__); } /** * {@inheritDoc} */ public function initializeDoctrineTypeMappings() { $this->doctrineTypeMapping = array( 'smallint' => 'smallint', 'bigint' => 'bigint', 'integer' => 'integer', 'time' => 'time', 'date' => 'date', 'varchar' => 'string', 'character' => 'string', 'clob' => 'text', 'decimal' => 'decimal', 'double' => 'float', 'real' => 'float', 'timestamp' => 'datetime', ); } /** * {@inheritDoc} */ protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) { return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(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 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'; } public function getListDatabasesSQL() { throw DBALException::notSupported(__METHOD__); } public function getListSequencesSQL($database) { throw DBALException::notSupported(__METHOD__); } public function getListTableConstraintsSQL($table) { throw DBALException::notSupported(__METHOD__); } /** * This code fragment is originally from the Zend_Db_Adapter_Db2 class. * * @license New BSD License * @param string $table * @param string $database * @return string */ public function getListTableColumnsSQL($table, $database = null) { return "SELECT DISTINCT c.tabschema, c.tabname, c.colname, c.colno, c.typename, c.default, c.nulls, c.length, c.scale, c.identity, tc.type AS tabconsttype, k.colseq FROM syscat.columns c LEFT JOIN (syscat.keycoluse k JOIN syscat.tabconst tc ON (k.tabschema = tc.tabschema AND k.tabname = tc.tabname AND tc.type = 'P')) ON (c.tabschema = k.tabschema AND c.tabname = k.tabname AND c.colname = k.colname) WHERE UPPER(c.tabname) = UPPER('" . $table . "') ORDER BY c.colno"; } public function getListTablesSQL() { return "SELECT NAME FROM SYSIBM.SYSTABLES WHERE TYPE = 'T'"; } public function getListUsersSQL() { throw DBALException::notSupported(__METHOD__); } /** * {@inheritDoc} */ public function getListViewsSQL($database) { return "SELECT NAME, TEXT FROM SYSIBM.SYSVIEWS"; } /** * {@inheritDoc} */ public function getListTableIndexesSQL($table, $currentDatabase = null) { return "SELECT NAME, COLNAMES, UNIQUERULE FROM SYSIBM.SYSINDEXES WHERE TBNAME = UPPER('" . $table . "')"; } public function getListTableForeignKeysSQL($table) { return "SELECT TBNAME, RELNAME, REFTBNAME, DELETERULE, UPDATERULE, FKCOLNAMES, PKCOLNAMES ". "FROM SYSIBM.SYSRELS WHERE TBNAME = UPPER('".$table."')"; } public function getCreateViewSQL($name, $sql) { return "CREATE VIEW ".$name." AS ".$sql; } public function getDropViewSQL($name) { return "DROP VIEW ".$name; } /** * {@inheritDoc} */ public function getDropSequenceSQL($sequence) { throw DBALException::notSupported(__METHOD__); } public function getSequenceNextValSQL($sequenceName) { throw DBALException::notSupported(__METHOD__); } /** * {@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 getCurrentDateSQL() { return 'VALUES CURRENT DATE'; } /** * {@inheritDoc} */ public function getCurrentTimeSQL() { return 'VALUES CURRENT TIME'; } /** * {@inheritDoc} */ public function getCurrentTimestampSQL() { return "VALUES CURRENT TIMESTAMP"; } /** * {@inheritDoc} */ public function getIndexDeclarationSQL($name, Index $index) { return $this->getUniqueConstraintDeclarationSQL($name, $index); } /** * {@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(); $queryParts = array(); foreach ($diff->addedColumns as $column) { if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { continue; } $queryParts[] = 'ADD COLUMN ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); } foreach ($diff->removedColumns as $column) { if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { continue; } $queryParts[] = 'DROP COLUMN ' . $column->getQuotedName($this); } foreach ($diff->changedColumns as $columnDiff) { if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { continue; } /* @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */ $column = $columnDiff->column; $queryParts[] = 'ALTER ' . ($columnDiff->oldColumnName) . ' ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); } foreach ($diff->renamedColumns as $oldColumnName => $column) { if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { continue; } $queryParts[] = 'RENAME ' . $oldColumnName . ' TO ' . $column->getQuotedName($this); } $tableSql = array(); if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { if (count($queryParts) > 0) { $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . implode(" ", $queryParts); } $sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff)); if ($diff->newName !== false) { $sql[] = 'RENAME TABLE TO ' . $diff->newName; } } return array_merge($sql, $tableSql, $columnSql); } /** * {@inheritDoc} */ public function getDefaultValueDeclarationSQL($field) { if (isset($field['notnull']) && $field['notnull'] && !isset($field['default'])) { if (in_array((string)$field['type'], array("Integer", "BigInteger", "SmallInteger"))) { $field['default'] = 0; } else if((string)$field['type'] == "DateTime") { $field['default'] = "00-00-00 00:00:00"; } else if ((string)$field['type'] == "Date") { $field['default'] = "00-00-00"; } else if((string)$field['type'] == "Time") { $field['default'] = "00:00:00"; } else { $field['default'] = ''; } } unset($field['default']); // @todo this needs fixing if (isset($field['version']) && $field['version']) { if ((string)$field['type'] != "DateTime") { $field['default'] = "1"; } } return parent::getDefaultValueDeclarationSQL($field); } /** * {@inheritDoc} */ public function getEmptyIdentityInsertSQL($tableName, $identifierColumnName) { return 'INSERT INTO ' . $tableName . ' (' . $identifierColumnName . ') VALUES (DEFAULT)'; } public function getCreateTemporaryTableSnippetSQL() { return "DECLARE GLOBAL TEMPORARY TABLE"; } /** * {@inheritDoc} */ public function getTemporaryTableName($tableName) { return "SESSION." . $tableName; } /** * {@inheritDoc} */ protected function doModifyLimitQuery($query, $limit, $offset = null) { if ($limit === null && $offset === null) { return $query; } $limit = (int)$limit; $offset = (int)(($offset)?:0); // Todo OVER() needs ORDER BY data! $sql = 'SELECT db22.* FROM (SELECT ROW_NUMBER() OVER() AS DC_ROWNUM, db21.* '. 'FROM (' . $query . ') db21) db22 WHERE db22.DC_ROWNUM BETWEEN ' . ($offset+1) .' AND ' . ($offset+$limit); return $sql; } /** * {@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); } 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'; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Platforms/DrizzlePlatform.php0000644000175100017510000003221712143374463024115 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\DBALException, Doctrine\DBAL\Schema\TableDiff, Doctrine\DBAL\Schema\Index, Doctrine\DBAL\Schema\Table; /** * 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} */ public function getDateDiffExpression($date1, $date2) { return 'DATEDIFF(' . $date1 . ', ' . $date2 . ')'; } /** * {@inheritDoc} */ public function getDateAddDaysExpression($date, $days) { return 'DATE_ADD(' . $date . ', INTERVAL ' . $days . ' DAY)'; } /** * {@inheritDoc} */ public function getDateSubDaysExpression($date, $days) { return 'DATE_SUB(' . $date . ', INTERVAL ' . $days . ' DAY)'; } /** * {@inheritDoc} */ public function getDateAddMonthExpression($date, $months) { return 'DATE_ADD(' . $date . ', INTERVAL ' . $months . ' MONTH)'; } /** * {@inheritDoc} */ public function getDateSubMonthExpression($date, $months) { return 'DATE_SUB(' . $date . ', INTERVAL ' . $months . ' MONTH)'; } /** * {@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 initializeDoctrineTypeMappings() { $this->doctrineTypeMapping = array( 'boolean' => 'boolean', 'varchar' => 'string', 'integer' => 'integer', 'blob' => 'text', '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; } 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'; } public function getListTablesSQL() { return "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE' AND TABLE_SCHEMA=DATABASE()"; } 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" . " FROM DATA_DICTIONARY.COLUMNS" . " WHERE TABLE_SCHEMA=" . $database . " AND TABLE_NAME = '" . $table . "'"; } 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 getDropIndexSQL($index, $table=null) { if ($index instanceof Index) { $indexName = $index->getQuotedName($this); } else if (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); } else if(!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; } /** * @param Index $index * @param Table $table * * @return string */ 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->newName; } 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(); $columnArray['comment'] = $this->getColumnComment($column); $queryParts[] = 'CHANGE ' . ($columnDiff->oldColumnName) . ' ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); } foreach ($diff->renamedColumns as $oldColumnName => $column) { if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { continue; } $columnArray = $column->toArray(); $columnArray['comment'] = $this->getColumnComment($column); $queryParts[] = 'CHANGE ' . $oldColumnName . ' ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); } $sql = array(); $tableSql = array(); if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { if (count($queryParts) > 0) { $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . implode(", ", $queryParts); } $sql = array_merge( $this->getPreAlterTableIndexForeignKeySQL($diff), $sql, $this->getPostAlterTableIndexForeignKeySQL($diff) ); } return array_merge($sql, $tableSql, $columnSql); } /** * {@inheritDoc} */ public function getDropTemporaryTableSQL($table) { if ($table instanceof Table) { $table = $table->getQuotedName($this); } else if(!is_string($table)) { throw new \InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); } return 'DROP TEMPORARY TABLE ' . $table; } /** * {@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'; } } } else if (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'; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Platforms/MySqlPlatform.php0000644000175100017510000005113112143374463023533 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\DBALException, Doctrine\DBAL\Schema\TableDiff, Doctrine\DBAL\Schema\Index, Doctrine\DBAL\Schema\Table; /** * The MySqlPlatform provides the behavior, features and SQL dialect of the * MySQL database platform. This platform represents a MySQL 5.0 or greater platform that * uses the InnoDB storage engine. * * @since 2.0 * @author Roman Borschel * @author Benjamin Eberlei * @todo Rename: MySQLPlatform */ class MySqlPlatform extends AbstractPlatform { /** * {@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} */ public function getDateDiffExpression($date1, $date2) { return 'DATEDIFF(' . $date1 . ', ' . $date2 . ')'; } /** * {@inheritDoc} */ public function getDateAddDaysExpression($date, $days) { return 'DATE_ADD(' . $date . ', INTERVAL ' . $days . ' DAY)'; } /** * {@inheritDoc} */ public function getDateSubDaysExpression($date, $days) { return 'DATE_SUB(' . $date . ', INTERVAL ' . $days . ' DAY)'; } /** * {@inheritDoc} */ public function getDateAddMonthExpression($date, $months) { return 'DATE_ADD(' . $date . ', INTERVAL ' . $months . ' MONTH)'; } /** * {@inheritDoc} */ public function getDateSubMonthExpression($date, $months) { return 'DATE_SUB(' . $date . ', INTERVAL ' . $months . ' MONTH)'; } public function getListDatabasesSQL() { return 'SHOW DATABASES'; } public function getListTableConstraintsSQL($table) { return 'SHOW INDEX FROM ' . $table; } /** * {@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". * * @param string $table * @param string $currentDatabase * @return string */ public function getListTableIndexesSQL($table, $currentDatabase = null) { if ($currentDatabase) { return "SELECT TABLE_NAME AS `Table`, NON_UNIQUE AS Non_Unique, INDEX_NAME AS Key_name, ". "SEQ_IN_INDEX AS Seq_in_index, COLUMN_NAME AS Column_Name, COLLATION AS Collation, ". "CARDINALITY AS Cardinality, SUB_PART AS Sub_Part, PACKED AS Packed, " . "NULLABLE AS `Null`, INDEX_TYPE AS Index_Type, COMMENT AS Comment " . "FROM information_schema.STATISTICS WHERE TABLE_NAME = '" . $table . "' AND TABLE_SCHEMA = '" . $currentDatabase . "'"; } return 'SHOW INDEX FROM ' . $table; } public function getListViewsSQL($database) { return "SELECT * FROM information_schema.VIEWS WHERE TABLE_SCHEMA = '".$database."'"; } public function getListTableForeignKeysSQL($table, $database = null) { $sql = "SELECT DISTINCT k.`CONSTRAINT_NAME`, k.`COLUMN_NAME`, k.`REFERENCED_TABLE_NAME`, ". "k.`REFERENCED_COLUMN_NAME` /*!50116 , c.update_rule, c.delete_rule */ ". "FROM information_schema.key_column_usage k /*!50116 ". "INNER JOIN information_schema.referential_constraints c ON ". " c.constraint_name = k.constraint_name AND ". " c.table_name = '$table' */ WHERE k.table_name = '$table'"; if ($database) { $sql .= " AND k.table_schema = '$database' /*!50116 AND c.constraint_schema = '$database' */"; } $sql .= " AND k.`REFERENCED_COLUMN_NAME` is not NULL"; return $sql; } public function getCreateViewSQL($name, $sql) { return 'CREATE VIEW ' . $name . ' AS ' . $sql; } public function getDropViewSQL($name) { return 'DROP VIEW '. $name; } /** * {@inheritDoc} */ protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) { return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'); } /** * {@inheritDoc} */ public function getClobTypeDeclarationSQL(array $field) { if ( ! empty($field['length']) && is_numeric($field['length'])) { $length = $field['length']; if ($length <= 255) { return 'TINYTEXT'; } if ($length <= 65532) { return 'TEXT'; } if ($length <= 16777215) { 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. * * @param string $collation name of the collation * * @return string DBMS specific SQL code portion needed to set the COLLATION * of a field declaration. */ public function getCollationFieldDeclaration($collation) { return 'COLLATE ' . $collation; } /** * {@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 getShowDatabasesSQL() { return 'SHOW DATABASES'; } public function getListTablesSQL() { return "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'"; } public function getListTableColumnsSQL($table, $database = null) { if ($database) { return "SELECT COLUMN_NAME AS Field, COLUMN_TYPE AS Type, IS_NULLABLE AS `Null`, ". "COLUMN_KEY AS `Key`, COLUMN_DEFAULT AS `Default`, EXTRA AS Extra, COLUMN_COMMENT AS Comment, " . "CHARACTER_SET_NAME AS CharacterSet, COLLATION_NAME AS CollactionName ". "FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = '" . $database . "' AND TABLE_NAME = '" . $table . "'"; } return 'DESCRIBE ' . $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 . ') '; if (isset($options['comment'])) { $comment = trim($options['comment'], " '"); $query .= sprintf("COMMENT = '%s' ", str_replace("'", "''", $comment)); } if ( ! isset($options['charset'])) { $options['charset'] = 'utf8'; } if ( ! isset($options['collate'])) { $options['collate'] = 'utf8_unicode_ci'; } $query .= 'DEFAULT CHARACTER SET ' . $options['charset']; $query .= ' COLLATE ' . $options['collate']; if ( ! isset($options['engine'])) { $options['engine'] = 'InnoDB'; } $query .= ' ENGINE = ' . $options['engine']; $sql[] = $query; if (isset($options['foreignKeys'])) { foreach ((array) $options['foreignKeys'] as $definition) { $sql[] = $this->getCreateForeignKeySQL($definition, $tableName); } } return $sql; } /** * {@inheritDoc} */ public function getAlterTableSQL(TableDiff $diff) { $columnSql = array(); $queryParts = array(); if ($diff->newName !== false) { $queryParts[] = 'RENAME TO ' . $diff->newName; } 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(); $columnArray['comment'] = $this->getColumnComment($column); $queryParts[] = 'CHANGE ' . ($columnDiff->oldColumnName) . ' ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); } foreach ($diff->renamedColumns as $oldColumnName => $column) { if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { continue; } $columnArray = $column->toArray(); $columnArray['comment'] = $this->getColumnComment($column); $queryParts[] = 'CHANGE ' . $oldColumnName . ' ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); } $sql = array(); $tableSql = array(); if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { if (count($queryParts) > 0) { $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . implode(", ", $queryParts); } $sql = array_merge( $this->getPreAlterTableIndexForeignKeySQL($diff), $sql, $this->getPostAlterTableIndexForeignKeySQL($diff) ); } return array_merge($sql, $tableSql, $columnSql); } /** * {@inheritDoc} */ protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) { $sql = array(); $table = $diff->name; foreach ($diff->removedIndexes as $remKey => $remIndex) { foreach ($diff->addedIndexes as $addKey => $addIndex) { if ($remIndex->getColumns() == $addIndex->getColumns()) { $columns = $addIndex->getColumns(); $type = ''; if ($addIndex->isUnique()) { $type = 'UNIQUE '; } $query = 'ALTER TABLE ' . $table . ' DROP INDEX ' . $remIndex->getName() . ', '; $query .= 'ADD ' . $type . 'INDEX ' . $addIndex->getName(); $query .= ' (' . $this->getIndexFieldDeclarationListSQL($columns) . ')'; $sql[] = $query; unset($diff->removedIndexes[$remKey]); unset($diff->addedIndexes[$addKey]); break; } } } $sql = array_merge($sql, parent::getPreAlterTableIndexForeignKeySQL($diff)); return $sql; } /** * {@inheritDoc} */ protected function getCreateIndexSQLFlags(Index $index) { $type = ''; if ($index->isUnique()) { $type .= 'UNIQUE '; } else if ($index->hasFlag('fulltext')) { $type .= 'FULLTEXT '; } 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); } else if(is_string($index)) { $indexName = $index; } else { throw new \InvalidArgumentException('MysqlPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.'); } if ($table instanceof Table) { $table = $table->getQuotedName($this); } else if(!is_string($table)) { throw new \InvalidArgumentException('MysqlPlatform::getDropIndexSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); } if ($index instanceof Index && $index->isPrimary()) { // mysql primary keys are always named "PRIMARY", // so we cannot use them in statements because of them being keyword. return $this->getDropPrimaryKeySQL($table); } return 'DROP INDEX ' . $indexName . ' ON ' . $table; } /** * @param 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' => 'blob', 'varbinary' => 'blob', 'set' => 'simple_array', ); } /** * {@inheritDoc} */ public function getVarcharMaxLength() { 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); } else if(!is_string($table)) { throw new \InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); } return 'DROP TEMPORARY TABLE ' . $table; } /** * {@inheritDoc} */ public function getBlobTypeDeclarationSQL(array $field) { return 'LONGBLOB'; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Platforms/OraclePlatform.php0000644000175100017510000005441212143374463023700 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\Sequence; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\DBALException; /** * 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 * * @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} * * 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 getDateAddDaysExpression($date, $days) { return '(' . $date . '+' . $days . ')'; } /** * {@inheritDoc} */ public function getDateSubDaysExpression($date, $days) { return '(' . $date . '-' . $days . ')'; } /** * {@inheritDoc} */ public function getDateAddMonthExpression($date, $months) { return "ADD_MONTHS(" . $date . ", " . $months . ")"; } /** * {@inheritDoc} */ public function getDateSubMonthExpression($date, $months) { return "ADD_MONTHS(" . $date . ", -" . $months . ")"; } /** * {@inheritDoc} */ public function getBitAndComparisonExpression($value1, $value2) { return 'BITAND('.$value1 . ', ' . $value2 . ')'; } /** * {@inheritDoc} */ public function getBitOrComparisonExpression($value1, $value2) { return '(' . $value1 . '-' . $this->getBitAndComparisonExpression($value1, $value2) . '+' . $value2 . ')'; } /** * {@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(); } /** * {@inheritDoc} */ public function getAlterSequenceSQL(\Doctrine\DBAL\Schema\Sequence $sequence) { return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) . ' INCREMENT BY ' . $sequence->getAllocationSize(); } /** * {@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} */ public function getClobTypeDeclarationSQL(array $field) { return 'CLOB'; } public function getListDatabasesSQL() { return 'SELECT username FROM all_users'; } public function getListSequencesSQL($database) { return "SELECT sequence_name, min_value, increment_by FROM sys.all_sequences ". "WHERE SEQUENCE_OWNER = '".strtoupper($database)."'"; } /** * {@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 = strtoupper($table); return "SELECT uind.index_name AS name, " . " uind.index_type AS type, " . " decode( uind.uniqueness, 'NONUNIQUE', 0, 'UNIQUE', 1 ) AS is_unique, " . " uind_col.column_name AS column_name, " . " uind_col.column_position AS column_pos, " . " (SELECT ucon.constraint_type FROM user_constraints ucon WHERE ucon.constraint_name = uind.index_name) AS is_primary ". "FROM user_indexes uind, user_ind_columns uind_col " . "WHERE uind.index_name = uind_col.index_name AND uind_col.table_name = '$table' ORDER BY uind_col.column_position ASC"; } public function getListTablesSQL() { return 'SELECT * FROM sys.user_tables'; } /** * {@inheritDoc} */ public function getListViewsSQL($database) { return 'SELECT view_name, text FROM sys.user_views'; } public function getCreateViewSQL($name, $sql) { return 'CREATE VIEW ' . $name . ' AS ' . $sql; } public function getDropViewSQL($name) { return 'DROP VIEW '. $name; } public function getCreateAutoincrementSql($name, $table, $start = 1) { $table = strtoupper($table); $sql = array(); $indexName = $table . '_AI_PK'; $idx = new Index($indexName, array($name), true, true); $sql[] = 'DECLARE constraints_Count NUMBER; BEGIN SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = \''.$table.'\' AND CONSTRAINT_TYPE = \'P\'; IF constraints_Count = 0 OR constraints_Count = \'\' THEN EXECUTE IMMEDIATE \''.$this->getCreateConstraintSQL($idx, $table).'\'; END IF; END;'; $sequenceName = $table . '_SEQ'; $sequence = new Sequence($sequenceName, $start); $sql[] = $this->getCreateSequenceSQL($sequence); $triggerName = $table . '_AI_PK'; $sql[] = 'CREATE TRIGGER ' . $triggerName . ' BEFORE INSERT ON ' . $table . ' FOR EACH ROW DECLARE last_Sequence NUMBER; last_InsertID NUMBER; BEGIN SELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $name . ' FROM DUAL; IF (:NEW.' . $name . ' IS NULL OR :NEW.'.$name.' = 0) THEN SELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $name . ' FROM DUAL; ELSE SELECT NVL(Last_Number, 0) INTO last_Sequence FROM User_Sequences WHERE Sequence_Name = \'' . $sequenceName . '\'; SELECT :NEW.' . $name . ' INTO last_InsertID FROM DUAL; WHILE (last_InsertID > last_Sequence) LOOP SELECT ' . $sequenceName . '.NEXTVAL INTO last_Sequence FROM DUAL; END LOOP; END IF; END;'; return $sql; } public function getDropAutoincrementSql($table) { $table = strtoupper($table); $trigger = $table . '_AI_PK'; $sql[] = 'DROP TRIGGER ' . $trigger; $sql[] = $this->getDropSequenceSQL($table.'_SEQ'); $indexName = $table . '_AI_PK'; $sql[] = $this->getDropConstraintSQL($indexName, $table); return $sql; } public function getListTableForeignKeysSQL($table) { $table = strtoupper($table); return "SELECT alc.constraint_name, alc.DELETE_RULE, alc.search_condition, cols.column_name \"local_column\", cols.position, r_alc.table_name \"references_table\", r_cols.column_name \"foreign_column\" FROM user_cons_columns cols LEFT JOIN user_constraints alc ON alc.constraint_name = cols.constraint_name LEFT JOIN user_constraints r_alc ON alc.r_constraint_name = r_alc.constraint_name LEFT JOIN user_cons_columns r_cols ON r_alc.constraint_name = r_cols.constraint_name AND cols.position = r_cols.position WHERE alc.constraint_name = cols.constraint_name AND alc.constraint_type = 'R' AND alc.table_name = '".$table."'"; } public function getListTableConstraintsSQL($table) { $table = strtoupper($table); return 'SELECT * FROM user_constraints WHERE table_name = \'' . $table . '\''; } public function getListTableColumnsSQL($table, $database = null) { $table = strtoupper($table); $tabColumnsTableName = "user_tab_columns"; $ownerCondition = ''; if (null !== $database){ $database = strtoupper($database); $tabColumnsTableName = "all_tab_columns"; $ownerCondition = "AND c.owner = '".$database."'"; } return "SELECT c.*, d.comments FROM $tabColumnsTableName c ". "INNER JOIN user_col_comments d ON d.TABLE_NAME = c.TABLE_NAME AND d.COLUMN_NAME = c.COLUMN_NAME ". "WHERE c.table_name = '" . $table . "' ".$ownerCondition." ORDER BY c.column_name"; } /** * {@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 = $foreignKey->getQuotedName($this); } if ($table instanceof Table) { $table = $table->getQuotedName($this); } return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $foreignKey; } /** * {@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->name, $column->getName(), $comment); } } if (count($fields)) { $sql[] = 'ALTER TABLE ' . $diff->name . ' ADD (' . implode(', ', $fields) . ')'; } $fields = array(); foreach ($diff->changedColumns as $columnDiff) { if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { continue; } $column = $columnDiff->column; $fields[] = $column->getQuotedName($this). ' ' . $this->getColumnDeclarationSQL('', $column->toArray()); if ($columnDiff->hasChanged('comment') && $comment = $this->getColumnComment($column)) { $commentsSQL[] = $this->getCommentOnColumnSQL($diff->name, $column->getName(), $comment); } } if (count($fields)) { $sql[] = 'ALTER TABLE ' . $diff->name . ' MODIFY (' . implode(', ', $fields) . ')'; } foreach ($diff->renamedColumns as $oldColumnName => $column) { if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { continue; } $sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME COLUMN ' . $oldColumnName .' TO ' . $column->getQuotedName($this); } $fields = array(); foreach ($diff->removedColumns as $column) { if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { continue; } $fields[] = $column->getQuotedName($this); } if (count($fields)) { $sql[] = 'ALTER TABLE ' . $diff->name . ' DROP (' . implode(', ', $fields).')'; } $tableSql = array(); if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { if ($diff->newName !== false) { $sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME TO ' . $diff->newName; } $sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff), $commentsSQL); } return array_merge($sql, $tableSql, $columnSql); } /** * {@inheritDoc} */ public function prefersSequences() { return true; } /** * {@inheritDoc} */ public function supportsCommentOnStatement() { return true; } /** * {@inheritDoc} */ public function getName() { return 'oracle'; } /** * {@inheritDoc} */ protected function doModifyLimitQuery($query, $limit, $offset = null) { $limit = (int) $limit; $offset = (int) $offset; if (preg_match('/^\s*SELECT/i', $query)) { if (!preg_match('/\sFROM\s/i', $query)) { $query .= " FROM dual"; } if ($limit > 0) { $max = $offset + $limit; $column = '*'; if ($offset > 0) { $min = $offset + 1; $query = 'SELECT * FROM (SELECT a.' . $column . ', rownum AS doctrine_rownum FROM (' . $query . ') a WHERE rownum <= ' . $max . ') WHERE doctrine_rownum >= ' . $min; } else { $query = 'SELECT a.' . $column . ' FROM (' . $query . ') a WHERE ROWNUM <= ' . $max; } } } return $query; } /** * {@inheritDoc} * * Oracle returns all column names in SQL result sets in uppercase. */ public function getSQLResultCasing($column) { return strtoupper($column); } 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) { return 'TRUNCATE TABLE '.$tableName; } /** * {@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' => 'datetime', 'timestamp' => 'datetime', 'timestamptz' => 'datetimetz', 'float' => 'float', 'long' => 'string', 'clob' => 'text', 'nclob' => 'text', 'raw' => 'text', 'long raw' => 'text', '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'; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php0000644000175100017510000005507012143374463024577 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\Schema\TableDiff, Doctrine\DBAL\Schema\Table; /** * PostgreSqlPlatform. * * @since 2.0 * @author Roman Borschel * @author Lukas Smith (PEAR MDB2 library) * @author Benjamin Eberlei * @todo Rename: PostgreSQLPlatform */ class PostgreSqlPlatform extends AbstractPlatform { /** * {@inheritDoc} */ public function getSubstringExpression($value, $from, $length = null) { if ($length === null) { return 'SUBSTR(' . $value . ', ' . $from . ')'; } return 'SUBSTR(' . $value . ', ' . $from . ', ' . $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} */ public function getDateDiffExpression($date1, $date2) { return '(DATE(' . $date1 . ')-DATE(' . $date2 . '))'; } /** * {@inheritDoc} */ public function getDateAddDaysExpression($date, $days) { return "(" . $date ." + (" . $days . " || ' day')::interval)"; } /** * {@inheritDoc} */ public function getDateSubDaysExpression($date, $days) { return "(" . $date ." - (" . $days . " || ' day')::interval)"; } /** * {@inheritDoc} */ public function getDateAddMonthExpression($date, $months) { return "(" . $date ." + (" . $months . " || ' month')::interval)"; } /** * {@inheritDoc} */ public function getDateSubMonthExpression($date, $months) { return "(" . $date ." - (" . $months . " || ' month')::interval)"; } /** * {@inheritDoc} */ public function supportsSequences() { return true; } /** * {@inheritDoc} */ public function supportsSchemas() { return true; } /** * {@inheritDoc} */ public function supportsIdentityColumns() { return true; } /** * {@inheritDoc} */ public function supportsCommentOnStatement() { return true; } /** * {@inheritDoc} */ public function prefersSequences() { return true; } public function getListDatabasesSQL() { return 'SELECT datname FROM pg_database'; } public function getListSequencesSQL($database) { return "SELECT c.relname, n.nspname AS schemaname FROM pg_class c, pg_namespace n WHERE relkind = 'S' AND n.oid = c.relnamespace AND (n.nspname NOT LIKE 'pg_%' AND n.nspname != 'information_schema')"; } public function getListTablesSQL() { return "SELECT tablename AS table_name, schemaname AS schema_name FROM pg_tables WHERE schemaname NOT LIKE 'pg_%' AND schemaname != 'information_schema' AND tablename != 'geometry_columns' AND tablename != 'spatial_ref_sys'"; } /** * {@inheritDoc} */ public function getListViewsSQL($database) { return 'SELECT viewname, definition FROM pg_views'; } public function getListTableForeignKeysSQL($table, $database = null) { return "SELECT r.conname, pg_catalog.pg_get_constraintdef(r.oid, true) as condef FROM pg_catalog.pg_constraint r WHERE r.conrelid = ( SELECT c.oid FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n WHERE " .$this->getTableWhereClause($table) ." AND n.oid = c.relnamespace ) AND r.contype = 'f'"; } public function getCreateViewSQL($name, $sql) { return 'CREATE VIEW ' . $name . ' AS ' . $sql; } public function getDropViewSQL($name) { return 'DROP VIEW '. $name; } public function getListTableConstraintsSQL($table) { return "SELECT relname FROM pg_class WHERE oid IN ( SELECT indexrelid FROM pg_index, pg_class WHERE pg_class.relname = '$table' AND pg_class.oid = pg_index.indrelid AND (indisunique = 't' OR indisprimary = 't') )"; } /** * {@inheritDoc} * * @license New BSD License * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html */ public function getListTableIndexesSQL($table, $currentDatabase = null) { return "SELECT relname, pg_index.indisunique, pg_index.indisprimary, pg_index.indkey, pg_index.indrelid FROM pg_class, pg_index WHERE oid IN ( SELECT indexrelid FROM pg_index si, pg_class sc, pg_namespace sn WHERE " . $this->getTableWhereClause($table, 'sc', 'sn')." AND sc.oid=si.indrelid AND sc.relnamespace = sn.oid ) AND pg_index.indexrelid = oid"; } /** * @param string $table * @param string $classAlias * @param string $namespaceAlias * * @return string */ private function getTableWhereClause($table, $classAlias = 'c', $namespaceAlias = 'n') { $whereClause = $namespaceAlias.".nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast') AND "; if (strpos($table, ".") !== false) { list($schema, $table) = explode(".", $table); $schema = "'" . $schema . "'"; } else { $schema = "ANY(string_to_array((select replace(setting,'\"\$user\"',user) from pg_catalog.pg_settings where name = 'search_path'),','))"; } $whereClause .= "$classAlias.relname = '" . $table . "' AND $namespaceAlias.nspname = $schema"; return $whereClause; } public function getListTableColumnsSQL($table, $database = null) { return "SELECT a.attnum, a.attname AS field, t.typname AS type, format_type(a.atttypid, a.atttypmod) AS complete_type, (SELECT t1.typname FROM pg_catalog.pg_type t1 WHERE t1.oid = t.typbasetype) AS domain_type, (SELECT format_type(t2.typbasetype, t2.typtypmod) FROM pg_catalog.pg_type t2 WHERE t2.typtype = 'd' AND t2.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_attrdef.adsrc FROM pg_attrdef WHERE c.oid = pg_attrdef.adrelid AND pg_attrdef.adnum=a.attnum ) AS default, (SELECT pg_description.description FROM pg_description WHERE pg_description.objoid = c.oid AND a.attnum = pg_description.objsubid ) AS comment FROM pg_attribute a, pg_class c, pg_type t, pg_namespace n WHERE ".$this->getTableWhereClause($table, 'c', 'n') ." AND a.attnum > 0 AND a.attrelid = c.oid AND a.atttypid = t.oid AND n.oid = c.relnamespace ORDER BY a.attnum"; } /** * {@inheritDoc} */ public function getCreateDatabaseSQL($name) { return 'CREATE DATABASE ' . $name; } /** * {@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) { $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->name . ' ' . $query; if ($comment = $this->getColumnComment($column)) { $commentsSQL[] = $this->getCommentOnColumnSQL($diff->name, $column->getName(), $comment); } } foreach ($diff->removedColumns as $column) { if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { continue; } $query = 'DROP ' . $column->getQuotedName($this); $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query; } foreach ($diff->changedColumns as $columnDiff) { /** @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */ if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { continue; } $oldColumnName = $columnDiff->oldColumnName; $column = $columnDiff->column; if ($columnDiff->hasChanged('type')) { $type = $column->getType(); // here was a server version check before, but DBAL API does not support this anymore. $query = 'ALTER ' . $oldColumnName . ' TYPE ' . $type->getSqlDeclaration($column->toArray(), $this); $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query; } if ($columnDiff->hasChanged('default')) { $query = 'ALTER ' . $oldColumnName . ' SET ' . $this->getDefaultValueDeclarationSQL($column->toArray()); $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query; } if ($columnDiff->hasChanged('notnull')) { $query = 'ALTER ' . $oldColumnName . ' ' . ($column->getNotNull() ? 'SET' : 'DROP') . ' NOT NULL'; $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query; } if ($columnDiff->hasChanged('autoincrement')) { if ($column->getAutoincrement()) { // add autoincrement $seqName = $diff->name . '_' . $oldColumnName . '_seq'; $sql[] = "CREATE SEQUENCE " . $seqName; $sql[] = "SELECT setval('" . $seqName . "', (SELECT MAX(" . $oldColumnName . ") FROM " . $diff->name . "))"; $query = "ALTER " . $oldColumnName . " SET DEFAULT nextval('" . $seqName . "')"; $sql[] = "ALTER TABLE " . $diff->name . " " . $query; } else { // Drop autoincrement, but do NOT drop the sequence. It might be re-used by other tables or have $query = "ALTER " . $oldColumnName . " " . "DROP DEFAULT"; $sql[] = "ALTER TABLE " . $diff->name . " " . $query; } } if ($columnDiff->hasChanged('comment') && $comment = $this->getColumnComment($column)) { $commentsSQL[] = $this->getCommentOnColumnSQL($diff->name, $column->getName(), $comment); } if ($columnDiff->hasChanged('length')) { $query = 'ALTER ' . $column->getName() . ' TYPE ' . $column->getType()->getSqlDeclaration($column->toArray(), $this); $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query; } } foreach ($diff->renamedColumns as $oldColumnName => $column) { if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { continue; } $sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME COLUMN ' . $oldColumnName . ' TO ' . $column->getQuotedName($this); } $tableSql = array(); if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { if ($diff->newName !== false) { $sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME TO ' . $diff->newName; } $sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff), $commentsSQL); } return array_merge($sql, $tableSql, $columnSql); } /** * {@inheritDoc} */ public function getCreateSequenceSQL(\Doctrine\DBAL\Schema\Sequence $sequence) { return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) . ' INCREMENT BY ' . $sequence->getAllocationSize() . ' MINVALUE ' . $sequence->getInitialValue() . ' START ' . $sequence->getInitialValue(); } /** * {@inheritDoc} */ public function getAlterSequenceSQL(\Doctrine\DBAL\Schema\Sequence $sequence) { return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) . ' INCREMENT BY ' . $sequence->getAllocationSize(); } /** * {@inheritDoc} */ public function getDropSequenceSQL($sequence) { if ($sequence instanceof \Doctrine\DBAL\Schema\Sequence) { $sequence = $sequence->getQuotedName($this); } return 'DROP SEQUENCE ' . $sequence . ' CASCADE'; } /** * {@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; } /** * {@inheritDoc} * * Postgres wants boolean values converted to the strings 'true'/'false'. */ public function convertBooleans($item) { if (is_array($item)) { foreach ($item as $key => $value) { if (is_bool($value) || is_numeric($item)) { $item[$key] = ($value) ? 'true' : 'false'; } } } else { if (is_bool($item) || is_numeric($item)) { $item = ($item) ? 'true' : 'false'; } } return $item; } public function getSequenceNextValSQL($sequenceName) { return "SELECT NEXTVAL('" . $sequenceName . "')"; } /** * {@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} */ 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} */ 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) { return 'TRUNCATE '.$tableName.' '.(($cascade)?'CASCADE':''); } /** * {@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', '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} */ protected function getReservedKeywordsClass() { return 'Doctrine\DBAL\Platforms\Keywords\PostgreSQLKeywords'; } /** * {@inheritDoc} */ public function getBlobTypeDeclarationSQL(array $field) { return 'BYTEA'; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Platforms/SQLAzurePlatform.php0000644000175100017510000000357312143374463024143 0ustar beberleibeberlei. */ 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; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Platforms/SqlitePlatform.php0000644000175100017510000003247012143374463023734 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\DBALException; /** * The SqlitePlatform class describes the specifics and dialects of the SQLite * database platform. * * @since 2.0 * @author Roman Borschel * @author Benjamin Eberlei * @todo Rename: SQLitePlatform */ class SqlitePlatform extends AbstractPlatform { /** * {@inheritDoc} */ public function getRegexpExpression() { return 'RLIKE'; } /** * {@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} */ public function getDateDiffExpression($date1, $date2) { return 'ROUND(JULIANDAY('.$date1 . ')-JULIANDAY('.$date2.'))'; } /** * {@inheritDoc} */ public function getDateAddDaysExpression($date, $days) { return "DATE(" . $date . ",'+". $days . " day')"; } /** * {@inheritDoc} */ public function getDateSubDaysExpression($date, $days) { return "DATE(" . $date . ",'-". $days . " day')"; } /** * {@inheritDoc} */ public function getDateAddMonthExpression($date, $months) { return "DATE(" . $date . ",'+". $months . " month')"; } /** * {@inheritDoc} */ public function getDateSubMonthExpression($date, $months) { return "DATE(" . $date . ",'-". $months . " month')"; } /** * {@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 $this->_getCommonIntegerTypeDeclarationSQL($field); } /** * {@inheritDoc} */ public function getBigIntTypeDeclarationSQL(array $field) { return $this->_getCommonIntegerTypeDeclarationSQL($field); } /** * {@inheritDoc} */ public function getTinyIntTypeDeclarationSql(array $field) { return $this->_getCommonIntegerTypeDeclarationSQL($field); } /** * {@inheritDoc} */ public function getSmallIntTypeDeclarationSQL(array $field) { return $this->_getCommonIntegerTypeDeclarationSQL($field); } /** * {@inheritDoc} */ public function getMediumIntTypeDeclarationSql(array $field) { return $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) { return 'INTEGER'; } /** * {@inheritDoc} */ protected function _getCreateTableSQL($name, array $columns, array $options = array()) { $name = str_replace(".", "__", $name); $queryFields = $this->getColumnDeclarationListSQL($columns); if (isset($options['primary']) && ! empty($options['primary'])) { $keyColumns = array_unique(array_values($options['primary'])); $queryFields.= ', PRIMARY KEY('.implode(', ', $keyColumns).')'; } $query[] = 'CREATE TABLE ' . $name . ' (' . $queryFields . ')'; if (isset($options['indexes']) && ! empty($options['indexes'])) { foreach ($options['indexes'] as $index => $indexDef) { $query[] = $this->getCreateIndexSQL($indexDef, $name); } } if (isset($options['unique']) && ! empty($options['unique'])) { foreach ($options['unique'] as $index => $indexDef) { $query[] = $this->getCreateIndexSQL($indexDef, $name); } } return $query; } /** * {@inheritDoc} */ protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) { return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') : ($length ? 'VARCHAR(' . $length . ')' : 'TEXT'); } /** * {@inheritDoc} */ public function getClobTypeDeclarationSQL(array $field) { return 'CLOB'; } public function getListTableConstraintsSQL($table) { $table = str_replace(".", "__", $table); return "SELECT sql FROM sqlite_master WHERE type='index' AND tbl_name = '$table' AND sql NOT NULL ORDER BY name"; } public function getListTableColumnsSQL($table, $currentDatabase = null) { $table = str_replace(".", "__", $table); return "PRAGMA table_info($table)"; } /** * {@inheritDoc} */ public function getListTableIndexesSQL($table, $currentDatabase = null) { $table = str_replace(".", "__", $table); return "PRAGMA index_list($table)"; } public function getListTablesSQL() { return "SELECT name FROM sqlite_master WHERE type = 'table' AND name != 'sqlite_sequence' AND name != 'geometry_columns' AND name != 'spatial_ref_sys' " . "UNION ALL SELECT name FROM sqlite_temp_master " . "WHERE type = 'table' ORDER BY name"; } /** * {@inheritDoc} */ public function getListViewsSQL($database) { return "SELECT name, sql FROM sqlite_master WHERE type='view' AND sql NOT NULL"; } public function getCreateViewSQL($name, $sql) { return 'CREATE VIEW ' . $name . ' AS ' . $sql; } public function getDropViewSQL($name) { return 'DROP VIEW '. $name; } /** * {@inheritDoc} * * SQLite does support foreign key constraints, but only in CREATE TABLE statements... * This really limits their usefulness and requires SQLite specific handling, so * we simply say that SQLite does NOT support foreign keys for now... */ public function supportsForeignKeyConstraints() { return false; } /** * {@inheritDoc} */ public function supportsAlterTable() { return false; } /** * {@inheritDoc} */ public function supportsIdentityColumns() { return true; } /** * {@inheritDoc} */ public function getName() { return 'sqlite'; } /** * {@inheritDoc} */ public function getTruncateTableSQL($tableName, $cascade = false) { $tableName = str_replace(".", "__", $tableName); return 'DELETE FROM '.$tableName; } /** * User-defined function for Sqlite that is used with PDO::sqliteCreateFunction() * * @param int|float $value * * @return float */ static public function udfSqrt($value) { return sqrt($value); } /** * User-defined function for Sqlite that implements MOD(a, b) * * @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) { $pos = strpos($str, $substr, $offset); if ($pos !== false) { return $pos+1; } return 0; } 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', 'integer unsigned' => 'integer', ); } /** * {@inheritDoc} */ protected function getReservedKeywordsClass() { return 'Doctrine\DBAL\Platforms\Keywords\SQLiteKeywords'; } /** * {@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; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Platforms/SQLServer2005Platform.php0000644000175100017510000000356412143374463024632 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Platforms; /** * Platform to ensure compatibility of Doctrine with SQLServer2005 version and * higher. * * Differences to SQL Server 2008 are: * * - DATETIME2 datatype does not exist, only DATETIME which has a precision of * 3. This is not supported by PHP DateTime, so we are emulating it by * setting .000 manually. * - Starting with SQLServer2005 VARCHAR(MAX), VARBINARY(MAX) and * NVARCHAR(max) replace the old TEXT, NTEXT and IMAGE types. See * {@link http://www.sql-server-helper.com/faq/sql-server-2005-varchar-max-p01.aspx} * for more information. */ class SQLServer2005Platform extends SQLServerPlatform { /** * {@inheritDoc} */ public function supportsLimitOffset() { return true; } /** * {@inheritDoc} */ public function getClobTypeDeclarationSQL(array $field) { return 'VARCHAR(MAX)'; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Platforms/SQLServer2008Platform.php0000644000175100017510000000522012143374463024624 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Platforms; /** * Platform to ensure compatibility of Doctrine with SQLServer2008 version. * * Differences to SQL Server 2005 and before are that a new DATETIME2 type was * introduced that has a higher precision. */ class SQLServer2008Platform extends SQLServer2005Platform { /** * {@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 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'; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Platforms/SQLServerPlatform.php0000644000175100017510000006044212143374463024321 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\DBALException; 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 */ class SQLServerPlatform extends AbstractPlatform { /** * {@inheritDoc} */ public function getDateDiffExpression($date1, $date2) { return 'DATEDIFF(day, ' . $date2 . ',' . $date1 . ')'; } /** * {@inheritDoc} */ public function getDateAddDaysExpression($date, $days) { return 'DATEADD(day, ' . $days . ', ' . $date . ')'; } /** * {@inheritDoc} */ public function getDateSubDaysExpression($date, $days) { return 'DATEADD(day, -1 * ' . $days . ', ' . $date . ')'; } /** * {@inheritDoc} */ public function getDateAddMonthExpression($date, $months) { return 'DATEADD(month, ' . $months . ', ' . $date . ')'; } /** * {@inheritDoc} */ public function getDateSubMonthExpression($date, $months) { return 'DATEADD(month, -1 * ' . $months . ', ' . $date . ')'; } /** * {@inheritDoc} * * MsSql prefers "autoincrement" identity columns since sequences can only * be emulated with a table. */ public function prefersIdentityColumns() { return true; } /** * {@inheritDoc} * * MsSql supports this through AUTO_INCREMENT columns. */ public function supportsIdentityColumns() { return true; } /** * {@inheritDoc} */ public function supportsReleaseSavepoints() { return false; } /** * {@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 getDropForeignKeySQL($foreignKey, $table) { if ($foreignKey instanceof ForeignKeyConstraint) { $foreignKey = $foreignKey->getQuotedName($this); } if ($table instanceof Table) { $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); } else if (!is_string($index)) { throw new \InvalidArgumentException('AbstractPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.'); } if (!isset($table)) { return 'DROP INDEX ' . $index; } 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()) { // @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; } } $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 $sql; } /** * {@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->getColumns()) . ')'; } /** * {@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 '; } else if ($index->hasFlag('nonclustered')) { $type .= 'NONCLUSTERED '; } return $type; } /** * Extend unique key constraint with required filters * * @param string $sql * @param Index $index * * @return string */ private function _appendUniqueConstraintDefinition($sql, Index $index) { $fields = array(); foreach ($index->getColumns() as $field => $definition) { if (!is_array($definition)) { $field = $definition; } $fields[] = $field . ' IS NOT NULL'; } return $sql . ' WHERE ' . implode(' AND ', $fields); } /** * {@inheritDoc} */ public function getAlterTableSQL(TableDiff $diff) { $queryParts = array(); $sql = array(); $columnSql = array(); foreach ($diff->addedColumns as $column) { if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { continue; } $queryParts[] = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); } foreach ($diff->removedColumns as $column) { if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { continue; } $queryParts[] = 'DROP COLUMN ' . $column->getQuotedName($this); } foreach ($diff->changedColumns as $columnDiff) { if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { continue; } /* @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */ $column = $columnDiff->column; $queryParts[] = 'ALTER COLUMN ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); } foreach ($diff->renamedColumns as $oldColumnName => $column) { if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { continue; } $sql[] = "sp_RENAME '". $diff->name. ".". $oldColumnName . "' , '".$column->getQuotedName($this)."', 'COLUMN'"; $queryParts[] = 'ALTER COLUMN ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); } $tableSql = array(); if ($this->onSchemaAlterTable($diff, $tableSql)) { return array_merge($tableSql, $columnSql); } foreach ($queryParts as $query) { $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query; } $sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff)); if ($diff->newName !== false) { $sql[] = "sp_RENAME '" . $diff->name . "', '" . $diff->newName . "'"; } return array_merge($sql, $tableSql, $columnSql); } /** * {@inheritDoc} */ public function getEmptyIdentityInsertSQL($quotedTableName, $quotedIdentifierColumnName) { return 'INSERT INTO ' . $quotedTableName . ' DEFAULT VALUES'; } /** * {@inheritDoc} */ public function getShowDatabasesSQL() { return 'SHOW DATABASES'; } /** * {@inheritDoc} */ public function getListTablesSQL() { // "sysdiagrams" table must be ignored as it's internal SQL Server table for Database Diagrams return "SELECT name FROM sysobjects WHERE type = 'U' AND name != 'sysdiagrams' ORDER BY name"; } /** * {@inheritDoc} */ public function getListTableColumnsSQL($table, $database = null) { return "exec sp_columns @table_name = '" . $table . "'"; } /** * {@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 OBJECT_NAME (f.parent_object_id) = '" . $table . "'"; } /** * {@inheritDoc} */ public function getListTableIndexesSQL($table, $currentDatabase = null) { return "exec sp_helpindex '" . $table . "'"; } /** * {@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"; } /** * {@inheritDoc} */ public function getDropViewSQL($name) { return 'DROP VIEW ' . $name; } /** * {@inheritDoc} */ public function getRegexpExpression() { return 'RLIKE'; } /** * {@inheritDoc} */ public function getGuidExpression() { return 'UUID()'; } /** * {@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) . ')'; } public function getListDatabasesSQL() { return 'SELECT * FROM SYS.DATABASES'; } /** * {@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} */ public function getClobTypeDeclarationSQL(array $field) { return 'TEXT'; } /** * {@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} * * @link http://lists.bestpractical.com/pipermail/rt-devel/2005-June/007339.html */ protected function doModifyLimitQuery($query, $limit, $offset = null) { if ($limit > 0) { if ($offset == 0) { $query = preg_replace('/^(SELECT\s(DISTINCT\s)?)/i', '\1TOP ' . $limit . ' ', $query); } else { $orderby = stristr($query, 'ORDER BY'); if ( ! $orderby) { $over = 'ORDER BY (SELECT 0)'; } else { $over = preg_replace('/\"[^,]*\".\"([^,]*)\"/i', '"inner_tbl"."$1"', $orderby); } // Remove ORDER BY clause from $query $query = preg_replace('/\s+ORDER BY(.*)/', '', $query); $query = preg_replace('/\sFROM/i', ", ROW_NUMBER() OVER ($over) AS doctrine_rownum FROM", $query); $start = $offset + 1; $end = $offset + $limit; $query = "SELECT * FROM ($query) AS doctrine_tbl WHERE doctrine_rownum BETWEEN $start AND $end"; } } return $query; } /** * {@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; } } } else if (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', 'datetimeoffset' => 'datetimetz', 'smalldatetime' => 'datetime', 'datetime' => 'datetime', 'char' => 'string', 'varchar' => 'string', 'text' => 'text', 'nchar' => 'string', 'nvarchar' => 'string', 'ntext' => 'text', 'binary' => 'text', 'varbinary' => 'blob', 'image' => 'text', '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 appendLockHint($fromClause, $lockMode) { // @todo coorect if ($lockMode == \Doctrine\DBAL\LockMode::PESSIMISTIC_READ) { return $fromClause . ' WITH (tablockx)'; } if ($lockMode == \Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE) { return $fromClause . ' WITH (tablockx)'; } return $fromClause; } /** * {@inheritDoc} */ public function getForUpdateSQL() { return ' '; } /** * {@inheritDoc} */ protected function getReservedKeywordsClass() { return 'Doctrine\DBAL\Platforms\Keywords\MsSQLKeywords'; } /** * {@inheritDoc} */ public function quoteSingleIdentifier($str) { return "[" . str_replace("]", "][", $str) . "]"; } /** * {@inheritDoc} */ public function getTruncateTableSQL($tableName, $cascade = false) { return 'TRUNCATE TABLE '.$tableName; } /** * {@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', 'BigInteger', 'SmallInteger'))) { return " DEFAULT " . $field['default']; } if ((string) $field['type'] == 'DateTime' && $field['default'] == $this->getCurrentTimestampSQL()) { return " DEFAULT " . $this->getCurrentTimestampSQL(); } if ((string) $field['type'] == 'Boolean') { return " DEFAULT '" . $this->convertBooleans($field['default']) . "'"; } return " DEFAULT '" . $field['default'] . "'"; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Platforms/Keywords/DB2Keywords.php0000644000175100017510000002434212143374463024673 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * DB2 Keywords * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 2.0 * @author Benjamin Eberlei */ class DB2Keywords extends KeywordList { public function getName() { return 'DB2'; } protected function getKeywords() { return array( 'ACTIVATE', 'ADD', 'AFTER', 'ALIAS', 'ALL', 'ALLOCATE', 'DOCUMENT', 'DOUBLE', 'DROP', 'DSSIZE', 'DYNAMIC', 'EACH', 'LOCK', 'LOCKMAX', 'LOCKSIZE', 'LONG', 'LOOP', 'MAINTAINED', 'ROUND_CEILING', 'ROUND_DOWN', 'ROUND_FLOOR', 'ROUND_HALF_DOWN', 'ROUND_HALF_EVEN', 'ROUND_HALF_UP', 'ALLOW', 'ALTER', 'AND', 'ANY', 'AS', 'ASENSITIVE', 'ASSOCIATE', 'ASUTIME', 'AT', 'ATTRIBUTES', 'AUDIT', 'AUTHORIZATION', 'AUX', 'AUXILIARY', 'BEFORE', 'BEGIN', 'BETWEEN', 'BINARY', 'BUFFERPOOL', 'BY', 'CACHE', 'CALL', 'CALLED', 'CAPTURE', 'CARDINALITY', 'CASCADED', 'CASE', 'CAST', 'CCSID', 'CHAR', 'CHARACTER', 'CHECK', 'CLONE', 'CLOSE', 'CLUSTER', 'COLLECTION', 'COLLID', 'COLUMN', 'COMMENT', 'COMMIT', 'CONCAT', 'CONDITION', 'CONNECT', 'CONNECTION', 'CONSTRAINT', 'CONTAINS', 'CONTINUE', 'COUNT', 'COUNT_BIG', 'CREATE', 'CROSS', 'CURRENT', 'CURRENT_DATE', 'CURRENT_LC_CTYPE', 'CURRENT_PATH', 'CURRENT_SCHEMA', 'CURRENT_SERVER', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURRENT_TIMEZONE', 'CURRENT_USER', 'CURSOR', 'CYCLE', 'DATA', 'DATABASE', 'DATAPARTITIONNAME', 'DATAPARTITIONNUM', 'EDITPROC', 'ELSE', 'ELSEIF', 'ENABLE', 'ENCODING', 'ENCRYPTION', 'END', 'END-EXEC', 'ENDING', 'ERASE', 'ESCAPE', 'EVERY', 'EXCEPT', 'EXCEPTION', 'EXCLUDING', 'EXCLUSIVE', 'EXECUTE', 'EXISTS', 'EXIT', 'EXPLAIN', 'EXTERNAL', 'EXTRACT', 'FENCED', 'FETCH', 'FIELDPROC', 'FILE', 'FINAL', 'FOR', 'FOREIGN', 'FREE', 'FROM', 'FULL', 'FUNCTION', 'GENERAL', 'GENERATED', 'GET', 'GLOBAL', 'GO', 'GOTO', 'GRANT', 'GRAPHIC', 'GROUP', 'HANDLER', 'HASH', 'HASHED_VALUE', 'HAVING', 'HINT', 'HOLD', 'HOUR', 'HOURS', 'IDENTITY', 'IF', 'IMMEDIATE', 'IN', 'INCLUDING', 'INCLUSIVE', 'INCREMENT', 'INDEX', 'INDICATOR', 'INF', 'INFINITY', 'INHERIT', 'INNER', 'INOUT', 'INSENSITIVE', 'INSERT', 'INTEGRITY', 'MATERIALIZED', 'MAXVALUE', 'MICROSECOND', 'MICROSECONDS', 'MINUTE', 'MINUTES', 'MINVALUE', 'MODE', 'MODIFIES', 'MONTH', 'MONTHS', 'NAN', 'NEW', 'NEW_TABLE', 'NEXTVAL', 'NO', 'NOCACHE', 'NOCYCLE', 'NODENAME', 'NODENUMBER', 'NOMAXVALUE', 'NOMINVALUE', 'NONE', 'NOORDER', 'NORMALIZED', 'NOT', 'NULL', 'NULLS', 'NUMPARTS', 'OBID', 'OF', 'OLD', 'OLD_TABLE', 'ON', 'OPEN', 'OPTIMIZATION', 'OPTIMIZE', 'OPTION', 'OR', 'ORDER', 'OUT', 'OUTER', 'OVER', 'OVERRIDING', 'PACKAGE', 'PADDED', 'PAGESIZE', 'PARAMETER', 'PART', 'PARTITION', 'PARTITIONED', 'PARTITIONING', 'PARTITIONS', 'PASSWORD', 'PATH', 'PIECESIZE', 'PLAN', 'POSITION', 'PRECISION', 'PREPARE', 'PREVVAL', 'PRIMARY', 'PRIQTY', 'PRIVILEGES', 'PROCEDURE', 'PROGRAM', 'PSID', 'ROUND_UP', 'ROUTINE', 'ROW', 'ROW_NUMBER', 'ROWNUMBER', 'ROWS', 'ROWSET', 'RRN', 'RUN', 'SAVEPOINT', 'SCHEMA', 'SCRATCHPAD', 'SCROLL', 'SEARCH', 'SECOND', 'SECONDS', 'SECQTY', 'SECURITY', 'SELECT', 'SENSITIVE', 'SEQUENCE', 'SESSION', 'SESSION_USER', 'SET', 'SIGNAL', 'SIMPLE', 'SNAN', 'SOME', 'SOURCE', 'SPECIFIC', 'SQL', 'SQLID', 'STACKED', 'STANDARD', 'START', 'STARTING', 'STATEMENT', 'STATIC', 'STATMENT', 'STAY', 'STOGROUP', 'STORES', 'STYLE', 'SUBSTRING', 'SUMMARY', 'SYNONYM', 'SYSFUN', 'SYSIBM', 'SYSPROC', 'SYSTEM', 'SYSTEM_USER', 'TABLE', 'TABLESPACE', 'THEN', 'TIME', 'TIMESTAMP', 'TO', 'TRANSACTION', 'TRIGGER', 'TRIM', 'TRUNCATE', 'TYPE', 'UNDO', 'UNION', 'UNIQUE', 'UNTIL', 'UPDATE', 'DATE', 'DAY', 'DAYS', 'DB2GENERAL', 'DB2GENRL', 'DB2SQL', 'DBINFO', 'DBPARTITIONNAME', 'DBPARTITIONNUM', 'DEALLOCATE', 'DECLARE', 'DEFAULT', 'DEFAULTS', 'DEFINITION', 'DELETE', 'DENSE_RANK', 'DENSERANK', 'DESCRIBE', 'DESCRIPTOR', 'DETERMINISTIC', 'DIAGNOSTICS', 'DISABLE', 'DISALLOW', 'DISCONNECT', 'DISTINCT', 'DO', 'INTERSECT', 'PUBLIC', 'USAGE', 'INTO', 'QUERY', 'USER', 'IS', 'QUERYNO', 'USING', 'ISOBID', 'RANGE', 'VALIDPROC', 'ISOLATION', 'RANK', 'VALUE', 'ITERATE', 'READ', 'VALUES', 'JAR', 'READS', 'VARIABLE', 'JAVA', 'RECOVERY', 'VARIANT', 'JOIN', 'REFERENCES', 'VCAT', 'KEEP', 'REFERENCING', 'VERSION', 'KEY', 'REFRESH', 'VIEW', 'LABEL', 'RELEASE', 'VOLATILE', 'LANGUAGE', 'RENAME', 'VOLUMES', 'LATERAL', 'REPEAT', 'WHEN', 'LC_CTYPE', 'RESET', 'WHENEVER', 'LEAVE', 'RESIGNAL', 'WHERE', 'LEFT', 'RESTART', 'WHILE', 'LIKE', 'RESTRICT', 'WITH', 'LINKTYPE', 'RESULT', 'WITHOUT', 'LOCAL', 'RESULT_SET_LOCATOR WLM', 'LOCALDATE', 'RETURN', 'WRITE', 'LOCALE', 'RETURNS', 'XMLELEMENT', 'LOCALTIME', 'REVOKE', 'XMLEXISTS', 'LOCALTIMESTAMP RIGHT', 'XMLNAMESPACES', 'LOCATOR', 'ROLE', 'YEAR', 'LOCATORS', 'ROLLBACK', 'YEARS', ); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Platforms/Keywords/DrizzleKeywords.php0000644000175100017510000001776312143374463025760 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * Drizzle Keywordlist * * @author Kim Hemsø Rasmussen */ class DrizzleKeywords extends KeywordList { public function getName() { return 'drizzle'; } 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', ); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Platforms/Keywords/KeywordList.php0000644000175100017510000000373712143374463025061 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * Abstract interface for a SQL reserved keyword dictionary. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 2.0 * @author Benjamin Eberlei */ abstract class KeywordList { private $keywords = null; /** * Check if the given word is a keyword of this dialect/vendor platform. * * @param string $word * @return bool */ public function isKeyword($word) { if ($this->keywords === null) { $this->initializeKeywords(); } return isset($this->keywords[strtoupper($word)]); } protected function initializeKeywords() { $this->keywords = array_flip(array_map('strtoupper', $this->getKeywords())); } abstract protected function getKeywords(); /** * Name of this keyword list. * * @return string */ abstract public function getName(); } DoctrineDBAL-2.3.4/Doctrine/DBAL/Platforms/Keywords/MsSQLKeywords.php0000644000175100017510000001346512143374463025267 0ustar beberleibeberlei. */ 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 */ class MsSQLKeywords extends KeywordList { public function getName() { return 'MsSQL'; } protected function getKeywords() { return array( 'ADD', 'CURRENT_TIMESTAMP', 'GROUP', 'OPENQUERY', 'SERIALIZABLE', 'ALL', 'CURRENT_USER', 'HAVING', 'OPENROWSET', 'SESSION_USER', 'ALTER', 'CURSOR', 'HOLDLOCK', 'OPTION', 'SET', 'AND', 'DATABASE', 'IDENTITY', 'OR', 'SETUSER', 'ANY', 'DBCC', 'IDENTITYCOL', 'ORDER', 'SHUTDOWN', 'AS', 'DEALLOCATE', 'IDENTITY_INSERT', 'OUTER', 'SOME', 'ASC', 'DECLARE', 'IF', 'OVER', 'STATISTICS', 'AUTHORIZATION', 'DEFAULT', 'IN', 'PERCENT', 'SUM', 'AVG', 'DELETE', 'INDEX', 'PERM', 'SYSTEM_USER', 'BACKUP', 'DENY', 'INNER', 'PERMANENT', 'TABLE', 'BEGIN', 'DESC', 'INSERT', 'PIPE', 'TAPE', 'BETWEEN', 'DISK', 'INTERSECT', 'PLAN', 'TEMP', 'BREAK', 'DISTINCT', 'INTO', 'PRECISION', 'TEMPORARY', 'BROWSE', 'DISTRIBUTED', 'IS', 'PREPARE', 'TEXTSIZE', 'BULK', 'DOUBLE', 'ISOLATION', 'PRIMARY', 'THEN', 'BY', 'DROP', 'JOIN', 'PRINT', 'TO', 'CASCADE', 'DUMMY', 'KEY', 'PRIVILEGES', 'TOP', 'CASE', 'DUMP', 'KILL', 'PROC', 'TRAN', 'CHECK', 'ELSE', 'LEFT', 'PROCEDURE', 'TRANSACTION', 'CHECKPOINT', 'END', 'LEVEL', 'PROCESSEXIT', 'TRIGGER', 'CLOSE', 'ERRLVL', 'LIKE', 'PUBLIC', 'TRUNCATE', 'CLUSTERED', 'ERROREXIT', 'LINENO', 'RAISERROR', 'TSEQUAL', 'COALESCE', 'ESCAPE', 'LOAD', 'READ', 'UNCOMMITTED', 'COLUMN', 'EXCEPT', 'MAX', 'READTEXT', 'UNION', 'COMMIT', 'EXEC', 'MIN', 'RECONFIGURE', 'UNIQUE', 'COMMITTED', 'EXECUTE', 'MIRROREXIT', 'REFERENCES', 'UPDATE', 'COMPUTE', 'EXISTS', 'NATIONAL', 'REPEATABLE', 'UPDATETEXT', 'CONFIRM', 'EXIT', 'NOCHECK', 'REPLICATION', 'USE', 'CONSTRAINT', 'FETCH', 'NONCLUSTERED', 'RESTORE', 'USER', 'CONTAINS', 'FILE', 'NOT', 'RESTRICT', 'VALUES', 'CONTAINSTABLE', 'FILLFACTOR', 'NULL', 'RETURN', 'VARYING', 'CONTINUE', 'FLOPPY', 'NULLIF', 'REVOKE', 'VIEW', 'CONTROLROW', 'FOR', 'OF', 'RIGHT', 'WAITFOR', 'CONVERT', 'FOREIGN', 'OFF', 'ROLLBACK', 'WHEN', 'COUNT', 'FREETEXT', 'OFFSETS', 'ROWCOUNT', 'WHERE', 'CREATE', 'FREETEXTTABLE', 'ON', 'ROWGUIDCOL', 'WHILE', 'CROSS', 'FROM', 'ONCE', 'RULE', 'WITH', 'CURRENT', 'FULL', 'ONLY', 'SAVE', 'WORK', 'CURRENT_DATE', 'GOTO', 'OPEN', 'SCHEMA', 'WRITETEXT', 'CURRENT_TIME', 'GRANT', 'OPENDATASOURCE', 'SELECT', ); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Platforms/Keywords/MySQLKeywords.php0000644000175100017510000001471412143374463025273 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * MySQL Keywordlist * * @license BSD http://www.opensource.org/licenses/bsd-license.php * @link www.doctrine-project.com * @since 2.0 * @author Benjamin Eberlei * @author David Coallier */ class MySQLKeywords extends KeywordList { public function getName() { return 'MySQL'; } protected function getKeywords() { return array( 'ADD', 'ALL', 'ALTER', 'ANALYZE', 'AND', 'AS', 'ASC', 'ASENSITIVE', 'BEFORE', 'BETWEEN', 'BIGINT', 'BINARY', 'BLOB', 'BOTH', 'BY', 'CALL', 'CASCADE', 'CASE', 'CHANGE', 'CHAR', 'CHARACTER', 'CHECK', 'COLLATE', 'COLUMN', 'CONDITION', 'CONNECTION', 'CONSTRAINT', 'CONTINUE', 'CONVERT', 'CREATE', 'CROSS', 'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURRENT_USER', 'CURSOR', 'DATABASE', 'DATABASES', 'DAY_HOUR', 'DAY_MICROSECOND', 'DAY_MINUTE', 'DAY_SECOND', 'DEC', 'DECIMAL', 'DECLARE', 'DEFAULT', 'DELAYED', 'DELETE', 'DESC', 'DESCRIBE', 'DETERMINISTIC', 'DISTINCT', 'DISTINCTROW', 'DIV', 'DOUBLE', 'DROP', 'DUAL', 'EACH', 'ELSE', 'ELSEIF', 'ENCLOSED', 'ESCAPED', 'EXISTS', 'EXIT', 'EXPLAIN', 'FALSE', 'FETCH', 'FLOAT', 'FLOAT4', 'FLOAT8', 'FOR', 'FORCE', 'FOREIGN', 'FROM', 'FULLTEXT', 'GOTO', 'GRANT', 'GROUP', 'HAVING', 'HIGH_PRIORITY', 'HOUR_MICROSECOND', 'HOUR_MINUTE', 'HOUR_SECOND', 'IF', 'IGNORE', 'IN', 'INDEX', 'INFILE', 'INNER', 'INOUT', 'INSENSITIVE', 'INSERT', 'INT', 'INT1', 'INT2', 'INT3', 'INT4', 'INT8', 'INTEGER', 'INTERVAL', 'INTO', 'IS', 'ITERATE', 'JOIN', 'KEY', 'KEYS', 'KILL', 'LABEL', 'LEADING', 'LEAVE', 'LEFT', 'LIKE', 'LIMIT', 'LINES', 'LOAD', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCK', 'LONG', 'LONGBLOB', 'LONGTEXT', 'LOOP', 'LOW_PRIORITY', 'MATCH', 'MEDIUMBLOB', 'MEDIUMINT', 'MEDIUMTEXT', 'MIDDLEINT', 'MINUTE_MICROSECOND', 'MINUTE_SECOND', 'MOD', 'MODIFIES', 'NATURAL', 'NOT', 'NO_WRITE_TO_BINLOG', 'NULL', 'NUMERIC', 'ON', 'OPTIMIZE', 'OPTION', 'OPTIONALLY', 'OR', 'ORDER', 'OUT', 'OUTER', 'OUTFILE', 'PRECISION', 'PRIMARY', 'PROCEDURE', 'PURGE', 'RAID0', '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', ); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Platforms/Keywords/OracleKeywords.php0000644000175100017510000000753312143374463025534 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * Oracle Keywordlist * * @license BSD http://www.opensource.org/licenses/bsd-license.php * @link www.doctrine-project.com * @since 2.0 * @author Benjamin Eberlei * @author David Coallier */ class OracleKeywords extends KeywordList { public function getName() { return 'Oracle'; } protected function getKeywords() { return array( 'ACCESS', 'ELSE', 'MODIFY', 'START', 'ADD', 'EXCLUSIVE', 'NOAUDIT', 'SELECT', 'ALL', 'EXISTS', 'NOCOMPRESS', 'SESSION', 'ALTER', 'FILE', 'NOT', 'SET', 'AND', 'FLOAT', 'NOTFOUND ', 'SHARE', 'ANY', 'FOR', 'NOWAIT', 'SIZE', 'ARRAYLEN', 'FROM', 'NULL', 'SMALLINT', 'AS', 'GRANT', 'NUMBER', 'SQLBUF', 'ASC', 'GROUP', 'OF', 'SUCCESSFUL', 'AUDIT', 'HAVING', 'OFFLINE ', 'SYNONYM', 'BETWEEN', 'IDENTIFIED', 'ON', 'SYSDATE', 'BY', 'IMMEDIATE', 'ONLINE', 'TABLE', 'CHAR', 'IN', 'OPTION', 'THEN', 'CHECK', 'INCREMENT', 'OR', 'TO', 'CLUSTER', 'INDEX', 'ORDER', 'TRIGGER', 'COLUMN', 'INITIAL', 'PCTFREE', 'UID', 'COMMENT', 'INSERT', 'PRIOR', 'UNION', 'COMPRESS', 'INTEGER', 'PRIVILEGES', 'UNIQUE', 'CONNECT', 'INTERSECT', 'PUBLIC', 'UPDATE', 'CREATE', 'INTO', 'RAW', 'USER', 'CURRENT', 'IS', 'RENAME', 'VALIDATE', 'DATE', 'LEVEL', 'RESOURCE', 'VALUES', 'DECIMAL', 'LIKE', 'REVOKE', 'VARCHAR', 'DEFAULT', 'LOCK', 'ROW', 'VARCHAR2', 'DELETE', 'LONG', 'ROWID', 'VIEW', 'DESC', 'MAXEXTENTS', 'ROWLABEL', 'WHENEVER', 'DISTINCT', 'MINUS', 'ROWNUM', 'WHERE', 'DROP', 'MODE', 'ROWS', 'WITH', 'RANGE', ); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Platforms/Keywords/PostgreSQLKeywords.php0000644000175100017510000000652712143374463026334 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * PostgreSQL Keywordlist * * @license BSD http://www.opensource.org/licenses/bsd-license.php * @link www.doctrine-project.com * @since 2.0 * @author Benjamin Eberlei * @author Marcelo Santos Araujo */ class PostgreSQLKeywords extends KeywordList { public function getName() { return 'PostgreSQL'; } protected function getKeywords() { return array( 'ALL', 'ANALYSE', 'ANALYZE', 'AND', 'ANY', 'AS', 'ASC', 'AUTHORIZATION', 'BETWEEN', 'BINARY', 'BOTH', 'CASE', 'CAST', 'CHECK', 'COLLATE', 'COLUMN', 'CONSTRAINT', 'CREATE', 'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURRENT_USER', 'DEFAULT', 'DEFERRABLE', 'DESC', 'DISTINCT', 'DO', 'ELSE', 'END', 'EXCEPT', 'FALSE', 'FOR', 'FOREIGN', 'FREEZE', 'FROM', 'FULL', 'GRANT', 'GROUP', 'HAVING', 'ILIKE', 'IN', 'INITIALLY', 'INNER', 'INTERSECT', 'INTO', 'IS', 'ISNULL', 'JOIN', 'LEADING', 'LEFT', 'LIKE', 'LIMIT', 'LOCALTIME', 'LOCALTIMESTAMP', 'NATURAL', 'NEW', 'NOT', 'NOTNULL', 'NULL', 'OFF', 'OFFSET', 'OLD', 'ON', 'ONLY', 'OR', 'ORDER', 'OUTER', 'OVERLAPS', 'PLACING', 'PRIMARY', 'REFERENCES', 'SELECT', 'SESSION_USER', 'SIMILAR', 'SOME', 'TABLE', 'THEN', 'TO', 'TRAILING', 'TRUE', 'UNION', 'UNIQUE', 'USER', 'USING', 'VERBOSE', 'WHEN', 'WHERE' ); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Platforms/Keywords/ReservedKeywordsValidator.php0000644000175100017510000000611212143374463027744 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Platforms\Keywords; use Doctrine\DBAL\Schema\Visitor\Visitor; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\Sequence; use Doctrine\DBAL\Schema\Index; class ReservedKeywordsValidator implements Visitor { /** * @var KeywordList[] */ private $keywordLists = array(); /** * @var array */ private $violations = array(); public function __construct(array $keywordLists) { $this->keywordLists = $keywordLists; } public function getViolations() { return $this->violations; } /** * @param string $word * @return array */ private function isReservedWord($word) { if ($word[0] == "`") { $word = str_replace('`', '', $word); } $keywordLists = array(); foreach ($this->keywordLists as $keywordList) { if ($keywordList->isKeyword($word)) { $keywordLists[] = $keywordList->getName(); } } return $keywordLists; } private function addViolation($asset, $violatedPlatforms) { if ( ! $violatedPlatforms) { return; } $this->violations[] = $asset . ' keyword violations: ' . implode(', ', $violatedPlatforms); } public function acceptColumn(Table $table, Column $column) { $this->addViolation( 'Table ' . $table->getName() . ' column ' . $column->getName(), $this->isReservedWord($column->getName()) ); } public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) { } public function acceptIndex(Table $table, Index $index) { } public function acceptSchema(Schema $schema) { } public function acceptSequence(Sequence $sequence) { } public function acceptTable(Table $table) { $this->addViolation( 'Table ' . $table->getName(), $this->isReservedWord($table->getName()) ); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Platforms/Keywords/SQLiteKeywords.php0000644000175100017510000000775212143374463025473 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Platforms\Keywords; /** * SQLite Keywords * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 2.0 * @author Benjamin Eberlei */ class SQLiteKeywords extends KeywordList { public function getName() { return 'SQLite'; } protected function getKeywords() { return array( 'ABORT', 'ACTION', 'ADD', 'AFTER', 'ALL', 'ALTER', 'ANALYZE', 'AND', 'AS', 'ASC', 'ATTACH', 'AUTOINCREMENT', 'BEFORE', 'BEGIN', 'BETWEEN', 'BY', 'CASCADE', 'CASE', 'CAST', 'CHECK', 'COLLATE', 'COLUMN', 'COMMIT', 'CONFLICT', 'CONSTRAINT', 'CREATE', 'CROSS', 'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'DATABASE', 'DEFAULT', 'DEFERRABLE', 'DEFERRED', 'DELETE', 'DESC', 'DETACH', 'DISTINCT', 'DROP', 'EACH', 'ELSE', 'END', 'ESCAPE', 'EXCEPT', 'EXCLUSIVE', 'EXISTS', 'EXPLAIN', 'FAIL', 'FOR', 'FOREIGN', 'FROM', 'FULL', 'GLOB', 'GROUP', 'HAVING', 'IF', 'IGNORE', 'IMMEDIATE', 'IN', 'INDEX', 'INDEXED', 'INITIALLY', 'INNER', 'INSERT', 'INSTEAD', 'INTERSECT', 'INTO', 'IS', 'ISNULL', 'JOIN', 'KEY', 'LEFT', 'LIKE', 'LIMIT', 'MATCH', 'NATURAL', 'NO', 'NOT', 'NOTNULL', 'NULL', 'OF', 'OFFSET', 'ON', 'OR', 'ORDER', 'OUTER', 'PLAN', 'PRAGMA', 'PRIMARY', 'QUERY', 'RAISE', 'REFERENCES', 'REGEXP', 'REINDEX', 'RELEASE', 'RENAME', 'REPLACE', 'RESTRICT', 'RIGHT', 'ROLLBACK', 'ROW', 'SAVEPOINT', 'SELECT', 'SET', 'TABLE', 'TEMP', 'TEMPORARY', 'THEN', 'TO', 'TRANSACTION', 'TRIGGER', 'UNION', 'UNIQUE', 'UPDATE', 'USING', 'VACUUM', 'VALUES', 'VIEW', 'VIRTUAL', 'WHEN', 'WHERE' ); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Portability/Connection.php0000644000175100017510000001062212143374463023413 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Portability; use Doctrine\Common\EventManager; use Doctrine\DBAL\Configuration; use Doctrine\DBAL\Driver; use Doctrine\DBAL\Cache\QueryCacheProfile; class Connection extends \Doctrine\DBAL\Connection { const PORTABILITY_ALL = 255; const PORTABILITY_NONE = 0; const PORTABILITY_RTRIM = 1; const PORTABILITY_EMPTY_TO_NULL = 4; const PORTABILITY_FIX_CASE = 8; const PORTABILITY_ORACLE = 9; const PORTABILITY_POSTGRESQL = 13; const PORTABILITY_SQLITE = 13; const PORTABILITY_OTHERVENDORS = 12; const PORTABILITY_DRIZZLE = 13; const PORTABILITY_SQLSRV = 13; /** * @var int */ private $portability = self::PORTABILITY_NONE; /** * @var int */ private $case; public function connect() { $ret = parent::connect(); if ($ret) { $params = $this->getParams(); if (isset($params['portability'])) { if ($this->_platform->getName() === "oracle") { $params['portability'] = $params['portability'] & self::PORTABILITY_ORACLE; } else if ($this->_platform->getName() === "postgresql") { $params['portability'] = $params['portability'] & self::PORTABILITY_POSTGRESQL; } else if ($this->_platform->getName() === "sqlite") { $params['portability'] = $params['portability'] & self::PORTABILITY_SQLITE; } else if ($this->_platform->getName() === "drizzle") { $params['portability'] = self::PORTABILITY_DRIZZLE; } else if ($this->_platform->getName() === 'sqlsrv') { $params['portability'] = $params['portabililty'] & 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; } public function getPortability() { return $this->portability; } public function getFetchCase() { return $this->case; } public function executeQuery($query, array $params = array(), $types = array(), QueryCacheProfile $qcp = null) { return new Statement(parent::executeQuery($query, $params, $types, $qcp), $this); } /** * Prepares an SQL statement. * * @param string $statement The SQL statement to prepare. * @return \Doctrine\DBAL\Driver\Statement The prepared statement. */ public function prepare($statement) { return new Statement(parent::prepare($statement), $this); } public function query() { $this->connect(); $stmt = call_user_func_array(array($this->_conn, 'query'), func_get_args()); return new Statement($stmt, $this); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Portability/Statement.php0000644000175100017510000001306012143374463023257 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Portability; use PDO; /** * Portability Wrapper for a Statement * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 2.0 * @author Benjamin Eberlei */ class Statement implements \IteratorAggregate, \Doctrine\DBAL\Driver\Statement { /** * @var int */ private $portability; /** * @var \Doctrine\DBAL\Driver\Statement */ private $stmt; /** * @var int */ private $case; /** * @var int */ private $defaultFetchMode = PDO::FETCH_BOTH; /** * Wraps Statement and applies portability measures * * @param \Doctrine\DBAL\Driver\Statement $stmt * @param \Doctrine\DBAL\Connection $conn */ public function __construct($stmt, Connection $conn) { $this->stmt = $stmt; $this->portability = $conn->getPortability(); $this->case = $conn->getFetchCase(); } public function bindParam($column, &$variable, $type = null,$length = null) { return $this->stmt->bindParam($column, $variable, $type); } public function bindValue($param, $value, $type = null) { return $this->stmt->bindValue($param, $value, $type); } public function closeCursor() { return $this->stmt->closeCursor(); } public function columnCount() { return $this->stmt->columnCount(); } public function errorCode() { return $this->stmt->errorCode(); } public function errorInfo() { return $this->stmt->errorInfo(); } public function execute($params = null) { return $this->stmt->execute($params); } public function setFetchMode($fetchMode, $arg1 = null, $arg2 = null) { $this->defaultFetchMode = $fetchMode; $this->stmt->setFetchMode($fetchMode, $arg1, $arg2); } public function getIterator() { $data = $this->fetchAll(); return new \ArrayIterator($data); } 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; } 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; } foreach ($rows as $num => $row) { $rows[$num] = $this->fixRow($row, $iterateRow, $fixCase); } return $rows; } protected function fixRow($row, $iterateRow, $fixCase) { if ( ! $row) { return $row; } if ($fixCase) { $row = array_change_key_case($row, $this->case); } if ($iterateRow) { foreach ($row as $k => $v) { if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) && $v === '') { $row[$k] = null; } else if (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($v)) { $row[$k] = rtrim($v); } } } return $row; } public function fetchColumn($columnIndex = 0) { $value = $this->stmt->fetchColumn($columnIndex); if ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) { if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) && $value === '') { $value = null; } else if (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($value)) { $value = rtrim($value); } } return $value; } public function rowCount() { return $this->stmt->rowCount(); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Query/QueryBuilder.php0000644000175100017510000010224012143374463022531 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Query; use Doctrine\DBAL\Query\Expression\CompositeExpression, 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. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 2.1 * @author Guilherme Blanco * @author Benjamin Eberlei */ class QueryBuilder { /* The query types. */ const SELECT = 0; const DELETE = 1; const UPDATE = 2; /** The builder states. */ const STATE_DIRTY = 0; const STATE_CLEAN = 1; /** * @var Doctrine\DBAL\Connection DBAL Connection */ private $connection = null; /** * @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() ); /** * @var string The complete SQL string for this query. */ private $sql; /** * @var array The query parameters. */ private $params = array(); /** * @var array The parameter type map of this query. */ private $paramTypes = array(); /** * @var integer The type of query this is. Can be select, update or delete. */ private $type = self::SELECT; /** * @var integer The state of the query object. Can be dirty or clean. */ private $state = self::STATE_CLEAN; /** * @var integer The index of the first result to retrieve. */ private $firstResult = null; /** * @var integer The maximum number of results to retrieve. */ private $maxResults = null; /** * The counter of bound parameters used with {@see bindValue) * * @var int */ private $boundCounter = 0; /** * Initializes a new QueryBuilder. * * @param \Doctrine\DBAL\Connection $connection 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(); } /** * Get the type of the currently built query. * * @return integer */ public function getType() { return $this->type; } /** * Get the associated DBAL Connection for this query builder. * * @return \Doctrine\DBAL\Connection */ public function getConnection() { return $this->connection; } /** * Get the state of this query builder instance. * * @return integer Either QueryBuilder::STATE_DIRTY or QueryBuilder::STATE_CLEAN. */ public function getState() { return $this->state; } /** * Execute 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 mixed */ 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); } } /** * Get 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; } $sql = ''; switch ($this->type) { 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 PDO::PARAM_* * @return QueryBuilder 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 QueryBuilder 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. * * @return array The currently defined query parameters. */ 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; } /** * Sets the position of the first result to retrieve (the "offset"). * * @param integer $firstResult The first result to return. * @return \Doctrine\DBAL\Query\QueryBuilder 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 \Doctrine\DBAL\Query\QueryBuilder 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 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 \Doctrine\DBAL\Query\QueryBuilder 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; } } else if ($isArray && is_array($sqlPart[key($sqlPart)])) { $key = key($sqlPart); $this->sqlParts[$sqlPartName][$key][] = $sqlPart[$key]; } else if ($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 QueryBuilder 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 QueryBuilder 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 QueryBuilder 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 QueryBuilder 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 )); } /** * Create and add 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 $alias The alias of the table * @return QueryBuilder This QueryBuilder instance. */ public function from($from, $alias) { 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 QueryBuilder 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 QueryBuilder 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 QueryBuilder 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 QueryBuilder 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 QueryBuilder 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 QueryBuilder 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 QueryBuilder This QueryBuilder instance. * @see where() */ public function andWhere($where) { $where = $this->getQueryPart('where'); $args = func_get_args(); 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 QueryBuilder $qb * @see where() */ public function orWhere($where) { $where = $this->getQueryPart('where'); $args = func_get_args(); 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 QueryBuilder 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 QueryBuilder 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); } /** * 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 QueryBuilder 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 QueryBuilder This QueryBuilder instance. */ public function andHaving($having) { $having = $this->getQueryPart('having'); $args = func_get_args(); 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 QueryBuilder This QueryBuilder instance. */ public function orHaving($having) { $having = $this->getQueryPart('having'); $args = func_get_args(); 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 QueryBuilder 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 QueryBuilder This QueryBuilder instance. */ public function addOrderBy($sort, $order = null) { return $this->add('orderBy', $sort . ' ' . (! $order ? 'ASC' : $order), true); } /** * Get a query part by its name. * * @param string $queryPartName * @return mixed $queryPart */ public function getQueryPart($queryPartName) { return $this->sqlParts[$queryPartName]; } /** * Get all query parts. * * @return array $sqlParts */ public function getQueryParts() { return $this->sqlParts; } /** * Reset SQL parts * * @param array $queryPartNames * @return QueryBuilder */ public function resetQueryParts($queryPartNames = null) { if (is_null($queryPartNames)) { $queryPartNames = array_keys($this->sqlParts); } foreach ($queryPartNames as $queryPartName) { $this->resetQueryPart($queryPartName); } return $this; } /** * Reset single SQL part * * @param string $queryPartName * @return QueryBuilder */ public function resetQueryPart($queryPartName) { $this->sqlParts[$queryPartName] = is_array($this->sqlParts[$queryPartName]) ? array() : null; $this->state = self::STATE_DIRTY; return $this; } private function getSQLForSelect() { $query = 'SELECT ' . implode(', ', $this->sqlParts['select']) . ' FROM '; $fromClauses = array(); $joinsPending = true; $joinAliases = array(); // Loop through all FROM clauses foreach ($this->sqlParts['from'] as $from) { $fromClause = $from['table'] . ' ' . $from['alias']; if ($joinsPending && isset($this->sqlParts['join'][$from['alias']])) { foreach ($this->sqlParts['join'] as $joins) { foreach ($joins as $join) { $fromClause .= ' ' . strtoupper($join['joinType']) . ' JOIN ' . $join['joinTable'] . ' ' . $join['joinAlias'] . ' ON ' . ((string) $join['joinCondition']); $joinAliases[$join['joinAlias']] = true; } } $joinsPending = false; } $fromClauses[$from['alias']] = $fromClause; } // loop through all JOIN clauses for validation purpose $knownAliases = array_merge($fromClauses,$joinAliases); foreach ($this->sqlParts['join'] as $fromAlias => $joins) { if ( ! isset($knownAliases[$fromAlias]) ) { throw QueryException::unknownAlias($fromAlias, array_keys($knownAliases)); } } $query .= implode(', ', $fromClauses) . ($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']) : ''); return ($this->maxResults === null && $this->firstResult == null) ? $query : $this->connection->getDatabasePlatform()->modifyLimitQuery($query, $this->maxResults, $this->firstResult); } /** * 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(); } /** * Create 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; } /** * Create 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 mixed $type * @return string */ public function createPositionalParameter($value, $type = \PDO::PARAM_STR) { $this->boundCounter++; $this->setParameter($this->boundCounter, $value, $type); return "?"; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Query/QueryException.php0000644000175100017510000000273712143374463023113 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Query; use Doctrine\DBAL\DBALException; /** * Driver interface. * Interface that all DBAL drivers must implement. * * @since 2.1.4 */ class QueryException extends DBALException { static public function 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) . "."); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Query/Expression/CompositeExpression.php0000644000175100017510000000672512143374463026311 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Query\Expression; /** * Composite expression is responsible to build a group of similar expression. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.org * @since 2.1 * @author Guilherme Blanco * @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'; /** * @var string Holds the instance type of composite expression */ private $type; /** * @var array Each expression part of the composite expression */ private $parts = array(); /** * Constructor. * * @param string $type Instance type of composite expression * @param array $parts Composition of expressions to be joined on composite expression */ public function __construct($type, array $parts = array()) { $this->type = $type; $this->addMultiple($parts); } /** * Adds multiple parts to composite expression. * * @param array $parts * * @return CompositeExpression */ public function addMultiple(array $parts = array()) { foreach ((array) $parts as $part) { $this->add($part); } return $this; } /** * Adds an expression to composite expression. * * @param mixed $part * @return CompositeExpression */ public function add($part) { if ( ! empty($part) || ($part instanceof self && $part->count() > 0)) { $this->parts[] = $part; } return $this; } /** * Retrieves the amount of expressions on composite expression. * * @return integer */ public function count() { return count($this->parts); } /** * Retrieve the string representation of this composite expression. * * @return string */ public function __toString() { if (count($this->parts) === 1) { return (string) $this->parts[0]; } return '(' . implode(') ' . $this->type . ' (', $this->parts) . ')'; } /** * Return type of this composite expression (AND/OR) * * @return string */ public function getType() { return $this->type; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php0000644000175100017510000001764312143374463025736 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Query\Expression; use Doctrine\DBAL\Connection; /** * ExpressionBuilder class is responsible to dynamically create SQL query parts. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 2.1 * @author Guilherme Blanco * @author Benjamin Eberlei */ class ExpressionBuilder { const EQ = '='; const NEQ = '<>'; const LT = '<'; const LTE = '<='; const GT = '>'; const GTE = '>='; /** * @var Doctrine\DBAL\Connection DBAL Connection */ private $connection = null; /** * Initializes a new ExpressionBuilder. * * @param \Doctrine\DBAL\Connection $connection DBAL Connection */ public function __construct(Connection $connection) { $this->connection = $connection; } /** * Creates a conjunction of the given boolean expressions. * * Example: * * [php] * // (u.type = ?) AND (u.role = ?) * $expr->andX('u.type = ?', 'u.role = ?')); * * @param mixed $x Optional clause. Defaults = null, but requires * at least one defined when converting to string. * @return CompositeExpression */ public function andX($x = null) { return new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args()); } /** * Creates a disjunction of the given boolean expressions. * * Example: * * [php] * // (u.type = ?) OR (u.role = ?) * $qb->where($qb->expr()->orX('u.type = ?', 'u.role = ?')); * * @param mixed $x Optional clause. Defaults = null, but requires * at least one defined when converting to string. * @return CompositeExpression */ public function orX($x = null) { return new CompositeExpression(CompositeExpression::TYPE_OR, func_get_args()); } /** * Creates a comparison expression. * * @param mixed $x Left expression * @param string $operator One of the ExpressionBuilder::* constants. * @param mixed $y Right expression * @return string */ public function comparison($x, $operator, $y) { return $x . ' ' . $operator . ' ' . $y; } /** * Creates an equality comparison expression with the given arguments. * * First argument is considered the left expression and the second is the right expression. * When converted to string, it will generated a = . Example: * * [php] * // u.id = ? * $expr->eq('u.id', '?'); * * @param mixed $x Left expression * @param mixed $y Right expression * @return string */ public function eq($x, $y) { return $this->comparison($x, self::EQ, $y); } /** * Creates a non equality comparison expression with the given arguments. * First argument is considered the left expression and the second is the right expression. * When converted to string, it will generated a <> . Example: * * [php] * // u.id <> 1 * $q->where($q->expr()->neq('u.id', '1')); * * @param mixed $x Left expression * @param mixed $y Right expression * @return string */ public function neq($x, $y) { return $this->comparison($x, self::NEQ, $y); } /** * Creates a lower-than comparison expression with the given arguments. * First argument is considered the left expression and the second is the right expression. * When converted to string, it will generated a < . Example: * * [php] * // u.id < ? * $q->where($q->expr()->lt('u.id', '?')); * * @param mixed $x Left expression * @param mixed $y Right expression * @return string */ public function lt($x, $y) { return $this->comparison($x, self::LT, $y); } /** * Creates a lower-than-equal comparison expression with the given arguments. * First argument is considered the left expression and the second is the right expression. * When converted to string, it will generated a <= . Example: * * [php] * // u.id <= ? * $q->where($q->expr()->lte('u.id', '?')); * * @param mixed $x Left expression * @param mixed $y Right expression * @return string */ public function lte($x, $y) { return $this->comparison($x, self::LTE, $y); } /** * Creates a greater-than comparison expression with the given arguments. * First argument is considered the left expression and the second is the right expression. * When converted to string, it will generated a > . Example: * * [php] * // u.id > ? * $q->where($q->expr()->gt('u.id', '?')); * * @param mixed $x Left expression * @param mixed $y Right expression * @return string */ public function gt($x, $y) { return $this->comparison($x, self::GT, $y); } /** * Creates a greater-than-equal comparison expression with the given arguments. * First argument is considered the left expression and the second is the right expression. * When converted to string, it will generated a >= . Example: * * [php] * // u.id >= ? * $q->where($q->expr()->gte('u.id', '?')); * * @param mixed $x Left expression * @param mixed $y Right expression * @return string */ public function gte($x, $y) { return $this->comparison($x, self::GTE, $y); } /** * Creates an IS NULL expression with the given arguments. * * @param string $x Field in string format to be restricted by IS NULL * * @return string */ public function isNull($x) { return $x . ' IS NULL'; } /** * Creates an IS NOT NULL expression with the given arguments. * * @param string $x Field in string format to be restricted by IS NOT NULL * * @return string */ public function isNotNull($x) { return $x . ' IS NOT NULL'; } /** * Creates a LIKE() comparison expression with the given arguments. * * @param string $x Field in string format to be inspected by LIKE() comparison. * @param mixed $y Argument to be used in LIKE() comparison. * * @return string */ public function like($x, $y) { return $this->comparison($x, 'LIKE', $y); } /** * Quotes a given input parameter. * * @param mixed $input Parameter to be quoted. * @param string $type Type of the parameter. * * @return string */ public function literal($input, $type = null) { return $this->connection->quote($input, $type); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/AbstractAsset.php0000644000175100017510000001434012143374463022756 0ustar beberleibeberlei. */ 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 */ protected $_namespace; /** * @var bool */ protected $_quoted = false; /** * Set name of this asset * * @param string $name */ 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 bool */ public function isInDefaultNamespace($defaultNamespaceName) { return $this->_namespace == $defaultNamespaceName || $this->_namespace === null; } /** * Get namespace name of this asset. * * If NULL is returned this means the default namespace is used. * * @return string */ public function getNamespaceName() { return $this->_namespace; } /** * The shortest name is stripped of the default namespace. All other * namespaced elements are returned as full-qualified names. * * @param string * @return string */ public function getShortestName($defaultNamespaceName) { $shortestName = $this->getName(); if ($this->_namespace == $defaultNamespaceName) { $shortestName = $this->_name; } return strtolower($shortestName); } /** * The normalized name is full-qualified and lowerspaced. Lowerspacing is * actually wrong, but we have to do it to keep our sanity. If you are * using database objects that only differentiate in the casing (FOO vs * Foo) then you will NOT be able to use Doctrine Schema abstraction. * * Every non-namespaced element is prefixed with the default namespace * name which is passed as argument to this method. * * @return string */ public function getFullQualifiedName($defaultNamespaceName) { $name = $this->getName(); if ( ! $this->_namespace) { $name = $defaultNamespaceName . "." . $name; } return strtolower($name); } /** * Check if this asset's name is quoted * * @return bool */ public function isQuoted() { return $this->_quoted; } /** * Check if this identifier is quoted. * * @param string $identifier * @return bool */ protected function isIdentifierQuoted($identifier) { return (isset($identifier[0]) && ($identifier[0] == '`' || $identifier[0] == '"')); } /** * Trim quotes from the identifier. * * @param string $identifier * @return string */ protected function trimQuotes($identifier) { return str_replace(array('`', '"'), '', $identifier); } /** * Return name of this schema asset. * * @return string */ public function getName() { if ($this->_namespace) { return $this->_namespace . "." . $this->_name; } return $this->_name; } /** * Get the quoted representation of this asset but only if it was defined with one. Otherwise * return the plain unquoted value as inserted. * * @param AbstractPlatform $platform * @return string */ public function getQuotedName(AbstractPlatform $platform) { $keywords = $platform->getReservedKeywordsList(); $parts = explode(".", $this->getName()); foreach ($parts as $k => $v) { $parts[$k] = ($this->_quoted || $keywords->isKeyword($v)) ? $platform->quoteIdentifier($v) : $v; } return implode(".", $parts); } /** * Generate an identifier from a list of column names obeying a certain string length. * * This is especially important for Oracle, since it does not allow identifiers larger than 30 chars, * however building idents automatically for foreign keys, composite keys or such can easily create * very long names. * * @param array $columnNames * @param string $prefix * @param int $maxSize * @return string */ protected function _generateIdentifierName($columnNames, $prefix='', $maxSize=30) { $hash = implode("", array_map(function($column) { return dechex(crc32($column)); }, $columnNames)); return substr(strtoupper($prefix . "_" . $hash), 0, $maxSize); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/AbstractSchemaManager.php0000644000175100017510000006372012143374463024400 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Events; use Doctrine\DBAL\Event\SchemaColumnDefinitionEventArgs; use Doctrine\DBAL\Event\SchemaIndexDefinitionEventArgs; use Doctrine\DBAL\Types; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Base class for schema managers. Schema managers are used to inspect and/or * modify the database schema/structure. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @author Konsta Vesterinen * @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 */ public function __construct(\Doctrine\DBAL\Connection $conn, AbstractPlatform $platform = null) { $this->_conn = $conn; $this->_platform = $platform ?: $this->_conn->getDatabasePlatform(); } /** * Return associated platform. * * @return \Doctrine\DBAL\Platforms\AbstractPlatform */ public function getDatabasePlatform() { return $this->_platform; } /** * Try any method on the schema manager. Normally a method throws an * exception when your DBMS doesn't support it or if an error occurs. * This method allows you to try and method on your SchemaManager * instance and will return false if it does not work or is not supported. * * * $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; } } /** * List the available databases for this connection * * @return array $databases */ public function listDatabases() { $sql = $this->_platform->getListDatabasesSQL(); $databases = $this->_conn->fetchAll($sql); return $this->_getPortableDatabasesList($databases); } /** * List the available sequences for this connection * * @return Sequence[] */ public function listSequences($database = null) { if (is_null($database)) { $database = $this->_conn->getDatabase(); } $sql = $this->_platform->getListSequencesSQL($database); $sequences = $this->_conn->fetchAll($sql); return $this->filterAssetNames($this->_getPortableSequencesList($sequences)); } /** * List the columns for a given table. * * In contrast to other libraries and to the old version of Doctrine, * this column definition does try to contain the 'primary' field for * the reason that it is not portable accross different RDBMS. Use * {@see listTableIndexes($tableName)} to retrieve the primary key * of a table. We're a RDBMS specifies more details these are held * in the platformDetails array. * * @param string $table The name of the table. * @param string $database * @return Column[] */ public function listTableColumns($table, $database = null) { if ( ! $database) { $database = $this->_conn->getDatabase(); } $sql = $this->_platform->getListTableColumnsSQL($table, $database); $tableColumns = $this->_conn->fetchAll($sql); return $this->_getPortableTableColumnList($table, $database, $tableColumns); } /** * List the indexes for a given table returning an array of Index instances. * * Keys of the portable indexes list are all lower-cased. * * @param string $table The name of the table * @return Index[] $tableIndexes */ public function listTableIndexes($table) { $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase()); $tableIndexes = $this->_conn->fetchAll($sql); return $this->_getPortableTableIndexesList($tableIndexes, $table); } /** * Return true if all the given tables exist. * * @param array $tableNames * @return bool */ public function tablesExist($tableNames) { $tableNames = array_map('strtolower', (array)$tableNames); return count($tableNames) == count(\array_intersect($tableNames, array_map('strtolower', $this->listTableNames()))); } /** * Return a list of all tables in the current database * * @return array */ public function listTableNames() { $sql = $this->_platform->getListTablesSQL(); $tables = $this->_conn->fetchAll($sql); $tableNames = $this->_getPortableTablesList($tables); return $this->filterAssetNames($tableNames); } /** * Filter asset names if they are configured to return only a subset of all * the found elements. * * @param array $assetNames * @return array */ protected function filterAssetNames($assetNames) { $filterExpr = $this->getFilterSchemaAssetsExpression(); if ( ! $filterExpr) { return $assetNames; } return array_values ( array_filter($assetNames, function ($assetName) use ($filterExpr) { $assetName = ($assetName instanceof AbstractAsset) ? $assetName->getName() : $assetName; return preg_match($filterExpr, $assetName); }) ); } protected function getFilterSchemaAssetsExpression() { return $this->_conn->getConfiguration()->getFilterSchemaAssetsExpression(); } /** * List the tables for this connection * * @return Table[] */ public function listTables() { $tableNames = $this->listTableNames(); $tables = array(); foreach ($tableNames as $tableName) { $tables[] = $this->listTableDetails($tableName); } return $tables; } /** * @param string $tableName * @return Table */ public function listTableDetails($tableName) { $columns = $this->listTableColumns($tableName); $foreignKeys = array(); if ($this->_platform->supportsForeignKeyConstraints()) { $foreignKeys = $this->listTableForeignKeys($tableName); } $indexes = $this->listTableIndexes($tableName); return new Table($tableName, $columns, $indexes, $foreignKeys, false, array()); } /** * List the views this connection has * * @return View[] */ public function listViews() { $database = $this->_conn->getDatabase(); $sql = $this->_platform->getListViewsSQL($database); $views = $this->_conn->fetchAll($sql); return $this->_getPortableViewsList($views); } /** * List the foreign keys for the given table * * @param string $table The name of the table * @return ForeignKeyConstraint[] */ public function listTableForeignKeys($table, $database = null) { if (is_null($database)) { $database = $this->_conn->getDatabase(); } $sql = $this->_platform->getListTableForeignKeysSQL($table, $database); $tableForeignKeys = $this->_conn->fetchAll($sql); return $this->_getPortableTableForeignKeysList($tableForeignKeys); } /* drop*() Methods */ /** * Drops a database. * * NOTE: You can not drop the database this SchemaManager is currently connected to. * * @param string $database The name of the database to drop */ public function dropDatabase($database) { $this->_execSql($this->_platform->getDropDatabaseSQL($database)); } /** * Drop the given table * * @param string $table The name of the table to drop */ public function dropTable($table) { $this->_execSql($this->_platform->getDropTableSQL($table)); } /** * Drop the index from the given table * * @param Index|string $index The name of the index * @param string|Table $table The name of the table */ public function dropIndex($index, $table) { if($index instanceof Index) { $index = $index->getQuotedName($this->_platform); } $this->_execSql($this->_platform->getDropIndexSQL($index, $table)); } /** * Drop the constraint from the given table * * @param Constraint $constraint * @param string $table The name of the table */ public function dropConstraint(Constraint $constraint, $table) { $this->_execSql($this->_platform->getDropConstraintSQL($constraint, $table)); } /** * Drops a foreign key from a table. * * @param ForeignKeyConstraint|string $table The name of the table with the foreign key. * @param Table|string $name The name of the foreign key. * @return boolean $result */ public function dropForeignKey($foreignKey, $table) { $this->_execSql($this->_platform->getDropForeignKeySQL($foreignKey, $table)); } /** * Drops a sequence with a given name. * * @param string $name The name of the sequence to drop. */ public function dropSequence($name) { $this->_execSql($this->_platform->getDropSequenceSQL($name)); } /** * Drop a view * * @param string $name The name of the view * @return boolean $result */ public function dropView($name) { $this->_execSql($this->_platform->getDropViewSQL($name)); } /* create*() Methods */ /** * Creates a new database. * * @param string $database The name of the database to create. */ public function createDatabase($database) { $this->_execSql($this->_platform->getCreateDatabaseSQL($database)); } /** * Create a new table. * * @param Table $table * @param int $createFlags */ public function createTable(Table $table) { $createFlags = AbstractPlatform::CREATE_INDEXES|AbstractPlatform::CREATE_FOREIGNKEYS; $this->_execSql($this->_platform->getCreateTableSQL($table, $createFlags)); } /** * Create a new sequence * * @param Sequence $sequence * @throws \Doctrine\DBAL\ConnectionException if something fails at database level */ public function createSequence($sequence) { $this->_execSql($this->_platform->getCreateSequenceSQL($sequence)); } /** * Create a constraint on a table * * @param Constraint $constraint * @param string|Table $table */ public function createConstraint(Constraint $constraint, $table) { $this->_execSql($this->_platform->getCreateConstraintSQL($constraint, $table)); } /** * Create a new index on a table * * @param Index $index * @param string $table name of the table on which the index is to be created */ public function createIndex(Index $index, $table) { $this->_execSql($this->_platform->getCreateIndexSQL($index, $table)); } /** * Create a new foreign key * * @param ForeignKeyConstraint $foreignKey ForeignKey instance * @param string|Table $table name of the table on which the foreign key is to be created */ public function createForeignKey(ForeignKeyConstraint $foreignKey, $table) { $this->_execSql($this->_platform->getCreateForeignKeySQL($foreignKey, $table)); } /** * Create a new view * * @param View $view */ public function createView(View $view) { $this->_execSql($this->_platform->getCreateViewSQL($view->getQuotedName($this->_platform), $view->getSql())); } /* dropAndCreate*() Methods */ /** * Drop and create a constraint * * @param Constraint $constraint * @param string $table * @see dropConstraint() * @see createConstraint() */ public function dropAndCreateConstraint(Constraint $constraint, $table) { $this->tryMethod('dropConstraint', $constraint, $table); $this->createConstraint($constraint, $table); } /** * Drop and create a new index on a table * * @param string|Table $table name of the table on which the index is to be created * @param Index $index */ public function dropAndCreateIndex(Index $index, $table) { $this->tryMethod('dropIndex', $index->getQuotedName($this->_platform), $table); $this->createIndex($index, $table); } /** * Drop and create a new foreign key * * @param ForeignKeyConstraint $foreignKey associative array that defines properties of the foreign key to be created. * @param string|Table $table name of the table on which the foreign key is to be created */ public function dropAndCreateForeignKey(ForeignKeyConstraint $foreignKey, $table) { $this->tryMethod('dropForeignKey', $foreignKey, $table); $this->createForeignKey($foreignKey, $table); } /** * Drop and create a new sequence * * @param Sequence $sequence * @throws \Doctrine\DBAL\ConnectionException if something fails at database level */ public function dropAndCreateSequence(Sequence $sequence) { $this->tryMethod('dropSequence', $sequence->getQuotedName($this->_platform)); $this->createSequence($sequence); } /** * Drop and create a new table. * * @param Table $table */ public function dropAndCreateTable(Table $table) { $this->tryMethod('dropTable', $table->getQuotedName($this->_platform)); $this->createTable($table); } /** * Drop and creates a new database. * * @param string $database The name of the database to create. */ public function dropAndCreateDatabase($database) { $this->tryMethod('dropDatabase', $database); $this->createDatabase($database); } /** * Drop and create a new view * * @param View $view */ public function dropAndCreateView(View $view) { $this->tryMethod('dropView', $view->getQuotedName($this->_platform)); $this->createView($view); } /* alterTable() Methods */ /** * Alter an existing tables schema * * @param TableDiff $tableDiff */ public function alterTable(TableDiff $tableDiff) { $queries = $this->_platform->getAlterTableSQL($tableDiff); if (is_array($queries) && count($queries)) { foreach ($queries as $ddlQuery) { $this->_execSql($ddlQuery); } } } /** * Rename a given table to another name * * @param string $name The current name of the table * @param string $newName The new name of the table */ public function renameTable($name, $newName) { $tableDiff = new TableDiff($name); $tableDiff->newName = $newName; $this->alterTable($tableDiff); } /** * Methods for filtering return values of list*() methods to convert * the native DBMS data definition to a portable Doctrine definition */ protected function _getPortableDatabasesList($databases) { $list = array(); foreach ($databases as $value) { if ($value = $this->_getPortableDatabaseDefinition($value)) { $list[] = $value; } } return $list; } protected function _getPortableDatabaseDefinition($database) { return $database; } protected function _getPortableFunctionsList($functions) { $list = array(); foreach ($functions as $value) { if ($value = $this->_getPortableFunctionDefinition($value)) { $list[] = $value; } } return $list; } protected function _getPortableFunctionDefinition($function) { return $function; } protected function _getPortableTriggersList($triggers) { $list = array(); foreach ($triggers as $value) { if ($value = $this->_getPortableTriggerDefinition($value)) { $list[] = $value; } } return $list; } protected function _getPortableTriggerDefinition($trigger) { return $trigger; } protected function _getPortableSequencesList($sequences) { $list = array(); foreach ($sequences as $value) { if ($value = $this->_getPortableSequenceDefinition($value)) { $list[] = $value; } } return $list; } /** * @param array $sequence * @return Sequence */ protected function _getPortableSequenceDefinition($sequence) { throw DBALException::notSupported('Sequences'); } /** * Independent of the database the keys of the column list result are lowercased. * * The name of the created column instance however is kept in its case. * * @param string $table The name of the table. * @param string $database * @param array $tableColumns * @return array */ protected function _getPortableTableColumnList($table, $database, $tableColumns) { $eventManager = $this->_platform->getEventManager(); $list = array(); foreach ($tableColumns as $tableColumn) { $column = null; $defaultPrevented = false; if (null !== $eventManager && $eventManager->hasListeners(Events::onSchemaColumnDefinition)) { $eventArgs = new SchemaColumnDefinitionEventArgs($tableColumn, $table, $database, $this->_conn); $eventManager->dispatchEvent(Events::onSchemaColumnDefinition, $eventArgs); $defaultPrevented = $eventArgs->isDefaultPrevented(); $column = $eventArgs->getColumn(); } if ( ! $defaultPrevented) { $column = $this->_getPortableTableColumnDefinition($tableColumn); } if ($column) { $name = strtolower($column->getQuotedName($this->_platform)); $list[$name] = $column; } } return $list; } /** * Get Table Column Definition * * @param array $tableColumn * @return Column */ abstract protected function _getPortableTableColumnDefinition($tableColumn); /** * Aggregate and group the index results according to the required data result. * * @param array $tableIndexRows * @param string $tableName * @return array */ protected function _getPortableTableIndexesList($tableIndexRows, $tableName=null) { $result = array(); foreach($tableIndexRows as $tableIndex) { $indexName = $keyName = $tableIndex['key_name']; if($tableIndex['primary']) { $keyName = 'primary'; } $keyName = strtolower($keyName); if(!isset($result[$keyName])) { $result[$keyName] = array( 'name' => $indexName, 'columns' => array($tableIndex['column_name']), 'unique' => $tableIndex['non_unique'] ? false : true, 'primary' => $tableIndex['primary'], 'flags' => isset($tableIndex['flags']) ? $tableIndex['flags'] : 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']); } if ($index) { $indexes[$indexKey] = $index; } } return $indexes; } protected function _getPortableTablesList($tables) { $list = array(); foreach ($tables as $value) { if ($value = $this->_getPortableTableDefinition($value)) { $list[] = $value; } } return $list; } protected function _getPortableTableDefinition($table) { return $table; } protected function _getPortableUsersList($users) { $list = array(); foreach ($users as $value) { if ($value = $this->_getPortableUserDefinition($value)) { $list[] = $value; } } return $list; } protected function _getPortableUserDefinition($user) { return $user; } protected function _getPortableViewsList($views) { $list = array(); foreach ($views as $value) { if ($view = $this->_getPortableViewDefinition($value)) { $viewName = strtolower($view->getQuotedName($this->_platform)); $list[$viewName] = $view; } } return $list; } protected function _getPortableViewDefinition($view) { return false; } protected function _getPortableTableForeignKeysList($tableForeignKeys) { $list = array(); foreach ($tableForeignKeys as $value) { if ($value = $this->_getPortableTableForeignKeyDefinition($value)) { $list[] = $value; } } return $list; } protected function _getPortableTableForeignKeyDefinition($tableForeignKey) { return $tableForeignKey; } protected function _execSql($sql) { foreach ((array) $sql as $query) { $this->_conn->executeUpdate($query); } } /** * Create a schema instance for the current database. * * @return Schema */ public function createSchema() { $sequences = array(); if($this->_platform->supportsSequences()) { $sequences = $this->listSequences(); } $tables = $this->listTables(); return new Schema($tables, $sequences, $this->createSchemaConfig()); } /** * Create the configuration for this schema. * * @return SchemaConfig */ public function createSchemaConfig() { $schemaConfig = new SchemaConfig(); $schemaConfig->setMaxIdentifierLength($this->_platform->getMaxIdentifierLength()); $searchPaths = $this->getSchemaSearchPaths(); if (isset($searchPaths[0])) { $schemaConfig->setName($searchPaths[0]); } $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; } public function removeDoctrineTypeFromComment($comment, $type) { return str_replace('(DC2Type:'.$type.')', '', $comment); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/Column.php0000644000175100017510000002126412143374463021453 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema; use \Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Schema\Visitor\Visitor; /** * Object representation of a database column * * * @link www.doctrine-project.org * @since 2.0 * @version $Revision$ * @author Benjamin Eberlei */ class Column extends AbstractAsset { /** * @var \Doctrine\DBAL\Types\Type */ protected $_type; /** * @var int */ protected $_length = null; /** * @var int */ protected $_precision = 10; /** * @var int */ protected $_scale = 0; /** * @var bool */ protected $_unsigned = false; /** * @var bool */ protected $_fixed = false; /** * @var bool */ protected $_notnull = true; /** * @var string */ protected $_default = null; /** * @var bool */ protected $_autoincrement = false; /** * @var array */ protected $_platformOptions = array(); /** * @var string */ protected $_columnDefinition = null; /** * @var string */ protected $_comment = null; /** * @var array */ protected $_customSchemaOptions = array(); /** * Create a new Column * * @param string $columnName * @param \Doctrine\DBAL\Types\Type $type * @param int $length * @param bool $notNull * @param mixed $default * @param bool $unsigned * @param bool $fixed * @param int $precision * @param int $scale * @param array $platformOptions */ public function __construct($columnName, Type $type, array $options=array()) { $this->_setName($columnName); $this->setType($type); $this->setOptions($options); } /** * @param array $options * @return Column */ public function setOptions(array $options) { foreach ($options as $name => $value) { $method = "set".$name; if (method_exists($this, $method)) { $this->$method($value); } } return $this; } /** * @param Type $type * @return Column */ public function setType(Type $type) { $this->_type = $type; return $this; } /** * @param int $length * @return Column */ public function setLength($length) { if($length !== null) { $this->_length = (int)$length; } else { $this->_length = null; } return $this; } /** * @param int $precision * @return Column */ public function setPrecision($precision) { if (!is_numeric($precision)) { $precision = 10; // defaults to 10 when no valid precision is given. } $this->_precision = (int)$precision; return $this; } /** * @param int $scale * @return Column */ public function setScale($scale) { if (!is_numeric($scale)) { $scale = 0; } $this->_scale = (int)$scale; return $this; } /** * * @param bool $unsigned * @return Column */ public function setUnsigned($unsigned) { $this->_unsigned = (bool)$unsigned; return $this; } /** * * @param bool $fixed * @return Column */ public function setFixed($fixed) { $this->_fixed = (bool)$fixed; return $this; } /** * @param bool $notnull * @return Column */ public function setNotnull($notnull) { $this->_notnull = (bool)$notnull; return $this; } /** * * @param mixed $default * @return Column */ public function setDefault($default) { $this->_default = $default; return $this; } /** * * @param array $platformOptions * @return Column */ public function setPlatformOptions(array $platformOptions) { $this->_platformOptions = $platformOptions; return $this; } /** * * @param string $name * @param mixed $value * @return Column */ public function setPlatformOption($name, $value) { $this->_platformOptions[$name] = $value; return $this; } /** * * @param string * @return Column */ public function setColumnDefinition($value) { $this->_columnDefinition = $value; return $this; } public function getType() { return $this->_type; } public function getLength() { return $this->_length; } public function getPrecision() { return $this->_precision; } public function getScale() { return $this->_scale; } public function getUnsigned() { return $this->_unsigned; } public function getFixed() { return $this->_fixed; } public function getNotnull() { return $this->_notnull; } public function getDefault() { return $this->_default; } public function getPlatformOptions() { return $this->_platformOptions; } public function hasPlatformOption($name) { return isset($this->_platformOptions[$name]); } public function getPlatformOption($name) { return $this->_platformOptions[$name]; } public function getColumnDefinition() { return $this->_columnDefinition; } public function getAutoincrement() { return $this->_autoincrement; } public function setAutoincrement($flag) { $this->_autoincrement = $flag; return $this; } public function setComment($comment) { $this->_comment = $comment; return $this; } public function getComment() { return $this->_comment; } /** * @param string $name * @param mixed $value * @return Column */ public function setCustomSchemaOption($name, $value) { $this->_customSchemaOptions[$name] = $value; return $this; } /** * @param string $name * @return boolean */ public function hasCustomSchemaOption($name) { return isset($this->_customSchemaOptions[$name]); } /** * @param string $name * @return mixed */ public function getCustomSchemaOption($name) { return $this->_customSchemaOptions[$name]; } /** * @param array $customSchemaOptions * @return Column */ public function setCustomSchemaOptions(array $customSchemaOptions) { $this->_customSchemaOptions = $customSchemaOptions; return $this; } /** * @return array */ public function getCustomSchemaOptions() { return $this->_customSchemaOptions; } /** * @param Visitor $visitor */ public function visit(\Doctrine\DBAL\Schema\Visitor $visitor) { $visitor->accept($this); } /** * @return array */ public function toArray() { return array_merge(array( 'name' => $this->_name, 'type' => $this->_type, 'default' => $this->_default, 'notnull' => $this->_notnull, 'length' => $this->_length, 'precision' => $this->_precision, 'scale' => $this->_scale, 'fixed' => $this->_fixed, 'unsigned' => $this->_unsigned, 'autoincrement' => $this->_autoincrement, 'columnDefinition' => $this->_columnDefinition, 'comment' => $this->_comment, ), $this->_platformOptions, $this->_customSchemaOptions); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/ColumnDiff.php0000644000175100017510000000334412143374463022243 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema; /** * Represent the change of a column * * * @link www.doctrine-project.org * @since 2.0 * @version $Revision$ * @author Benjamin Eberlei */ class ColumnDiff { public $oldColumnName; /** * @var Column */ public $column; /** * @var array */ public $changedProperties = array(); public function __construct($oldColumnName, Column $column, array $changedProperties = array()) { $this->oldColumnName = $oldColumnName; $this->column = $column; $this->changedProperties = $changedProperties; } public function hasChanged($propertyName) { return in_array($propertyName, $this->changedProperties); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/Comparator.php0000644000175100017510000003724512143374463022333 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema; /** * Compare to Schemas and return an instance of SchemaDiff * * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved. * @license http://ez.no/licenses/new_bsd New BSD License * * @link www.doctrine-project.org * @since 2.0 * @version $Revision$ * @author Benjamin Eberlei */ class Comparator { /** * @param Schema $fromSchema * @param Schema $toSchema * @return SchemaDiff */ static public function compareSchemas( Schema $fromSchema, Schema $toSchema ) { $c = new self(); return $c->compare($fromSchema, $toSchema); } /** * Returns a SchemaDiff object containing the differences between the schemas $fromSchema and $toSchema. * * The returned 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 Schema $fromSchema * @param Schema $toSchema * * @return SchemaDiff */ public function compare(Schema $fromSchema, Schema $toSchema) { $diff = new SchemaDiff(); $foreignKeysToTable = array(); foreach ( $toSchema->getTables() as $table ) { $tableName = $table->getShortestName($toSchema->getName()); if ( ! $fromSchema->hasTable($tableName)) { $diff->newTables[$tableName] = $toSchema->getTable($tableName); } else { $tableDifferences = $this->diffTable($fromSchema->getTable($tableName), $toSchema->getTable($tableName)); if ($tableDifferences !== false) { $diff->changedTables[$tableName] = $tableDifferences; } } } /* Check if there are tables removed */ foreach ($fromSchema->getTables() as $table) { $tableName = $table->getShortestName($fromSchema->getName()); $table = $fromSchema->getTable($tableName); if ( ! $toSchema->hasTable($tableName) ) { $diff->removedTables[$tableName] = $table; } // also remember all foreign keys that point to a specific table foreach ($table->getForeignKeys() as $foreignKey) { $foreignTable = strtolower($foreignKey->getForeignTableName()); if (!isset($foreignKeysToTable[$foreignTable])) { $foreignKeysToTable[$foreignTable] = array(); } $foreignKeysToTable[$foreignTable][] = $foreignKey; } } foreach ($diff->removedTables as $tableName => $table) { if (isset($foreignKeysToTable[$tableName])) { $diff->orphanedForeignKeys = array_merge($diff->orphanedForeignKeys, $foreignKeysToTable[$tableName]); // 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) { unset($diff->changedTables[$localTableName]->removedForeignKeys[$key]); } } } } } foreach ($toSchema->getSequences() as $sequence) { $sequenceName = $sequence->getShortestName($toSchema->getName()); if ( ! $fromSchema->hasSequence($sequenceName)) { $diff->newSequences[] = $sequence; } else { if ($this->diffSequence($sequence, $fromSchema->getSequence($sequenceName))) { $diff->changedSequences[] = $toSchema->getSequence($sequenceName); } } } foreach ($fromSchema->getSequences() as $sequence) { if ($this->isAutoIncrementSequenceInSchema($toSchema, $sequence)) { continue; } $sequenceName = $sequence->getShortestName($fromSchema->getName()); if ( ! $toSchema->hasSequence($sequenceName)) { $diff->removedSequences[] = $sequence; } } return $diff; } private function isAutoIncrementSequenceInSchema($schema, $sequence) { foreach ($schema->getTables() as $table) { if ($sequence->isAutoIncrementsFor($table)) { return true; } } return false; } /** * * @param Sequence $sequence1 * @param Sequence $sequence2 */ public function diffSequence(Sequence $sequence1, Sequence $sequence2) { if($sequence1->getAllocationSize() != $sequence2->getAllocationSize()) { return true; } if($sequence1->getInitialValue() != $sequence2->getInitialValue()) { return true; } return false; } /** * Returns the difference between the tables $table1 and $table2. * * If there are no differences this method returns the boolean false. * * @param Table $table1 * @param Table $table2 * * @return bool|TableDiff */ public function diffTable(Table $table1, Table $table2) { $changes = 0; $tableDifferences = new TableDiff($table1->getName()); $table1Columns = $table1->getColumns(); $table2Columns = $table2->getColumns(); /* See if all the fields in table 1 exist in table 2 */ foreach ( $table2Columns as $columnName => $column ) { if ( !$table1->hasColumn($columnName) ) { $tableDifferences->addedColumns[$columnName] = $column; $changes++; } } /* See if there are any removed fields in table 2 */ foreach ( $table1Columns as $columnName => $column ) { if ( !$table2->hasColumn($columnName) ) { $tableDifferences->removedColumns[$columnName] = $column; $changes++; } } foreach ( $table1Columns as $columnName => $column ) { if ( $table2->hasColumn($columnName) ) { $changedProperties = $this->diffColumn( $column, $table2->getColumn($columnName) ); if (count($changedProperties) ) { $columnDiff = new ColumnDiff($column->getName(), $table2->getColumn($columnName), $changedProperties); $tableDifferences->changedColumns[$column->getName()] = $columnDiff; $changes++; } } } $this->detectColumnRenamings($tableDifferences); $table1Indexes = $table1->getIndexes(); $table2Indexes = $table2->getIndexes(); foreach ($table2Indexes as $index2Name => $index2Definition) { foreach ($table1Indexes as $index1Name => $index1Definition) { if ($this->diffIndex($index1Definition, $index2Definition) === false) { unset($table1Indexes[$index1Name]); unset($table2Indexes[$index2Name]); } else { if ($index1Name == $index2Name) { $tableDifferences->changedIndexes[$index2Name] = $table2Indexes[$index2Name]; unset($table1Indexes[$index1Name]); unset($table2Indexes[$index2Name]); $changes++; } } } } foreach ($table1Indexes as $index1Name => $index1Definition) { $tableDifferences->removedIndexes[$index1Name] = $index1Definition; $changes++; } foreach ($table2Indexes as $index2Name => $index2Definition) { $tableDifferences->addedIndexes[$index2Name] = $index2Definition; $changes++; } $fromFkeys = $table1->getForeignKeys(); $toFkeys = $table2->getForeignKeys(); foreach ($fromFkeys as $key1 => $constraint1) { foreach ($toFkeys as $key2 => $constraint2) { if($this->diffForeignKey($constraint1, $constraint2) === false) { unset($fromFkeys[$key1]); unset($toFkeys[$key2]); } else { if (strtolower($constraint1->getName()) == strtolower($constraint2->getName())) { $tableDifferences->changedForeignKeys[] = $constraint2; $changes++; unset($fromFkeys[$key1]); unset($toFkeys[$key2]); } } } } foreach ($fromFkeys as $key1 => $constraint1) { $tableDifferences->removedForeignKeys[] = $constraint1; $changes++; } foreach ($toFkeys as $key2 => $constraint2) { $tableDifferences->addedForeignKeys[] = $constraint2; $changes++; } return $changes ? $tableDifferences : false; } /** * Try to find columns that only changed their name, rename operations maybe cheaper than add/drop * however ambiguities between different possibilities should not lead to renaming at all. * * @param TableDiff $tableDifferences */ private function detectColumnRenamings(TableDiff $tableDifferences) { $renameCandidates = array(); foreach ($tableDifferences->addedColumns as $addedColumnName => $addedColumn) { foreach ($tableDifferences->removedColumns as $removedColumnName => $removedColumn) { if (count($this->diffColumn($addedColumn, $removedColumn)) == 0) { $renameCandidates[$addedColumn->getName()][] = array($removedColumn, $addedColumn, $addedColumnName); } } } foreach ($renameCandidates as $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]); } } } } /** * @param ForeignKeyConstraint $key1 * @param ForeignKeyConstraint $key2 * @return bool */ public function diffForeignKey(ForeignKeyConstraint $key1, ForeignKeyConstraint $key2) { if (array_map('strtolower', $key1->getLocalColumns()) != array_map('strtolower', $key2->getLocalColumns())) { return true; } if (array_map('strtolower', $key1->getForeignColumns()) != array_map('strtolower', $key2->getForeignColumns())) { return true; } if ($key1->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 Column $column1 * @param Column $column2 * * @return array */ public function diffColumn(Column $column1, Column $column2) { $changedProperties = array(); if ( $column1->getType() != $column2->getType() ) { $changedProperties[] = 'type'; } if ($column1->getNotnull() != $column2->getNotnull()) { $changedProperties[] = 'notnull'; } if ($column1->getDefault() != $column2->getDefault()) { $changedProperties[] = 'default'; } if ($column1->getUnsigned() != $column2->getUnsigned()) { $changedProperties[] = 'unsigned'; } if ($column1->getType() instanceof \Doctrine\DBAL\Types\StringType) { // check if value of length is set at all, default value assumed otherwise. $length1 = $column1->getLength() ?: 255; $length2 = $column2->getLength() ?: 255; if ($length1 != $length2) { $changedProperties[] = 'length'; } if ($column1->getFixed() != $column2->getFixed()) { $changedProperties[] = 'fixed'; } } if ($column1->getType() instanceof \Doctrine\DBAL\Types\DecimalType) { if (($column1->getPrecision()?:10) != ($column2->getPrecision()?:10)) { $changedProperties[] = 'precision'; } if ($column1->getScale() != $column2->getScale()) { $changedProperties[] = 'scale'; } } if ($column1->getAutoincrement() != $column2->getAutoincrement()) { $changedProperties[] = 'autoincrement'; } // only allow to delete comment if its set to '' not to null. if ($column1->getComment() !== null && $column1->getComment() != $column2->getComment()) { $changedProperties[] = 'comment'; } $options1 = $column1->getCustomSchemaOptions(); $options2 = $column2->getCustomSchemaOptions(); $commonKeys = array_keys(array_intersect_key($options1, $options2)); foreach ($commonKeys as $key) { if ($options1[$key] !== $options2[$key]) { $changedProperties[] = $key; } } $diffKeys = array_keys(array_diff_key($options1, $options2) + array_diff_key($options2, $options1)); $changedProperties = array_merge($changedProperties, $diffKeys); return $changedProperties; } /** * Finds the difference between the indexes $index1 and $index2. * * Compares $index1 with $index2 and returns $index2 if there are any * differences or false in case there are no differences. * * @param Index $index1 * @param Index $index2 * @return bool */ public function diffIndex(Index $index1, Index $index2) { if ($index1->isFullfilledBy($index2) && $index2->isFullfilledBy($index1)) { return false; } return true; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/Constraint.php0000644000175100017510000000260412143374463022337 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Marker interface for contraints * * * @link www.doctrine-project.org * @since 2.0 * @version $Revision$ * @author Benjamin Eberlei */ interface Constraint { public function getName(); public function getQuotedName(AbstractPlatform $platform); public function getColumns(); } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/DB2SchemaManager.php0000644000175100017510000001636712143374463023211 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Event\SchemaIndexDefinitionEventArgs; use Doctrine\DBAL\Events; /** * IBM Db2 Schema Manager * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 1.0 * @version $Revision$ * @author Benjamin Eberlei */ class DB2SchemaManager extends AbstractSchemaManager { /** * Return a list of all tables in the current database * * Apparently creator is the schema not the user who created it: * {@link http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=/com.ibm.db29.doc.sqlref/db2z_sysibmsystablestable.htm} * * @return array */ public function listTableNames() { $sql = $this->_platform->getListTablesSQL(); $sql .= " AND CREATOR = UPPER('".$this->_conn->getUsername()."')"; $tables = $this->_conn->fetchAll($sql); return $this->_getPortableTablesList($tables); } /** * Get Table Column Definition * * @param array $tableColumn * @return Column */ protected function _getPortableTableColumnDefinition($tableColumn) { $tableColumn = array_change_key_case($tableColumn, \CASE_LOWER); $length = null; $fixed = null; $unsigned = false; $scale = false; $precision = false; $type = $this->_platform->getDoctrineTypeMapping($tableColumn['typename']); switch (strtolower($tableColumn['typename'])) { case 'varchar': $length = $tableColumn['length']; $fixed = false; break; case 'character': $length = $tableColumn['length']; $fixed = true; break; case 'clob': $length = $tableColumn['length']; break; case 'decimal': case 'double': case 'real': $scale = $tableColumn['scale']; $precision = $tableColumn['length']; break; } $options = array( 'length' => $length, 'unsigned' => (bool)$unsigned, 'fixed' => (bool)$fixed, 'default' => ($tableColumn['default'] == "NULL") ? null : $tableColumn['default'], 'notnull' => (bool) ($tableColumn['nulls'] == 'N'), 'scale' => null, 'precision' => null, 'platformOptions' => array(), ); if ($scale !== null && $precision !== null) { $options['scale'] = $scale; $options['precision'] = $precision; } return new Column($tableColumn['colname'], \Doctrine\DBAL\Types\Type::getType($type), $options); } protected function _getPortableTablesList($tables) { $tableNames = array(); foreach ($tables as $tableRow) { $tableRow = array_change_key_case($tableRow, \CASE_LOWER); $tableNames[] = $tableRow['name']; } return $tableNames; } protected function _getPortableTableIndexesList($tableIndexes, $tableName=null) { $eventManager = $this->_platform->getEventManager(); $indexes = array(); foreach($tableIndexes as $indexKey => $data) { $data = array_change_key_case($data, \CASE_LOWER); $unique = ($data['uniquerule'] == "D") ? false : true; $primary = ($data['uniquerule'] == "P"); $indexName = strtolower($data['name']); if ($primary) { $keyName = 'primary'; } else { $keyName = $indexName; } $data = array( 'name' => $indexName, 'columns' => explode("+", ltrim($data['colnames'], '+')), 'unique' => $unique, 'primary' => $primary ); $index = null; $defaultPrevented = false; if (null !== $eventManager && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) { $eventArgs = new SchemaIndexDefinitionEventArgs($data, $tableName, $this->_conn); $eventManager->dispatchEvent(Events::onSchemaIndexDefinition, $eventArgs); $defaultPrevented = $eventArgs->isDefaultPrevented(); $index = $eventArgs->getIndex(); } if ( ! $defaultPrevented) { $index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary']); } if ($index) { $indexes[$indexKey] = $index; } } return $indexes; } protected function _getPortableTableForeignKeyDefinition($tableForeignKey) { $tableForeignKey = array_change_key_case($tableForeignKey, CASE_LOWER); $tableForeignKey['deleterule'] = $this->_getPortableForeignKeyRuleDef($tableForeignKey['deleterule']); $tableForeignKey['updaterule'] = $this->_getPortableForeignKeyRuleDef($tableForeignKey['updaterule']); return new ForeignKeyConstraint( array_map('trim', (array)$tableForeignKey['fkcolnames']), $tableForeignKey['reftbname'], array_map('trim', (array)$tableForeignKey['pkcolnames']), $tableForeignKey['relname'], array( 'onUpdate' => $tableForeignKey['updaterule'], 'onDelete' => $tableForeignKey['deleterule'], ) ); } protected function _getPortableForeignKeyRuleDef($def) { if ($def == "C") { return "CASCADE"; } else if ($def == "N") { return "SET NULL"; } return null; } protected function _getPortableViewDefinition($view) { $view = array_change_key_case($view, \CASE_LOWER); // sadly this still segfaults on PDO_IBM, see http://pecl.php.net/bugs/bug.php?id=17199 //$view['text'] = (is_resource($view['text']) ? stream_get_contents($view['text']) : $view['text']); if (!is_resource($view['text'])) { $pos = strpos($view['text'], ' AS '); $sql = substr($view['text'], $pos+4); } else { $sql = ''; } return new View($view['name'], $sql); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/DrizzleSchemaManager.php0000644000175100017510000000715512143374463024260 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema; /** * Schema manager for the Drizzle RDBMS. * * @author Kim Hemsø Rasmussen */ class DrizzleSchemaManager extends AbstractSchemaManager { protected function _getPortableTableColumnDefinition($tableColumn) { $tableName = $tableColumn['COLUMN_NAME']; $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' => empty($tableColumn['COLUMN_DEFAULT']) ? null : $tableColumn['COLUMN_DEFAULT'], 'autoincrement' => (bool)$tableColumn['IS_AUTO_INCREMENT'], 'scale' => (int)$tableColumn['NUMERIC_SCALE'], 'precision' => (int)$tableColumn['NUMERIC_PRECISION'], 'comment' => (isset($tableColumn['COLUMN_COMMENT']) ? $tableColumn['COLUMN_COMMENT'] : null), ); return new Column($tableName, \Doctrine\DBAL\Types\Type::getType($type), $options); } protected function _getPortableDatabaseDefinition($database) { return $database['SCHEMA_NAME']; } protected function _getPortableTableDefinition($table) { return $table['TABLE_NAME']; } public function _getPortableTableForeignKeyDefinition($tableForeignKey) { $columns = array(); foreach (explode(',', $tableForeignKey['CONSTRAINT_COLUMNS']) as $value) { $columns[] = trim($value, ' `'); } $ref_columns = array(); foreach (explode(',', $tableForeignKey['REFERENCED_TABLE_COLUMNS']) as $value) { $ref_columns[] = trim($value, ' `'); } return new ForeignKeyConstraint( $columns, $tableForeignKey['REFERENCED_TABLE_NAME'], $ref_columns, $tableForeignKey['CONSTRAINT_NAME'], array( 'onUpdate' => $tableForeignKey['UPDATE_RULE'], 'onDelete' => $tableForeignKey['DELETE_RULE'], ) ); } protected function _getPortableTableIndexesList($tableIndexes, $tableName = null) { $indexes = array(); foreach ($tableIndexes as $k) { $k['primary'] = (boolean)$k['primary']; $indexes[] = $k; } return parent::_getPortableTableIndexesList($indexes, $tableName); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/ForeignKeyConstraint.php0000644000175100017510000001151212143374463024320 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Schema\Visitor\Visitor; use Doctrine\DBAL\Platforms\AbstractPlatform; class ForeignKeyConstraint extends AbstractAsset implements Constraint { /** * @var Table */ protected $_localTable; /** * @var array */ protected $_localColumnNames; /** * @var string */ protected $_foreignTableName; /** * @var array */ protected $_foreignColumnNames; /** * @var string */ protected $_cascade = ''; /** * @var array */ protected $_options; /** * * @param array $localColumnNames * @param string $foreignTableName * @param array $foreignColumnNames * @param string $cascade * @param string|null $name */ public function __construct(array $localColumnNames, $foreignTableName, array $foreignColumnNames, $name=null, array $options=array()) { $this->_setName($name); $this->_localColumnNames = $localColumnNames; $this->_foreignTableName = $foreignTableName; $this->_foreignColumnNames = $foreignColumnNames; $this->_options = $options; } /** * @return string */ public function getLocalTableName() { return $this->_localTable->getName(); } /** * @param Table $table */ public function setLocalTable(Table $table) { $this->_localTable = $table; } /** * @return array */ public function getLocalColumns() { return $this->_localColumnNames; } public function getColumns() { return $this->_localColumnNames; } /** * @return string */ public function getForeignTableName() { return $this->_foreignTableName; } /** * Return the non-schema qualified foreign table name. * * @return string */ public function getUnqualifiedForeignTableName() { $parts = explode(".", $this->_foreignTableName); return strtolower(end($parts)); } /** * Get the quoted representation of this asset but only if it was defined with one. Otherwise * return the plain unquoted value as inserted. * * @param AbstractPlatform $platform * @return string */ public function getQuotedForeignTableName(AbstractPlatform $platform) { $keywords = $platform->getReservedKeywordsList(); $parts = explode(".", $this->getForeignTableName()); foreach ($parts AS $k => $v) { $parts[$k] = ($this->_quoted || $keywords->isKeyword($v)) ? $platform->quoteIdentifier($v) : $v; } return implode(".", $parts); } /** * @return array */ public function getForeignColumns() { return $this->_foreignColumnNames; } public function hasOption($name) { return isset($this->_options[$name]); } public function getOption($name) { return $this->_options[$name]; } /** * Gets the options associated with this constraint * * @return array */ public function getOptions() { return $this->_options; } /** * Foreign Key onUpdate status * * @return string|null */ public function onUpdate() { return $this->_onEvent('onUpdate'); } /** * Foreign Key onDelete status * * @return string|null */ public function onDelete() { return $this->_onEvent('onDelete'); } /** * @param string $event * @return string|null */ private function _onEvent($event) { if (isset($this->_options[$event])) { $onEvent = strtoupper($this->_options[$event]); if (!in_array($onEvent, array('NO ACTION', 'RESTRICT'))) { return $onEvent; } } return false; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/Index.php0000644000175100017510000001505212143374463021263 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Schema\Visitor\Visitor; class Index extends AbstractAsset implements Constraint { /** * @var array */ protected $_columns; /** * @var bool */ protected $_isUnique = false; /** * @var bool */ protected $_isPrimary = false; /** * Platform specific flags for indexes. * * @var array */ protected $_flags = array(); /** * @param string $indexName * @param array $column * @param bool $isUnique * @param bool $isPrimary */ public function __construct($indexName, array $columns, $isUnique = false, $isPrimary = false, array $flags = array()) { $isUnique = ($isPrimary)?true:$isUnique; $this->_setName($indexName); $this->_isUnique = $isUnique; $this->_isPrimary = $isPrimary; foreach ($columns as $column) { $this->_addColumn($column); } foreach ($flags as $flag) { $this->addFlag($flag); } } /** * @param string $column */ protected function _addColumn($column) { if(is_string($column)) { $this->_columns[] = $column; } else { throw new \InvalidArgumentException("Expecting a string as Index Column"); } } /** * @return array */ public function getColumns() { return $this->_columns; } /** * @return array */ public function getUnquotedColumns() { return array_map(array($this, 'trimQuotes'), $this->getColumns()); } /** * Is the index neither unique nor primary key? * * @return bool */ public function isSimpleIndex() { return !$this->_isPrimary && !$this->_isUnique; } /** * @return bool */ public function isUnique() { return $this->_isUnique; } /** * @return bool */ public function isPrimary() { return $this->_isPrimary; } /** * @param string $columnName * @param int $pos * @return bool */ public function hasColumnAtPosition($columnName, $pos = 0) { $columnName = $this->trimQuotes(strtolower($columnName)); $indexColumns = array_map('strtolower', $this->getUnquotedColumns()); return array_search($columnName, $indexColumns) === $pos; } /** * Check if this index exactly spans the given column names in the correct order. * * @param array $columnNames * @return boolean */ public function spansColumns(array $columnNames) { $sameColumns = true; for ($i = 0; $i < count($this->_columns); $i++) { if (!isset($columnNames[$i]) || $this->trimQuotes(strtolower($this->_columns[$i])) != $this->trimQuotes(strtolower($columnNames[$i]))) { $sameColumns = false; } } return $sameColumns; } /** * Check if the other index already fullfills all the indexing and constraint needs of the current one. * * @param Index $other * @return bool */ public function isFullfilledBy(Index $other) { // allow the other index to be equally large only. It being larger is an option // but it creates a problem with scenarios of the kind PRIMARY KEY(foo,bar) UNIQUE(foo) if (count($other->getColumns()) != count($this->getColumns())) { return false; } // Check if columns are the same, and even in the same order $sameColumns = $this->spansColumns($other->getColumns()); if ($sameColumns) { if ( ! $this->isUnique() && !$this->isPrimary()) { // this is a special case: If the current key is neither primary or unique, any uniqe or // primary key will always have the same effect for the index and there cannot be any constraint // overlaps. This means a primary or unique index can always fullfill the requirements of just an // index that has no constraints. return true; } else if ($other->isPrimary() != $this->isPrimary()) { return false; } else if ($other->isUnique() != $this->isUnique()) { return false; } return true; } return false; } /** * Detect if the other index is a non-unique, non primary index that can be overwritten by this one. * * @param Index $other * @return bool */ public function overrules(Index $other) { if ($other->isPrimary()) { return false; } else if ($this->isSimpleIndex() && $other->isUnique()) { return false; } if ($this->spansColumns($other->getColumns()) && ($this->isPrimary() || $this->isUnique())) { return true; } return false; } /** * Add 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 bool */ public function hasFlag($flag) { return isset($this->flags[strtolower($flag)]); } /** * Remove a flag * * @param string $flag * @return void */ public function removeFlag($flag) { unset($this->flags[strtolower($flag)]); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/MySqlSchemaManager.php0000644000175100017510000001643112143374463023677 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema; /** * Schema manager for the MySql RDBMS. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @author Konsta Vesterinen * @author Lukas Smith (PEAR MDB2 library) * @author Roman Borschel * @author Benjamin Eberlei * @version $Revision$ * @since 2.0 */ class MySqlSchemaManager extends AbstractSchemaManager { protected function _getPortableViewDefinition($view) { return new View($view['TABLE_NAME'], $view['VIEW_DEFINITION']); } protected function _getPortableTableDefinition($table) { return array_shift($table); } protected function _getPortableUserDefinition($user) { return array( 'user' => $user['User'], 'password' => $user['Password'], ); } protected function _getPortableTableIndexesList($tableIndexes, $tableName=null) { foreach($tableIndexes as $k => $v) { $v = array_change_key_case($v, CASE_LOWER); if($v['key_name'] == 'PRIMARY') { $v['primary'] = true; } else { $v['primary'] = false; } if (strpos($v['index_type'], 'FULLTEXT') !== false) { $v['flags'] = array('FULLTEXT'); } $tableIndexes[$k] = $v; } return parent::_getPortableTableIndexesList($tableIndexes, $tableName); } protected function _getPortableSequenceDefinition($sequence) { return end($sequence); } protected function _getPortableDatabaseDefinition($database) { return $database['Database']; } /** * Gets a portable column definition. * * The database type is mapped to a corresponding Doctrine mapping type. * * @param $tableColumn * @return array */ protected function _getPortableTableColumnDefinition($tableColumn) { $tableColumn = array_change_key_case($tableColumn, CASE_LOWER); $dbType = strtolower($tableColumn['type']); $dbType = strtok($dbType, '(), '); if (isset($tableColumn['length'])) { $length = $tableColumn['length']; $decimal = ''; } else { $length = strtok('(), '); $decimal = strtok('(), ') ? strtok('(), '):null; } $type = array(); $fixed = null; if ( ! isset($tableColumn['name'])) { $tableColumn['name'] = ''; } $scale = null; $precision = null; $type = $this->_platform->getDoctrineTypeMapping($dbType); $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type); $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type); switch ($dbType) { case 'char': $fixed = true; break; case 'float': case 'double': case 'real': case 'numeric': case 'decimal': if(preg_match('([A-Za-z]+\(([0-9]+)\,([0-9]+)\))', $tableColumn['type'], $match)) { $precision = $match[1]; $scale = $match[2]; $length = null; } break; case 'tinyint': case 'smallint': case 'mediumint': case 'int': case 'integer': case 'bigint': case 'tinyblob': case 'mediumblob': case 'longblob': case 'blob': case 'year': $length = null; break; } $length = ((int) $length == 0) ? null : (int) $length; $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'] : null ); if ($scale !== null && $precision !== null) { $options['scale'] = $scale; $options['precision'] = $precision; } return new Column($tableColumn['field'], \Doctrine\DBAL\Types\Type::getType($type), $options); } protected function _getPortableTableForeignKeysList($tableForeignKeys) { $list = array(); foreach ($tableForeignKeys as $key => $value) { $value = array_change_key_case($value, CASE_LOWER); if (!isset($list[$value['constraint_name']])) { if (!isset($value['delete_rule']) || $value['delete_rule'] == "RESTRICT") { $value['delete_rule'] = null; } if (!isset($value['update_rule']) || $value['update_rule'] == "RESTRICT") { $value['update_rule'] = null; } $list[$value['constraint_name']] = array( 'name' => $value['constraint_name'], 'local' => array(), 'foreign' => array(), 'foreignTable' => $value['referenced_table_name'], 'onDelete' => $value['delete_rule'], 'onUpdate' => $value['update_rule'], ); } $list[$value['constraint_name']]['local'][] = $value['column_name']; $list[$value['constraint_name']]['foreign'][] = $value['referenced_column_name']; } $result = array(); foreach($list as $constraint) { $result[] = new ForeignKeyConstraint( array_values($constraint['local']), $constraint['foreignTable'], array_values($constraint['foreign']), $constraint['name'], array( 'onDelete' => $constraint['onDelete'], 'onUpdate' => $constraint['onUpdate'], ) ); } return $result; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/OracleSchemaManager.php0000644000175100017510000002347712143374463024047 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema; /** * Oracle Schema Manager * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @author Konsta Vesterinen * @author Lukas Smith (PEAR MDB2 library) * @author Benjamin Eberlei * @version $Revision$ * @since 2.0 */ class OracleSchemaManager extends AbstractSchemaManager { protected function _getPortableViewDefinition($view) { $view = \array_change_key_case($view, CASE_LOWER); return new View($view['view_name'], $view['text']); } protected function _getPortableUserDefinition($user) { $user = \array_change_key_case($user, CASE_LOWER); return array( 'user' => $user['username'], ); } protected function _getPortableTableDefinition($table) { $table = \array_change_key_case($table, CASE_LOWER); return $table['table_name']; } /** * @license New BSD License * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html * @param array $tableIndexes * @param string $tableName * @return array */ protected function _getPortableTableIndexesList($tableIndexes, $tableName=null) { $indexBuffer = array(); foreach ( $tableIndexes as $tableIndex ) { $tableIndex = \array_change_key_case($tableIndex, CASE_LOWER); $keyName = strtolower($tableIndex['name']); if ( strtolower($tableIndex['is_primary']) == "p" ) { $keyName = 'primary'; $buffer['primary'] = true; $buffer['non_unique'] = false; } else { $buffer['primary'] = false; $buffer['non_unique'] = ( $tableIndex['is_unique'] == 0 ) ? true : false; } $buffer['key_name'] = $keyName; $buffer['column_name'] = $tableIndex['column_name']; $indexBuffer[] = $buffer; } return parent::_getPortableTableIndexesList($indexBuffer, $tableName); } protected function _getPortableTableColumnDefinition($tableColumn) { $tableColumn = \array_change_key_case($tableColumn, CASE_LOWER); $dbType = strtolower($tableColumn['data_type']); if(strpos($dbType, "timestamp(") === 0) { if (strpos($dbType, "WITH TIME ZONE")) { $dbType = "timestamptz"; } else { $dbType = "timestamp"; } } $type = array(); $length = $unsigned = $fixed = null; if ( ! empty($tableColumn['data_length'])) { $length = $tableColumn['data_length']; } if ( ! isset($tableColumn['column_name'])) { $tableColumn['column_name'] = ''; } if (stripos($tableColumn['data_default'], 'NULL') !== null) { $tableColumn['data_default'] = null; } $precision = null; $scale = null; $type = $this->_platform->getDoctrineTypeMapping($dbType); $type = $this->extractDoctrineTypeFromComment($tableColumn['comments'], $type); $tableColumn['comments'] = $this->removeDoctrineTypeFromComment($tableColumn['comments'], $type); switch ($dbType) { case 'number': if ($tableColumn['data_precision'] == 20 && $tableColumn['data_scale'] == 0) { $precision = 20; $scale = 0; $type = 'bigint'; } elseif ($tableColumn['data_precision'] == 5 && $tableColumn['data_scale'] == 0) { $type = 'smallint'; $precision = 5; $scale = 0; } elseif ($tableColumn['data_precision'] == 1 && $tableColumn['data_scale'] == 0) { $precision = 1; $scale = 0; $type = 'boolean'; } elseif ($tableColumn['data_scale'] > 0) { $precision = $tableColumn['data_precision']; $scale = $tableColumn['data_scale']; $type = 'decimal'; } $length = null; break; case 'pls_integer': case 'binary_integer': $length = null; break; case 'varchar': case 'varchar2': case 'nvarchar2': $length = $tableColumn['char_length']; $fixed = false; break; case 'char': case 'nchar': $length = $tableColumn['char_length']; $fixed = true; break; case 'date': case 'timestamp': $length = null; break; case 'float': $precision = $tableColumn['data_precision']; $scale = $tableColumn['data_scale']; $length = null; break; case 'clob': case 'nclob': $length = null; break; case 'blob': case 'raw': case 'long raw': case 'bfile': $length = null; break; case 'rowid': case 'urowid': default: $length = null; } $options = array( 'notnull' => (bool) ($tableColumn['nullable'] === 'N'), 'fixed' => (bool) $fixed, 'unsigned' => (bool) $unsigned, 'default' => $tableColumn['data_default'], 'length' => $length, 'precision' => $precision, 'scale' => $scale, 'comment' => (isset($tableColumn['comments'])) ? $tableColumn['comments'] : null, 'platformDetails' => array(), ); return new Column($tableColumn['column_name'], \Doctrine\DBAL\Types\Type::getType($type), $options); } protected function _getPortableTableForeignKeysList($tableForeignKeys) { $list = array(); foreach ($tableForeignKeys as $value) { $value = \array_change_key_case($value, CASE_LOWER); if (!isset($list[$value['constraint_name']])) { if ($value['delete_rule'] == "NO ACTION") { $value['delete_rule'] = null; } $list[$value['constraint_name']] = array( 'name' => $value['constraint_name'], 'local' => array(), 'foreign' => array(), 'foreignTable' => $value['references_table'], 'onDelete' => $value['delete_rule'], ); } $list[$value['constraint_name']]['local'][$value['position']] = $value['local_column']; $list[$value['constraint_name']]['foreign'][$value['position']] = $value['foreign_column']; } $result = array(); foreach($list as $constraint) { $result[] = new ForeignKeyConstraint( array_values($constraint['local']), $constraint['foreignTable'], array_values($constraint['foreign']), $constraint['name'], array('onDelete' => $constraint['onDelete']) ); } return $result; } protected function _getPortableSequenceDefinition($sequence) { $sequence = \array_change_key_case($sequence, CASE_LOWER); return new Sequence($sequence['sequence_name'], $sequence['increment_by'], $sequence['min_value']); } protected function _getPortableFunctionDefinition($function) { $function = \array_change_key_case($function, CASE_LOWER); return $function['name']; } protected function _getPortableDatabaseDefinition($database) { $database = \array_change_key_case($database, CASE_LOWER); return $database['username']; } public function createDatabase($database = null) { if (is_null($database)) { $database = $this->_conn->getDatabase(); } $params = $this->_conn->getParams(); $username = $database; $password = $params['password']; $query = 'CREATE USER ' . $username . ' IDENTIFIED BY ' . $password; $result = $this->_conn->executeUpdate($query); $query = 'GRANT CREATE SESSION, CREATE TABLE, UNLIMITED TABLESPACE, CREATE SEQUENCE, CREATE TRIGGER TO ' . $username; $result = $this->_conn->executeUpdate($query); return true; } public function dropAutoincrement($table) { $sql = $this->_platform->getDropAutoincrementSql($table); foreach ($sql as $query) { $this->_conn->executeUpdate($query); } return true; } public function dropTable($name) { $this->dropAutoincrement($name); return parent::dropTable($name); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php0000644000175100017510000003023712143374463024735 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema; /** * PostgreSQL Schema Manager * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @author Konsta Vesterinen * @author Lukas Smith (PEAR MDB2 library) * @author Benjamin Eberlei * @since 2.0 */ class PostgreSqlSchemaManager extends AbstractSchemaManager { /** * @var array */ private $existingSchemaPaths; /** * Get all the existing schema names. * * @return array */ public function getSchemaNames() { $rows = $this->_conn->fetchAll("SELECT nspname as schema_name FROM pg_namespace WHERE nspname !~ '^pg_.*' and nspname != 'information_schema'"); return array_map(function($v) { return $v['schema_name']; }, $rows); } /** * Return an array of schema search paths * * This is a PostgreSQL only function. * * @return array */ public function getSchemaSearchPaths() { $params = $this->_conn->getParams(); $schema = explode(",", $this->_conn->fetchColumn('SHOW search_path')); if (isset($params['user'])) { $schema = str_replace('"$user"', $params['user'], $schema); } return array_map('trim', $schema); } /** * Get names of all existing schemas in the current users search path. * * This is a PostgreSQL only function. * * @return array */ public function getExistingSchemaSearchPaths() { if ($this->existingSchemaPaths === null) { $this->determineExistingSchemaSearchPaths(); } return $this->existingSchemaPaths; } /** * Use this to set or reset the order of the existing schemas in the current search path of the user * * This is a PostgreSQL only function. * * @return void */ public function determineExistingSchemaSearchPaths() { $names = $this->getSchemaNames(); $paths = $this->getSchemaSearchPaths(); $this->existingSchemaPaths = array_filter($paths, function ($v) use ($names) { return in_array($v, $names); }); } protected function _getPortableTableForeignKeyDefinition($tableForeignKey) { $onUpdate = null; $onDelete = null; if (preg_match('(ON UPDATE ([a-zA-Z0-9]+( (NULL|ACTION|DEFAULT))?))', $tableForeignKey['condef'], $match)) { $onUpdate = $match[1]; } if (preg_match('(ON DELETE ([a-zA-Z0-9]+( (NULL|ACTION|DEFAULT))?))', $tableForeignKey['condef'], $match)) { $onDelete = $match[1]; } if (preg_match('/FOREIGN KEY \((.+)\) REFERENCES (.+)\((.+)\)/', $tableForeignKey['condef'], $values)) { // PostgreSQL returns identifiers that are keywords with quotes, we need them later, don't get // the idea to trim them here. $localColumns = array_map('trim', explode(",", $values[1])); $foreignColumns = array_map('trim', explode(",", $values[3])); $foreignTable = $values[2]; } return new ForeignKeyConstraint( $localColumns, $foreignTable, $foreignColumns, $tableForeignKey['conname'], array('onUpdate' => $onUpdate, 'onDelete' => $onDelete) ); } public function dropDatabase($database) { $params = $this->_conn->getParams(); $params["dbname"] = "postgres"; $tmpPlatform = $this->_platform; $tmpConn = $this->_conn; $this->_conn = \Doctrine\DBAL\DriverManager::getConnection($params); $this->_platform = $this->_conn->getDatabasePlatform(); parent::dropDatabase($database); $this->_platform = $tmpPlatform; $this->_conn = $tmpConn; } public function createDatabase($database) { $params = $this->_conn->getParams(); $params["dbname"] = "postgres"; $tmpPlatform = $this->_platform; $tmpConn = $this->_conn; $this->_conn = \Doctrine\DBAL\DriverManager::getConnection($params); $this->_platform = $this->_conn->getDatabasePlatform(); parent::createDatabase($database); $this->_platform = $tmpPlatform; $this->_conn = $tmpConn; } protected function _getPortableTriggerDefinition($trigger) { return $trigger['trigger_name']; } protected function _getPortableViewDefinition($view) { return new View($view['viewname'], $view['definition']); } protected function _getPortableUserDefinition($user) { return array( 'user' => $user['usename'], 'password' => $user['passwd'] ); } protected function _getPortableTableDefinition($table) { $schemas = $this->getExistingSchemaSearchPaths(); $firstSchema = array_shift($schemas); if ($table['schema_name'] == $firstSchema) { return $table['table_name']; } else { return $table['schema_name'] . "." . $table['table_name']; } } /** * @license New BSD License * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html * @param array $tableIndexes * @param string $tableName * @return array */ protected function _getPortableTableIndexesList($tableIndexes, $tableName=null) { $buffer = array(); foreach ($tableIndexes as $row) { $colNumbers = explode(' ', $row['indkey']); $colNumbersSql = 'IN (' . join(' ,', $colNumbers) . ' )'; $columnNameSql = "SELECT attnum, attname FROM pg_attribute WHERE attrelid={$row['indrelid']} AND attnum $colNumbersSql ORDER BY attnum ASC;"; $stmt = $this->_conn->executeQuery($columnNameSql); $indexColumns = $stmt->fetchAll(); // required for getting the order of the columns right. foreach ($colNumbers as $colNum) { foreach ($indexColumns as $colRow) { if ($colNum == $colRow['attnum']) { $buffer[] = array( 'key_name' => $row['relname'], 'column_name' => trim($colRow['attname']), 'non_unique' => !$row['indisunique'], 'primary' => $row['indisprimary'] ); } } } } return parent::_getPortableTableIndexesList($buffer, $tableName); } protected function _getPortableDatabaseDefinition($database) { return $database['datname']; } protected function _getPortableSequenceDefinition($sequence) { if ($sequence['schemaname'] != 'public') { $sequenceName = $sequence['schemaname'] . "." . $sequence['relname']; } else { $sequenceName = $sequence['relname']; } $data = $this->_conn->fetchAll('SELECT min_value, increment_by FROM ' . $sequenceName); return new Sequence($sequenceName, $data[0]['increment_by'], $data[0]['min_value']); } protected function _getPortableTableColumnDefinition($tableColumn) { $tableColumn = array_change_key_case($tableColumn, CASE_LOWER); if (strtolower($tableColumn['type']) === 'varchar') { // get length from varchar definition $length = preg_replace('~.*\(([0-9]*)\).*~', '$1', $tableColumn['complete_type']); $tableColumn['length'] = $length; } $matches = array(); $autoincrement = false; if (preg_match("/^nextval\('(.*)'(::.*)?\)$/", $tableColumn['default'], $matches)) { $tableColumn['sequence'] = $matches[1]; $tableColumn['default'] = null; $autoincrement = true; } if (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': $length = null; break; case 'text': $fixed = false; break; case 'varchar': case 'interval': case '_varchar': $fixed = false; break; case 'char': case 'bpchar': $fixed = true; break; case 'float': case 'float4': case 'float8': case 'double': case 'double precision': case 'real': case 'decimal': case 'money': case 'numeric': if (preg_match('([A-Za-z]+\(([0-9]+)\,([0-9]+)\))', $tableColumn['complete_type'], $match)) { $precision = $match[1]; $scale = $match[2]; $length = null; } break; case 'year': $length = null; break; } if ($tableColumn['default'] && preg_match("('([^']+)'::)", $tableColumn['default'], $match)) { $tableColumn['default'] = $match[1]; } $options = array( 'length' => $length, 'notnull' => (bool) $tableColumn['isnotnull'], 'default' => $tableColumn['default'], 'primary' => (bool) ($tableColumn['pri'] == 't'), 'precision' => $precision, 'scale' => $scale, 'fixed' => $fixed, 'unsigned' => false, 'autoincrement' => $autoincrement, 'comment' => $tableColumn['comment'], ); return new Column($tableColumn['field'], \Doctrine\DBAL\Types\Type::getType($type), $options); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/Schema.php0000644000175100017510000002510012143374463021407 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Schema\Visitor\CreateSchemaSqlCollector; use Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector; use Doctrine\DBAL\Schema\Visitor\Visitor; /** * Object representation of a database schema * * Different vendors have very inconsistent naming with regard to the concept * of a "schema". Doctrine understands a schema as the entity that conceptually * wraps a set of database objects such as tables, sequences, indexes and * foreign keys that belong to each other into a namespace. A Doctrine Schema * has nothing to do with the "SCHEMA" defined as in PostgreSQL, it is more * related to the concept of "DATABASE" that exists in MySQL and PostgreSQL. * * Every asset in the doctrine schema has a name. A name consists of either a * namespace.local name pair or just a local unqualified name. * * The abstraction layer that covers a PostgreSQL schema is the namespace of an * database object (asset). A schema can have a name, which will be used as * default namespace for the unqualified database objects that are created in * the schema. * * In the case of MySQL where cross-database queries are allowed this leads to * databases being "misinterpreted" as namespaces. This is intentional, however * the CREATE/DROP SQL visitors will just filter this queries and do not * execute them. Only the queries for the currently connected database are * executed. * * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ class Schema extends AbstractAsset { /** * @var array */ protected $_tables = array(); /** * @var array */ protected $_sequences = array(); /** * @var SchemaConfig */ protected $_schemaConfig = false; /** * @param array $tables * @param array $sequences * @param array $views * @param array $triggers * @param SchemaConfig $schemaConfig */ public function __construct(array $tables=array(), array $sequences=array(), SchemaConfig $schemaConfig=null) { if ($schemaConfig == null) { $schemaConfig = new SchemaConfig(); } $this->_schemaConfig = $schemaConfig; $this->_setName($schemaConfig->getName() ?: 'public'); foreach ($tables as $table) { $this->_addTable($table); } foreach ($sequences as $sequence) { $this->_addSequence($sequence); } } /** * @return bool */ public function hasExplicitForeignKeyIndexes() { return $this->_schemaConfig->hasExplicitForeignKeyIndexes(); } /** * @param Table $table */ protected function _addTable(Table $table) { $tableName = $table->getFullQualifiedName($this->getName()); if(isset($this->_tables[$tableName])) { throw SchemaException::tableAlreadyExists($tableName); } $this->_tables[$tableName] = $table; $table->setSchemaConfig($this->_schemaConfig); } /** * @param Sequence $sequence */ protected function _addSequence(Sequence $sequence) { $seqName = $sequence->getFullQualifiedName($this->getName()); if (isset($this->_sequences[$seqName])) { throw SchemaException::sequenceAlreadyExists($seqName); } $this->_sequences[$seqName] = $sequence; } /** * Get all tables of this schema. * * @return array */ public function getTables() { return $this->_tables; } /** * @param string $tableName * @return Table */ public function getTable($tableName) { $tableName = $this->getFullQualifiedAssetName($tableName); if (!isset($this->_tables[$tableName])) { throw SchemaException::tableDoesNotExist($tableName); } return $this->_tables[$tableName]; } /** * @return string */ private function getFullQualifiedAssetName($name) { if ($this->isIdentifierQuoted($name)) { $name = $this->trimQuotes($name); } if (strpos($name, ".") === false) { $name = $this->getName() . "." . $name; } return strtolower($name); } /** * Does this schema have a table with the given name? * * @param string $tableName * @return Schema */ public function hasTable($tableName) { $tableName = $this->getFullQualifiedAssetName($tableName); return isset($this->_tables[$tableName]); } /** * Get all table names, prefixed with a schema name, even the default one * if present. * * @return array */ public function getTableNames() { return array_keys($this->_tables); } public function hasSequence($sequenceName) { $sequenceName = $this->getFullQualifiedAssetName($sequenceName); return isset($this->_sequences[$sequenceName]); } /** * @throws SchemaException * @param string $sequenceName * @return \Doctrine\DBAL\Schema\Sequence */ public function getSequence($sequenceName) { $sequenceName = $this->getFullQualifiedAssetName($sequenceName); if(!$this->hasSequence($sequenceName)) { throw SchemaException::sequenceDoesNotExist($sequenceName); } return $this->_sequences[$sequenceName]; } /** * @return \Doctrine\DBAL\Schema\Sequence[] */ public function getSequences() { return $this->_sequences; } /** * Create a new table * * @param string $tableName * @return Table */ public function createTable($tableName) { $table = new Table($tableName); $this->_addTable($table); foreach ($this->_schemaConfig->getDefaultTableOptions() as $name => $value) { $table->addOption($name, $value); } return $table; } /** * Rename a table * * @param string $oldTableName * @param string $newTableName * @return Schema */ public function renameTable($oldTableName, $newTableName) { $table = $this->getTable($oldTableName); $table->_setName($newTableName); $this->dropTable($oldTableName); $this->_addTable($table); return $this; } /** * Drop a table from the schema. * * @param string $tableName * @return Schema */ public function dropTable($tableName) { $tableName = $this->getFullQualifiedAssetName($tableName); $table = $this->getTable($tableName); unset($this->_tables[$tableName]); return $this; } /** * Create a new sequence * * @param string $sequenceName * @param int $allocationSize * @param int $initialValue * @return Sequence */ public function createSequence($sequenceName, $allocationSize=1, $initialValue=1) { $seq = new Sequence($sequenceName, $allocationSize, $initialValue); $this->_addSequence($seq); return $seq; } /** * @param string $sequenceName * @return Schema */ public function dropSequence($sequenceName) { $sequenceName = $this->getFullQualifiedAssetName($sequenceName); unset($this->_sequences[$sequenceName]); return $this; } /** * Return an array of necessary sql queries to create the schema on the given platform. * * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform * @return array */ public function toSql(\Doctrine\DBAL\Platforms\AbstractPlatform $platform) { $sqlCollector = new CreateSchemaSqlCollector($platform); $this->visit($sqlCollector); return $sqlCollector->getQueries(); } /** * Return an array of necessary sql queries to drop the schema on the given platform. * * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform * @return array */ public function toDropSql(\Doctrine\DBAL\Platforms\AbstractPlatform $platform) { $dropSqlCollector = new DropSchemaSqlCollector($platform); $this->visit($dropSqlCollector); return $dropSqlCollector->getQueries(); } /** * @param Schema $toSchema * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform */ public function getMigrateToSql(Schema $toSchema, \Doctrine\DBAL\Platforms\AbstractPlatform $platform) { $comparator = new Comparator(); $schemaDiff = $comparator->compare($this, $toSchema); return $schemaDiff->toSql($platform); } /** * @param Schema $fromSchema * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform */ public function getMigrateFromSql(Schema $fromSchema, \Doctrine\DBAL\Platforms\AbstractPlatform $platform) { $comparator = new Comparator(); $schemaDiff = $comparator->compare($fromSchema, $this); return $schemaDiff->toSql($platform); } /** * @param Visitor $visitor */ public function visit(Visitor $visitor) { $visitor->acceptSchema($this); foreach ($this->_tables as $table) { $table->visit($visitor); } foreach ($this->_sequences as $sequence) { $sequence->visit($visitor); } } /** * Cloning a Schema triggers a deep clone of all related assets. * * @return void */ public function __clone() { foreach ($this->_tables as $k => $table) { $this->_tables[$k] = clone $table; } foreach ($this->_sequences as $k => $sequence) { $this->_sequences[$k] = clone $sequence; } } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/SchemaConfig.php0000644000175100017510000000546112143374463022545 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema; /** * Configuration for a Schema * * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ class SchemaConfig { /** * @var bool */ protected $hasExplicitForeignKeyIndexes = false; /** * @var int */ protected $maxIdentifierLength = 63; /** * @var string */ protected $name; /** * @var array */ protected $defaultTableOptions = array(); /** * @return bool */ public function hasExplicitForeignKeyIndexes() { return $this->hasExplicitForeignKeyIndexes; } /** * @param bool $flag */ public function setExplicitForeignKeyIndexes($flag) { $this->hasExplicitForeignKeyIndexes = (bool)$flag; } /** * @param int $length */ public function setMaxIdentifierLength($length) { $this->maxIdentifierLength = (int)$length; } /** * @return int */ public function getMaxIdentifierLength() { return $this->maxIdentifierLength; } /** * Get default namespace of schema objects. * * @return string */ public function getName() { return $this->name; } /** * set default namespace name of schema objects. * * @param string $name the value to set. */ public function setName($name) { $this->name = $name; } /** * Get the default options that are passed to Table instances created with * Schema#createTable(). * * @return array */ public function getDefaultTableOptions() { return $this->defaultTableOptions; } public function setDefaultTableOptions(array $defaultTableOptions) { $this->defaultTableOptions = $defaultTableOptions; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/SchemaDiff.php0000644000175100017510000001220212143374463022177 0ustar beberleibeberlei. */ 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 * @version $Revision$ * @author Benjamin Eberlei */ class SchemaDiff { /** * All added tables * * @var array(string=>ezcDbSchemaTable) */ public $newTables = array(); /** * All changed tables * * @var array(string=>ezcDbSchemaTableDiff) */ public $changedTables = array(); /** * All removed tables * * @var array(string=>Table) */ public $removedTables = array(); /** * @var array */ public $newSequences = array(); /** * @var array */ public $changedSequences = array(); /** * @var array */ public $removedSequences = array(); /** * @var array */ public $orphanedForeignKeys = array(); /** * Constructs an SchemaDiff object. * * @param array(string=>Table) $newTables * @param array(string=>TableDiff) $changedTables * @param array(string=>bool) $removedTables */ public function __construct($newTables = array(), $changedTables = array(), $removedTables = array()) { $this->newTables = $newTables; $this->changedTables = $changedTables; $this->removedTables = $removedTables; } /** * The to save sql mode ensures that the following things don't happen: * * 1. Tables are deleted * 2. Sequences are deleted * 3. Foreign Keys which reference tables that would otherwise be deleted. * * This way it is ensured that assets are deleted which might not be relevant to the metadata schema at all. * * @param AbstractPlatform $platform * @return array */ public function toSaveSql(AbstractPlatform $platform) { return $this->_toSql($platform, true); } /** * @param AbstractPlatform $platform * @return array */ public function toSql(AbstractPlatform $platform) { return $this->_toSql($platform, false); } /** * @param AbstractPlatform $platform * @param bool $saveMode * @return array */ protected function _toSql(AbstractPlatform $platform, $saveMode = false) { $sql = array(); if ($platform->supportsForeignKeyConstraints() && $saveMode == false) { foreach ($this->orphanedForeignKeys as $orphanedForeignKey) { $sql[] = $platform->getDropForeignKeySQL($orphanedForeignKey, $orphanedForeignKey->getLocalTableName()); } } if ($platform->supportsSequences() == true) { foreach ($this->changedSequences as $sequence) { $sql[] = $platform->getAlterSequenceSQL($sequence); } if ($saveMode === false) { foreach ($this->removedSequences as $sequence) { $sql[] = $platform->getDropSequenceSQL($sequence); } } foreach ($this->newSequences as $sequence) { $sql[] = $platform->getCreateSequenceSQL($sequence); } } $foreignKeySql = array(); foreach ($this->newTables as $table) { $sql = array_merge( $sql, $platform->getCreateTableSQL($table, AbstractPlatform::CREATE_INDEXES) ); if ($platform->supportsForeignKeyConstraints()) { foreach ($table->getForeignKeys() as $foreignKey) { $foreignKeySql[] = $platform->getCreateForeignKeySQL($foreignKey, $table); } } } $sql = array_merge($sql, $foreignKeySql); if ($saveMode === false) { foreach ($this->removedTables as $table) { $sql[] = $platform->getDropTableSQL($table); } } foreach ($this->changedTables as $tableDiff) { $sql = array_merge($sql, $platform->getAlterTableSQL($tableDiff)); } return $sql; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/SchemaException.php0000644000175100017510000000756412143374463023304 0ustar beberleibeberleigetName()." requires a named foreign key, ". "but the given foreign key from (".implode(", ", $foreignKey->getColumns()).") onto foreign table ". "'".$foreignKey->getForeignTableName()."' (".implode(", ", $foreignKey->getForeignColumns()).") is currently ". "unnamed." ); } static public function alterTableChangeNotSupported($changeName) { return new self ("Alter table change not supported, given '$changeName'"); } }DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/Sequence.php0000644000175100017510000000654712143374463021775 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Schema\Visitor\Visitor; /** * Sequence Structure * * * @link www.doctrine-project.org * @since 2.0 * @version $Revision$ * @author Benjamin Eberlei */ class Sequence extends AbstractAsset { /** * @var int */ protected $_allocationSize = 1; /** * @var int */ protected $_initialValue = 1; /** * * @param string $name * @param int $allocationSize * @param int $initialValue */ public function __construct($name, $allocationSize=1, $initialValue=1) { $this->_setName($name); $this->_allocationSize = (is_numeric($allocationSize))?$allocationSize:1; $this->_initialValue = (is_numeric($initialValue))?$initialValue:1; } public function getAllocationSize() { return $this->_allocationSize; } public function getInitialValue() { return $this->_initialValue; } public function setAllocationSize($allocationSize) { $this->_allocationSize = (is_numeric($allocationSize))?$allocationSize:1; } public function setInitialValue($initialValue) { $this->_initialValue = (is_numeric($initialValue))?$initialValue:1; } /** * Check 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 Table $table * * @return bool */ 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, $pkColumns[0]); return $tableSequenceName === $sequenceName; } /** * @param Visitor $visitor */ public function visit(Visitor $visitor) { $visitor->acceptSequence($this); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/SqliteSchemaManager.php0000644000175100017510000001454312143374463024075 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema; /** * SqliteSchemaManager * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @author Konsta Vesterinen * @author Lukas Smith (PEAR MDB2 library) * @author Jonathan H. Wage * @version $Revision$ * @since 2.0 */ class SqliteSchemaManager extends AbstractSchemaManager { /** * {@inheritdoc} * * @override */ public function dropDatabase($database) { if (file_exists($database)) { unlink($database); } } /** * {@inheritdoc} * * @override */ public function createDatabase($database) { $params = $this->_conn->getParams(); $driver = $params['driver']; $options = array( 'driver' => $driver, 'path' => $database ); $conn = \Doctrine\DBAL\DriverManager::getConnection($options); $conn->connect(); $conn->close(); } protected function _getPortableTableDefinition($table) { return $table['name']; } /** * @license New BSD License * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html * @param array $tableIndexes * @param string $tableName * @return array */ protected function _getPortableTableIndexesList($tableIndexes, $tableName=null) { $indexBuffer = array(); // fetch primary $stmt = $this->_conn->executeQuery( "PRAGMA TABLE_INFO ('$tableName')" ); $indexArray = $stmt->fetchAll(\PDO::FETCH_ASSOC); foreach($indexArray as $indexColumnRow) { if($indexColumnRow['pk'] == "1") { $indexBuffer[] = array( 'key_name' => 'primary', 'primary' => true, 'non_unique' => false, 'column_name' => $indexColumnRow['name'] ); } } // fetch regular indexes foreach($tableIndexes as $tableIndex) { // Ignore indexes with reserved names, e.g. autoindexes if (strpos($tableIndex['name'], 'sqlite_') !== 0) { $keyName = $tableIndex['name']; $idx = array(); $idx['key_name'] = $keyName; $idx['primary'] = false; $idx['non_unique'] = $tableIndex['unique']?false:true; $stmt = $this->_conn->executeQuery( "PRAGMA INDEX_INFO ( '{$keyName}' )" ); $indexArray = $stmt->fetchAll(\PDO::FETCH_ASSOC); foreach ( $indexArray as $indexColumnRow ) { $idx['column_name'] = $indexColumnRow['name']; $indexBuffer[] = $idx; } } } return parent::_getPortableTableIndexesList($indexBuffer, $tableName); } protected function _getPortableTableIndexDefinition($tableIndex) { return array( 'name' => $tableIndex['name'], 'unique' => (bool) $tableIndex['unique'] ); } protected function _getPortableTableColumnDefinition($tableColumn) { $e = explode('(', $tableColumn['type']); $tableColumn['type'] = $e[0]; if (isset($e[1])) { $length = trim($e[1], ')'); $tableColumn['length'] = $length; } $dbType = strtolower($tableColumn['type']); $length = isset($tableColumn['length']) ? $tableColumn['length'] : null; $unsigned = (boolean) isset($tableColumn['unsigned']) ? $tableColumn['unsigned'] : false; $fixed = false; $type = $this->_platform->getDoctrineTypeMapping($dbType); $default = $tableColumn['dflt_value']; if ($default == 'NULL') { $default = null; } if ($default !== null) { // SQLite returns strings wrapped in single quotes, so we need to strip them $default = preg_replace("/^'(.*)'$/", '\1', $default); } $notnull = (bool) $tableColumn['notnull']; if ( ! isset($tableColumn['name'])) { $tableColumn['name'] = ''; } $precision = null; $scale = null; switch ($dbType) { case 'char': $fixed = true; break; case 'float': case 'double': case 'real': case 'decimal': case 'numeric': if (isset($tableColumn['length'])) { 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); } protected function _getPortableViewDefinition($view) { return new View($view['name'], $view['sql']); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/SQLServerSchemaManager.php0000644000175100017510000002177712143374463024471 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Events; use Doctrine\DBAL\Event\SchemaIndexDefinitionEventArgs; use Doctrine\DBAL\Driver\SQLSrv\SQLSrvException; /** * SQL Server Schema Manager * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @author Konsta Vesterinen * @author Lukas Smith (PEAR MDB2 library) * @author Juozas Kaziukenas * @since 2.0 */ class SQLServerSchemaManager extends AbstractSchemaManager { /** * @override */ protected function _getPortableTableColumnDefinition($tableColumn) { $dbType = strtolower($tableColumn['TYPE_NAME']); $autoincrement = false; if (stripos($dbType, 'identity')) { $dbType = trim(str_ireplace('identity', '', $dbType)); $autoincrement = true; } $dbType = strtok($dbType, '(), '); $type = array(); $unsigned = $fixed = null; if (!isset($tableColumn['name'])) { $tableColumn['name'] = ''; } $default = $tableColumn['COLUMN_DEF']; while ($default != ($default2 = preg_replace("/^\((.*)\)$/", '$1', $default))) { $default = trim($default2, "'"); } $length = (int) $tableColumn['LENGTH']; $type = $this->_platform->getDoctrineTypeMapping($dbType); switch ($type) { case 'char': if ($tableColumn['LENGTH'] == '1') { $type = 'boolean'; if (preg_match('/^(is|has)/', $tableColumn['name'])) { $type = array_reverse($type); } } $fixed = true; break; case 'text': $fixed = false; break; } switch ($dbType) { case 'nchar': case 'nvarchar': case 'ntext': // Unicode data requires 2 bytes per character $length = $length / 2; break; } $options = array( 'length' => ($length == 0 || !in_array($type, array('text', 'string'))) ? null : $length, 'unsigned' => (bool) $unsigned, 'fixed' => (bool) $fixed, 'default' => $default !== 'NULL' ? $default : null, 'notnull' => (bool) ($tableColumn['IS_NULLABLE'] != 'YES'), 'scale' => $tableColumn['SCALE'], 'precision' => $tableColumn['PRECISION'], 'autoincrement' => $autoincrement, ); return new Column($tableColumn['COLUMN_NAME'], \Doctrine\DBAL\Types\Type::getType($type), $options); } /** * @override */ protected function _getPortableTableIndexesList($tableIndexRows, $tableName=null) { // TODO: Remove code duplication with AbstractSchemaManager; $result = array(); foreach ($tableIndexRows as $tableIndex) { $indexName = $keyName = $tableIndex['index_name']; if (strpos($tableIndex['index_description'], 'primary key') !== false) { $keyName = 'primary'; } $keyName = strtolower($keyName); $flags = array(); if (strpos($tableIndex['index_description'], 'clustered') !== false) { $flags[] = 'clustered'; } else if (strpos($tableIndex['index_description'], 'nonclustered') !== false) { $flags[] = 'nonclustered'; } $result[$keyName] = array( 'name' => $indexName, 'columns' => explode(', ', $tableIndex['index_keys']), 'unique' => strpos($tableIndex['index_description'], 'unique') !== false, 'primary' => strpos($tableIndex['index_description'], 'primary key') !== false, 'flags' => $flags, ); } $eventManager = $this->_platform->getEventManager(); $indexes = array(); foreach ($result as $indexKey => $data) { $index = null; $defaultPrevented = false; if (null !== $eventManager && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) { $eventArgs = new SchemaIndexDefinitionEventArgs($data, $tableName, $this->_conn); $eventManager->dispatchEvent(Events::onSchemaIndexDefinition, $eventArgs); $defaultPrevented = $eventArgs->isDefaultPrevented(); $index = $eventArgs->getIndex(); } if ( ! $defaultPrevented) { $index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary']); } if ($index) { $indexes[$indexKey] = $index; } } return $indexes; } /** * @override */ public function _getPortableTableForeignKeyDefinition($tableForeignKey) { return new ForeignKeyConstraint( (array) $tableForeignKey['ColumnName'], $tableForeignKey['ReferenceTableName'], (array) $tableForeignKey['ReferenceColumnName'], $tableForeignKey['ForeignKey'], array( 'onUpdate' => str_replace('_', ' ', $tableForeignKey['update_referential_action_desc']), 'onDelete' => str_replace('_', ' ', $tableForeignKey['delete_referential_action_desc']), ) ); } /** * @override */ protected function _getPortableTableDefinition($table) { return $table['name']; } /** * @override */ protected function _getPortableDatabaseDefinition($database) { return $database['name']; } /** * @override */ protected function _getPortableViewDefinition($view) { // @todo return new View($view['name'], null); } /** * List the indexes for a given table returning an array of Index instances. * * Keys of the portable indexes list are all lower-cased. * * @param string $table The name of the table * @return Index[] $tableIndexes */ public function listTableIndexes($table) { $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase()); try { $tableIndexes = $this->_conn->fetchAll($sql); } catch(\PDOException $e) { if ($e->getCode() == "IMSSP") { return array(); } else { throw $e; } } catch(SQLSrvException $e) { if (strpos($e->getMessage(), 'SQLSTATE [01000, 15472]') === 0) { return array(); } else { throw $e; } } return $this->_getPortableTableIndexesList($tableIndexes, $table); } /** * @override */ public function alterTable(TableDiff $tableDiff) { if(count($tableDiff->removedColumns) > 0) { foreach($tableDiff->removedColumns as $col){ $columnConstraintSql = $this->getColumnConstraintSQL($tableDiff->name, $col->getName()); foreach ($this->_conn->fetchAll($columnConstraintSql) as $constraint) { $this->_conn->exec("ALTER TABLE $tableDiff->name DROP CONSTRAINT " . $constraint['Name']); } } } return parent::alterTable($tableDiff); } /** * This function retrieves the constraints for a given column. */ private function getColumnConstraintSQL($table, $column) { return "SELECT SysObjects.[Name] FROM SysObjects INNER JOIN (SELECT [Name],[ID] FROM SysObjects WHERE XType = 'U') AS Tab ON Tab.[ID] = Sysobjects.[Parent_Obj] INNER JOIN sys.default_constraints DefCons ON DefCons.[object_id] = Sysobjects.[ID] INNER JOIN SysColumns Col ON Col.[ColID] = DefCons.[parent_column_id] AND Col.[ID] = Tab.[ID] WHERE Col.[Name] = " . $this->_conn->quote($column) ." AND Tab.[Name] = " . $this->_conn->quote($table) . " ORDER BY Col.[Name]"; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/Table.php0000644000175100017510000004515412143374463021251 0ustar beberleibeberlei. */ 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 * @version $Revision$ * @author Benjamin Eberlei */ class Table extends AbstractAsset { /** * @var string */ protected $_name = null; /** * @var array */ protected $_columns = array(); /** * @var array */ protected $_indexes = array(); /** * @var string */ protected $_primaryKeyName = false; /** * @var array */ protected $_fkConstraints = array(); /** * @var array */ protected $_options = array(); /** * @var SchemaConfig */ protected $_schemaConfig = null; /** * * @param string $tableName * @param array $columns * @param array $indexes * @param array $fkConstraints * @param int $idGeneratorType * @param array $options */ 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); $this->_idGeneratorType = $idGeneratorType; 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 */ public function setSchemaConfig(SchemaConfig $schemaConfig) { $this->_schemaConfig = $schemaConfig; } /** * @return int */ protected function _getMaxIdentifierLength() { if ($this->_schemaConfig instanceof SchemaConfig) { return $this->_schemaConfig->getMaxIdentifierLength(); } else { return 63; } } /** * Set Primary Key * * @param array $columns * @param string $indexName * @return Table */ public function setPrimaryKey(array $columns, $indexName = false) { $primaryKey = $this->_createIndex($columns, $indexName ?: "primary", true, true); foreach ($columns as $columnName) { $column = $this->getColumn($columnName); $column->setNotnull(true); } return $primaryKey; } /** * @param array $columnNames * @param string $indexName * @return Table */ public function addIndex(array $columnNames, $indexName = null) { if($indexName == null) { $indexName = $this->_generateIdentifierName( array_merge(array($this->getName()), $columnNames), "idx", $this->_getMaxIdentifierLength() ); } return $this->_createIndex($columnNames, $indexName, false, false); } /** * Drop an index from this table. * * @param string $indexName * @return void */ public function dropPrimaryKey() { $this->dropIndex($this->_primaryKeyName); $this->_primaryKeyName = false; } /** * Drop an index from this table. * * @param string $indexName * @return void */ public function dropIndex($indexName) { $indexName = strtolower($indexName); if ( ! $this->hasIndex($indexName)) { throw SchemaException::indexDoesNotExist($indexName, $this->_name); } unset($this->_indexes[$indexName]); } /** * * @param array $columnNames * @param string $indexName * @return Table */ public function addUniqueIndex(array $columnNames, $indexName = null) { if ($indexName === null) { $indexName = $this->_generateIdentifierName( array_merge(array($this->getName()), $columnNames), "uniq", $this->_getMaxIdentifierLength() ); } return $this->_createIndex($columnNames, $indexName, true, false); } /** * Check if an index begins in the order of the given columns. * * @param array $columnsNames * @return bool */ 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 bool $isUnique * @param bool $isPrimary * @return Table */ private function _createIndex(array $columnNames, $indexName, $isUnique, $isPrimary) { if (preg_match('(([^a-zA-Z0-9_]+))', $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); } } $this->_addIndex(new Index($indexName, $columnNames, $isUnique, $isPrimary)); return $this; } /** * @param string $columnName * @param string $columnType * @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; } /** * Rename Column * * @param string $oldColumnName * @param string $newColumnName * @return Table */ 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 Table */ public function changeColumn($columnName, array $options) { $column = $this->getColumn($columnName); $column->setOptions($options); return $this; } /** * Drop Column from Table * * @param string $columnName * @return Table */ public function dropColumn($columnName) { $columnName = strtolower($columnName); $column = $this->getColumn($columnName); unset($this->_columns[$columnName]); return $this; } /** * Add a foreign key constraint * * Name is inferred from the local columns * * @param Table $foreignTable * @param array $localColumns * @param array $foreignColumns * @param array $options * @param string $constraintName * @return Table */ 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); } /** * Add a foreign key constraint * * Name is to be generated by the database itsself. * * @deprecated Use {@link addForeignKeyConstraint} * @param Table $foreignTable * @param array $localColumns * @param array $foreignColumns * @param array $options * @return Table */ public function addUnnamedForeignKeyConstraint($foreignTable, array $localColumnNames, array $foreignColumnNames, array $options=array()) { return $this->addForeignKeyConstraint($foreignTable, $localColumnNames, $foreignColumnNames, $options); } /** * Add a foreign key constraint with a given name * * @deprecated Use {@link addForeignKeyConstraint} * @param string $name * @param Table $foreignTable * @param array $localColumns * @param array $foreignColumns * @param array $options * @return Table */ public function addNamedForeignKeyConstraint($name, $foreignTable, array $localColumnNames, array $foreignColumnNames, array $options=array()) { if ($foreignTable instanceof Table) { $foreignTableName = $foreignTable->getName(); foreach ($foreignColumnNames as $columnName) { if ( ! $foreignTable->hasColumn($columnName)) { throw SchemaException::columnDoesNotExist($columnName, $foreignTable->getName()); } } } else { $foreignTableName = $foreignTable; } foreach ($localColumnNames as $columnName) { if ( ! $this->hasColumn($columnName)) { throw SchemaException::columnDoesNotExist($columnName, $this->_name); } } $constraint = new ForeignKeyConstraint( $localColumnNames, $foreignTableName, $foreignColumnNames, $name, $options ); $this->_addForeignKeyConstraint($constraint); return $this; } /** * @param string $name * @param string $value * @return Table */ public function addOption($name, $value) { $this->_options[$name] = $value; return $this; } /** * @param Column $column */ protected function _addColumn(Column $column) { $columnName = $column->getName(); $columnName = strtolower($columnName); if (isset($this->_columns[$columnName])) { throw SchemaException::columnAlreadyExists($this->getName(), $columnName); } $this->_columns[$columnName] = $column; } /** * Add index to table * * @param Index $indexCandidate * @return Table */ protected function _addIndex(Index $indexCandidate) { // check for duplicates foreach ($this->_indexes as $existingIndex) { if ($indexCandidate->isFullfilledBy($existingIndex)) { return $this; } } $indexName = $indexCandidate->getName(); $indexName = strtolower($indexName); if (isset($this->_indexes[$indexName]) || ($this->_primaryKeyName != false && $indexCandidate->isPrimary())) { throw SchemaException::indexAlreadyExists($indexName, $this->_name); } // remove overruled indexes foreach ($this->_indexes as $idxKey => $existingIndex) { if ($indexCandidate->overrules($existingIndex)) { unset($this->_indexes[$idxKey]); } } if ($indexCandidate->isPrimary()) { $this->_primaryKeyName = $indexName; } $this->_indexes[$indexName] = $indexCandidate; return $this; } /** * @param ForeignKeyConstraint $constraint */ 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 = strtolower($name); $this->_fkConstraints[$name] = $constraint; // add an explicit index on the foreign key columns. If there is already an index that fullfils 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 compuation overhead in this case, however no duplicate indexes are ever added (based on columns). $this->addIndex($constraint->getColumns()); } /** * Does Table have a foreign key constraint with the given name? * * * @param string $constraintName * @return bool */ public function hasForeignKey($constraintName) { $constraintName = strtolower($constraintName); return isset($this->_fkConstraints[$constraintName]); } /** * @param string $constraintName * @return ForeignKeyConstraint */ public function getForeignKey($constraintName) { $constraintName = strtolower($constraintName); if(!$this->hasForeignKey($constraintName)) { throw SchemaException::foreignKeyDoesNotExist($constraintName, $this->_name); } return $this->_fkConstraints[$constraintName]; } public function removeForeignKey($constraintName) { $constraintName = strtolower($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; } /** * Does this table have a column with the given name? * * @param string $columnName * @return bool */ public function hasColumn($columnName) { $columnName = $this->trimQuotes(strtolower($columnName)); return isset($this->_columns[$columnName]); } /** * Get a column instance * * @param string $columnName * @return Column */ public function getColumn($columnName) { $columnName = strtolower($this->trimQuotes($columnName)); if ( ! $this->hasColumn($columnName)) { throw SchemaException::columnDoesNotExist($columnName, $this->_name); } return $this->_columns[$columnName]; } /** * @return Index|null */ public function getPrimaryKey() { if ( ! $this->hasPrimaryKey()) { return null; } return $this->getIndex($this->_primaryKeyName); } public function getPrimaryKeyColumns() { if ( ! $this->hasPrimaryKey()) { throw new DBALException("Table " . $this->getName() . " has no primary key."); } return $this->getPrimaryKey()->getColumns(); } /** * Check if this table has a primary key. * * @return bool */ public function hasPrimaryKey() { return ($this->_primaryKeyName && $this->hasIndex($this->_primaryKeyName)); } /** * @param string $indexName * @return bool */ public function hasIndex($indexName) { $indexName = strtolower($indexName); return (isset($this->_indexes[$indexName])); } /** * @param string $indexName * @return Index */ public function getIndex($indexName) { $indexName = strtolower($indexName); if ( ! $this->hasIndex($indexName)) { throw SchemaException::indexDoesNotExist($indexName, $this->_name); } return $this->_indexes[$indexName]; } /** * @return array */ public function getIndexes() { return $this->_indexes; } /** * Get Constraints * * @return array */ public function getForeignKeys() { return $this->_fkConstraints; } public function hasOption($name) { return isset($this->_options[$name]); } public function getOption($name) { return $this->_options[$name]; } public function getOptions() { return $this->_options; } /** * @param Visitor $visitor */ 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 */ 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); } } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/TableDiff.php0000644000175100017510000000700412143374463022032 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema; /** * Table 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 TableDiff { /** * @var string */ public $name = null; /** * @var string */ public $newName = false; /** * All added fields * * @var array(string=>Column) */ public $addedColumns; /** * All changed fields * * @var array(string=>Column) */ public $changedColumns = array(); /** * All removed fields * * @var array(string=>Column) */ public $removedColumns = array(); /** * Columns that are only renamed from key to column instance name. * * @var array(string=>Column) */ public $renamedColumns = array(); /** * All added indexes * * @var array(string=>Index) */ public $addedIndexes = array(); /** * All changed indexes * * @var array(string=>Index) */ public $changedIndexes = array(); /** * All removed indexes * * @var array(string=>bool) */ public $removedIndexes = array(); /** * All added foreign key definitions * * @var array */ public $addedForeignKeys = array(); /** * All changed foreign keys * * @var array */ public $changedForeignKeys = array(); /** * All removed foreign keys * * @var array */ public $removedForeignKeys = array(); /** * Constructs an TableDiff object. * * @param array(string=>Column) $addedColumns * @param array(string=>Column) $changedColumns * @param array(string=>bool) $removedColumns * @param array(string=>Index) $addedIndexes * @param array(string=>Index) $changedIndexes * @param array(string=>bool) $removedIndexes */ public function __construct($tableName, $addedColumns = array(), $changedColumns = array(), $removedColumns = array(), $addedIndexes = array(), $changedIndexes = array(), $removedIndexes = array()) { $this->name = $tableName; $this->addedColumns = $addedColumns; $this->changedColumns = $changedColumns; $this->removedColumns = $removedColumns; $this->addedIndexes = $addedIndexes; $this->changedIndexes = $changedIndexes; $this->removedIndexes = $removedIndexes; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/View.php0000644000175100017510000000311612143374463021124 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema; /** * Representation of a Database View * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 1.0 * @version $Revision$ * @author Benjamin Eberlei */ class View extends AbstractAsset { /** * @var string */ private $_sql; public function __construct($name, $sql) { $this->_setName($name); $this->_sql = $sql; } /** * @return string */ public function getSql() { return $this->_sql; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/Synchronizer/AbstractSchemaSynchronizer.php0000644000175100017510000000330512143374463030211 0ustar beberleibeberlei. */ 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 Connection */ protected $conn; public function __construct(Connection $conn) { $this->conn = $conn; } protected function processSqlSafely(array $sql) { foreach ($sql as $s) { try { $this->conn->exec($s); } catch(\Exception $e) { } } } protected function processSql(array $sql) { foreach ($sql as $s) { $this->conn->exec($s); } } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/Synchronizer/SchemaSynchronizer.php0000644000175100017510000000525112143374463026527 0ustar beberleibeberlei. */ 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 { /** * Get the SQL statements that can be executed to create the schema. * * @param Schema $createSchema * @return array */ function getCreateSchema(Schema $createSchema); /** * Get the SQL Statements to update given schema with the underlying db. * * @param Schema $toSchema * @param bool $noDrops * @return array */ function getUpdateSchema(Schema $toSchema, $noDrops = false); /** * Get the SQL Statements to drop the given schema from underlying db. * * @param Schema $dropSchema * @return array */ function getDropSchema(Schema $dropSchema); /** * Get the SQL statements to drop all schema assets from underlying db. * * @return array */ function getDropAllSchema(); /** * Create the Schema * * @param Schema $createSchema * @return void */ function createSchema(Schema $createSchema); /** * Update the Schema to new schema version. * * @param Schema $toSchema * @param bool $noDrops * @return void */ function updateSchema(Schema $toSchema, $noDrops = false); /** * Drop the given database schema from the underlying db. * * @param Schema $dropSchema * @return void */ function dropSchema(Schema $dropSchema); /** * Drop all assets from the underyling db. * * @return void */ function dropAllSchema(); } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/Synchronizer/SingleDatabaseSynchronizer.php0000644000175100017510000001323512143374463030176 0ustar beberleibeberlei. */ 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; public function __construct(Connection $conn) { parent::__construct($conn); $this->platform = $conn->getDatabasePlatform(); } /** * Get the SQL statements that can be executed to create the schema. * * @param Schema $createSchema * @return array */ public function getCreateSchema(Schema $createSchema) { return $createSchema->toSql($this->platform); } /** * Get the SQL Statements to update given schema with the underlying db. * * @param Schema $toSchema * @param bool $noDrops * @return array */ 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); } /** * Get the SQL Statements to drop the given schema from underlying db. * * @param Schema $dropSchema * @return array */ 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) { /* @var $sequence 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(); } /** * Get the SQL statements to drop all schema assets from underlying db. * * @return array */ 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(); } /** * Create the Schema * * @param Schema $createSchema * @return void */ public function createSchema(Schema $createSchema) { $this->processSql($this->getCreateSchema($createSchema)); } /** * Update the Schema to new schema version. * * @param Schema $toSchema * @param bool $noDrops * @return void */ public function updateSchema(Schema $toSchema, $noDrops = false) { $this->processSql($this->getUpdateSchema($toSchema, $noDrops)); } /** * Drop the given database schema from the underlying db. * * @param Schema $dropSchema * @return void */ public function dropSchema(Schema $dropSchema) { $this->processSqlSafely($this->getDropSchema($dropSchema)); } /** * Drop all assets from the underyling db. * * @return void */ public function dropAllSchema() { $this->processSql($this->getDropAllSchema()); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/Visitor/CreateSchemaSqlCollector.php0000644000175100017510000001167212143374463026532 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema\Visitor; use Doctrine\DBAL\Platforms\AbstractPlatform, Doctrine\DBAL\Schema\Table, Doctrine\DBAL\Schema\Schema, Doctrine\DBAL\Schema\Column, Doctrine\DBAL\Schema\ForeignKeyConstraint, Doctrine\DBAL\Schema\Constraint, Doctrine\DBAL\Schema\Sequence, Doctrine\DBAL\Schema\Index; class CreateSchemaSqlCollector implements Visitor { /** * @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; } /** * @param Schema $schema */ public function acceptSchema(Schema $schema) { } /** * Generate DDL Statements to create the accepted table with all its dependencies. * * @param Table $table */ public function acceptTable(Table $table) { $namespace = $this->getNamespace($table); $this->_createTableQueries[$namespace] = array_merge( $this->_createTableQueries[$namespace], $this->_platform->getCreateTableSQL($table) ); } public function acceptColumn(Table $table, Column $column) { } /** * @param Table $localTable * @param ForeignKeyConstraint $fkConstraint */ public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) { $namespace = $this->getNamespace($localTable); if ($this->_platform->supportsForeignKeyConstraints()) { $this->_createFkConstraintQueries[$namespace] = array_merge( $this->_createFkConstraintQueries[$namespace], (array) $this->_platform->getCreateForeignKeySQL( $fkConstraint, $localTable ) ); } } /** * @param Table $table * @param Index $index */ public function acceptIndex(Table $table, Index $index) { } /** * @param Sequence $sequence */ public function acceptSequence(Sequence $sequence) { $namespace = $this->getNamespace($sequence); $this->_createSequenceQueries[$namespace] = array_merge( $this->_createSequenceQueries[$namespace], (array)$this->_platform->getCreateSequenceSQL($sequence) ); } private function getNamespace($asset) { $namespace = $asset->getNamespaceName() ?: 'default'; if ( !isset($this->_createTableQueries[$namespace])) { $this->_createTableQueries[$namespace] = array(); $this->_createSequenceQueries[$namespace] = array(); $this->_createFkConstraintQueries[$namespace] = array(); } return $namespace; } /** * @return array */ public function resetQueries() { $this->_createTableQueries = array(); $this->_createSequenceQueries = array(); $this->_createFkConstraintQueries = array(); } /** * Get all queries collected so far. * * @return array */ public function getQueries() { $sql = array(); foreach (array_keys($this->_createTableQueries) as $namespace) { if ($this->_platform->supportsSchemas()) { // TODO: Create Schema here } } foreach ($this->_createTableQueries as $schemaSql) { $sql = array_merge($sql, $schemaSql); } foreach ($this->_createSequenceQueries as $schemaSql) { $sql = array_merge($sql, $schemaSql); } foreach ($this->_createFkConstraintQueries as $schemaSql) { $sql = array_merge($sql, $schemaSql); } return $sql; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/Visitor/DropSchemaSqlCollector.php0000644000175100017510000001001112143374463026215 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema\Visitor; use Doctrine\DBAL\Platforms\AbstractPlatform, Doctrine\DBAL\Schema\Table, Doctrine\DBAL\Schema\Schema, Doctrine\DBAL\Schema\Column, Doctrine\DBAL\Schema\ForeignKeyConstraint, Doctrine\DBAL\Schema\Constraint, Doctrine\DBAL\Schema\Sequence, Doctrine\DBAL\Schema\SchemaException, Doctrine\DBAL\Schema\Index; /** * Gather SQL statements that allow to completly drop the current schema. * * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei */ class DropSchemaSqlCollector implements Visitor { /** * @var \SplObjectStorage */ private $constraints; /** * @var \SplObjectStorage */ private $sequences; /** * @var \SplObjectStorage */ private $tables; /** * * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ private $platform; /** * @param AbstractPlatform $platform */ public function __construct(AbstractPlatform $platform) { $this->platform = $platform; $this->clearQueries(); } /** * @param Schema $schema */ public function acceptSchema(Schema $schema) { } /** * @param Table $table */ public function acceptTable(Table $table) { $this->tables->attach($table); } /** * @param Column $column */ public function acceptColumn(Table $table, Column $column) { } /** * @param Table $localTable * @param ForeignKeyConstraint $fkConstraint */ public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) { if (strlen($fkConstraint->getName()) == 0) { throw SchemaException::namedForeignKeyRequired($localTable, $fkConstraint); } $this->constraints->attach($fkConstraint); $this->constraints[$fkConstraint] = $localTable; } /** * @param Table $table * @param Index $index */ public function acceptIndex(Table $table, Index $index) { } /** * @param Sequence $sequence */ 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; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/Visitor/Graphviz.php0000644000175100017510000001200212143374463023435 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema\Visitor; use Doctrine\DBAL\Platforms\AbstractPlatform, Doctrine\DBAL\Schema\Table, Doctrine\DBAL\Schema\Schema, Doctrine\DBAL\Schema\Column, Doctrine\DBAL\Schema\ForeignKeyConstraint, Doctrine\DBAL\Schema\Constraint, Doctrine\DBAL\Schema\Sequence, Doctrine\DBAL\Schema\Index; class Graphviz implements \Doctrine\DBAL\Schema\Visitor\Visitor { private $output = ''; public function acceptColumn(Table $table, Column $column) { } 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', ) ); } public function acceptIndex(Table $table, Index $index) { } 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"; } public function acceptSequence(Sequence $sequence) { } public function acceptTable(Table $table) { $this->output .= $this->createNode( $table->getName(), array( 'label' => $this->createTableLabel( $table ), 'shape' => 'plaintext', ) ); } 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; } private function createNode( $name, $options ) { $node = $name . " ["; foreach( $options as $key => $value ) { $node .= $key . '=' . $value . ' '; } $node .= "]\n"; return $node; } private function createNodeRelation( $node1, $node2, $options ) { $relation = $node1 . ' -> ' . $node2 . ' ['; foreach( $options as $key => $value ) { $relation .= $key . '=' . $value . ' '; } $relation .= "]\n"; return $relation; } /** * Write 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->output . "}"); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/Visitor/RemoveNamespacedAssets.php0000644000175100017510000000712212143374463026253 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema\Visitor; use Doctrine\DBAL\Platforms\AbstractPlatform, Doctrine\DBAL\Schema\Table, Doctrine\DBAL\Schema\Schema, Doctrine\DBAL\Schema\Column, Doctrine\DBAL\Schema\ForeignKeyConstraint, Doctrine\DBAL\Schema\Constraint, Doctrine\DBAL\Schema\Sequence, Doctrine\DBAL\Schema\Index; /** * Remove 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 implements Visitor { /** * @var Schema */ private $schema; /** * @param Schema $schema */ public function acceptSchema(Schema $schema) { $this->schema = $schema; } /** * @param Table $table */ public function acceptTable(Table $table) { if ( ! $table->isInDefaultNamespace($this->schema->getName()) ) { $this->schema->dropTable($table->getName()); } } /** * @param Sequence $sequence */ public function acceptSequence(Sequence $sequence) { if ( ! $sequence->isInDefaultNamespace($this->schema->getName()) ) { $this->schema->dropSequence($sequence->getName()); } } /** * @param Column $column */ public function acceptColumn(Table $table, Column $column) { } /** * @param Table $localTable * @param ForeignKeyConstraint $fkConstraint */ 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()); } } /** * @param Table $table * @param Index $index */ public function acceptIndex(Table $table, Index $index) { } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Schema/Visitor/Visitor.php0000644000175100017510000000436112143374463023313 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Schema\Visitor; use Doctrine\DBAL\Platforms\AbstractPlatform, Doctrine\DBAL\Schema\Table, Doctrine\DBAL\Schema\Schema, Doctrine\DBAL\Schema\Column, Doctrine\DBAL\Schema\ForeignKeyConstraint, Doctrine\DBAL\Schema\Constraint, Doctrine\DBAL\Schema\Sequence, Doctrine\DBAL\Schema\Index; /** * Schema Visitor used for Validation or Generation purposes. * * * @link www.doctrine-project.org * @since 2.0 * @version $Revision$ * @author Benjamin Eberlei */ interface Visitor { /** * @param Schema $schema */ public function acceptSchema(Schema $schema); /** * @param Table $table */ public function acceptTable(Table $table); /** * @param Column $column */ public function acceptColumn(Table $table, Column $column); /** * @param Table $localTable * @param ForeignKeyConstraint $fkConstraint */ public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint); /** * @param Table $table * @param Index $index */ public function acceptIndex(Table $table, Index $index); /** * @param Sequence $sequence */ public function acceptSequence(Sequence $sequence); } DoctrineDBAL-2.3.4/Doctrine/DBAL/Sharding/PoolingShardConnection.php0000644000175100017510000001515412143374463025167 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Sharding; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Event\ConnectionEventArgs; use Doctrine\DBAL\Events; use Doctrine\DBAL\Driver; use Doctrine\DBAL\Configuration; use Doctrine\Common\EventManager; 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 int */ private $activeShardId; /** * @var array */ private $connections; /** * @var ShardManager */ private $shardManager; 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 specificy 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); } /** * Connect to a given shard * * @param mixed $shardId * @return bool */ 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 Event\ConnectionEventArgs($this); $this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs); } return true; } /** * Connect to a specific connection * * @param string $shardId * @return Driver */ 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); } public function isConnected($shardId = null) { if ($shardId === null) { return $this->_conn !== null; } return isset($this->activeConnections[$shardId]); } public function close() { $this->_conn = null; $this->activeConnections = null; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Sharding/PoolingShardManager.php0000644000175100017510000000563112143374463024441 0ustar beberleibeberlei. */ 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 { private $conn; private $choser; private $currentDistributionValue; public function __construct(PoolingShardConnection $conn) { $params = $conn->getParams(); $this->conn = $conn; $this->choser = $params['shardChoser']; } public function selectGlobal() { $this->conn->connect(0); $this->currentDistributionValue = null; } public function selectShard($distributionValue) { $shardId = $this->choser->pickShard($distributionValue, $this->conn); $this->conn->connect($shardId); $this->currentDistributionValue = $distributionValue; } public function getCurrentDistributionValue() { return $this->currentDistributionValue; } public function getShards() { $params = $this->conn->getParams(); $shards = array(); foreach ($params['shards'] as $shard) { $shards[] = array('id' => $shard['id']); } return $shards; } 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->selectShard($shard['id']); foreach ($this->conn->fetchAll($sql, $params, $types) as $row) { $result[] = $row; } } if ($oldDistribution === null) { $this->selectGlobal(); } else { $this->selectShard($oldDistribution); } return $result; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Sharding/ShardingException.php0000644000175100017510000000424412143374463024172 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Sharding; use Doctrine\DBAL\DBALException; /** * Sharding related Exceptions * * @since 2.3 */ class ShardingException extends DBALException { static public function notImplemented() { return new self("This functionality is not implemented with this sharding provider.", 1331557937); } static public function missingDefaultFederationName() { return new self("SQLAzure requires a federation name to be set during sharding configuration.", 1332141280); } static public function missingDefaultDistributionKey() { return new self("SQLAzure requires a distribution key to be set during sharding configuration.", 1332141329); } static public function activeTransaction() { return new self("Cannot switch shard during an active transaction.", 1332141766); } static public function noShardDistributionValue() { return new self("You have to specify a string or integer as shard distribution value.", 1332142103); } static public function missingDistributionType() { return new self("You have to specify a sharding distribution type such as 'integer', 'string', 'guid'."); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Sharding/ShardManager.php0000644000175100017510000000632412143374463023111 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Sharding; use Doctrine\DBAL\Connection; /** * 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 excecuted you * will hit the wrong shard. * * @author Benjamin Eberlei */ interface ShardManager { /** * Select global database with global data. * * This is the default database that is connected when no shard is * selected. * * @return void */ function selectGlobal(); /** * SELECT queries after this statement will be issued against the selected * shard. * * @throws ShardingException If no value is passed as shard identifier. * @param mixed $distributionValue * @param array $options * @return void */ function selectShard($distributionValue); /** * Get the distribution value currently used for sharding. * * @return string */ function getCurrentDistributionValue(); /** * Get information about the amount of shards and other details. * * Format is implementation specific, each shard is one element and has a * 'name' attribute at least. * * @return array */ function getShards(); /** * Query all shards in undefined order and return the results appended to * each other. Restore the previous distribution value after execution. * * Using {@link Connection::fetchAll} to retrieve rows internally. * * @param string $sql * @param array $params * @param array $types * @return array */ function queryAll($sql, array $params, array $types); } DoctrineDBAL-2.3.4/Doctrine/DBAL/Sharding/ShardChoser/MultiTenantShardChoser.php0000644000175100017510000000263312143374463027353 0ustar beberleibeberlei. */ 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 { public function pickShard($distributionValue, PoolingShardConnection $conn) { return $distributionValue; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Sharding/ShardChoser/ShardChoser.php0000644000175100017510000000304312143374463025162 0ustar beberleibeberlei. */ 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 { /** * Pick a shard for the given distribution value * * @param string $distributionValue * @param PoolingShardConnection $conn * @return int */ function pickShard($distributionValue, PoolingShardConnection $conn); } DoctrineDBAL-2.3.4/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php0000644000175100017510000002356012143374463030474 0ustar beberleibeberlei. */ 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\Sharding\SingleDatabaseSynchronizer; /** * 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\Sharding\SingleDatabaseSynchronizer}. * * @author Benjamin Eberlei */ class SQLAzureFederationsSynchronizer extends AbstractSchemaSynchronizer { const FEDERATION_TABLE_FEDERATED = 'azure.federated'; const FEDERATION_DISTRIBUTION_NAME = 'azure.federatedOnDistributionName'; /** * @var SQLAzureShardManager */ private $shardManager; /** * @var SchemaSynchronizer */ private $synchronizer; public function __construct(Connection $conn, SQLAzureShardManager $shardManager, SchemaSynchronizer $sync = null) { parent::__construct($conn); $this->shardManager = $shardManager; $this->synchronizer = $sync ?: new SingleDatabaseSynchronizer($conn); } /** * Get the SQL statements that can be executed to create the schema. * * @param Schema $createSchema * @return array */ 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; } /** * Get the SQL Statements to update given schema with the underlying db. * * @param Schema $toSchema * @param bool $noDrops * @return array */ public function getUpdateSchema(Schema $toSchema, $noDrops = false) { return $this->work($toSchema, function($synchronizer, $schema) use ($noDrops) { return $synchronizer->getUpdateSchema($schema, $noDrops); }); } /** * Get the SQL Statements to drop the given schema from underlying db. * * @param Schema $dropSchema * @return array */ public function getDropSchema(Schema $dropSchema) { return $this->work($dropSchema, function($synchronizer, $schema) { return $synchronizer->getDropSchema($schema); }); } /** * Create the Schema * * @param Schema $createSchema * @return void */ public function createSchema(Schema $createSchema) { $this->processSql($this->getCreateSchema($createSchema)); } /** * Update the Schema to new schema version. * * @param Schema $toSchema * @return void */ public function updateSchema(Schema $toSchema, $noDrops = false) { $this->processSql($this->getUpdateSchema($toSchema, $noDrops)); } /** * Drop the given database schema from the underlying db. * * @param Schema $dropSchema * @return void */ public function dropSchema(Schema $dropSchema) { $this->processSqlSafely($this->getDropSchema($dropSchema)); } /** * Get the SQL statements to drop all schema assets from underlying db. * * @return array */ 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; } /** * Drop all assets from the underyling db. * * @return void */ public function dropAllSchema() { $this->processSqlSafely($this->getDropAllSchema()); } private function partitionSchema(Schema $schema) { return array( $this->extractSchemaFederation($schema, false), $this->extractSchemaFederation($schema, true), ); } private function extractSchemaFederation(Schema $schema, $isFederation) { $partionedSchema = clone $schema; foreach ($partionedSchema->getTables() as $table) { if ($isFederation) { $table->addOption(self::FEDERATION_DISTRIBUTION_NAME, $this->shardManager->getDistributionKey()); } if ( $table->hasOption(self::FEDERATION_TABLE_FEDERATED) !== $isFederation) { $partionedSchema->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 $partionedSchema; } /** * Work on the Global/Federation based on currently existing shards and * perform the given operation on the underyling schema synchronizer given * the different partioned schema instances. * * @param 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; } 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; } 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)"; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php0000644000175100017510000001513112143374463026142 0ustar beberleibeberlei. */ 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 bool */ private $filteringEnabled; /** * @var string */ private $distributionKey; /** * @var string */ private $distributionType; /** * @var Connection */ private $conn; /** * @var string */ private $currentDistributionValue; /** * @param Connection $conn */ 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; } /** * Get name of the federation * * @return string */ public function getFederationName() { return $this->federationName; } /** * Get the distribution key * * @return string */ public function getDistributionKey() { return $this->distributionKey; } /** * Get the Doctrine Type name used for the distribution * * @return string */ public function getDistributionType() { return $this->distributionType; } /** * Enabled/Disable filtering on the fly. * * @param bool $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; } /** * Split Federation at a given distribution value. * * @param mixed $splitDistributionValue */ 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); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php0000644000175100017510000001213312143374463027242 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Sharding\SQLAzure\Schema; use Doctrine\DBAL\Schema\Visitor\Visitor, Doctrine\DBAL\Schema\Table, Doctrine\DBAL\Schema\Schema, Doctrine\DBAL\Schema\Column, Doctrine\DBAL\Schema\ForeignKeyConstraint, Doctrine\DBAL\Schema\Constraint, Doctrine\DBAL\Schema\Sequence, 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; public function __construct(array $excludedTables = array(), $tenantColumnName = 'tenant_id', $distributionName = null) { $this->excludedTables = $excludedTables; $this->tenantColumnName = $tenantColumnName; $this->distributionName = $distributionName ?: $tenantColumnName; } /** * @param Table $table */ 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'); } } private function getClusteredIndex($table) { foreach ($table->getIndexes() as $index) { if ($index->isPrimary() && ! $index->hasFlag('nonclustered')) { return $index; } else if ($index->hasFlag('clustered')) { return $index; } } throw new \RuntimeException("No clustered index found on table " . $table->getName()); } /** * @param Schema $schema */ public function acceptSchema(Schema $schema) { } /** * @param Column $column */ public function acceptColumn(Table $table, Column $column) { } /** * @param Table $localTable * @param ForeignKeyConstraint $fkConstraint */ public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) { } /** * @param Table $table * @param Index $index */ public function acceptIndex(Table $table, Index $index) { } /** * @param Sequence $sequence */ public function acceptSequence(Sequence $sequence) { } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php0000644000175100017510000001071012143374463025641 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Tools\Console\Command; use Symfony\Component\Console\Input\InputArgument, Symfony\Component\Console; /** * 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 Console\Command\Command { /** * @see Console\Command\Command */ 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) { $fileName = realpath($fileName); if ( ! file_exists($fileName)) { throw new \InvalidArgumentException( sprintf("SQL file '%s' does not exist.", $fileName) ); } else if ( ! is_readable($fileName)) { throw new \InvalidArgumentException( sprintf("SQL file '%s' does not have read permissions.", $fileName) ); } $output->write(sprintf("Processing file '%s'... ", $fileName)); $sql = file_get_contents($fileName); 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(); } } } } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php0000644000175100017510000001153312143374463027171 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Tools\Console\Command; use Symfony\Component\Console\Input\InputArgument, Symfony\Component\Console\Input\InputOption, Symfony\Component\Console\Command\Command, Symfony\Component\Console\Input\InputInterface, Symfony\Component\Console\Output\OutputInterface; use Doctrine\DBAL\Platforms\Keywords\ReservedKeywordsValidator; class ReservedWordsCommand extends Command { private $keywordListClasses = array( 'mysql' => 'Doctrine\DBAL\Platforms\Keywords\MySQLKeywords', 'mssql' => 'Doctrine\DBAL\Platforms\Keywords\MsSQLKeywords', 'sqlite' => 'Doctrine\DBAL\Platforms\Keywords\SQLiteKeywords', 'pgsql' => 'Doctrine\DBAL\Platforms\Keywords\PostgreSQLKeywords', 'oracle' => 'Doctrine\DBAL\Platforms\Keywords\OracleKeywords', 'db2' => 'Doctrine\DBAL\Platforms\Keywords\DB2Keywords', ); /** * If you want to add or replace a keywords list use this command * * @param string $name * @param string $class */ public function setKeywordListClass($name, $class) { $this->keywordListClasses[$name] = $class; } /** * @see Console\Command\Command */ 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 * pgsql * sqlite * oracle * mssql * db2 (Not checked by default) EOT ); } /** * @see Console\Command\Command */ 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', 'pgsql', 'sqlite', 'oracle', 'mssql'); } $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); } } } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php0000644000175100017510000000603712143374463025622 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Tools\Console\Command; use Symfony\Component\Console\Input\InputArgument, Symfony\Component\Console\Input\InputOption, Symfony\Component\Console; /** * 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 Console\Command\Command { /** * @see Console\Command\Command */ 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); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Tools/Console/Helper/ConnectionHelper.php0000644000175100017510000000407412143374463026176 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Tools\Console\Helper; use Symfony\Component\Console\Helper\Helper, Doctrine\DBAL\Connection; /** * Doctrine CLI Connection Helper. * * * @link www.doctrine-project.org * @since 2.0 * @version $Revision$ * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel */ class ConnectionHelper extends Helper { /** * Doctrine Database Connection * @var Connection */ protected $_connection; /** * Constructor * * @param Connection $connection Doctrine Database Connection */ public function __construct(Connection $connection) { $this->_connection = $connection; } /** * Retrieves Doctrine Database Connection * * @return Connection */ public function getConnection() { return $this->_connection; } /** * @see Helper */ public function getName() { return 'connection'; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Types/ArrayType.php0000644000175100017510000000416212143374463022040 0ustar beberleibeberlei. */ 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 { public function getSQLDeclaration(array $fieldDeclaration, \Doctrine\DBAL\Platforms\AbstractPlatform $platform) { return $platform->getClobTypeDeclarationSQL($fieldDeclaration); } public function convertToDatabaseValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform) { return serialize($value); } public function convertToPHPValue($value, \Doctrine\DBAL\Platforms\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; } public function getName() { return Type::TARRAY; } public function requiresSQLCommentHint(AbstractPlatform $platform) { return true; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Types/BigIntType.php0000644000175100017510000000330012143374463022127 0ustar beberleibeberlei. */ 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 { public function getName() { return Type::BIGINT; } public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getBigIntTypeDeclarationSQL($fieldDeclaration); } public function getBindingType() { return \PDO::PARAM_STR; } /** * {@inheritdoc} */ public function convertToPHPValue($value, AbstractPlatform $platform) { return (null === $value) ? null : (string) $value; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Types/BlobType.php0000644000175100017510000000435312143374463021642 0ustar beberleibeberlei. */ 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 { /** @override */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getBlobTypeDeclarationSQL($fieldDeclaration); } /** * Converts a value from its database representation to its PHP representation * of this type. * * @param mixed $value The value to convert. * @param AbstractPlatform $platform The currently used database platform. * @return mixed The PHP representation of the value. */ public function convertToPHPValue($value, AbstractPlatform $platform) { if (null === $value) { return null; } if (is_string($value)) { $value = fopen('data://text/plain;base64,' . base64_encode($value), 'r'); } if ( ! is_resource($value)) { throw ConversionException::conversionFailed($value, self::BLOB); } return $value; } public function getName() { return Type::BLOB; } public function getBindingType() { return \PDO::PARAM_LOB; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Types/BooleanType.php0000644000175100017510000000342412143374463022341 0ustar beberleibeberlei. */ 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 { public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getBooleanTypeDeclarationSQL($fieldDeclaration); } public function convertToDatabaseValue($value, AbstractPlatform $platform) { return $platform->convertBooleans($value); } public function convertToPHPValue($value, AbstractPlatform $platform) { return (null === $value) ? null : (bool) $value; } public function getName() { return Type::BOOLEAN; } public function getBindingType() { return \PDO::PARAM_BOOL; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Types/ConversionException.php0000644000175100017510000000502312143374463024121 0ustar beberleibeberlei. */ /** * Conversion Exception is thrown when the database to PHP conversion fails * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @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 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 * @return 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 ); } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Types/DateTimeType.php0000644000175100017510000000407612143374463022462 0ustar beberleibeberlei. */ 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 { public function getName() { return Type::DATETIME; } public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getDateTimeTypeDeclarationSQL($fieldDeclaration); } public function convertToDatabaseValue($value, AbstractPlatform $platform) { return ($value !== null) ? $value->format($platform->getDateTimeFormatString()) : null; } public function convertToPHPValue($value, AbstractPlatform $platform) { if ($value === null || $value instanceof \DateTime) { return $value; } $val = \DateTime::createFromFormat($platform->getDateTimeFormatString(), $value); if ( ! $val) { throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getDateTimeFormatString()); } return $val; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Types/DateTimeTzType.php0000644000175100017510000000632412143374463022776 0ustar beberleibeberlei. */ 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. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 1.0 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel */ class DateTimeTzType extends Type { public function getName() { return Type::DATETIMETZ; } public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getDateTimeTzTypeDeclarationSQL($fieldDeclaration); } public function convertToDatabaseValue($value, AbstractPlatform $platform) { return ($value !== null) ? $value->format($platform->getDateTimeTzFormatString()) : null; } 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; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Types/DateType.php0000644000175100017510000000403012143374463021631 0ustar beberleibeberlei. */ 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 { public function getName() { return Type::DATE; } public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getDateTypeDeclarationSQL($fieldDeclaration); } public function convertToDatabaseValue($value, AbstractPlatform $platform) { return ($value !== null) ? $value->format($platform->getDateFormatString()) : null; } 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; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Types/DecimalType.php0000644000175100017510000000303612143374463022317 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Type that maps an SQL DECIMAL to a PHP double. * * @since 2.0 */ class DecimalType extends Type { public function getName() { return Type::DECIMAL; } public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getDecimalTypeDeclarationSQL($fieldDeclaration); } public function convertToPHPValue($value, AbstractPlatform $platform) { return (null === $value) ? null : $value; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Types/FloatType.php0000644000175100017510000000360112143374463022024 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; class FloatType extends Type { public function getName() { return Type::FLOAT; } /** * @param array $fieldDeclaration * @param AbstractPlatform $platform * @return string */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getFloatDeclarationSQL($fieldDeclaration); } /** * Converts a value from its database representation to its PHP representation * of this type. * * @param mixed $value The value to convert. * @param AbstractPlatform $platform The currently used database platform. * @return mixed The PHP representation of the value. */ public function convertToPHPValue($value, AbstractPlatform $platform) { return (null === $value) ? null : (double) $value; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Types/GuidType.php0000644000175100017510000000274312143374463021655 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** * Represents a GUID/UUID datatype (both are actually synomys) in the database. * * @author Benjamin Eberlei * @since 2.3 */ class GuidType extends StringType { public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getGuidTypeDeclarationSQL($fieldDeclaration); } public function getName() { return Type::GUID; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Types/IntegerType.php0000644000175100017510000000326212143374463022357 0ustar beberleibeberlei. */ 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 { public function getName() { return Type::INTEGER; } public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getIntegerTypeDeclarationSQL($fieldDeclaration); } public function convertToPHPValue($value, AbstractPlatform $platform) { return (null === $value) ? null : (int) $value; } public function getBindingType() { return \PDO::PARAM_INT; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Types/JsonArrayType.php0000755000175100017510000000402712143374463022675 0ustar beberleibeberlei. */ 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 { public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getClobTypeDeclarationSQL($fieldDeclaration); } public function convertToDatabaseValue($value, AbstractPlatform $platform) { if (null === $value) { return null; } return json_encode($value); } public function convertToPHPValue($value, AbstractPlatform $platform) { if ($value === null) { return array(); } $value = (is_resource($value)) ? stream_get_contents($value) : $value; return json_decode($value, true); } public function getName() { return Type::JSON_ARRAY; } public function requiresSQLCommentHint(AbstractPlatform $platform) { return true; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Types/ObjectType.php0000644000175100017510000000416512143374463022173 0ustar beberleibeberlei. */ 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 { public function getSQLDeclaration(array $fieldDeclaration, \Doctrine\DBAL\Platforms\AbstractPlatform $platform) { return $platform->getClobTypeDeclarationSQL($fieldDeclaration); } public function convertToDatabaseValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform) { return serialize($value); } public function convertToPHPValue($value, \Doctrine\DBAL\Platforms\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; } public function getName() { return Type::OBJECT; } public function requiresSQLCommentHint(AbstractPlatform $platform) { return true; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Types/SimpleArrayType.php0000755000175100017510000000413412143374463023214 0ustar beberleibeberlei. */ 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 { public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getClobTypeDeclarationSQL($fieldDeclaration); } public function convertToDatabaseValue($value, AbstractPlatform $platform) { if (!$value) { return null; } return implode(',', $value); } public function convertToPHPValue($value, AbstractPlatform $platform) { if ($value === null) { return array(); } $value = (is_resource($value)) ? stream_get_contents($value) : $value; return explode(',', $value); } public function getName() { return Type::SIMPLE_ARRAY; } public function requiresSQLCommentHint(AbstractPlatform $platform) { return true; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Types/SmallIntType.php0000644000175100017510000000321512143374463022503 0ustar beberleibeberlei. */ 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 { public function getName() { return Type::SMALLINT; } public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getSmallIntTypeDeclarationSQL($fieldDeclaration); } public function convertToPHPValue($value, AbstractPlatform $platform) { return (null === $value) ? null : (int) $value; } public function getBindingType() { return \PDO::PARAM_INT; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Types/StringType.php0000644000175100017510000000314112143374463022224 0ustar beberleibeberlei. */ 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 { /** @override */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getVarcharTypeDeclarationSQL($fieldDeclaration); } /** @override */ public function getDefaultLength(AbstractPlatform $platform) { return $platform->getVarcharDefaultLength(); } /** @override */ public function getName() { return Type::STRING; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Types/TextType.php0000644000175100017510000000360712143374463021711 0ustar beberleibeberlei. */ 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 { /** @override */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { return $platform->getClobTypeDeclarationSQL($fieldDeclaration); } /** * Converts a value from its database representation to its PHP representation * of this type. * * @param mixed $value The value to convert. * @param AbstractPlatform $platform The currently used database platform. * @return mixed The PHP representation of the value. */ public function convertToPHPValue($value, AbstractPlatform $platform) { return (is_resource($value)) ? stream_get_contents($value) : $value; } public function getName() { return Type::TEXT; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Types/TimeType.php0000644000175100017510000000420712143374463021660 0ustar beberleibeberlei. */ 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 { 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; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Types/Type.php0000644000175100017510000002250012143374463021035 0ustar beberleibeberlei. */ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform, 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 BLOB = 'blob'; const FLOAT = 'float'; const GUID = 'guid'; /** Map of already instantiated type objects. One instance per type (flyweight). */ private static $_typeObjects = array(); /** The map of supported doctrine mapping types. */ 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::BLOB => 'Doctrine\DBAL\Types\BlobType', self::GUID => 'Doctrine\DBAL\Types\GuidType', ); /* Prevent instantiation and force 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 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 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. * * @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 AbstractPlatform $platform The currently used database platform. */ 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. * * @static * @throws DBALException * @param string $name The name of the type (as returned by getName()). * @return \Doctrine\DBAL\Types\Type */ 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. * * @static * @param string $name Name of the type. This should correspond to what getName() returns. * @param string $className The class name of the custom type. * @throws 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. * * @static * @param string $name 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. * * @static * @param string $name * @param string $className * @throws 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; } /** * Get the types array map which holds all registered types and the corresponding * type class * * @return array $typesMap */ public static function getTypesMap() { return self::$_typesMap; } 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 bool */ public function canRequireSQLConversion() { return false; } /** * Modifies the SQL expression (identifier, parameter) to convert to a database value. * * @param string $sqlExpr * @param 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 AbstractPlatform $platform * @return string */ public function convertToPHPValueSQL($sqlExpr, $platform) { return $sqlExpr; } /** * Get an array of database types that map to this Doctrine type. * * @param 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 AbstractPlatform $platform * @return bool */ public function requiresSQLCommentHint(AbstractPlatform $platform) { return false; } } DoctrineDBAL-2.3.4/Doctrine/DBAL/Types/VarDateTimeType.php0000644000175100017510000000440012143374463023122 0ustar beberleibeberlei. */ 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. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.com * @since 2.0 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel */ class VarDateTimeType extends DateTimeType { /** * @throws ConversionException * @param string $value * @param AbstractPlatform $platform * @return \DateTime */ 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; } } DoctrineDBAL-2.3.4/LICENSE0000644000175100017510000000205112143374463015032 0ustar beberleibeberleiCopyright (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.