diff --git a/src/Illuminate/Database/Schema/Grammars/PostgresGrammar.php b/src/Illuminate/Database/Schema/Grammars/PostgresGrammar.php index 708e75058d1f..66b4c755f55c 100755 --- a/src/Illuminate/Database/Schema/Grammars/PostgresGrammar.php +++ b/src/Illuminate/Database/Schema/Grammars/PostgresGrammar.php @@ -281,6 +281,15 @@ public function compileAutoIncrementStartingValues(Blueprint $blueprint, Fluent public function compileChange(Blueprint $blueprint, Fluent $command) { $column = $command->column; + $statements = []; + + if ($column->type === 'enum') { + $constraintName = $blueprint->getTable().'_'.$column->name.'_check'; + $statements[] = sprintf('alter table %s drop constraint if exists %s', + $this->wrapTable($blueprint), + $this->wrap($constraintName) + ); + } $changes = ['type '.$this->getType($column).$this->modifyCollate($blueprint, $column)]; @@ -298,10 +307,23 @@ public function compileChange(Blueprint $blueprint, Fluent $command) } } - return sprintf('alter table %s %s', + $statements[] = sprintf('alter table %s %s', $this->wrapTable($blueprint), implode(', ', $this->prefixArray('alter column '.$this->wrap($column), $changes)) ); + + if ($column->type === 'enum') { + $constraintName = $blueprint->getTable().'_'.$column->name.'_check'; + $statements[] = sprintf('alter table %s add constraint %s check ("%s" in (%s))', + $this->wrapTable($blueprint), + $this->wrap($constraintName), + $column->name, + $this->quoteString($column->allowed) + ); + } + + // Return single statement or array of statements + return count($statements) === 1 ? $statements[0] : $statements; } /** @@ -922,6 +944,10 @@ protected function typeBoolean(Fluent $column) */ protected function typeEnum(Fluent $column) { + if ($column->change) { + return 'varchar(255)'; + } + return sprintf( 'varchar(255) check ("%s" in (%s))', $column->name, diff --git a/tests/Database/DatabasePostgresSchemaGrammarTest.php b/tests/Database/DatabasePostgresSchemaGrammarTest.php index 6a21cca7093d..79bce3527124 100755 --- a/tests/Database/DatabasePostgresSchemaGrammarTest.php +++ b/tests/Database/DatabasePostgresSchemaGrammarTest.php @@ -1201,6 +1201,28 @@ public function testDropAllDomainsWithPrefixAndSchema() $this->assertSame('drop domain "schema"."alpha", "schema"."beta", "schema"."gamma" cascade', $statement); } + public function testNativeColumnModifyingOnPostgres() + { + $blueprint = new Blueprint($this->getConnection(), 'tasks', function ($table) { + $table->enum('status', ['pending', 'queued'])->default('pending')->change(); + }); + + $statements = $blueprint->toSql(); + + $this->assertCount(4, $statements); + + $this->assertStringContainsString('drop constraint if exists "tasks_status_check"', $statements[0]); + + $this->assertStringContainsString('alter table "tasks" alter column "status" type varchar(255)', $statements[1]); + $this->assertStringNotContainsString('check (', $statements[1]); + $this->assertStringContainsString('set default \'pending\'', $statements[1]); + $this->assertStringContainsString('set not null', $statements[1]); + + $this->assertStringContainsString('add constraint "tasks_status_check" check ("status" in (\'pending\', \'queued\'))', $statements[2]); + + $this->assertStringContainsString('comment on column', $statements[3]); + } + public function testCompileColumns() { $connection = $this->getConnection(); diff --git a/tests/Integration/Database/Postgres/DatabasePostgresSchemaBuilderAlterTableWithEnumTest.php b/tests/Integration/Database/Postgres/DatabasePostgresSchemaBuilderAlterTableWithEnumTest.php new file mode 100644 index 000000000000..7319ca9d16a7 --- /dev/null +++ b/tests/Integration/Database/Postgres/DatabasePostgresSchemaBuilderAlterTableWithEnumTest.php @@ -0,0 +1,55 @@ +integer('id'); + $table->string('name'); + $table->enum('status', ['pending', 'processing'])->default('pending'); + }); + } + + protected function destroyDatabaseMigrations() + { + Schema::drop('orders'); + } + + public function testChangeEnumColumnValues() + { + Schema::table('orders', function (Blueprint $table) { + $table->enum('status', ['pending', 'queued'])->default('pending')->change(); + }); + + $this->assertTrue(Schema::hasColumn('orders', 'status')); + $this->assertSame('varchar', Schema::getColumnType('orders', 'status')); + } + + public function testRenameColumnOnTableWithEnum() + { + Schema::table('orders', function (Blueprint $table) { + $table->renameColumn('name', 'title'); + }); + + $this->assertTrue(Schema::hasColumn('orders', 'title')); + } + + public function testChangeNonEnumColumnOnTableWithEnum() + { + Schema::table('orders', function (Blueprint $table) { + $table->unsignedInteger('id')->change(); + }); + + $this->assertSame('int4', Schema::getColumnType('orders', 'id')); + } +}