From 59549b7ebef94f16f79f990f23ce2f36d388032e Mon Sep 17 00:00:00 2001 From: Rachman Chavik Date: Fri, 31 Jan 2014 15:11:09 +0700 Subject: [PATCH] Fix: Changing boolean to integer for Postgres Closes #2751, CakeDC/migrations#149 --- .../Model/Datasource/Database/Postgres.php | 16 +++++++++-- .../Datasource/Database/PostgresTest.php | 28 +++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/lib/Cake/Model/Datasource/Database/Postgres.php b/lib/Cake/Model/Datasource/Database/Postgres.php index 9d299a133f5..9c71c592a49 100644 --- a/lib/Cake/Model/Datasource/Database/Postgres.php +++ b/lib/Cake/Model/Datasource/Database/Postgres.php @@ -528,14 +528,17 @@ public function alterSchema($compare, $table = null) { } break; case 'change': + $schema = $this->describe($curTable); foreach ($column as $field => $col) { if (!isset($col['name'])) { $col['name'] = $field; } + $original = $schema[$field]; $fieldName = $this->name($field); $default = isset($col['default']) ? $col['default'] : null; $nullable = isset($col['null']) ? $col['null'] : null; + $boolToInt = $original['type'] == 'boolean' && $col['type'] == 'integer'; unset($col['default'], $col['null']); if ($field !== $col['name']) { $newName = $this->name($col['name']); @@ -543,14 +546,23 @@ public function alterSchema($compare, $table = null) { $out .= 'ALTER TABLE ' . $this->fullTableName($curTable) . " \n"; $fieldName = $newName; } - $colList[] = 'ALTER COLUMN ' . $fieldName . ' TYPE ' . str_replace(array($fieldName, 'NOT NULL'), '', $this->buildColumn($col)); + + if ($boolToInt) { + $colList[] = 'ALTER COLUMN ' . $fieldName . ' SET DEFAULT NULL'; + $colList[] = 'ALTER COLUMN ' . $fieldName . ' TYPE ' . str_replace(array($fieldName, 'NOT NULL'), '', $this->buildColumn($col)) . ' USING CASE WHEN TRUE THEN 1 ELSE 0 END'; + } else { + $colList[] = 'ALTER COLUMN ' . $fieldName . ' TYPE ' . str_replace(array($fieldName, 'NOT NULL'), '', $this->buildColumn($col)); + } + if (isset($nullable)) { $nullable = ($nullable) ? 'DROP NOT NULL' : 'SET NOT NULL'; $colList[] = 'ALTER COLUMN ' . $fieldName . ' ' . $nullable; } if (isset($default)) { - $colList[] = 'ALTER COLUMN ' . $fieldName . ' SET DEFAULT ' . $this->value($default, $col['type']); + if (!$boolToInt) { + $colList[] = 'ALTER COLUMN ' . $fieldName . ' SET DEFAULT ' . $this->value($default, $col['type']); + } } else { $colList[] = 'ALTER COLUMN ' . $fieldName . ' DROP DEFAULT'; } diff --git a/lib/Cake/Test/Case/Model/Datasource/Database/PostgresTest.php b/lib/Cake/Test/Case/Model/Datasource/Database/PostgresTest.php index 689dd323319..18b981b6a62 100644 --- a/lib/Cake/Test/Case/Model/Datasource/Database/PostgresTest.php +++ b/lib/Cake/Test/Case/Model/Datasource/Database/PostgresTest.php @@ -695,6 +695,34 @@ public function testAlterSchema() { $this->assertNotRegExp('/varchar\(36\) NOT NULL/i', $result); } +/** + * Test the alterSchema changing boolean to integer + * + * @return void + */ + public function testAlterSchemaBooleanToIntegerField() { + $default = array( + 'connection' => 'test', + 'name' => 'BoolField', + 'bool_fields' => array( + 'id' => array('type' => 'integer', 'key' => 'primary'), + 'name' => array('type' => 'string', 'length' => 50), + 'active' => array('type' => 'boolean', 'null' => false), + ) + ); + $Old = new CakeSchema($default); + $result = $this->Dbo->query($this->Dbo->createSchema($Old)); + $this->assertTrue($result); + + $modified = $default; + $modified['bool_fields']['active'] = array('type' => 'integer', 'null' => true); + + $New = new CakeSchema($modified); + $query = $this->Dbo->alterSchema($New->compare($Old)); + $result = $this->Dbo->query($query); + $this->Dbo->query($this->Dbo->dropSchema($Old)); + } + /** * Test the alter index capabilities of postgres *