Disallow USING clause when altering type of generated column
authorPeter Eisentraut
Thu, 29 Aug 2024 06:38:29 +0000 (08:38 +0200)
committerPeter Eisentraut
Thu, 29 Aug 2024 07:01:02 +0000 (09:01 +0200)
This does not make sense.  It would write the output of the USING
clause into the converted column, which would violate the generation
expression.  This adds a check to error out if this is specified.

There was a test for this, but that test errored out for a different
reason, so it was not effective.

Reported-by: Jian He
Reviewed-by: Yugo NAGATA
Discussion: https://www.postgresql.org/message-id/flat/c7083982-69f4-4b14-8315-f9ddb20b9834%40eisentraut.org

src/backend/commands/tablecmds.c
src/test/regress/expected/generated.out

index 44629fb52f42d3130e4d48872b30a32e26af2a2a..4f6bf4c959c6cdd25c3da1690e6f9fcda5bf191d 100644 (file)
@@ -12307,6 +12307,16 @@ ATPrepAlterColumnType(List **wqueue,
                 errmsg("cannot alter system column \"%s\"",
                        colName)));
 
+   /*
+    * Cannot specify USING when altering type of a generated column, because
+    * that would violate the generation expression.
+    */
+   if (attTup->attgenerated && def->cooked_default)
+       ereport(ERROR,
+               (errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
+                errmsg("cannot specify USING when altering type of generated column"),
+                errdetail("Column \"%s\" is a generated column.", colName)));
+
    /*
     * Don't alter inherited columns.  At outer level, there had better not be
     * any inherited definition; when recursing, we assume this was checked at
@@ -12383,11 +12393,12 @@ ATPrepAlterColumnType(List **wqueue,
                        (errcode(ERRCODE_DATATYPE_MISMATCH),
                         errmsg("column \"%s\" cannot be cast automatically to type %s",
                                colName, format_type_be(targettype)),
+                        !attTup->attgenerated ?
                /* 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))));
+                                                         targettypmod)) : 0));
        }
 
        /* Fix collations after all else */
index 10208484ee5bfaa89a2856eedc353230e0593426..9ee4559bd5a658daeade6803aa1a2c3bfd10148d 100644 (file)
@@ -836,7 +836,8 @@ SELECT * FROM gtest27;
 (2 rows)
 
 ALTER TABLE gtest27 ALTER COLUMN x TYPE boolean USING x <> 0;  -- error
-ERROR:  generation expression for column "x" cannot be cast automatically to type boolean
+ERROR:  cannot specify USING when altering type of generated column
+DETAIL:  Column "x" is a generated column.
 ALTER TABLE gtest27 ALTER COLUMN x DROP DEFAULT;  -- error
 ERROR:  column "x" of relation "gtest27" is a generated column
 HINT:  Use ALTER TABLE ... ALTER COLUMN ... DROP EXPRESSION instead.