Commit 5b8f4f03 authored by Guilherme Blanco's avatar Guilherme Blanco

Merge pull request #245 from hason/column_collation

Added support for column collation
parents 3faa3a65 87273b29
...@@ -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.
......
...@@ -228,6 +228,116 @@ class DrizzlePlatform extends AbstractPlatform ...@@ -228,6 +228,116 @@ class DrizzlePlatform extends AbstractPlatform
return 'DROP DATABASE ' . $name; return 'DROP DATABASE ' . $name;
} }
/**
* {@inheritDoc}
*/
protected function _getCreateTableSQL($tableName, array $columns, array $options = array())
{
$queryFields = $this->getColumnDeclarationListSQL($columns);
if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) {
foreach ($options['uniqueConstraints'] as $index => $definition) {
$queryFields .= ', ' . $this->getUniqueConstraintDeclarationSQL($index, $definition);
}
}
// add all indexes
if (isset($options['indexes']) && ! empty($options['indexes'])) {
foreach($options['indexes'] as $index => $definition) {
$queryFields .= ', ' . $this->getIndexDeclarationSQL($index, $definition);
}
}
// attach all primary keys
if (isset($options['primary']) && ! empty($options['primary'])) {
$keyColumns = array_unique(array_values($options['primary']));
$queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')';
}
$query = 'CREATE ';
if (!empty($options['temporary'])) {
$query .= 'TEMPORARY ';
}
$query .= 'TABLE ' . $tableName . ' (' . $queryFields . ') ';
$query .= $this->buildTableOptions($options);
$query .= $this->buildPartitionOptions($options);
$sql[] = $query;
if (isset($options['foreignKeys'])) {
foreach ((array) $options['foreignKeys'] as $definition) {
$sql[] = $this->getCreateForeignKeySQL($definition, $tableName);
}
}
return $sql;
}
/**
* Build SQL for table options
*
* @param array $options
*
* @return string
*/
private function buildTableOptions(array $options)
{
if (isset($options['table_options'])) {
return $options['table_options'];
}
$tableOptions = array();
// Collate
if ( ! isset($options['collate'])) {
$options['collate'] = 'utf8_unicode_ci';
}
$tableOptions[] = sprintf('COLLATE %s', $options['collate']);
// Engine
if ( ! isset($options['engine'])) {
$options['engine'] = 'InnoDB';
}
$tableOptions[] = sprintf('ENGINE = %s', $options['engine']);
// Auto increment
if (isset($options['auto_increment'])) {
$tableOptions[] = sprintf('AUTO_INCREMENT = %s', $options['auto_increment']);
}
// Comment
if (isset($options['comment'])) {
$comment = trim($options['comment'], " '");
$tableOptions[] = sprintf("COMMENT = '%s' ", str_replace("'", "''", $comment));
}
// Row format
if (isset($options['row_format'])) {
$tableOptions[] = sprintf('ROW_FORMAT = %s', $options['row_format']);
}
return implode(' ', $tableOptions);
}
/**
* Build SQL for partition options.
*
* @param array $options
*
* @return string
*/
private function buildPartitionOptions(array $options)
{
return (isset($options['partition_options']))
? ' ' . $options['partition_options']
: '';
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
...@@ -264,7 +374,7 @@ class DrizzlePlatform extends AbstractPlatform ...@@ -264,7 +374,7 @@ class DrizzlePlatform extends AbstractPlatform
} }
return "SELECT COLUMN_NAME, DATA_TYPE, COLUMN_COMMENT, IS_NULLABLE, IS_AUTO_INCREMENT, CHARACTER_MAXIMUM_LENGTH, COLUMN_DEFAULT," . return "SELECT COLUMN_NAME, DATA_TYPE, COLUMN_COMMENT, IS_NULLABLE, IS_AUTO_INCREMENT, CHARACTER_MAXIMUM_LENGTH, COLUMN_DEFAULT," .
" NUMERIC_PRECISION, NUMERIC_SCALE" . " NUMERIC_PRECISION, NUMERIC_SCALE, COLLATION_NAME" .
" FROM DATA_DICTIONARY.COLUMNS" . " FROM DATA_DICTIONARY.COLUMNS" .
" WHERE TABLE_SCHEMA=" . $database . " AND TABLE_NAME = '" . $table . "'"; " WHERE TABLE_SCHEMA=" . $database . " AND TABLE_NAME = '" . $table . "'";
} }
...@@ -333,6 +443,14 @@ class DrizzlePlatform extends AbstractPlatform ...@@ -333,6 +443,14 @@ class DrizzlePlatform extends AbstractPlatform
return false; return false;
} }
/**
* {@inheritdoc}
*/
public function supportsColumnCollation()
{
return true;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
......
<?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}
*/ */
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
namespace Doctrine\DBAL\Schema; namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Types;
/** /**
* Compares two Schemas and return an instance of SchemaDiff. * Compares two Schemas and return an instance of SchemaDiff.
* *
...@@ -365,82 +367,72 @@ class Comparator ...@@ -365,82 +367,72 @@ class Comparator
*/ */
public function diffColumn(Column $column1, Column $column2) public function diffColumn(Column $column1, Column $column2)
{ {
$properties1 = $column1->toArray();
$properties2 = $column2->toArray();
$changedProperties = array(); $changedProperties = array();
if ($column1->getType() != $column2->getType()) {
$changedProperties[] = 'type';
}
if ($column1->getNotnull() != $column2->getNotnull()) { foreach (array('type', 'notnull', 'unsigned', 'autoincrement') as $property) {
$changedProperties[] = 'notnull'; if ($properties1[$property] != $properties2[$property]) {
$changedProperties[] = $property;
}
} }
$column1Default = $column1->getDefault(); if ($properties1['default'] != $properties2['default'] ||
$column2Default = $column2->getDefault();
if ($column1Default != $column2Default ||
// Null values need to be checked additionally as they tell whether to create or drop a default value. // Null values need to be checked additionally as they tell whether to create or drop a default value.
// null != 0, null != false, null != '' etc. This affects platform's table alteration SQL generation. // null != 0, null != false, null != '' etc. This affects platform's table alteration SQL generation.
(null === $column1Default && null !== $column2Default) || (null === $properties1['default'] && null !== $properties2['default']) ||
(null === $column2Default && null !== $column1Default) (null === $properties2['default'] && null !== $properties1['default'])
) { ) {
$changedProperties[] = 'default'; $changedProperties[] = 'default';
} }
if ($column1->getUnsigned() != $column2->getUnsigned()) { if ($properties1['type'] instanceof Types\StringType || $properties1['type'] instanceof Types\BinaryType) {
$changedProperties[] = 'unsigned';
}
$column1Type = $column1->getType();
if ($column1Type instanceof \Doctrine\DBAL\Types\StringType ||
$column1Type instanceof \Doctrine\DBAL\Types\BinaryType
) {
// check if value of length is set at all, default value assumed otherwise. // check if value of length is set at all, default value assumed otherwise.
$length1 = $column1->getLength() ?: 255; $length1 = $properties1['length'] ?: 255;
$length2 = $column2->getLength() ?: 255; $length2 = $properties2['length'] ?: 255;
if ($length1 != $length2) { if ($length1 != $length2) {
$changedProperties[] = 'length'; $changedProperties[] = 'length';
} }
if ($column1->getFixed() != $column2->getFixed()) { if ($properties1['fixed'] != $properties2['fixed']) {
$changedProperties[] = 'fixed'; $changedProperties[] = 'fixed';
} }
} } elseif ($properties1['type'] instanceof Types\DecimalType) {
if (($properties1['precision'] ?: 10) != ($properties2['precision'] ?: 10)) {
if ($column1->getType() instanceof \Doctrine\DBAL\Types\DecimalType) {
if (($column1->getPrecision()?:10) != ($column2->getPrecision()?:10)) {
$changedProperties[] = 'precision'; $changedProperties[] = 'precision';
} }
if ($column1->getScale() != $column2->getScale()) { if ($properties1['scale'] != $properties2['scale']) {
$changedProperties[] = 'scale'; $changedProperties[] = 'scale';
} }
} }
if ($column1->getAutoincrement() != $column2->getAutoincrement()) {
$changedProperties[] = 'autoincrement';
}
// only allow to delete comment if its set to '' not to null. // only allow to delete comment if its set to '' not to null.
if ($column1->getComment() !== null && $column1->getComment() != $column2->getComment()) { if ($properties1['comment'] !== null && $properties1['comment'] != $properties2['comment']) {
$changedProperties[] = 'comment'; $changedProperties[] = 'comment';
} }
$options1 = $column1->getCustomSchemaOptions(); $customOptions1 = $column1->getCustomSchemaOptions();
$options2 = $column2->getCustomSchemaOptions(); $customOptions2 = $column2->getCustomSchemaOptions();
$commonKeys = array_keys(array_intersect_key($options1, $options2));
foreach ($commonKeys as $key) { foreach (array_merge(array_keys($customOptions1), array_keys($customOptions2)) as $key) {
if ($options1[$key] !== $options2[$key]) { if ( ! array_key_exists($key, $properties1) || ! array_key_exists($key, $properties2)) {
$changedProperties[] = $key;
} elseif ($properties1[$key] !== $properties2[$key]) {
$changedProperties[] = $key; $changedProperties[] = $key;
} }
} }
$diffKeys = array_keys(array_diff_key($options1, $options2) + array_diff_key($options2, $options1)); $platformOptions1 = $column1->getPlatformOptions();
$platformOptions2 = $column2->getPlatformOptions();
$changedProperties = array_merge($changedProperties, $diffKeys); foreach (array_keys(array_intersect_key($platformOptions1, $platformOptions2)) as $key) {
if ($properties1[$key] !== $properties2[$key]) {
$changedProperties[] = $key;
}
}
return $changedProperties; 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 Drizzle RDBMS. * Schema manager for the Drizzle RDBMS.
* *
...@@ -31,7 +33,6 @@ class DrizzleSchemaManager extends AbstractSchemaManager ...@@ -31,7 +33,6 @@ class DrizzleSchemaManager extends AbstractSchemaManager
*/ */
protected function _getPortableTableColumnDefinition($tableColumn) protected function _getPortableTableColumnDefinition($tableColumn)
{ {
$tableName = $tableColumn['COLUMN_NAME'];
$dbType = strtolower($tableColumn['DATA_TYPE']); $dbType = strtolower($tableColumn['DATA_TYPE']);
$type = $this->_platform->getDoctrineTypeMapping($dbType); $type = $this->_platform->getDoctrineTypeMapping($dbType);
...@@ -48,7 +49,13 @@ class DrizzleSchemaManager extends AbstractSchemaManager ...@@ -48,7 +49,13 @@ class DrizzleSchemaManager extends AbstractSchemaManager
'comment' => (isset($tableColumn['COLUMN_COMMENT']) ? $tableColumn['COLUMN_COMMENT'] : null), 'comment' => (isset($tableColumn['COLUMN_COMMENT']) ? $tableColumn['COLUMN_COMMENT'] : null),
); );
return new Column($tableName, \Doctrine\DBAL\Types\Type::getType($type), $options); $column = new Column($tableColumn['COLUMN_NAME'], Type::getType($type), $options);
if ( ! empty($tableColumn['COLLATION_NAME'])) {
$column->setPlatformOption('collation', $tableColumn['COLLATION_NAME']);
}
return $column;
} }
/** /**
......
...@@ -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',
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
namespace Doctrine\Tests\DBAL\Functional\Schema; namespace Doctrine\Tests\DBAL\Functional\Schema;
use Doctrine\DBAL\Schema\Table;
require_once __DIR__ . '/../../../TestInit.php'; require_once __DIR__ . '/../../../TestInit.php';
class DrizzleSchemaManagerTest extends SchemaManagerFunctionalTestCase class DrizzleSchemaManagerTest extends SchemaManagerFunctionalTestCase
...@@ -10,7 +12,7 @@ class DrizzleSchemaManagerTest extends SchemaManagerFunctionalTestCase ...@@ -10,7 +12,7 @@ class DrizzleSchemaManagerTest extends SchemaManagerFunctionalTestCase
{ {
$tableName = 'test_binary_table'; $tableName = 'test_binary_table';
$table = new \Doctrine\DBAL\Schema\Table($tableName); $table = new Table($tableName);
$table->addColumn('id', 'integer'); $table->addColumn('id', 'integer');
$table->addColumn('column_varbinary', 'binary', array()); $table->addColumn('column_varbinary', 'binary', array());
$table->addColumn('column_binary', 'binary', array('fixed' => true)); $table->addColumn('column_binary', 'binary', array('fixed' => true));
...@@ -26,4 +28,22 @@ class DrizzleSchemaManagerTest extends SchemaManagerFunctionalTestCase ...@@ -26,4 +28,22 @@ class DrizzleSchemaManagerTest extends SchemaManagerFunctionalTestCase
$this->assertInstanceOf('Doctrine\DBAL\Types\BinaryType', $table->getColumn('column_binary')->getType()); $this->assertInstanceOf('Doctrine\DBAL\Types\BinaryType', $table->getColumn('column_binary')->getType());
$this->assertFalse($table->getColumn('column_binary')->getFixed()); $this->assertFalse($table->getColumn('column_binary')->getFixed());
} }
public function testColumnCollation()
{
$table = new Table('test_collation');
$table->addOption('collate', $collation = 'utf8_unicode_ci');
$table->addColumn('id', 'integer');
$table->addColumn('text', 'text');
$table->addColumn('foo', 'text')->setPlatformOption('collation', 'utf8_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('utf8_unicode_ci', $columns['text']->getPlatformOption('collation'));
$this->assertEquals('utf8_swedish_ci', $columns['foo']->getPlatformOption('collation'));
$this->assertEquals('utf8_general_ci', $columns['bar']->getPlatformOption('collation'));
}
} }
...@@ -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'));
}
} }
...@@ -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,38 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase ...@@ -1001,4 +1001,38 @@ 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'), array('platformOptions' => array('foo' => 'foo', 'bar' => 'bar')));
$column2 = new Column('foo', Type::getType('string'), array('platformOptions' => array('foo' => 'foo', 'foobar' => 'foobar')));
$column3 = new Column('foo', Type::getType('string'), array('platformOptions' => 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));
}
public function testComplexDiffColumn()
{
$column1 = new Column('foo', Type::getType('string'), array(
'platformOptions' => array('foo' => 'foo'),
'customSchemaOptions' => array('foo' => 'bar'),
));
$column2 = new Column('foo', Type::getType('string'), array(
'platformOptions' => array('foo' => 'bar'),
));
$comparator = new Comparator();
$this->assertEquals(array(), $comparator->diffColumn($column1, $column2));
$this->assertEquals(array(), $comparator->diffColumn($column2, $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