Commit 2a6ec4d5 authored by Martin Hasoň's avatar Martin Hasoň

Added column collation support for MySQL, SQLite and PostgreSQL

parent 3faa3a65
...@@ -53,6 +53,7 @@ PostgreSQL ...@@ -53,6 +53,7 @@ PostgreSQL
^^^^^^^^^^ ^^^^^^^^^^
- ``PostgreSqlPlatform`` for all versions. - ``PostgreSqlPlatform`` for all versions.
- ``PostgreSQL91Platform`` for version 9.1 and above.
- ``PostgreSQL92Platform`` for version 9.2 and above. - ``PostgreSQL92Platform`` for version 9.2 and above.
SAP Sybase SQL Anywhere SAP Sybase SQL Anywhere
......
...@@ -2317,7 +2317,7 @@ abstract class AbstractPlatform ...@@ -2317,7 +2317,7 @@ abstract class AbstractPlatform
*/ */
public function getColumnCollationDeclarationSQL($collation) public function getColumnCollationDeclarationSQL($collation)
{ {
return ''; return $this->supportsColumnCollation() ? 'COLLATE ' . $collation : '';
} }
/** /**
...@@ -2948,6 +2948,16 @@ abstract class AbstractPlatform ...@@ -2948,6 +2948,16 @@ abstract class AbstractPlatform
return true; return true;
} }
/**
* Does this platform support column collation?
*
* @return boolean
*/
public function supportsColumnCollation()
{
return false;
}
/** /**
* Gets the format string, as accepted by the date() function, that describes * Gets the format string, as accepted by the date() function, that describes
* the format of a stored datetime value of this platform. * the format of a stored datetime value of this platform.
......
<?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 MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms\Keywords;
/**
* PostgreSQL 9.1 reserved keywords list.
*
* @author Martin Hasoň <martin.hason@gmail.com>
* @author Steve Müller <st.mueller@dzh-online.de>
* @link www.doctrine-project.org
* @since 2.5
*/
class PostgreSQL91Keywords extends PostgreSQLKeywords
{
/**
* {@inheritdoc}
*/
public function getName()
{
return 'PostgreSQL91';
}
/**
* {@inheritdoc}
*
* @link http://www.postgresql.org/docs/9.1/static/sql-keywords-appendix.html
*/
protected function getKeywords()
{
return array(
'ALL',
'ANALYSE',
'ANALYZE',
'AND',
'ANY',
'ARRAY',
'AS',
'ASC',
'ASYMMETRIC',
'AUTHORIZATION',
'BINARY',
'BOTH',
'CASE',
'CAST',
'CHECK',
'COLLATE',
'COLUMN',
'CONCURRENTLY',
'CONSTRAINT',
'CREATE',
'CROSS',
'CURRENT_CATALOG',
'CURRENT_DATE',
'CURRENT_ROLE',
'CURRENT_SCHEMA',
'CURRENT_TIME',
'CURRENT_TIMESTAMP',
'CURRENT_USER',
'DEFAULT',
'DEFERRABLE',
'DESC',
'DISTINCT',
'DO',
'ELSE',
'END',
'EXCEPT',
'FALSE',
'FETCH',
'FOR',
'FOREIGN',
'FREEZE',
'FROM',
'FULL',
'GRANT',
'GROUP',
'HAVING',
'ILIKE',
'IN',
'INITIALLY',
'INNER',
'INTERSECT',
'INTO',
'IS',
'ISNULL',
'JOIN',
'LEADING',
'LEFT',
'LIKE',
'LIMIT',
'LOCALTIME',
'LOCALTIMESTAMP',
'NATURAL',
'NOT',
'NOTNULL',
'NULL',
'OFFSET',
'ON',
'ONLY',
'OR',
'ORDER',
'OUTER',
'OVER',
'OVERLAPS',
'PLACING',
'PRIMARY',
'REFERENCES',
'RETURNING',
'RIGHT',
'SELECT',
'SESSION_USER',
'SIMILAR',
'SOME',
'SYMMETRIC',
'TABLE',
'THEN',
'TO',
'TRAILING',
'TRUE',
'UNION',
'UNIQUE',
'USER',
'USING',
'VARIADIC',
'VERBOSE',
'WHEN',
'WHERE',
'WINDOW',
'WITH',
);
}
}
...@@ -26,7 +26,7 @@ namespace Doctrine\DBAL\Platforms\Keywords; ...@@ -26,7 +26,7 @@ namespace Doctrine\DBAL\Platforms\Keywords;
* @link www.doctrine-project.org * @link www.doctrine-project.org
* @since 2.5 * @since 2.5
*/ */
class PostgreSQL92Keywords extends PostgreSQLKeywords class PostgreSQL92Keywords extends PostgreSQL91Keywords
{ {
/** /**
* {@inheritdoc} * {@inheritdoc}
...@@ -43,106 +43,8 @@ class PostgreSQL92Keywords extends PostgreSQLKeywords ...@@ -43,106 +43,8 @@ class PostgreSQL92Keywords extends PostgreSQLKeywords
*/ */
protected function getKeywords() protected function getKeywords()
{ {
return array( return array_merge(parent::getKeywords(), array(
'ALL',
'ANALYSE',
'ANALYZE',
'AND',
'ANY',
'ARRAY',
'AS',
'ASC',
'ASYMMETRIC',
'AUTHORIZATION',
'BINARY',
'BOTH',
'CASE',
'CAST',
'CHECK',
'COLLATE',
'COLLATION', 'COLLATION',
'COLUMN', ));
'CONCURRENTLY',
'CONSTRAINT',
'CREATE',
'CROSS',
'CURRENT_CATALOG',
'CURRENT_DATE',
'CURRENT_ROLE',
'CURRENT_SCHEMA',
'CURRENT_TIME',
'CURRENT_TIMESTAMP',
'CURRENT_USER',
'DEFAULT',
'DEFERRABLE',
'DESC',
'DISTINCT',
'DO',
'ELSE',
'END',
'EXCEPT',
'FALSE',
'FETCH',
'FOR',
'FOREIGN',
'FREEZE',
'FROM',
'FULL',
'GRANT',
'GROUP',
'HAVING',
'ILIKE',
'IN',
'INITIALLY',
'INNER',
'INTERSECT',
'INTO',
'IS',
'ISNULL',
'JOIN',
'LEADING',
'LEFT',
'LIKE',
'LIMIT',
'LOCALTIME',
'LOCALTIMESTAMP',
'NATURAL',
'NOT',
'NOTNULL',
'NULL',
'OFFSET',
'ON',
'ONLY',
'OR',
'ORDER',
'OUTER',
'OVER',
'OVERLAPS',
'PLACING',
'PRIMARY',
'REFERENCES',
'RETURNING',
'RIGHT',
'SELECT',
'SESSION_USER',
'SIMILAR',
'SOME',
'SYMMETRIC',
'TABLE',
'THEN',
'TO',
'TRAILING',
'TRUE',
'UNION',
'UNIQUE',
'USER',
'USING',
'VARIADIC',
'VERBOSE',
'WHEN',
'WHERE',
'WINDOW',
'WITH',
);
} }
} }
...@@ -334,6 +334,8 @@ class MySqlPlatform extends AbstractPlatform ...@@ -334,6 +334,8 @@ class MySqlPlatform extends AbstractPlatform
* Obtain DBMS specific SQL code portion needed to set the COLLATION * Obtain DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration to be used in statements like CREATE TABLE. * of a field declaration to be used in statements like CREATE TABLE.
* *
* @deprecated Deprecated since version 2.5, Use {@link self::getColumnCollationDeclarationSQL()} instead.
*
* @param string $collation name of the collation * @param string $collation name of the collation
* *
* @return string DBMS specific SQL code portion needed to set the COLLATION * @return string DBMS specific SQL code portion needed to set the COLLATION
...@@ -341,7 +343,7 @@ class MySqlPlatform extends AbstractPlatform ...@@ -341,7 +343,7 @@ class MySqlPlatform extends AbstractPlatform
*/ */
public function getCollationFieldDeclaration($collation) public function getCollationFieldDeclaration($collation)
{ {
return 'COLLATE ' . $collation; return $this->getColumnCollationDeclarationSQL($collation);
} }
/** /**
...@@ -376,6 +378,11 @@ class MySqlPlatform extends AbstractPlatform ...@@ -376,6 +378,11 @@ class MySqlPlatform extends AbstractPlatform
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function supportsColumnCollation()
{
return true;
}
public function getListTablesSQL() public function getListTablesSQL()
{ {
return "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'"; return "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'";
...@@ -387,13 +394,15 @@ class MySqlPlatform extends AbstractPlatform ...@@ -387,13 +394,15 @@ class MySqlPlatform extends AbstractPlatform
public function getListTableColumnsSQL($table, $database = null) public function getListTableColumnsSQL($table, $database = null)
{ {
if ($database) { if ($database) {
return "SELECT COLUMN_NAME AS Field, COLUMN_TYPE AS Type, IS_NULLABLE AS `Null`, ". $database = "'" . $database . "'";
"COLUMN_KEY AS `Key`, COLUMN_DEFAULT AS `Default`, EXTRA AS Extra, COLUMN_COMMENT AS Comment, " . } else {
"CHARACTER_SET_NAME AS CharacterSet, COLLATION_NAME AS CollationName ". $database = 'DATABASE()';
"FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = '" . $database . "' AND TABLE_NAME = '" . $table . "'";
} }
return 'DESCRIBE ' . $table; return "SELECT COLUMN_NAME AS Field, COLUMN_TYPE AS Type, IS_NULLABLE AS `Null`, ".
"COLUMN_KEY AS `Key`, COLUMN_DEFAULT AS `Default`, EXTRA AS Extra, COLUMN_COMMENT AS Comment, " .
"CHARACTER_SET_NAME AS CharacterSet, COLLATION_NAME AS Collation ".
"FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = " . $database . " AND TABLE_NAME = '" . $table . "'";
} }
/** /**
......
<?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 MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms;
/**
* Provides the behavior, features and SQL dialect of the PostgreSQL 9.1 database platform.
*
* @author Martin Hasoň <martin.hason@gmail.com>
* @link www.doctrine-project.org
* @since 2.5
*/
class PostgreSQL91Platform extends PostgreSqlPlatform
{
/**
* {@inheritDoc}
*/
public function supportsColumnCollation()
{
return true;
}
/**
* {@inheritdoc}
*/
protected function getReservedKeywordsClass()
{
return 'Doctrine\DBAL\Platforms\Keywords\PostgreSQL91Keywords';
}
/**
* {@inheritDoc}
*/
public function getColumnCollationDeclarationSQL($collation)
{
return 'COLLATE ' . $this->quoteSingleIdentifier($collation);
}
/**
* {@inheritDoc}
*/
public function getListTableColumnsSQL($table, $database = null)
{
$sql = parent::getListTableColumnsSQL($table, $database);
$parts = explode('AS complete_type,', $sql, 2);
return $parts[0].'AS complete_type, (SELECT tc.collcollate FROM pg_catalog.pg_collation tc WHERE tc.oid = a.attcollation) AS collation,'.$parts[1];
}
}
...@@ -26,7 +26,7 @@ namespace Doctrine\DBAL\Platforms; ...@@ -26,7 +26,7 @@ namespace Doctrine\DBAL\Platforms;
* @link www.doctrine-project.org * @link www.doctrine-project.org
* @since 2.5 * @since 2.5
*/ */
class PostgreSQL92Platform extends PostgreSqlPlatform class PostgreSQL92Platform extends PostgreSQL91Platform
{ {
/** /**
* {@inheritdoc} * {@inheritdoc}
......
...@@ -139,6 +139,14 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -139,6 +139,14 @@ class SQLServerPlatform extends AbstractPlatform
return 'dbo'; return 'dbo';
} }
/**
* {@inheritDoc}
*/
public function supportsColumnCollation()
{
return true;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
...@@ -1438,14 +1446,6 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -1438,14 +1446,6 @@ class SQLServerPlatform extends AbstractPlatform
return " DEFAULT '" . $field['default'] . "'"; return " DEFAULT '" . $field['default'] . "'";
} }
/**
* {@inheritdoc}
*/
public function getColumnCollationDeclarationSQL($collation)
{
return 'COLLATE ' . $collation;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
* *
...@@ -1456,8 +1456,8 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -1456,8 +1456,8 @@ class SQLServerPlatform extends AbstractPlatform
if (isset($field['columnDefinition'])) { if (isset($field['columnDefinition'])) {
$columnDef = $this->getCustomTypeDeclarationSQL($field); $columnDef = $this->getCustomTypeDeclarationSQL($field);
} else { } else {
$collation = (isset($field['collate']) && $field['collate']) ? $collation = (isset($field['collation']) && $field['collation']) ?
' ' . $this->getColumnCollationDeclarationSQL($field['collate']) : ''; ' ' . $this->getColumnCollationDeclarationSQL($field['collation']) : '';
$notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : ''; $notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : '';
......
...@@ -478,6 +478,14 @@ class SqlitePlatform extends AbstractPlatform ...@@ -478,6 +478,14 @@ class SqlitePlatform extends AbstractPlatform
return true; return true;
} }
/**
* {@inheritDoc}
*/
public function supportsColumnCollation()
{
return true;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
......
...@@ -440,7 +440,16 @@ class Comparator ...@@ -440,7 +440,16 @@ class Comparator
$changedProperties = array_merge($changedProperties, $diffKeys); $changedProperties = array_merge($changedProperties, $diffKeys);
return $changedProperties; $platformOptions1 = $column1->getPlatformOptions();
$platformOptions2 = $column2->getPlatformOptions();
foreach (array_keys(array_intersect_key($platformOptions1, $platformOptions2)) as $key) {
if ($platformOptions1[$key] !== $platformOptions2[$key]) {
$changedProperties[] = $key;
}
}
return array_unique($changedProperties);
} }
/** /**
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
namespace Doctrine\DBAL\Schema; namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Types\Type;
/** /**
* Schema manager for the MySql RDBMS. * Schema manager for the MySql RDBMS.
* *
...@@ -168,7 +170,7 @@ class MySqlSchemaManager extends AbstractSchemaManager ...@@ -168,7 +170,7 @@ class MySqlSchemaManager extends AbstractSchemaManager
'scale' => null, 'scale' => null,
'precision' => null, 'precision' => null,
'autoincrement' => (bool) (strpos($tableColumn['extra'], 'auto_increment') !== false), 'autoincrement' => (bool) (strpos($tableColumn['extra'], 'auto_increment') !== false),
'comment' => (isset($tableColumn['comment'])) ? $tableColumn['comment'] : null 'comment' => isset($tableColumn['comment']) ? $tableColumn['comment'] : null,
); );
if ($scale !== null && $precision !== null) { if ($scale !== null && $precision !== null) {
...@@ -176,7 +178,13 @@ class MySqlSchemaManager extends AbstractSchemaManager ...@@ -176,7 +178,13 @@ class MySqlSchemaManager extends AbstractSchemaManager
$options['precision'] = $precision; $options['precision'] = $precision;
} }
return new Column($tableColumn['field'], \Doctrine\DBAL\Types\Type::getType($type), $options); $column = new Column($tableColumn['field'], Type::getType($type), $options);
if (isset($tableColumn['collation'])) {
$column->setPlatformOption('collation', $tableColumn['collation']);
}
return $column;
} }
/** /**
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
namespace Doctrine\DBAL\Schema; namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Types\Type;
/** /**
* PostgreSQL Schema Manager. * PostgreSQL Schema Manager.
* *
...@@ -402,6 +404,12 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager ...@@ -402,6 +404,12 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager
'comment' => $tableColumn['comment'], 'comment' => $tableColumn['comment'],
); );
return new Column($tableColumn['field'], \Doctrine\DBAL\Types\Type::getType($type), $options); $column = new Column($tableColumn['field'], Type::getType($type), $options);
if (isset($tableColumn['collation']) && !empty($tableColumn['collation'])) {
$column->setPlatformOption('collation', $tableColumn['collation']);
}
return $column;
} }
} }
...@@ -99,12 +99,11 @@ class SQLServerSchemaManager extends AbstractSchemaManager ...@@ -99,12 +99,11 @@ class SQLServerSchemaManager extends AbstractSchemaManager
'comment' => $tableColumn['comment'] !== '' ? $tableColumn['comment'] : null, 'comment' => $tableColumn['comment'] !== '' ? $tableColumn['comment'] : null,
); );
$platformOptions = array(
'collate' => $tableColumn['collation'] == 'NULL' ? null : $tableColumn['collation']
);
$column = new Column($tableColumn['name'], Type::getType($type), $options); $column = new Column($tableColumn['name'], Type::getType($type), $options);
$column->setPlatformOptions($platformOptions);
if (isset($tableColumn['collation']) && $tableColumn['collation'] !== 'NULL') {
$column->setPlatformOption('collation', $tableColumn['collation']);
}
return $column; return $column;
} }
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
namespace Doctrine\DBAL\Schema; namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\DBALException; use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Types\StringType;
use Doctrine\DBAL\Types\TextType;
/** /**
* Sqlite SchemaManager. * Sqlite SchemaManager.
...@@ -217,8 +219,11 @@ class SqliteSchemaManager extends AbstractSchemaManager ...@@ -217,8 +219,11 @@ class SqliteSchemaManager extends AbstractSchemaManager
protected function _getPortableTableColumnList($table, $database, $tableColumns) protected function _getPortableTableColumnList($table, $database, $tableColumns)
{ {
$list = parent::_getPortableTableColumnList($table, $database, $tableColumns); $list = parent::_getPortableTableColumnList($table, $database, $tableColumns);
// find column with autoincrement
$autoincrementColumn = null; $autoincrementColumn = null;
$autoincrementCount = 0; $autoincrementCount = 0;
foreach ($tableColumns as $tableColumn) { foreach ($tableColumns as $tableColumn) {
if ('0' != $tableColumn['pk']) { if ('0' != $tableColumn['pk']) {
$autoincrementCount++; $autoincrementCount++;
...@@ -236,6 +241,18 @@ class SqliteSchemaManager extends AbstractSchemaManager ...@@ -236,6 +241,18 @@ class SqliteSchemaManager extends AbstractSchemaManager
} }
} }
// inspect column collation
$createSql = $this->_conn->fetchAll("SELECT sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type = 'table' AND name = '$table'");
$createSql = isset($createSql[0]['sql']) ? $createSql[0]['sql'] : '';
foreach ($list as $columnName => $column) {
$type = $column->getType();
if ($type instanceof StringType || $type instanceof TextType) {
$column->setPlatformOption('collation', $this->parseColumnCollationFromSQL($columnName, $createSql) ?: 'BINARY');
}
}
return $list; return $list;
} }
...@@ -393,4 +410,17 @@ class SqliteSchemaManager extends AbstractSchemaManager ...@@ -393,4 +410,17 @@ class SqliteSchemaManager extends AbstractSchemaManager
return $tableDiff; return $tableDiff;
} }
private function parseColumnCollationFromSQL($column, $sql)
{
if (preg_match(
'{(?:'.preg_quote($column).'|'.preg_quote($this->_platform->quoteSingleIdentifier($column)).')
[^,(]+(?:\([^()]+\)[^,]*)?
(?:(?:DEFAULT|CHECK)\s*(?:\(.*?\))?[^,]*)*
COLLATE\s+["\']?([^\s,"\')]+)}isx', $sql, $match)) {
return $match[1];
}
return false;
}
} }
...@@ -40,6 +40,7 @@ class ReservedWordsCommand extends Command ...@@ -40,6 +40,7 @@ class ReservedWordsCommand extends Command
'sqlserver2012' => 'Doctrine\DBAL\Platforms\Keywords\SQLServer2012Keywords', 'sqlserver2012' => 'Doctrine\DBAL\Platforms\Keywords\SQLServer2012Keywords',
'sqlite' => 'Doctrine\DBAL\Platforms\Keywords\SQLiteKeywords', 'sqlite' => 'Doctrine\DBAL\Platforms\Keywords\SQLiteKeywords',
'pgsql' => 'Doctrine\DBAL\Platforms\Keywords\PostgreSQLKeywords', 'pgsql' => 'Doctrine\DBAL\Platforms\Keywords\PostgreSQLKeywords',
'pgsql91' => 'Doctrine\DBAL\Platforms\Keywords\PostgreSQL91Keywords',
'pgsql92' => 'Doctrine\DBAL\Platforms\Keywords\PostgreSQL92Keywords', 'pgsql92' => 'Doctrine\DBAL\Platforms\Keywords\PostgreSQL92Keywords',
'oracle' => 'Doctrine\DBAL\Platforms\Keywords\OracleKeywords', 'oracle' => 'Doctrine\DBAL\Platforms\Keywords\OracleKeywords',
'db2' => 'Doctrine\DBAL\Platforms\Keywords\DB2Keywords', 'db2' => 'Doctrine\DBAL\Platforms\Keywords\DB2Keywords',
......
...@@ -153,4 +153,23 @@ class MySqlSchemaManagerTest extends SchemaManagerFunctionalTestCase ...@@ -153,4 +153,23 @@ class MySqlSchemaManagerTest extends SchemaManagerFunctionalTestCase
$this->assertNull($onlineTable->getColumn('def_blob_null')->getDefault()); $this->assertNull($onlineTable->getColumn('def_blob_null')->getDefault());
$this->assertFalse($onlineTable->getColumn('def_blob_null')->getNotnull()); $this->assertFalse($onlineTable->getColumn('def_blob_null')->getNotnull());
} }
public function testColumnCollation()
{
$table = new Table('test_collation');
$table->addOption('collate', $collation = 'latin1_swedish_ci');
$table->addOption('charset', 'latin1');
$table->addColumn('id', 'integer');
$table->addColumn('text', 'text');
$table->addColumn('foo', 'text')->setPlatformOption('collation', 'latin1_swedish_ci');
$table->addColumn('bar', 'text')->setPlatformOption('collation', 'utf8_general_ci');
$this->_sm->dropAndCreateTable($table);
$columns = $this->_sm->listTableColumns('test_collation');
$this->assertArrayNotHasKey('collation', $columns['id']->getPlatformOptions());
$this->assertEquals('latin1_swedish_ci', $columns['text']->getPlatformOption('collation'));
$this->assertEquals('latin1_swedish_ci', $columns['foo']->getPlatformOption('collation'));
$this->assertEquals('utf8_general_ci', $columns['bar']->getPlatformOption('collation'));
}
} }
...@@ -10,10 +10,10 @@ use Doctrine\DBAL\Types\Type; ...@@ -10,10 +10,10 @@ use Doctrine\DBAL\Types\Type;
class SQLServerSchemaManagerTest extends SchemaManagerFunctionalTestCase class SQLServerSchemaManagerTest extends SchemaManagerFunctionalTestCase
{ {
protected function getPlatformName() protected function getPlatformName()
{ {
return "mssql"; return "mssql";
} }
/** /**
* @group DBAL-255 * @group DBAL-255
...@@ -35,22 +35,22 @@ class SQLServerSchemaManagerTest extends SchemaManagerFunctionalTestCase ...@@ -35,22 +35,22 @@ class SQLServerSchemaManagerTest extends SchemaManagerFunctionalTestCase
$this->assertEquals(1, count($columns)); $this->assertEquals(1, count($columns));
} }
public function testCollationCharset() public function testColumnCollation()
{ {
$table = new \Doctrine\DBAL\Schema\Table($tableName = 'test_collation_charset'); $table = new \Doctrine\DBAL\Schema\Table($tableName = 'test_collation');
$column = $table->addColumn($columnName = 'test', 'string'); $column = $table->addColumn($columnName = 'test', 'string');
$this->_sm->dropAndCreateTable($table); $this->_sm->dropAndCreateTable($table);
$columns = $this->_sm->listTableColumns($tableName); $columns = $this->_sm->listTableColumns($tableName);
$this->assertTrue($columns[$columnName]->hasPlatformOption('collate')); // SQL Server should report a default collation on the column $this->assertTrue($columns[$columnName]->hasPlatformOption('collation')); // SQL Server should report a default collation on the column
$column->setPlatformOption('collate', $collation = 'Icelandic_CS_AS'); $column->setPlatformOption('collation', $collation = 'Icelandic_CS_AS');
$this->_sm->dropAndCreateTable($table); $this->_sm->dropAndCreateTable($table);
$columns = $this->_sm->listTableColumns($tableName); $columns = $this->_sm->listTableColumns($tableName);
$this->assertEquals($collation, $columns[$columnName]->getPlatformOption('collate')); $this->assertEquals($collation, $columns[$columnName]->getPlatformOption('collation'));
} }
public function testDefaultContraints() public function testDefaultContraints()
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
namespace Doctrine\Tests\DBAL\Functional\Schema; namespace Doctrine\Tests\DBAL\Functional\Schema;
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
use Doctrine\DBAL\Schema; use Doctrine\DBAL\Schema;
require_once __DIR__ . '/../../../TestInit.php'; require_once __DIR__ . '/../../../TestInit.php';
...@@ -62,17 +60,34 @@ EOS ...@@ -62,17 +60,34 @@ EOS
); );
$expected = array( $expected = array(
new ForeignKeyConstraint(array('log'), 'log', array(null), 'FK_3', new Schema\ForeignKeyConstraint(array('log'), 'log', array(null), 'FK_3',
array('onUpdate' => 'SET NULL', 'onDelete' => 'NO ACTION', 'deferrable' => false, 'deferred' => false)), array('onUpdate' => 'SET NULL', 'onDelete' => 'NO ACTION', 'deferrable' => false, 'deferred' => false)),
new ForeignKeyConstraint(array('parent'), 'user', array('id'), '1', new Schema\ForeignKeyConstraint(array('parent'), 'user', array('id'), '1',
array('onUpdate' => 'NO ACTION', 'onDelete' => 'CASCADE', 'deferrable' => false, 'deferred' => false)), array('onUpdate' => 'NO ACTION', 'onDelete' => 'CASCADE', 'deferrable' => false, 'deferred' => false)),
new ForeignKeyConstraint(array('page'), 'page', array('key'), 'FK_1', new Schema\ForeignKeyConstraint(array('page'), 'page', array('key'), 'FK_1',
array('onUpdate' => 'NO ACTION', 'onDelete' => 'NO ACTION', 'deferrable' => true, 'deferred' => true)), array('onUpdate' => 'NO ACTION', 'onDelete' => 'NO ACTION', 'deferrable' => true, 'deferred' => true)),
); );
$this->assertEquals($expected, $this->_sm->listTableForeignKeys('user')); $this->assertEquals($expected, $this->_sm->listTableForeignKeys('user'));
} }
public function testColumnCollation()
{
$table = new Schema\Table('test_collation');
$table->addColumn('id', 'integer');
$table->addColumn('text', 'text');
$table->addColumn('foo', 'text')->setPlatformOption('collation', 'BINARY');
$table->addColumn('bar', 'text')->setPlatformOption('collation', 'NOCASE');
$this->_sm->dropAndCreateTable($table);
$columns = $this->_sm->listTableColumns('test_collation');
$this->assertArrayNotHasKey('collation', $columns['id']->getPlatformOptions());
$this->assertEquals('BINARY', $columns['text']->getPlatformOption('collation'));
$this->assertEquals('BINARY', $columns['foo']->getPlatformOption('collation'));
$this->assertEquals('NOCASE', $columns['bar']->getPlatformOption('collation'));
}
public function testListTableWithBinary() public function testListTableWithBinary()
{ {
$tableName = 'test_binary_table'; $tableName = 'test_binary_table';
......
<?php
namespace Doctrine\Tests\DBAL\Platforms;
use Doctrine\DBAL\Platforms\PostgreSQL91Platform;
class PostgreSql91PlatformTest extends PostgreSqlPlatformTest
{
public function createPlatform()
{
return new PostgreSQL91Platform();
}
public function testColumnCollationDeclarationSQL()
{
$this->assertEquals(
'COLLATE "en_US.UTF-8"',
$this->_platform->getColumnCollationDeclarationSQL('en_US.UTF-8')
);
}
}
...@@ -1001,4 +1001,27 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase ...@@ -1001,4 +1001,27 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($changeSequenceCount, count($diff->changedSequences), "Expected number of changed sequences is wrong."); $this->assertEquals($changeSequenceCount, count($diff->changedSequences), "Expected number of changed sequences is wrong.");
$this->assertEquals($removeSequenceCount, count($diff->removedSequences), "Expected number of removed sequences is wrong."); $this->assertEquals($removeSequenceCount, count($diff->removedSequences), "Expected number of removed sequences is wrong.");
} }
public function testDiffColumnPlatformOptions()
{
$column1 = new Column('foo', Type::getType('string'));
$column1->setPlatformOptions(array('foo' => 'foo', 'bar' => 'bar'));
$column2 = new Column('foo', Type::getType('string'));
$column2->setPlatformOptions(array('foo' => 'foo', 'foobar' => 'foobar'));
$column3 = new Column('foo', Type::getType('string'));
$column3->setPlatformOptions(array('foo' => 'foo', 'bar' => 'rab'));
$column4 = new Column('foo', Type::getType('string'));
$comparator = new Comparator();
$this->assertEquals(array(), $comparator->diffColumn($column1, $column2));
$this->assertEquals(array(), $comparator->diffColumn($column2, $column1));
$this->assertEquals(array('bar'), $comparator->diffColumn($column1, $column3));
$this->assertEquals(array('bar'), $comparator->diffColumn($column3, $column1));
$this->assertEquals(array(), $comparator->diffColumn($column1, $column4));
$this->assertEquals(array(), $comparator->diffColumn($column4, $column1));
}
} }
<?php
namespace Doctrine\Tests\DBAL\Schema;
use Doctrine\DBAL\Schema\SqliteSchemaManager;
use Doctrine\DBAL\Platforms\SqlitePlatform;
class SqliteSchemaManagerTest extends \PHPUnit_Framework_TestCase
{
/**
* @dataProvider getDataColumnCollation
*/
public function testParseColumnCollation($collation, $column, $sql)
{
$conn = $this->getMockBuilder('Doctrine\DBAL\Connection')->disableOriginalConstructor()->getMock();
$conn->expects($this->any())->method('getDatabasePlatform')->will($this->returnValue(new SqlitePlatform()));
$manager = new SqliteSchemaManager($conn);
$ref = new \ReflectionMethod($manager, 'parseColumnCollationFromSQL');
$ref->setAccessible(true);
$this->assertEquals($collation, $ref->invoke($manager, $column, $sql));
}
public function getDataColumnCollation()
{
return array(
array(
'RTRIM', 'a', 'CREATE TABLE "a" ("a" text DEFAULT "aa" COLLATE "RTRIM" NOT NULL)'
),
array(
'utf-8', 'a', 'CREATE TABLE "a" ("b" text UNIQUE NOT NULL COLLATE NOCASE, "a" text DEFAULT "aa" COLLATE "utf-8" NOT NULL)'
),
array(
'NOCASE', 'a', 'CREATE TABLE "a" ("a" text DEFAULT (lower(ltrim(" a") || rtrim("a "))) CHECK ("a") NOT NULL COLLATE NOCASE UNIQUE, "b" text COLLATE RTRIM)'
),
array(
false, 'a', 'CREATE TABLE "a" ("a" text CHECK ("a") NOT NULL, "b" text COLLATE RTRIM)'
),
array(
'RTRIM', 'a"b', 'CREATE TABLE "a" ("a""b" text COLLATE RTRIM)'
),
);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment