Skip to content

Commit 26958f4

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 98821ea commit 26958f4

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
@@ -135,6 +135,9 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
135135

136136
if (stmt->whereClause)
137137
{
138+
Bitmapset *expr_attrs = NULL;
139+
int i;
140+
138141
/* add nsitem to query namespace */
139142
addNSItemToQuery(pstate, nsitem, false, true, true);
140143

@@ -147,6 +150,40 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
147150
/* we have to fix its collations too */
148151
assign_expr_collations(pstate, whereClause);
149152

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

152189
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)