aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/executor/execQual.c7
-rw-r--r--src/test/regress/expected/copy2.out35
-rw-r--r--src/test/regress/sql/copy2.sql19
3 files changed, 59 insertions, 2 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index dae8bf0f2c1..c6386e46f2f 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -900,7 +900,9 @@ ExecEvalWholeRowVar(WholeRowVarExprState *wrvstate, ExprContext *econtext,
* If we can't locate the RTE, assume the column names we've got are OK.
* (As of this writing, the only cases where we can't locate the RTE are
* in execution of trigger WHEN clauses, and then the Var will have the
- * trigger's relation's rowtype, so its names are fine.)
+ * trigger's relation's rowtype, so its names are fine.) Also, if the
+ * creator of the RTE didn't bother to fill in an eref field, assume our
+ * column names are OK. (This happens in COPY, and perhaps other places.)
*/
if (variable->vartype == RECORDOID &&
econtext->ecxt_estate &&
@@ -909,7 +911,8 @@ ExecEvalWholeRowVar(WholeRowVarExprState *wrvstate, ExprContext *econtext,
RangeTblEntry *rte = rt_fetch(variable->varno,
econtext->ecxt_estate->es_range_table);
- ExecTypeSetColNames(output_tupdesc, rte->eref->colnames);
+ if (rte->eref)
+ ExecTypeSetColNames(output_tupdesc, rte->eref->colnames);
}
/* Bless the tupdesc if needed, and save it in the execution state */
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index 34fa131c52b..33ee8832dbe 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -382,6 +382,41 @@ SELECT * FROM vistest;
e
(2 rows)
+-- test case with whole-row Var in a check constraint
+create table check_con_tbl (f1 int);
+create function check_con_function(check_con_tbl) returns bool as $$
+begin
+ raise notice 'input = %', row_to_json($1);
+ return $1.f1 > 0;
+end $$ language plpgsql immutable;
+alter table check_con_tbl add check (check_con_function(check_con_tbl.*));
+\d+ check_con_tbl
+ Table "public.check_con_tbl"
+ Column | Type | Modifiers | Storage | Stats target | Description
+--------+---------+-----------+---------+--------------+-------------
+ f1 | integer | | plain | |
+Check constraints:
+ "check_con_tbl_check" CHECK (check_con_function(check_con_tbl.*))
+Has OIDs: no
+
+copy check_con_tbl from stdin;
+NOTICE: input = {"f1":1}
+CONTEXT: COPY check_con_tbl, line 1: "1"
+NOTICE: input = {"f1":null}
+CONTEXT: COPY check_con_tbl, line 2: "\N"
+copy check_con_tbl from stdin;
+NOTICE: input = {"f1":0}
+CONTEXT: COPY check_con_tbl, line 1: "0"
+ERROR: new row for relation "check_con_tbl" violates check constraint "check_con_tbl_check"
+DETAIL: Failing row contains (0).
+CONTEXT: COPY check_con_tbl, line 1: "0"
+select * from check_con_tbl;
+ f1
+----
+ 1
+
+(2 rows)
+
DROP TABLE vistest;
DROP FUNCTION truncate_in_subxact();
DROP TABLE x, y;
diff --git a/src/test/regress/sql/copy2.sql b/src/test/regress/sql/copy2.sql
index c46128b38a1..bd27a25c026 100644
--- a/src/test/regress/sql/copy2.sql
+++ b/src/test/regress/sql/copy2.sql
@@ -270,6 +270,25 @@ e
SELECT * FROM vistest;
COMMIT;
SELECT * FROM vistest;
+
+-- test case with whole-row Var in a check constraint
+create table check_con_tbl (f1 int);
+create function check_con_function(check_con_tbl) returns bool as $$
+begin
+ raise notice 'input = %', row_to_json($1);
+ return $1.f1 > 0;
+end $$ language plpgsql immutable;
+alter table check_con_tbl add check (check_con_function(check_con_tbl.*));
+\d+ check_con_tbl
+copy check_con_tbl from stdin;
+1
+\N
+\.
+copy check_con_tbl from stdin;
+0
+\.
+select * from check_con_tbl;
+
DROP TABLE vistest;
DROP FUNCTION truncate_in_subxact();
DROP TABLE x, y;