Skip to content

Commit

Permalink
Merge pull request #2027 from cakephp/mpeveler/bugfix-postgresql-boolean
Browse files Browse the repository at this point in the history
Fix changing boolean column option's in postgresql
  • Loading branch information
dereuromark committed Oct 12, 2021
2 parents dd3fc7f + 0c060ec commit 5a0146a
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 15 deletions.
22 changes: 12 additions & 10 deletions src/Phinx/Db/Adapter/PostgresAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -537,26 +537,27 @@ protected function getRenameColumnInstructions($tableName, $columnName, $newColu
*/
protected function getChangeColumnInstructions($tableName, $columnName, Column $newColumn)
{
$quotedColumnName = $this->quoteColumnName($columnName);
$instructions = new AlterInstructions();
if ($newColumn->getType() === 'boolean') {
$sql = sprintf('ALTER COLUMN %s DROP DEFAULT', $this->quoteColumnName($columnName));
$sql = sprintf('ALTER COLUMN %s DROP DEFAULT', $quotedColumnName);
$instructions->addAlter($sql);
}
$sql = sprintf(
'ALTER COLUMN %s TYPE %s',
$this->quoteColumnName($columnName),
$quotedColumnName,
$this->getColumnSqlDefinition($newColumn)
);
if (in_array($newColumn->getType(), ['smallinteger', 'integer', 'biginteger'], true)) {
$sql .= sprintf(
' USING (%s::bigint)',
$this->quoteColumnName($columnName)
$quotedColumnName
);
}
if ($newColumn->getType() === 'uuid') {
$sql .= sprintf(
' USING (%s::uuid)',
$this->quoteColumnName($columnName)
$quotedColumnName
);
}
//NULL and DEFAULT cannot be set while changing column type
Expand All @@ -566,16 +567,17 @@ protected function getChangeColumnInstructions($tableName, $columnName, Column $
$sql = preg_replace('/DEFAULT .*/', '', $sql);
if ($newColumn->getType() === 'boolean') {
$sql .= sprintf(
' USING (CASE WHEN %s=0 THEN FALSE ELSE TRUE END)',
$this->quoteColumnName($columnName)
' USING (CASE WHEN %s IS NULL THEN NULL WHEN %s::int=0 THEN FALSE ELSE TRUE END)',
$quotedColumnName,
$quotedColumnName
);
}
$instructions->addAlter($sql);

// process null
$sql = sprintf(
'ALTER COLUMN %s',
$this->quoteColumnName($columnName)
$quotedColumnName
);

if ($newColumn->isNull()) {
Expand All @@ -589,14 +591,14 @@ protected function getChangeColumnInstructions($tableName, $columnName, Column $
if ($newColumn->getDefault() !== null) {
$instructions->addAlter(sprintf(
'ALTER COLUMN %s SET %s',
$this->quoteColumnName($columnName),
$quotedColumnName,
$this->getDefaultValueDefinition($newColumn->getDefault(), $newColumn->getType())
));
} else {
//drop default
$instructions->addAlter(sprintf(
'ALTER COLUMN %s DROP DEFAULT',
$this->quoteColumnName($columnName)
$quotedColumnName
));
}

Expand All @@ -605,7 +607,7 @@ protected function getChangeColumnInstructions($tableName, $columnName, Column $
$instructions->addPostStep(sprintf(
'ALTER TABLE %s RENAME COLUMN %s TO %s',
$this->quoteTableName($tableName),
$this->quoteColumnName($columnName),
$quotedColumnName,
$this->quoteColumnName($newColumn->getName())
));
}
Expand Down
33 changes: 28 additions & 5 deletions tests/Phinx/Db/Adapter/PostgresAdapterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,29 @@ public function testChangeColumnFromTextToInteger($type, $value)
$this->assertSame($value, $row['column1']);
}

public function testChangeBooleanOptions()
{
$table = new \Phinx\Db\Table('t', ['id' => false], $this->adapter);
$table->addColumn('my_bool', 'boolean', ['default' => true, 'null' => true])
->create();
$table
->insert([
['my_bool' => true],
['my_bool' => false],
['my_bool' => null],
])
->update();
$table->changeColumn('my_bool', 'boolean', ['default' => false, 'null' => true])->update();
$columns = $this->adapter->getColumns('t');
$this->assertStringContainsString('false', $columns[0]->getDefault());

$rows = $this->adapter->fetchAll('SELECT * FROM t');
$this->assertCount(3, $rows);
$this->assertSame([true, false, null], array_map(function ($row) {
return $row['my_bool'];
}, $rows));
}

public function testChangeColumnFromIntegerToBoolean()
{
$table = new \Phinx\Db\Table('t', [], $this->adapter);
Expand Down Expand Up @@ -1058,8 +1081,8 @@ public function testAddIndexWithSort()
LEFT JOIN LATERAL unnest (i.indoption) WITH ORDINALITY AS o (option, ordinality)
ON c.ordinality = o.ordinality
JOIN pg_attribute AS a ON trel.oid = a.attrelid AND a.attnum = c.colnum
WHERE trel.relname = 'table1'
AND irel.relname = 'table1_email_username'
WHERE trel.relname = 'table1'
AND irel.relname = 'table1_email_username'
AND a.attname = 'email'
GROUP BY o.option, tnsp.nspname, trel.relname, irel.relname");
$emailOrder = $rows[0];
Expand Down Expand Up @@ -1097,14 +1120,14 @@ public function testAddIndexWithIncludeColumns()
->save();
$this->assertTrue($table->hasIndexByName('table1_include_idx'));
$rows = $this->adapter->fetchAll("SELECT CASE WHEN attnum <= indnkeyatts THEN 'KEY' ELSE 'INCLUDED' END as index_column
FROM pg_index ix
FROM pg_index ix
JOIN pg_class t ON ix.indrelid = t.oid
JOIN pg_class i ON ix.indexrelid = i.oid
JOIN pg_attribute a ON i.oid = a.attrelid
JOIN pg_attribute a ON i.oid = a.attrelid
JOIN pg_namespace nsp ON t.relnamespace = nsp.oid
WHERE nsp.nspname = 'public'
AND t.relkind = 'r'
AND t.relname = 'table1'
AND t.relname = 'table1'
AND a.attname = 'email'");
$indexColumn = $rows[0];
$this->assertEquals($indexColumn['index_column'], 'KEY');
Expand Down

0 comments on commit 5a0146a

Please sign in to comment.