Fix ALTER TABLE ADD VIRTUAL GENERATED COLUMN when table rewrite
authorPeter Eisentraut <[email protected]>
Tue, 4 Mar 2025 08:18:32 +0000 (09:18 +0100)
committerPeter Eisentraut <[email protected]>
Tue, 4 Mar 2025 08:18:32 +0000 (09:18 +0100)
demo:
CREATE TABLE gtest20a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL);
ALTER TABLE gtest20a ADD COLUMN c float8 DEFAULT RANDOM() CHECK (b < 60);
ERROR:  no generation expression found for column number 2 of table "pg_temp_17306"

In ATRewriteTable, the variable OIDNewHeap (if valid) corresponding
pg_attrdef default expression entry was not populated.  So OIDNewHeap
cannot be used to call expand_generated_columns_in_expr or
build_generation_expression.  Therefore in ATRewriteTable, we can only
use the existing relation to expand the generated expression.

Author: jian he <[email protected]>
Reviewed-by: Srinath Reddy <[email protected]>
Discussion: https://www.postgresql.org/message-id/flat/CACJufxEJ%3DFoajabWXjszo_yrQeKSxdZ87KJqBW373rSbajKGAA%40mail.gmail.com

src/backend/commands/tablecmds.c
src/test/regress/expected/generated_stored.out
src/test/regress/expected/generated_virtual.out
src/test/regress/sql/generated_stored.sql
src/test/regress/sql/generated_virtual.sql

index 13156391241eacc6dc36ca58446ee8f73ae64dea..8826ca5c32c39fd2fbc65293cfa7a79f045f0b00 100644 (file)
@@ -6137,7 +6137,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap)
        {
            case CONSTR_CHECK:
                needscan = true;
-               con->qualstate = ExecPrepareExpr((Expr *) expand_generated_columns_in_expr(con->qual, newrel ? newrel : oldrel, 1), estate);
+               con->qualstate = ExecPrepareExpr((Expr *) expand_generated_columns_in_expr(con->qual, oldrel, 1), estate);
                break;
            case CONSTR_FOREIGN:
                /* Nothing to do here */
index 3ce0dd1831c74c78c6b80138ee07eafdb49b6bd1..8cccd1d7fe9e57a237ffc42d925e4cfef51ed62c 100644 (file)
@@ -656,6 +656,10 @@ INSERT INTO gtest20a (a) VALUES (10);
 INSERT INTO gtest20a (a) VALUES (30);
 ALTER TABLE gtest20a ADD CHECK (b < 50);  -- fails on existing row
 ERROR:  check constraint "gtest20a_b_check" of relation "gtest20a" is violated by some row
+-- table rewrite cases
+ALTER TABLE gtest20a ADD COLUMN c float8 DEFAULT random() CHECK (b < 50); -- fails on existing row
+ERROR:  check constraint "gtest20a_b_check" of relation "gtest20a" is violated by some row
+ALTER TABLE gtest20a ADD COLUMN c float8 DEFAULT random() CHECK (b < 61); -- ok
 CREATE TABLE gtest20b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STORED);
 INSERT INTO gtest20b (a) VALUES (10);
 INSERT INTO gtest20b (a) VALUES (30);
index b339fbcebfa32bdd25d68afb99360ba284ba2018..7ef05f45be70031263642b665cb4e275125070ae 100644 (file)
@@ -647,6 +647,10 @@ INSERT INTO gtest20a (a) VALUES (10);
 INSERT INTO gtest20a (a) VALUES (30);
 ALTER TABLE gtest20a ADD CHECK (b < 50);  -- fails on existing row
 ERROR:  check constraint "gtest20a_b_check" of relation "gtest20a" is violated by some row
+-- table rewrite cases
+ALTER TABLE gtest20a ADD COLUMN c float8 DEFAULT random() CHECK (b < 50); -- fails on existing row
+ERROR:  check constraint "gtest20a_b_check" of relation "gtest20a" is violated by some row
+ALTER TABLE gtest20a ADD COLUMN c float8 DEFAULT random() CHECK (b < 61); -- ok
 CREATE TABLE gtest20b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL);
 INSERT INTO gtest20b (a) VALUES (10);
 INSERT INTO gtest20b (a) VALUES (30);
index b7749ce355f51b1b7000797e9633a3b36c6daf68..50e94e5c6739a71911334e1b12a818efebc6ef75 100644 (file)
@@ -319,6 +319,9 @@ CREATE TABLE gtest20a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STOR
 INSERT INTO gtest20a (a) VALUES (10);
 INSERT INTO gtest20a (a) VALUES (30);
 ALTER TABLE gtest20a ADD CHECK (b < 50);  -- fails on existing row
+-- table rewrite cases
+ALTER TABLE gtest20a ADD COLUMN c float8 DEFAULT random() CHECK (b < 50); -- fails on existing row
+ALTER TABLE gtest20a ADD COLUMN c float8 DEFAULT random() CHECK (b < 61); -- ok
 
 CREATE TABLE gtest20b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STORED);
 INSERT INTO gtest20b (a) VALUES (10);
index c80630c11a5462f845483da308358739a3f15ace..dab8c92ef99288f0f41e830f49c1bb3b32e1dfde 100644 (file)
@@ -319,6 +319,9 @@ CREATE TABLE gtest20a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRT
 INSERT INTO gtest20a (a) VALUES (10);
 INSERT INTO gtest20a (a) VALUES (30);
 ALTER TABLE gtest20a ADD CHECK (b < 50);  -- fails on existing row
+-- table rewrite cases
+ALTER TABLE gtest20a ADD COLUMN c float8 DEFAULT random() CHECK (b < 50); -- fails on existing row
+ALTER TABLE gtest20a ADD COLUMN c float8 DEFAULT random() CHECK (b < 61); -- ok
 
 CREATE TABLE gtest20b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL);
 INSERT INTO gtest20b (a) VALUES (10);