Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 61feb86

Browse files
committed
Disallow whole-row variables in GENERATED expressions.
This was previously allowed, but I think that was just an oversight. It's a clear violation of the rule that a generated column cannot depend on itself or other generated columns. Moreover, because the code was relying on the assumption that no such cross-references exist, it was pretty easy to crash ALTER TABLE and perhaps other places. Even if you managed not to crash, you got quite unstable, implementation-dependent results. Per report from Vitaly Ustinov. Back-patch to v12 where GENERATED came in. Discussion: https://postgr.es/m/CAM_DEiWR2DPT6U4xb-Ehigozzd3n3G37ZB1+867zbsEVtYoJww@mail.gmail.com
1 parent dfe51ff commit 61feb86

File tree

3 files changed

+23
-2
lines changed

3 files changed

+23
-2
lines changed

src/backend/catalog/heap.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2977,15 +2977,26 @@ check_nested_generated_walker(Node *node, void *context)
29772977
AttrNumber attnum;
29782978

29792979
relid = rt_fetch(var->varno, pstate->p_rtable)->relid;
2980+
if (!OidIsValid(relid))
2981+
return false; /* XXX shouldn't we raise an error? */
2982+
29802983
attnum = var->varattno;
29812984

2982-
if (OidIsValid(relid) && AttributeNumberIsValid(attnum) && get_attgenerated(relid, attnum))
2985+
if (attnum > 0 && get_attgenerated(relid, attnum))
29832986
ereport(ERROR,
2984-
(errcode(ERRCODE_SYNTAX_ERROR),
2987+
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
29852988
errmsg("cannot use generated column \"%s\" in column generation expression",
29862989
get_attname(relid, attnum, false)),
29872990
errdetail("A generated column cannot reference another generated column."),
29882991
parser_errposition(pstate, var->location)));
2992+
/* A whole-row Var is necessarily self-referential, so forbid it */
2993+
if (attnum == 0)
2994+
ereport(ERROR,
2995+
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2996+
errmsg("cannot use whole-row variable in column generation expression"),
2997+
errdetail("This would cause the generated column to depend on its own value."),
2998+
parser_errposition(pstate, var->location)));
2999+
/* System columns were already checked in the parser */
29893000

29903001
return false;
29913002
}

src/test/regress/expected/generated.out

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ ERROR: cannot use generated column "b" in column generation expression
4646
LINE 1: ...AYS AS (a * 2) STORED, c int GENERATED ALWAYS AS (b * 3) STO...
4747
^
4848
DETAIL: A generated column cannot reference another generated column.
49+
-- a whole-row var is a self-reference on steroids, so disallow that too
50+
CREATE TABLE gtest_err_2c (a int PRIMARY KEY,
51+
b int GENERATED ALWAYS AS (num_nulls(gtest_err_2c)) STORED);
52+
ERROR: cannot use whole-row variable in column generation expression
53+
LINE 2: b int GENERATED ALWAYS AS (num_nulls(gtest_err_2c)) STOR...
54+
^
55+
DETAIL: This would cause the generated column to depend on its own value.
4956
-- invalid reference
5057
CREATE TABLE gtest_err_3 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (c * 2) STORED);
5158
ERROR: column "c" does not exist

src/test/regress/sql/generated.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ CREATE TABLE gtest_err_1 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) S
1717
-- references to other generated columns, including self-references
1818
CREATE TABLE gtest_err_2a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (b * 2) STORED);
1919
CREATE TABLE gtest_err_2b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STORED, c int GENERATED ALWAYS AS (b * 3) STORED);
20+
-- a whole-row var is a self-reference on steroids, so disallow that too
21+
CREATE TABLE gtest_err_2c (a int PRIMARY KEY,
22+
b int GENERATED ALWAYS AS (num_nulls(gtest_err_2c)) STORED);
2023

2124
-- invalid reference
2225
CREATE TABLE gtest_err_3 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (c * 2) STORED);

0 commit comments

Comments
 (0)