Skip to content
Open
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
24 changes: 17 additions & 7 deletions lib/SQL/Translator/Producer/PostgreSQL.pm
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ The version of postgres to generate DDL for. Turns on features only available in
If your postgres_version is higher than 8.003 (I should hope it is by now), then the DDL
generated for dropping objects in the database will contain IF EXISTS.

=item ALTER COLUMN ... TYPE ... USING

Postgres 8 and later require a C<< USING expression >> clause when changing the type of a column
in a potentially lossy manner, such as from C<text> to C<numeric>. This the default when the
version is undefined, or when set to a number greater or equal to 8.

=back

=item attach_comments
Expand Down Expand Up @@ -910,27 +916,31 @@ sub alter_field {
# rename later
# BUT: drop geometry is done before the rename, cause it work's on the
# $from_field directly
my $to_table_quoted= $generator->quote($to_field->table->name);
my $to_field_quoted= $generator->quote($to_field->name);
push @out,
sprintf('ALTER TABLE %s RENAME COLUMN %s TO %s',
map($generator->quote($_), $to_field->table->name, $from_field->name, $to_field->name,),)
$to_table_quoted, $generator->quote($from_field->name), $to_field_quoted)
if ($from_field->name ne $to_field->name);

push @out,
sprintf('ALTER TABLE %s ALTER COLUMN %s SET NOT NULL',
map($generator->quote($_), $to_field->table->name, $to_field->name),)
$to_table_quoted, $to_field_quoted)
if (!$to_field->is_nullable and $from_field->is_nullable);

push @out,
sprintf('ALTER TABLE %s ALTER COLUMN %s DROP NOT NULL',
map($generator->quote($_), $to_field->table->name, $to_field->name),)
$to_table_quoted, $to_field_quoted)
if (!$from_field->is_nullable and $to_field->is_nullable);

my $from_dt = convert_datatype($from_field);
my $to_dt = convert_datatype($to_field);
push @out,
sprintf('ALTER TABLE %s ALTER COLUMN %s TYPE %s',
map($generator->quote($_), $to_field->table->name, $to_field->name), $to_dt,)
if ($to_dt ne $from_dt);
push @out, ($options->{postgres_version}//8) < 8
? sprintf('ALTER TABLE %s ALTER COLUMN %s TYPE %s',
$to_table_quoted, $to_field_quoted, $to_dt)
: sprintf('ALTER TABLE %s ALTER COLUMN %s TYPE %s USING (%s::%s)',
$to_table_quoted, $to_field_quoted, $to_dt, $to_field_quoted, $to_dt)
if $to_dt ne $from_dt;

my ($from_enum_typename, $from_list) = _enum_typename_and_values($from_field);
my ($to_enum_typename, $to_list) = _enum_typename_and_values($to_field);
Expand Down
12 changes: 6 additions & 6 deletions t/30sqlt-new-diff-pgsql.t
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,19 @@ DROP INDEX "u_name";

ALTER TABLE "person" ADD COLUMN "is_rock_star" smallint DEFAULT 1;

ALTER TABLE "person" ALTER COLUMN "person_id" TYPE serial;
ALTER TABLE "person" ALTER COLUMN "person_id" TYPE serial USING ("person_id"::serial);

ALTER TABLE "person" ALTER COLUMN "name" SET NOT NULL;

ALTER TABLE "person" ALTER COLUMN "age" SET DEFAULT 18;

ALTER TABLE "person" ALTER COLUMN "weight" DROP NOT NULL;

ALTER TABLE "person" ALTER COLUMN "iq" TYPE bigint;
ALTER TABLE "person" ALTER COLUMN "iq" TYPE bigint USING ("iq"::bigint);

ALTER TABLE "person" ALTER COLUMN "nickname" SET NOT NULL;

ALTER TABLE "person" ALTER COLUMN "nickname" TYPE character varying(24);
ALTER TABLE "person" ALTER COLUMN "nickname" TYPE character varying(24) USING ("nickname"::character varying(24));

ALTER TABLE "person" RENAME COLUMN "description" TO "physical_description";

Expand Down Expand Up @@ -134,19 +134,19 @@ ALTER TABLE person DROP CONSTRAINT UC_age_name;

ALTER TABLE person ADD COLUMN is_rock_star smallint DEFAULT 1;

ALTER TABLE person ALTER COLUMN person_id TYPE serial;
ALTER TABLE person ALTER COLUMN person_id TYPE serial USING (person_id::serial);

ALTER TABLE person ALTER COLUMN name SET NOT NULL;

ALTER TABLE person ALTER COLUMN age SET DEFAULT 18;

ALTER TABLE person ALTER COLUMN weight DROP NOT NULL;

ALTER TABLE person ALTER COLUMN iq TYPE bigint;
ALTER TABLE person ALTER COLUMN iq TYPE bigint USING (iq::bigint);

ALTER TABLE person ALTER COLUMN nickname SET NOT NULL;

ALTER TABLE person ALTER COLUMN nickname TYPE character varying(24);
ALTER TABLE person ALTER COLUMN nickname TYPE character varying(24) USING (nickname::character varying(24));

ALTER TABLE person RENAME COLUMN description TO physical_description;

Expand Down
4 changes: 2 additions & 2 deletions t/47postgres-producer.t
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ subtest 'exclude constraints' => sub {
my $alter_field = SQL::Translator::Producer::PostgreSQL::alter_field($field1, $field2);
is(
$alter_field, qq[ALTER TABLE mytable ALTER COLUMN myfield SET NOT NULL;
ALTER TABLE mytable ALTER COLUMN myfield TYPE character varying(25)],
ALTER TABLE mytable ALTER COLUMN myfield TYPE character varying(25) USING (myfield::character varying(25))],
'Alter field works'
);

Expand Down Expand Up @@ -296,7 +296,7 @@ my $alter_field_complex = SQL::Translator::Producer::PostgreSQL::alter_field($fi
is(
$alter_field_complex,
q{ALTER TABLE mytable RENAME COLUMN my_complex_field TO my_altered_field;
ALTER TABLE mytable ALTER COLUMN my_altered_field TYPE character varying(60);
ALTER TABLE mytable ALTER COLUMN my_altered_field TYPE character varying(60) USING (my_altered_field::character varying(60));
ALTER TABLE mytable ALTER COLUMN my_altered_field SET DEFAULT 'whatever'},
'Complex Alter field works'
);
Expand Down
4 changes: 2 additions & 2 deletions t/63-spacial-pgsql.t
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,15 @@ ALTER TABLE "my'table" DROP CONSTRAINT "enforce_dims_myfield";
ALTER TABLE "my'table" DROP CONSTRAINT "enforce_srid_myfield";
ALTER TABLE "my'table" DROP CONSTRAINT "enforce_geotype_myfield";
ALTER TABLE "my'table" ALTER COLUMN "myfield" SET NOT NULL;
ALTER TABLE "my'table" ALTER COLUMN "myfield" TYPE character varying(25)],
ALTER TABLE "my'table" ALTER COLUMN "myfield" TYPE character varying(25) USING ("myfield"::character varying(25))],
'Alter field geometry to non geometry works'
);

my $alter_field2 = SQL::Translator::Producer::PostgreSQL::alter_field($field2, $field1, $options);
is(
$alter_field2,
qq[ALTER TABLE "my'table" ALTER COLUMN "myfield" DROP NOT NULL;
ALTER TABLE "my'table" ALTER COLUMN "myfield" TYPE geometry;
ALTER TABLE "my'table" ALTER COLUMN "myfield" TYPE geometry USING ("myfield"::geometry);
INSERT INTO geometry_columns VALUES ('','myschema','my''table','myfield','2','-1','POINT');
ALTER TABLE "my'table" ADD CONSTRAINT "enforce_dims_myfield" CHECK ((ST_NDims("myfield") = 2));
ALTER TABLE "my'table" ADD CONSTRAINT "enforce_srid_myfield" CHECK ((ST_SRID("myfield") = -1));
Expand Down
Loading