From 9367af4b1523741bba1ebb3bd5788c835fd49f1e Mon Sep 17 00:00:00 2001 From: DarkDef Date: Sun, 25 Apr 2021 20:19:14 +0300 Subject: [PATCH] Fix for issue #18604 --- framework/db/mssql/QueryBuilder.php | 5 +-- tests/framework/db/mssql/QueryBuilderTest.php | 32 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/framework/db/mssql/QueryBuilder.php b/framework/db/mssql/QueryBuilder.php index df399712c1..66e169cb46 100644 --- a/framework/db/mssql/QueryBuilder.php +++ b/framework/db/mssql/QueryBuilder.php @@ -184,9 +184,10 @@ class QueryBuilder extends \yii\db\QueryBuilder $type = $this->getColumnType($type); if (preg_match('/\s+DEFAULT\s+(["\']?\w*["\']?)/i', $type, $matches)) { + $value = strtolower($matches[1]) === 'null' ? null : $matches[1]; $type = preg_replace('/\s+DEFAULT\s+(["\']?\w*["\']?)/i', '', $type); $sqlAfter[] = $this->dropConstraintsForColumn($table, $column, 'D'); - $sqlAfter[] = $this->addDefaultValue("DF_{$constraintBase}", $table, $column, $matches[1]); + $sqlAfter[] = $this->addDefaultValue("DF_{$constraintBase}", $table, $column, $value); } else { $sqlAfter[] = $this->dropConstraintsForColumn($table, $column, 'D'); } @@ -213,7 +214,7 @@ class QueryBuilder extends \yii\db\QueryBuilder public function addDefaultValue($name, $table, $column, $value) { return 'ALTER TABLE ' . $this->db->quoteTableName($table) . ' ADD CONSTRAINT ' - . $this->db->quoteColumnName($name) . ' DEFAULT ' . $this->db->quoteValue($value) . ' FOR ' + . $this->db->quoteColumnName($name) . ' DEFAULT ' . ($value === null ? 'NULL' : $this->db->quoteValue($value)) . ' FOR ' . $this->db->quoteColumnName($column); } diff --git a/tests/framework/db/mssql/QueryBuilderTest.php b/tests/framework/db/mssql/QueryBuilderTest.php index 624ca723b9..df16edc3ae 100644 --- a/tests/framework/db/mssql/QueryBuilderTest.php +++ b/tests/framework/db/mssql/QueryBuilderTest.php @@ -656,6 +656,38 @@ ALTER TABLE [foo1] ADD CONSTRAINT [UQ_foo1_bar] UNIQUE ([bar])"; $this->assertEquals(false, $schema->getColumn('bar')->allowNull); } + public function testAlterColumnWithNull() + { + $qb = $this->getQueryBuilder(); + + $expected = "ALTER TABLE [foo1] ALTER COLUMN [bar] int NULL +DECLARE @tableName VARCHAR(MAX) = '[foo1]' +DECLARE @columnName VARCHAR(MAX) = 'bar' + +WHILE 1=1 BEGIN + DECLARE @constraintName NVARCHAR(128) + SET @constraintName = (SELECT TOP 1 OBJECT_NAME(cons.[object_id]) + FROM ( + SELECT sc.[constid] object_id + FROM [sys].[sysconstraints] sc + JOIN [sys].[columns] c ON c.[object_id]=sc.[id] AND c.[column_id]=sc.[colid] AND c.[name]=@columnName + WHERE sc.[id] = OBJECT_ID(@tableName) + UNION + SELECT object_id(i.[name]) FROM [sys].[indexes] i + JOIN [sys].[columns] c ON c.[object_id]=i.[object_id] AND c.[name]=@columnName + JOIN [sys].[index_columns] ic ON ic.[object_id]=i.[object_id] AND i.[index_id]=ic.[index_id] AND c.[column_id]=ic.[column_id] + WHERE i.[is_unique_constraint]=1 and i.[object_id]=OBJECT_ID(@tableName) + ) cons + JOIN [sys].[objects] so ON so.[object_id]=cons.[object_id] + WHERE so.[type]='D') + IF @constraintName IS NULL BREAK + EXEC (N'ALTER TABLE ' + @tableName + ' DROP CONSTRAINT [' + @constraintName + ']') +END +ALTER TABLE [foo1] ADD CONSTRAINT [DF_foo1_bar] DEFAULT NULL FOR [bar]"; + $sql = $qb->alterColumn('foo1', 'bar', $this->integer()->null()->defaultValue(NULL)); + $this->assertEquals($expected, $sql); + } + public function testAlterColumnWithCheckConstraintOnDb() { $connection = $this->getConnection();