Skip to content

Commit 07f787e

Browse files
peterejianhe-fun
andcommitted
Disallow generated columns in COPY WHERE clause
Stored generated columns are not yet computed when the filtering happens, so we need to prohibit them to avoid incorrect behavior. Co-authored-by: jian he <jian.universality@gmail.com> Reviewed-by: Kirill Reshke <reshkekirill@gmail.com> Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com> Discussion: https://www.postgresql.org/message-id/flat/CACJufxHb8YPQ095R_pYDr77W9XKNaXg5Rzy-WP525mkq+hRM3g@mail.gmail.com
1 parent 726e77d commit 07f787e

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

src/backend/commands/copy.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
133133

134134
if (stmt->whereClause)
135135
{
136+
Bitmapset *expr_attrs = NULL;
137+
int i;
138+
136139
/* add nsitem to query namespace */
137140
addNSItemToQuery(pstate, nsitem, false, true, true);
138141

@@ -145,6 +148,40 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
145148
/* we have to fix its collations too */
146149
assign_expr_collations(pstate, whereClause);
147150

151+
/*
152+
* Examine all the columns in the WHERE clause expression. When
153+
* the whole-row reference is present, examine all the columns of
154+
* the table.
155+
*/
156+
pull_varattnos(whereClause, 1, &expr_attrs);
157+
if (bms_is_member(0 - FirstLowInvalidHeapAttributeNumber, expr_attrs))
158+
{
159+
expr_attrs = bms_add_range(expr_attrs,
160+
1 - FirstLowInvalidHeapAttributeNumber,
161+
RelationGetNumberOfAttributes(rel) - FirstLowInvalidHeapAttributeNumber);
162+
expr_attrs = bms_del_member(expr_attrs, 0 - FirstLowInvalidHeapAttributeNumber);
163+
}
164+
165+
i = -1;
166+
while ((i = bms_next_member(expr_attrs, i)) >= 0)
167+
{
168+
AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber;
169+
170+
Assert(attno != 0);
171+
172+
/*
173+
* Prohibit generated columns in the WHERE clause. Stored
174+
* generated columns are not yet computed when the filtering
175+
* happens.
176+
*/
177+
if (TupleDescAttr(RelationGetDescr(rel), attno - 1)->attgenerated)
178+
ereport(ERROR,
179+
errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
180+
errmsg("generated columns are not supported in COPY FROM WHERE conditions"),
181+
errdetail("Column \"%s\" is a generated column.",
182+
get_attname(RelationGetRelid(rel), attno, false)));
183+
}
184+
148185
whereClause = eval_const_expressions(NULL, whereClause);
149186

150187
whereClause = (Node *) canonicalize_qual((Expr *) whereClause, false);

src/test/regress/expected/generated.out

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,12 @@ COPY gtest1 FROM stdin;
432432
COPY gtest1 (a, b) FROM stdin;
433433
ERROR: column "b" is a generated column
434434
DETAIL: Generated columns cannot be used in COPY.
435+
COPY gtest1 FROM stdin WHERE b <> 10;
436+
ERROR: generated columns are not supported in COPY FROM WHERE conditions
437+
DETAIL: Column "b" is a generated column.
438+
COPY gtest1 FROM stdin WHERE gtest1 IS NULL;
439+
ERROR: generated columns are not supported in COPY FROM WHERE conditions
440+
DETAIL: Column "b" is a generated column.
435441
SELECT * FROM gtest1 ORDER BY a;
436442
a | b
437443
---+---

src/test/regress/sql/generated.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,10 @@ COPY gtest1 FROM stdin;
199199

200200
COPY gtest1 (a, b) FROM stdin;
201201

202+
COPY gtest1 FROM stdin WHERE b <> 10;
203+
204+
COPY gtest1 FROM stdin WHERE gtest1 IS NULL;
205+
202206
SELECT * FROM gtest1 ORDER BY a;
203207

204208
TRUNCATE gtest3;

0 commit comments

Comments
 (0)