]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Disallow generated columns in COPY WHERE clause
authorPeter Eisentraut <peter@eisentraut.org>
Thu, 6 Nov 2025 10:52:47 +0000 (11:52 +0100)
committerPeter Eisentraut <peter@eisentraut.org>
Thu, 6 Nov 2025 13:02:09 +0000 (14:02 +0100)
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

src/backend/commands/copy.c
src/test/regress/expected/generated.out
src/test/regress/sql/generated.sql

index e4dee3f11ff648d7d72fa88183bfbd4772bcef4e..e56eff02c6c8adbf23d025eeff2f8c5338d93387 100644 (file)
@@ -128,6 +128,9 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
 
                if (stmt->whereClause)
                {
+                       Bitmapset  *expr_attrs = NULL;
+                       int                     i;
+
                        /* add nsitem to query namespace */
                        addNSItemToQuery(pstate, nsitem, false, true, true);
 
@@ -140,6 +143,40 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
                        /* we have to fix its collations too */
                        assign_expr_collations(pstate, whereClause);
 
+                       /*
+                        * Examine all the columns in the WHERE clause expression.  When
+                        * the whole-row reference is present, examine all the columns of
+                        * the table.
+                        */
+                       pull_varattnos(whereClause, 1, &expr_attrs);
+                       if (bms_is_member(0 - FirstLowInvalidHeapAttributeNumber, expr_attrs))
+                       {
+                               expr_attrs = bms_add_range(expr_attrs,
+                                                                                  1 - FirstLowInvalidHeapAttributeNumber,
+                                                                                  RelationGetNumberOfAttributes(rel) - FirstLowInvalidHeapAttributeNumber);
+                               expr_attrs = bms_del_member(expr_attrs, 0 - FirstLowInvalidHeapAttributeNumber);
+                       }
+
+                       i = -1;
+                       while ((i = bms_next_member(expr_attrs, i)) >= 0)
+                       {
+                               AttrNumber      attno = i + FirstLowInvalidHeapAttributeNumber;
+
+                               Assert(attno != 0);
+
+                               /*
+                                * Prohibit generated columns in the WHERE clause.  Stored
+                                * generated columns are not yet computed when the filtering
+                                * happens.
+                                */
+                               if (TupleDescAttr(RelationGetDescr(rel), attno - 1)->attgenerated)
+                                       ereport(ERROR,
+                                                       errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
+                                                       errmsg("generated columns are not supported in COPY FROM WHERE conditions"),
+                                                       errdetail("Column \"%s\" is a generated column.",
+                                                                         get_attname(RelationGetRelid(rel), attno, false)));
+                       }
+
                        whereClause = eval_const_expressions(NULL, whereClause);
 
                        whereClause = (Node *) canonicalize_qual((Expr *) whereClause, false);
index 5cf99c202130bc661e7985067481651b09796c75..e1161010bbdcf458f0ae9135c13f8caff284d5c0 100644 (file)
@@ -415,6 +415,12 @@ COPY gtest1 FROM stdin;
 COPY gtest1 (a, b) FROM stdin;
 ERROR:  column "b" is a generated column
 DETAIL:  Generated columns cannot be used in COPY.
+COPY gtest1 FROM stdin WHERE b <> 10;
+ERROR:  generated columns are not supported in COPY FROM WHERE conditions
+DETAIL:  Column "b" is a generated column.
+COPY gtest1 FROM stdin WHERE gtest1 IS NULL;
+ERROR:  generated columns are not supported in COPY FROM WHERE conditions
+DETAIL:  Column "b" is a generated column.
 SELECT * FROM gtest1 ORDER BY a;
  a | b 
 ---+---
index 1a0b24104986639f8089ff819edbb813046b5865..0dc4e7af932ab7d7e8525020619e10731533e8c3 100644 (file)
@@ -189,6 +189,10 @@ COPY gtest1 FROM stdin;
 
 COPY gtest1 (a, b) FROM stdin;
 
+COPY gtest1 FROM stdin WHERE b <> 10;
+
+COPY gtest1 FROM stdin WHERE gtest1 IS NULL;
+
 SELECT * FROM gtest1 ORDER BY a;
 
 TRUNCATE gtest3;