Commit b0098234 authored by Tom Lane's avatar Tom Lane

Improve error message and hint for ALTER COLUMN TYPE can't-cast failure.

We already tried to improve this once, but the "improved" text was rather
off-target if you had provided a USING clause.  Also, it seems helpful
to provide the exact text of a suggested USING clause, so users can just
copy-and-paste it when needed.  Per complaint from Keith Rarick and a
suggestion from Merlin Moncure.

Back-patch to 9.2 where the current wording was adopted.
parent b5fe6203
...@@ -7888,11 +7888,26 @@ ATPrepAlterColumnType(List **wqueue, ...@@ -7888,11 +7888,26 @@ ATPrepAlterColumnType(List **wqueue,
COERCE_IMPLICIT_CAST, COERCE_IMPLICIT_CAST,
-1); -1);
if (transform == NULL) if (transform == NULL)
{
/* error text depends on whether USING was specified or not */
if (def->cooked_default != NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("result of USING clause for column \"%s\""
" cannot be cast automatically to type %s",
colName, format_type_be(targettype)),
errhint("You might need to add an explicit cast.")));
else
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH), (errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("column \"%s\" cannot be cast automatically to type %s", errmsg("column \"%s\" cannot be cast automatically to type %s",
colName, format_type_be(targettype)), colName, format_type_be(targettype)),
errhint("Specify a USING expression to perform the conversion."))); /* translator: USING is SQL, don't translate it */
errhint("You might need to specify \"USING %s::%s\".",
quote_identifier(colName),
format_type_with_typemod(targettype,
targettypmod))));
}
/* Fix collations after all else */ /* Fix collations after all else */
assign_expr_collations(pstate, transform); assign_expr_collations(pstate, transform);
......
...@@ -1665,7 +1665,7 @@ select f3,max(f1) from foo group by f3; ...@@ -1665,7 +1665,7 @@ select f3,max(f1) from foo group by f3;
-- Simple tests for alter table column type -- Simple tests for alter table column type
alter table foo alter f1 TYPE integer; -- fails alter table foo alter f1 TYPE integer; -- fails
ERROR: column "f1" cannot be cast automatically to type integer ERROR: column "f1" cannot be cast automatically to type integer
HINT: Specify a USING expression to perform the conversion. HINT: You might need to specify "USING f1::integer".
alter table foo alter f1 TYPE varchar(10); alter table foo alter f1 TYPE varchar(10);
create table anothertab (atcol1 serial8, atcol2 boolean, create table anothertab (atcol1 serial8, atcol2 boolean,
constraint anothertab_chk check (atcol1 <= 3)); constraint anothertab_chk check (atcol1 <= 3));
...@@ -1680,7 +1680,10 @@ select * from anothertab; ...@@ -1680,7 +1680,10 @@ select * from anothertab;
alter table anothertab alter column atcol1 type boolean; -- fails alter table anothertab alter column atcol1 type boolean; -- fails
ERROR: column "atcol1" cannot be cast automatically to type boolean ERROR: column "atcol1" cannot be cast automatically to type boolean
HINT: Specify a USING expression to perform the conversion. HINT: You might need to specify "USING atcol1::boolean".
alter table anothertab alter column atcol1 type boolean using atcol1::int; -- fails
ERROR: result of USING clause for column "atcol1" cannot be cast automatically to type boolean
HINT: You might need to add an explicit cast.
alter table anothertab alter column atcol1 type integer; alter table anothertab alter column atcol1 type integer;
select * from anothertab; select * from anothertab;
atcol1 | atcol2 atcol1 | atcol2
......
...@@ -1175,6 +1175,7 @@ insert into anothertab (atcol1, atcol2) values (default, false); ...@@ -1175,6 +1175,7 @@ insert into anothertab (atcol1, atcol2) values (default, false);
select * from anothertab; select * from anothertab;
alter table anothertab alter column atcol1 type boolean; -- fails alter table anothertab alter column atcol1 type boolean; -- fails
alter table anothertab alter column atcol1 type boolean using atcol1::int; -- fails
alter table anothertab alter column atcol1 type integer; alter table anothertab alter column atcol1 type integer;
select * from anothertab; select * from anothertab;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment