From 8d6b714264a26888da6e94e7e71a596e24fe6597 Mon Sep 17 00:00:00 2001
From: jian he <jian.universality@gmail.com>
Date: Mon, 27 Oct 2025 14:30:24 +0800
Subject: [PATCH v1 1/2] diallow COPY WHERE clause system column references

discussion: https://postgr.es/m/
---
 src/backend/commands/copy.c         | 17 +++++++++++++++++
 src/test/regress/expected/copy2.out |  3 +++
 src/test/regress/sql/copy2.sql      |  4 ++++
 3 files changed, 24 insertions(+)

diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 44020d0ae80..a112812d96f 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -133,6 +133,9 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
 
 		if (stmt->whereClause)
 		{
+			Bitmapset  *attnums = NULL;
+			int			k;
+
 			/* add nsitem to query namespace */
 			addNSItemToQuery(pstate, nsitem, false, true, true);
 
@@ -145,6 +148,20 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
 			/* we have to fix its collations too */
 			assign_expr_collations(pstate, whereClause);
 
+			pull_varattnos(whereClause, 1, &attnums);
+
+			k = -1;
+			while ((k = bms_next_member(attnums, k)) >= 0)
+			{
+				AttrNumber	attnum = k + FirstLowInvalidHeapAttributeNumber;
+
+				/* Disallow expressions referencing system attributes. */
+				if (attnum <= 0 && attnum != TableOidAttributeNumber)
+					ereport(ERROR,
+							errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+							errmsg("COPY FROM WHERE on system columns is not supported"));
+			}
+
 			whereClause = eval_const_expressions(NULL, whereClause);
 
 			whereClause = (Node *) canonicalize_qual((Expr *) whereClause, false);
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index f3fdce23459..cae2c89b95e 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -159,6 +159,9 @@ CONTEXT:  COPY x, line 1: "2002	232	40	50	60	70	80"
 COPY x (b, c, d, e) from stdin delimiter ',' null 'x';
 COPY x from stdin WITH DELIMITER AS ';' NULL AS '';
 COPY x from stdin WITH DELIMITER AS ':' NULL AS E'\\X' ENCODING 'sql_ascii';
+COPY x from stdin WHERE xmin IS NULL; --error
+ERROR:  COPY FROM WHERE on system columns is not supported
+COPY x from stdin WHERE tableoid IS NULL; --ok
 COPY x TO stdout WHERE a = 1;
 ERROR:  WHERE clause not allowed with COPY TO
 LINE 1: COPY x TO stdout WHERE a = 1;
diff --git a/src/test/regress/sql/copy2.sql b/src/test/regress/sql/copy2.sql
index cef45868db5..383c8204094 100644
--- a/src/test/regress/sql/copy2.sql
+++ b/src/test/regress/sql/copy2.sql
@@ -136,6 +136,10 @@ COPY x from stdin WITH DELIMITER AS ':' NULL AS E'\\X' ENCODING 'sql_ascii';
 4008:8:Delimiter:\::\:
 \.
 
+COPY x from stdin WHERE xmin IS NULL; --error
+COPY x from stdin WHERE tableoid IS NULL; --ok
+\.
+
 COPY x TO stdout WHERE a = 1;
 COPY x from stdin WHERE a = 50004;
 50003	24	34	44	54
-- 
2.34.1

