Skip to content

Commit 90762f3

Browse files
authored
Merge pull request #7371 from kenjis/fix-modifyColumn-SQLite3
fix: [SQLite3][Postgres][SQLSRV][OCI8] Forge::modifyColumn() changes NULL constraint incorrectly
2 parents e4438f7 + 3b416c8 commit 90762f3

File tree

16 files changed

+191
-22
lines changed

16 files changed

+191
-22
lines changed

system/Database/Forge.php

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ class Forge
153153
*
154154
* @internal Used for marking nullable fields. Not covered by BC promise.
155155
*/
156-
protected $null = '';
156+
protected $null = 'NULL';
157157

158158
/**
159159
* DEFAULT value representation in CREATE/ALTER TABLE statements
@@ -562,7 +562,7 @@ public function createTable(string $table, bool $ifNotExists = false, array $att
562562
}
563563

564564
/**
565-
* @return string
565+
* @return string SQL string
566566
*
567567
* @deprecated $ifNotExists is no longer used, and will be removed.
568568
*/
@@ -897,13 +897,19 @@ protected function _processFields(bool $createTable = false): array
897897
$this->_attributeDefault($attributes, $field);
898898

899899
if (isset($attributes['NULL'])) {
900+
$nullString = ' ' . $this->null;
901+
900902
if ($attributes['NULL'] === true) {
901-
$field['null'] = empty($this->null) ? '' : ' ' . $this->null;
903+
$field['null'] = empty($this->null) ? '' : $nullString;
904+
} elseif ($attributes['NULL'] === $nullString) {
905+
$field['null'] = $nullString;
906+
} elseif ($attributes['NULL'] === '') {
907+
$field['null'] = '';
902908
} else {
903-
$field['null'] = ' NOT NULL';
909+
$field['null'] = ' NOT ' . $this->null;
904910
}
905911
} elseif ($createTable === true) {
906-
$field['null'] = ' NOT NULL';
912+
$field['null'] = ' NOT ' . $this->null;
907913
}
908914

909915
$this->_attributeAutoIncrement($attributes, $field);

system/Database/OCI8/Forge.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,17 @@ protected function _alterTable(string $alterType, string $table, $field)
120120
// If a null constraint is added to a column with a null constraint,
121121
// ORA-01451 will occur,
122122
// so add null constraint is used only when it is different from the current null constraint.
123-
$isWantToAddNull = strpos($field[$i]['null'], ' NOT') === false;
124-
$currentNullAddable = $nullableMap[$field[$i]['name']];
123+
// If a not null constraint is added to a column with a not null constraint,
124+
// ORA-01442 will occur.
125+
$wantToAddNull = strpos($field[$i]['null'], ' NOT') === false;
126+
$currentNullable = $nullableMap[$field[$i]['name']];
125127

126-
if ($isWantToAddNull === $currentNullAddable) {
128+
if ($wantToAddNull === true && $currentNullable === true) {
129+
$field[$i]['null'] = '';
130+
} elseif ($field[$i]['null'] === '' && $currentNullable === false) {
131+
// Nullable by default
132+
$field[$i]['null'] = ' NULL';
133+
} elseif ($wantToAddNull === false && $currentNullable === false) {
127134
$field[$i]['null'] = '';
128135
}
129136
}

system/Database/Postgre/Forge.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,12 @@ protected function _alterTable(string $alterType, string $table, $field)
109109
. " SET DEFAULT {$data['default']}";
110110
}
111111

112-
if (isset($data['null'])) {
113-
$sqls[] = $sql . ' ALTER COLUMN ' . $this->db->escapeIdentifiers($data['name'])
114-
. ($data['null'] === true ? ' DROP' : ' SET') . ' NOT NULL';
112+
$nullable = true; // Nullable by default.
113+
if (isset($data['null']) && ($data['null'] === false || $data['null'] === ' NOT ' . $this->null)) {
114+
$nullable = false;
115115
}
116+
$sqls[] = $sql . ' ALTER COLUMN ' . $this->db->escapeIdentifiers($data['name'])
117+
. ($nullable === true ? ' DROP' : ' SET') . ' NOT NULL';
116118

117119
if (! empty($data['new_name'])) {
118120
$sqls[] = $sql . ' RENAME COLUMN ' . $this->db->escapeIdentifiers($data['name'])

system/Database/SQLSRV/Forge.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,10 +203,12 @@ protected function _alterTable(string $alterType, string $table, $field)
203203
. " DEFAULT {$data['default']} FOR " . $this->db->escapeIdentifiers($data['name']);
204204
}
205205

206-
if (isset($data['null'])) {
207-
$sqls[] = $sql . ' ALTER COLUMN ' . $this->db->escapeIdentifiers($data['name'])
208-
. ($data['null'] === true ? ' DROP' : '') . " {$data['type']}{$data['length']} NOT NULL";
206+
$nullable = true; // Nullable by default.
207+
if (isset($data['null']) && ($data['null'] === false || $data['null'] === ' NOT ' . $this->null)) {
208+
$nullable = false;
209209
}
210+
$sqls[] = $sql . ' ALTER COLUMN ' . $this->db->escapeIdentifiers($data['name'])
211+
. " {$data['type']}{$data['length']} " . ($nullable === true ? '' : 'NOT') . ' NULL';
210212

211213
if (! empty($data['comment'])) {
212214
$sqls[] = 'EXEC sys.sp_addextendedproperty '

system/Database/SQLite3/Table.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -183,14 +183,14 @@ public function dropColumn($columns)
183183
*
184184
* @return Table
185185
*/
186-
public function modifyColumn(array $field)
186+
public function modifyColumn(array $fields)
187187
{
188-
$field = $field[0];
189-
190-
$oldName = $field['name'];
191-
unset($field['name']);
188+
foreach ($fields as $field) {
189+
$oldName = $field['name'];
190+
unset($field['name']);
192191

193-
$this->fields[$oldName] = $field;
192+
$this->fields[$oldName] = $field;
193+
}
194194

195195
return $this;
196196
}

tests/_support/MigrationTestMigrations/Database/Migrations/2018-01-24-102301_Some_migration.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public function up()
2121
'constraint' => 255,
2222
],
2323
]);
24-
$this->forge->createTable('foo', true);
24+
$this->forge->createTable('foo');
2525

2626
$this->db->table('foo')->insert([
2727
'key' => 'foobar',

tests/system/Commands/Database/MigrateStatusTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use CodeIgniter\CLI\CLI;
1515
use CodeIgniter\Test\CIUnitTestCase;
1616
use CodeIgniter\Test\StreamFilterTrait;
17+
use Config\Database;
1718

1819
/**
1920
* @group DatabaseLive
@@ -29,6 +30,9 @@ final class MigrateStatusTest extends CIUnitTestCase
2930

3031
protected function setUp(): void
3132
{
33+
$forge = Database::forge();
34+
$forge->dropTable('foo', true);
35+
3236
parent::setUp();
3337

3438
if (! is_file($this->migrationFileFrom)) {

tests/system/Database/DatabaseTestCase/DatabaseTestCaseMigrationOnce1Test.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ final class DatabaseTestCaseMigrationOnce1Test extends CIUnitTestCase
5656

5757
protected function setUp(): void
5858
{
59+
$forge = Database::forge();
60+
$forge->dropTable('foo', true);
61+
5962
$this->setUpMethods[] = 'setUpAddNamespace';
6063

6164
parent::setUp();

tests/system/Database/DatabaseTestCase/DatabaseTestCaseMigrationOnce2Test.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use CodeIgniter\Test\CIUnitTestCase;
1515
use CodeIgniter\Test\DatabaseTestTrait;
16+
use Config\Database;
1617
use Config\Services;
1718

1819
/**
@@ -55,6 +56,9 @@ final class DatabaseTestCaseMigrationOnce2Test extends CIUnitTestCase
5556

5657
protected function setUp(): void
5758
{
59+
$forge = Database::forge();
60+
$forge->dropTable('foo', true);
61+
5862
$this->setUpMethods[] = 'setUpAddNamespace';
5963

6064
parent::setUp();

tests/system/Database/DatabaseTestCaseTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use CodeIgniter\Test\CIUnitTestCase;
1515
use CodeIgniter\Test\DatabaseTestTrait;
16+
use Config\Database;
1617
use Config\Services;
1718
use Tests\Support\Database\Seeds\AnotherSeeder;
1819
use Tests\Support\Database\Seeds\CITestSeeder;
@@ -60,6 +61,9 @@ final class DatabaseTestCaseTest extends CIUnitTestCase
6061

6162
protected function setUp(): void
6263
{
64+
$forge = Database::forge();
65+
$forge->dropTable('foo', true);
66+
6367
$this->setUpMethods[] = 'setUpAddNamespace';
6468

6569
parent::setUp();

0 commit comments

Comments
 (0)