Skip to content

Commit a91571c

Browse files
committed
Added support to alter column;
1 parent a5f6f9d commit a91571c

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

QueryBuilder.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,10 +250,62 @@ public function dropColumn($table, $column)
250250
. " DROP " . $this->db->quoteColumnName($column);
251251
}
252252

253+
/**
254+
* @inheritdoc
255+
*/
253256
public function renameColumn($table, $oldName, $newName)
254257
{
255258
return "ALTER TABLE " . $this->db->quoteTableName($table)
256259
. " ALTER " . $this->db->quoteColumnName($oldName)
257260
. " TO " . $this->db->quoteColumnName($newName);
258261
}
262+
263+
/**
264+
* @inheritdoc
265+
*/
266+
public function alterColumn($table, $column, $type)
267+
{
268+
$schema = $this->db->getSchema();
269+
$tableSchema = $schema->getTableSchema($table);
270+
$columnSchema = $tableSchema->getColumn($column);
271+
272+
$allowNullNewType = !preg_match("/not +null/i", $type);
273+
274+
$type = preg_replace("/ +(not)? *null/i", "", $type);
275+
276+
$hasType = false;
277+
278+
$matches = [];
279+
if (isset($this->typeMap[$type])) {
280+
$hasType = true;
281+
} elseif (preg_match('/^(\w+)[\( ]/', $type, $matches)) {
282+
if (isset($this->typeMap[$matches[1]])) {
283+
$hasType = true;
284+
}
285+
}
286+
287+
$baseSql = 'ALTER TABLE ' . $this->db->quoteTableName($table)
288+
. ' ALTER '. $this->db->quoteColumnName($column)
289+
. (($hasType)? ' TYPE ': ' ') . $this->getColumnType($type);
290+
291+
if ($columnSchema->allowNull == $allowNullNewType) {
292+
return $baseSql;
293+
} else {
294+
$sql = 'EXECUTE BLOCK AS BEGIN'
295+
. ' EXECUTE STATEMENT ' . $this->db->quoteValue($baseSql) . ';'
296+
. ' UPDATE RDB$RELATION_FIELDS SET RDB$NULL_FLAG = ' . ($allowNullNewType ? 'NULL' : '1')
297+
. ' WHERE UPPER(RDB$FIELD_NAME) = UPPER(\'' . $column . '\') AND UPPER(RDB$RELATION_NAME) = UPPER(\'' . $table . '\');';
298+
/**
299+
* In any case (whichever option you choose), make sure that the column doesn't have any NULLs.
300+
* Firebird will not check it for you. Later when you backup the database, everything is fine,
301+
* but restore will fail as the NOT NULL column has NULLs in it. To be safe, each time you change from NULL to NOT NULL.
302+
*/
303+
if (!$allowNullNewType) {
304+
$sql .= ' UPDATE ' . $this->db->quoteTableName($table) . ' SET ' . $this->db->quoteColumnName($column) . ' = 0'
305+
. ' WHERE ' . $this->db->quoteColumnName($column) . ' IS NULL;';
306+
}
307+
$sql .= ' END';
308+
return $sql;
309+
}
310+
}
259311
}

tests/QueryBuilderTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,4 +198,23 @@ public function testRenameColumn()
198198
$this->assertContains($column.'_new', $schema->columnNames);
199199
}
200200
}
201+
202+
public function testAlterColumn()
203+
{
204+
$connection = $this->getConnection(true);
205+
$qb = $this->getQueryBuilder();
206+
207+
$connection->createCommand($qb->alterColumn('customer', 'email', Schema::TYPE_STRING . '(128) NULL'))->execute();
208+
$connection->createCommand($qb->alterColumn('customer', 'name', "SET DEFAULT 'NO NAME'"))->execute();
209+
$connection->createCommand($qb->alterColumn('customer', 'name', Schema::TYPE_STRING . "(128) NOT NULL"))->execute();
210+
$connection->createCommand($qb->alterColumn('customer', 'profile_id', Schema::TYPE_INTEGER . ' NOT NULL'))->execute();
211+
212+
$newColumns = $connection->getTableSchema('customer', true)->columns;
213+
214+
$this->assertEquals(true, $newColumns['email']->allowNull);
215+
$this->assertEquals(false, $newColumns['name']->allowNull);
216+
$this->assertEquals('NO NAME', $newColumns['name']->defaultValue);
217+
$this->assertEquals(false, $newColumns['profile_id']->allowNull);
218+
$this->assertEquals(0, $newColumns['profile_id']->defaultValue);
219+
}
201220
}

0 commit comments

Comments
 (0)