Permalink
Browse files

[DBAL-203] SQLServerPlatform Refactoring

  • Loading branch information...
1 parent 6034634 commit b8033f8ef05d7a2da91c25af54dde662a8634fd1 @beberlei beberlei committed Jan 15, 2012
View
57 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
@mikaelkael

mikaelkael Jan 15, 2012

s/introced/introduced/ ?

+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
+ ));
@@ -1,7 +1,5 @@
<?php
/*
- * $Id$
- *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -65,12 +63,12 @@ private function _constructPdoDsn(array $params)
public function getDatabasePlatform()
{
- return new \Doctrine\DBAL\Platforms\MsSqlPlatform();
+ return new \Doctrine\DBAL\Platforms\SQLServer2005Platform();
}
public function getSchemaManager(\Doctrine\DBAL\Connection $conn)
{
- return new \Doctrine\DBAL\Schema\MsSqlSchemaManager($conn);
+ return new \Doctrine\DBAL\Schema\SQLServerSchemaManager($conn);
}
public function getName()
@@ -83,4 +81,4 @@ public function getDatabase(\Doctrine\DBAL\Connection $conn)
$params = $conn->getParams();
return $params['dbname'];
}
-}
+}
@@ -2454,6 +2454,13 @@ public function getTimeFormatString()
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);
@@ -2479,6 +2486,16 @@ protected function doModifyLimitQuery($query, $limit, $offset)
}
/**
+ * 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.
*
* @param string $column The column name for which to get the correct character casing.
@@ -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;
+ }
}
@@ -0,0 +1,66 @@
+<?php
+/*
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.doctrine-project.org>.
+ */
+
+namespace Doctrine\DBAL\Platforms;
+
+/**
+ * Platform to ensure compatibility of Doctrine with SQLServer2008 version.
+ *
+ * Differences to SQL Server 2005 and before are that a new DATETIME2 type was
+ * introduced that has a higher precision.
+ */
+class SQLServer2008Platform extends SQLServer2005Platform
+{
+ /**
+ * @override
+ */
+ public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
+ {
+ // 3 - microseconds precision length
+ // http://msdn.microsoft.com/en-us/library/ms187819.aspx
+ return 'DATETIME2(6)';
+ }
+
+ /**
+ * @override
+ */
+ public function getDateTypeDeclarationSQL(array $fieldDeclaration)
+ {
+ return 'DATE';
+ }
+
+ /**
+ * @override
+ */
+ public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
+ {
+ return 'TIME(0)';
+ }
+
+ /**
+ * Adding Datetime2 Type
+ */
+ protected function initializeDoctrineTypeMappings()
+ {
+ parent::initializeDoctrineTypeMappings();
+ $this->doctrineTypeMapping = array(
+ 'datetime2' => 'datetime',
+ );
+ }
+}
@@ -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 <roman@code-factory.org>
* @author Jonathan H. Wage <jonwage@gmail.com>
* @author Benjamin Eberlei <kontakt@beberlei.de>
- * @todo Rename: MsSQLPlatform
*/
-class MsSqlPlatform extends AbstractPlatform
+class SQLServerPlatform extends AbstractPlatform
{
/**
* {@inheritDoc}
@@ -599,24 +598,23 @@ protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef)
*/
public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
{
- // 6 - microseconds precision length
- return 'DATETIME2(6)';
+ return 'DATETIME';
}
/**
* @override
*/
public function getDateTypeDeclarationSQL(array $fieldDeclaration)
{
- return 'DATE';
+ return 'DATETIME';
}
/**
* @override
*/
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";
}
@@ -674,6 +665,14 @@ protected function doModifyLimitQuery($query, $limit, $offset = null)
/**
* @override
*/
+ public function supportsLimitOffset()
+ {
+ return false;
+ }
+
+ /**
+ * @override
+ */
public function convertBooleans($item)
{
if (is_array($item)) {
@@ -753,7 +752,6 @@ protected function initializeDoctrineTypeMappings()
'double precision' => 'float',
'date' => 'date',
'datetimeoffset' => 'datetimetz',
- 'datetime2' => 'datetime',
'smalldatetime' => 'datetime',
'datetime' => 'datetime',
'time' => 'time',
@@ -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 <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Juozas Kaziukenas <juozas@juokaz.com>
- * @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);
}
-}
+}
@@ -1,12 +0,0 @@
-<?php
-
-namespace Doctrine\Tests\DBAL\Functional\Schema;
-
-use Doctrine\DBAL\Schema;
-
-require_once __DIR__ . '/../../../TestInit.php';
-
-class MsSqlSchemaManagerTest extends SchemaManagerFunctionalTestCase
-{
-
-}
@@ -0,0 +1,10 @@
+<?php
+
+namespace Doctrine\Tests\DBAL\Functional\Schema;
+
+use Doctrine\DBAL\Schema;
+
+class SQLServerSchemaManagerTest extends SchemaManagerFunctionalTestCase
+{
+
+}
Oops, something went wrong.

0 comments on commit b8033f8

Please sign in to comment.