Disallow USING clause when altering type of generated column
authorPeter Eisentraut <[email protected]>
Thu, 29 Aug 2024 06:38:29 +0000 (08:38 +0200)
committerPeter Eisentraut <[email protected]>
Thu, 29 Aug 2024 07:06:15 +0000 (09:06 +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 <[email protected]>
Reviewed-by: Yugo NAGATA <[email protected]>
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 94fc3a082b24dd5e3bda2035781f06b050723dca..70cd266916429373a86efdf0223ae9284e5ffd61 100644 (file)
@@ -12677,6 +12677,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
@@ -12753,11 +12763,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 44058db7c1d512b0e2d6e9b54a10b44c843bfd5a..499072e14ca8726db20ab293269dcececec12a7f 100644 (file)
@@ -1026,7 +1026,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.