diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index baa02f256e3afa2cdf5df943e8a3a1317af59cc9..14a858091945b7eed733ca7bdee3ce058151e897 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -898,7 +898,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 &&
@@ -907,7 +909,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 2449eefb16d4b8712b7e78f39ff42886a098789c..816fa77056ca53766885bf92d4b48f45b3b3a93d 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -255,6 +255,41 @@ SELECT * FROM testnull;
     | 
 (4 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 x, y;
 DROP FUNCTION fn_x_before();
 DROP FUNCTION fn_x_after();
diff --git a/src/test/regress/sql/copy2.sql b/src/test/regress/sql/copy2.sql
index 1961446fdb1b25f5b415f747236832e3689d53a1..97d975b6303e9a92949b118ac6eab2b5dfb702aa 100644
--- a/src/test/regress/sql/copy2.sql
+++ b/src/test/regress/sql/copy2.sql
@@ -178,6 +178,23 @@ COPY testnull FROM stdin WITH NULL AS E'\\0';
 
 SELECT * FROM testnull;
 
+-- 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 x, y;
 DROP FUNCTION fn_x_before();