Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion src/Illuminate/Database/Schema/Grammars/PostgresGrammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)];

Expand All @@ -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;
}

/**
Expand Down Expand Up @@ -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,
Expand Down
22 changes: 22 additions & 0 deletions tests/Database/DatabasePostgresSchemaGrammarTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace Illuminate\Tests\Integration\Database\Postgres;

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use PHPUnit\Framework\Attributes\RequiresOperatingSystem;
use PHPUnit\Framework\Attributes\RequiresPhpExtension;

#[RequiresOperatingSystem('Linux|Darwin')]
#[RequiresPhpExtension('pdo_pgsql')]
class DatabasePostgresSchemaBuilderAlterTableWithEnumTest extends PostgresTestCase
{
protected function afterRefreshingDatabase()
{
Schema::create('orders', function (Blueprint $table) {
$table->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'));
}
}