Skip to content

Commit 3717849

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 324051f commit 3717849

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

904904
if (stmt->whereClause)
905905
{
906+
Bitmapset *expr_attrs = NULL;
907+
int i;
908+
906909
/* add nsitem to query namespace */
907910
addNSItemToQuery(pstate, nsitem, false, true, true);
908911

@@ -915,6 +918,40 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
915918
/* we have to fix its collations too */
916919
assign_expr_collations(pstate, whereClause);
917920

921+
/*
922+
* Examine all the columns in the WHERE clause expression. When
923+
* the whole-row reference is present, examine all the columns of
924+
* the table.
925+
*/
926+
pull_varattnos(whereClause, 1, &expr_attrs);
927+
if (bms_is_member(0 - FirstLowInvalidHeapAttributeNumber, expr_attrs))
928+
{
929+
expr_attrs = bms_add_range(expr_attrs,
930+
1 - FirstLowInvalidHeapAttributeNumber,
931+
RelationGetNumberOfAttributes(rel) - FirstLowInvalidHeapAttributeNumber);
932+
expr_attrs = bms_del_member(expr_attrs, 0 - FirstLowInvalidHeapAttributeNumber);
933+
}
934+
935+
i = -1;
936+
while ((i = bms_next_member(expr_attrs, i)) >= 0)
937+
{
938+
AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber;
939+
940+
Assert(attno != 0);
941+
942+
/*
943+
* Prohibit generated columns in the WHERE clause. Stored
944+
* generated columns are not yet computed when the filtering
945+
* happens.
946+
*/
947+
if (TupleDescAttr(RelationGetDescr(rel), attno - 1)->attgenerated)
948+
ereport(ERROR,
949+
errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
950+
errmsg("generated columns are not supported in COPY FROM WHERE conditions"),
951+
errdetail("Column \"%s\" is a generated column.",
952+
get_attname(RelationGetRelid(rel), attno, false)));
953+
}
954+
918955
whereClause = eval_const_expressions(NULL, whereClause);
919956

920957
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
@@ -374,6 +374,12 @@ COPY gtest1 FROM stdin;
374374
COPY gtest1 (a, b) FROM stdin;
375375
ERROR: column "b" is a generated column
376376
DETAIL: Generated columns cannot be used in COPY.
377+
COPY gtest1 FROM stdin WHERE b <> 10;
378+
ERROR: generated columns are not supported in COPY FROM WHERE conditions
379+
DETAIL: Column "b" is a generated column.
380+
COPY gtest1 FROM stdin WHERE gtest1 IS NULL;
381+
ERROR: generated columns are not supported in COPY FROM WHERE conditions
382+
DETAIL: Column "b" is a generated column.
377383
SELECT * FROM gtest1 ORDER BY a;
378384
a | b
379385
---+---

src/test/regress/sql/generated.sql

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

173173
COPY gtest1 (a, b) FROM stdin;
174174

175+
COPY gtest1 FROM stdin WHERE b <> 10;
176+
177+
COPY gtest1 FROM stdin WHERE gtest1 IS NULL;
178+
175179
SELECT * FROM gtest1 ORDER BY a;
176180

177181
TRUNCATE gtest3;

0 commit comments

Comments
 (0)