Skip to content

Commit cd9af18

Browse files
committed
Postgres producer ALTER COLUMN: specify USING for datatype change
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 change adds an automatic "USING (colname::datatype)" suffix any time the data type has changed, which should be a safe default. It is also conditioned on the version of Postgres, but also makes it the default in absence of a version, since Pg 8 is so old.
1 parent 18be6d1 commit cd9af18

1 file changed

Lines changed: 17 additions & 7 deletions

File tree

lib/SQL/Translator/Producer/PostgreSQL.pm

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ The version of postgres to generate DDL for. Turns on features only available in
3535
If your postgres_version is higher than 8.003 (I should hope it is by now), then the DDL
3636
generated for dropping objects in the database will contain IF EXISTS.
3737
38+
=item ALTER COLUMN ... TYPE ... USING
39+
40+
Postgres 8 and later require a C<< USING expression >> clause when changing the type of a column
41+
in a potentially lossy manner, such as from C<text> to C<numeric>. This the default when the
42+
version is undefined, or when set to a number greater or equal to 8.
43+
3844
=back
3945
4046
=item attach_comments
@@ -910,27 +916,31 @@ sub alter_field {
910916
# rename later
911917
# BUT: drop geometry is done before the rename, cause it work's on the
912918
# $from_field directly
919+
my $to_table_quoted= $generator->quote($to_field->table->name);
920+
my $to_field_quoted= $generator->quote($to_field->name);
913921
push @out,
914922
sprintf('ALTER TABLE %s RENAME COLUMN %s TO %s',
915-
map($generator->quote($_), $to_field->table->name, $from_field->name, $to_field->name,),)
923+
$to_table_quoted, $generator->quote($from_field->name), $to_field_quoted)
916924
if ($from_field->name ne $to_field->name);
917925

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

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

928936
my $from_dt = convert_datatype($from_field);
929937
my $to_dt = convert_datatype($to_field);
930-
push @out,
931-
sprintf('ALTER TABLE %s ALTER COLUMN %s TYPE %s',
932-
map($generator->quote($_), $to_field->table->name, $to_field->name), $to_dt,)
933-
if ($to_dt ne $from_dt);
938+
push @out, ($options->{postgres_version}//8) < 8
939+
? sprintf('ALTER TABLE %s ALTER COLUMN %s TYPE %s',
940+
$to_table_quoted, $to_field_quoted, $to_dt)
941+
: sprintf('ALTER TABLE %s ALTER COLUMN %s TYPE %s USING (%s::%s)',
942+
$to_table_quoted, $to_field_quoted, $to_dt, $to_field_quoted, $to_dt)
943+
if $to_dt ne $from_dt;
934944

935945
my ($from_enum_typename, $from_list) = _enum_typename_and_values($from_field);
936946
my ($to_enum_typename, $to_list) = _enum_typename_and_values($to_field);

0 commit comments

Comments
 (0)