From b8033f8ef05d7a2da91c25af54dde662a8634fd1 Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Sun, 15 Jan 2012 19:36:38 +0100 Subject: [PATCH] [DBAL-203] SQLServerPlatform Refactoring --- UPGRADE | 57 ++++++++++++++++ lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php | 8 +-- .../DBAL/Platforms/AbstractPlatform.php | 17 +++++ .../DBAL/Platforms/SQLServer2005Platform.php | 27 +++++++- .../DBAL/Platforms/SQLServer2008Platform.php | 66 +++++++++++++++++++ ...sSqlPlatform.php => SQLServerPlatform.php} | 38 +++++------ ...Manager.php => SQLServerSchemaManager.php} | 8 +-- .../Schema/MsSqlSchemaManagerTest.php | 12 ---- .../Schema/SQLServerSchemaManagerTest.php | 10 +++ ...formTest.php => SQLServerPlatformTest.php} | 9 +-- 10 files changed, 202 insertions(+), 50 deletions(-) create mode 100644 lib/Doctrine/DBAL/Platforms/SQLServer2008Platform.php rename lib/Doctrine/DBAL/Platforms/{MsSqlPlatform.php => SQLServerPlatform.php} (97%) rename lib/Doctrine/DBAL/{Schema/MsSqlSchemaManager.php => SQLServerSchemaManager.php} (98%) delete mode 100644 tests/Doctrine/Tests/DBAL/Functional/Schema/MsSqlSchemaManagerTest.php create mode 100644 tests/Doctrine/Tests/DBAL/Functional/Schema/SQLServerSchemaManagerTest.php rename tests/Doctrine/Tests/DBAL/Platforms/{MsSqlPlatformTest.php => SQLServerPlatformTest.php} (97%) diff --git a/UPGRADE b/UPGRADE index c2cc79fed6a..49c5d8c3536 100644 --- a/UPGRADE +++ b/UPGRADE @@ -13,3 +13,60 @@ Doctrine\DBAL\Connection#executeQuery() got a new last parameter "QueryCacheProf The Driver statement was split into a ResultStatement and the normal statement extending from it. This seperates the configuration and the retrieval API from a statement. + +## MsSql Platform/SchemaManager renamed + +The MsSqlPlatform was renamed to SQLServerPlatform, the MsSqlSchemaManager was renamed +to SQLServerSchemaManager. + +## Cleanup SQLServer Platform version mess + +DBAL 2.1 and before were actually only compatible to SQL Server 2008, not earlier versions. +Still other parts of the platform did use old features instead of newly introced datatypes +in SQL Server 2005. Starting with DBAL 2.2 you can pick the Doctrine abstraction exactly +matching your SQL Server version. + +The PDO SqlSrv driver now uses the new `SQLServer2008Platform` as default platform. +This platform uses new features of SQL Server as of version 2008. This also includes a switch +in the used fields for "text" and "blob" field types to: + + "text" => "VARCHAR(MAX)" + "blob" => "VARBINARY(MAX)" + +Additionally `SQLServerPlatform` in DBAL 2.1 and before used "DATE", "TIME" and "DATETIME2" for dates. +This types are only available since version 2008 and the introduction of an explicit +SQLServer 2008 platform makes this dependency explicit. + +An `SQLServer2005Platform` was also introduced to differentiate the features between +versions 2003, earlier and 2005. + +With this change the `SQLServerPlatform` now throws an exception for using limit queries +with an offset, since SQLServer 2003 and lower do not support this feature. + +To use the old SQL Server Platform, because you are using SQL Server 2003 and below use +the following configuration code: + + use Doctrine\DBAL\DriverManager; + use Doctrine\DBAL\Platforms\SQLServerPlatform; + use Doctrine\DBAL\Platforms\SQLServer2005Platform; + + // You are using SQL Server 2003 or earlier + $conn = DriverManager::getConnection(array( + 'driver' => 'pdo_sqlsrv', + 'platform' => new SQLServerPlatform() + // .. additional parameters + )); + + // You are using SQL Server 2005 + $conn = DriverManager::getConnection(array( + 'driver' => 'pdo_sqlsrv', + 'platform' => new SQLServer2005Platform() + // .. additional parameters + )); + + // You are using SQL Server 2008 + $conn = DriverManager::getConnection(array( + 'driver' => 'pdo_sqlsrv', + // 2008 is default platform + // .. additional parameters + )); diff --git a/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php b/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php index d364eb937f7..949f179f541 100644 --- a/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php +++ b/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php @@ -1,7 +1,5 @@ getParams(); return $params['dbname']; } -} \ No newline at end of file +} diff --git a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php index 79fa95c202c..f54948a4cba 100644 --- a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php @@ -2454,6 +2454,13 @@ final public function modifyLimitQuery($query, $limit, $offset = null) 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); @@ -2478,6 +2485,16 @@ protected function doModifyLimitQuery($query, $limit, $offset) return $query; } + /** + * Does the database platform support offsets in modify limit clauses? + * + * @return bool + */ + public function supportsLimitOffset() + { + return true; + } + /** * Gets the character casing of a column in an SQL result set of this platform. * diff --git a/lib/Doctrine/DBAL/Platforms/SQLServer2005Platform.php b/lib/Doctrine/DBAL/Platforms/SQLServer2005Platform.php index 59c142f2c79..94d8e85ca0d 100644 --- a/lib/Doctrine/DBAL/Platforms/SQLServer2005Platform.php +++ b/lib/Doctrine/DBAL/Platforms/SQLServer2005Platform.php @@ -20,15 +20,20 @@ namespace Doctrine\DBAL\Platforms; /** - * Platform to ensure compatibility of Doctrine with the old SQLServer2005 version. + * 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 MsSqlPlatform +class SQLServer2005Platform extends SQLServerPlatform { public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) { @@ -44,5 +49,23 @@ public function getDateTimeFormatString() { return 'Y-m-d H:i:s.000'; } + + /** + */ + protected function initializeDoctrineTypeMappings() + { + parent::initializeDoctrineTypeMappings(); + $this->doctrineTypeMapping = array( + + ); + } + + /** + * @override + */ + public function supportsLimitOffset() + { + return true; + } } diff --git a/lib/Doctrine/DBAL/Platforms/SQLServer2008Platform.php b/lib/Doctrine/DBAL/Platforms/SQLServer2008Platform.php new file mode 100644 index 00000000000..794c85489d7 --- /dev/null +++ b/lib/Doctrine/DBAL/Platforms/SQLServer2008Platform.php @@ -0,0 +1,66 @@ +. + */ + +namespace Doctrine\DBAL\Platforms; + +/** + * Platform to ensure compatibility of Doctrine with SQLServer2008 version. + * + * Differences to SQL Server 2005 and before are that a new DATETIME2 type was + * introduced that has a higher precision. + */ +class SQLServer2008Platform extends SQLServer2005Platform +{ + /** + * @override + */ + public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) + { + // 3 - microseconds precision length + // http://msdn.microsoft.com/en-us/library/ms187819.aspx + return 'DATETIME2(6)'; + } + + /** + * @override + */ + public function getDateTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATE'; + } + + /** + * @override + */ + public function getTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIME(0)'; + } + + /** + * Adding Datetime2 Type + */ + protected function initializeDoctrineTypeMappings() + { + parent::initializeDoctrineTypeMappings(); + $this->doctrineTypeMapping = array( + 'datetime2' => 'datetime', + ); + } +} diff --git a/lib/Doctrine/DBAL/Platforms/MsSqlPlatform.php b/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php similarity index 97% rename from lib/Doctrine/DBAL/Platforms/MsSqlPlatform.php rename to lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php index a05302e4c98..0c0209c2c66 100644 --- a/lib/Doctrine/DBAL/Platforms/MsSqlPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php @@ -26,16 +26,15 @@ Doctrine\DBAL\Schema\Table; /** - * The MsSqlPlatform provides the behavior, features and SQL dialect of the - * MySQL database platform. + * 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 - * @todo Rename: MsSQLPlatform */ -class MsSqlPlatform extends AbstractPlatform +class SQLServerPlatform extends AbstractPlatform { /** * {@inheritDoc} @@ -599,8 +598,7 @@ protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) */ public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) { - // 6 - microseconds precision length - return 'DATETIME2(6)'; + return 'DATETIME'; } /** @@ -608,7 +606,7 @@ public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) */ public function getDateTypeDeclarationSQL(array $fieldDeclaration) { - return 'DATE'; + return 'DATETIME'; } /** @@ -616,7 +614,7 @@ public function getDateTypeDeclarationSQL(array $fieldDeclaration) */ public function getTimeTypeDeclarationSQL(array $fieldDeclaration) { - return 'TIME(0)'; + return 'DATETIME'; } /** @@ -631,23 +629,16 @@ public function getBooleanTypeDeclarationSQL(array $field) * Adds an adapter-specific LIMIT clause to the SELECT statement. * * @param string $query - * @param mixed $limit - * @param mixed $offset + * @param integer $limit + * @param integer $offset * @link http://lists.bestpractical.com/pipermail/rt-devel/2005-June/007339.html * @return string */ protected function doModifyLimitQuery($query, $limit, $offset = null) { if ($limit > 0) { - $count = intval($limit); - $offset = intval($offset); - - if ($offset < 0) { - throw new DBALException("LIMIT argument offset=$offset is not valid"); - } - if ($offset == 0) { - $query = preg_replace('/^(SELECT\s(DISTINCT\s)?)/i', '\1TOP ' . $count . ' ', $query); + $query = preg_replace('/^(SELECT\s(DISTINCT\s)?)/i', '\1TOP ' . $limit . ' ', $query); } else { $orderby = stristr($query, 'ORDER BY'); @@ -662,7 +653,7 @@ protected function doModifyLimitQuery($query, $limit, $offset = null) $query = preg_replace('/^SELECT\s/', '', $query); $start = $offset + 1; - $end = $offset + $count; + $end = $offset + $limit; $query = "SELECT * FROM (SELECT ROW_NUMBER() OVER ($over) AS \"doctrine_rownum\", $query) AS doctrine_tbl WHERE \"doctrine_rownum\" BETWEEN $start AND $end"; } @@ -671,6 +662,14 @@ protected function doModifyLimitQuery($query, $limit, $offset = null) return $query; } + /** + * @override + */ + public function supportsLimitOffset() + { + return false; + } + /** * @override */ @@ -753,7 +752,6 @@ protected function initializeDoctrineTypeMappings() 'double precision' => 'float', 'date' => 'date', 'datetimeoffset' => 'datetimetz', - 'datetime2' => 'datetime', 'smalldatetime' => 'datetime', 'datetime' => 'datetime', 'time' => 'time', diff --git a/lib/Doctrine/DBAL/Schema/MsSqlSchemaManager.php b/lib/Doctrine/DBAL/SQLServerSchemaManager.php similarity index 98% rename from lib/Doctrine/DBAL/Schema/MsSqlSchemaManager.php rename to lib/Doctrine/DBAL/SQLServerSchemaManager.php index 27d2053f11c..45a2c55db33 100644 --- a/lib/Doctrine/DBAL/Schema/MsSqlSchemaManager.php +++ b/lib/Doctrine/DBAL/SQLServerSchemaManager.php @@ -23,18 +23,16 @@ use Doctrine\DBAL\Event\SchemaIndexDefinitionEventArgs; /** - * xxx + * 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 - * @version $Revision$ * @since 2.0 */ -class MsSqlSchemaManager extends AbstractSchemaManager +class SQLServerSchemaManager extends AbstractSchemaManager { - /** * @override */ @@ -215,4 +213,4 @@ public function listTableIndexes($table) return $this->_getPortableTableIndexesList($tableIndexes, $table); } -} \ No newline at end of file +} diff --git a/tests/Doctrine/Tests/DBAL/Functional/Schema/MsSqlSchemaManagerTest.php b/tests/Doctrine/Tests/DBAL/Functional/Schema/MsSqlSchemaManagerTest.php deleted file mode 100644 index 6361d432dad..00000000000 --- a/tests/Doctrine/Tests/DBAL/Functional/Schema/MsSqlSchemaManagerTest.php +++ /dev/null @@ -1,12 +0,0 @@ -