From 86437ddf8c8da6fff49bdf08a22af3460e078eeb Mon Sep 17 00:00:00 2001
From: Robert Haas <rhaas@postgresql.org>
Date: Fri, 1 Jul 2016 11:29:25 -0400
Subject: [PATCH] postgres_fdw: Fix cache lookup failure while creating error
 context.

This is fallout from join pushdown; get_relid_attribute_name can't
handle an attribute number of 0, indicating a whole-row reference,
and shouldn't be called in that case.

Etsuro Fujita, reviewed by Ashutosh Bapat
---
 contrib/postgres_fdw/expected/postgres_fdw.out |  3 +++
 contrib/postgres_fdw/postgres_fdw.c            | 17 ++++++++++++++---
 contrib/postgres_fdw/sql/postgres_fdw.sql      |  1 +
 3 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index 15642e43aa0..107f0b73717 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -2591,6 +2591,9 @@ CONTEXT:  column "c8" of foreign table "ft1"
 SELECT  ft1.c1,  ft2.c2, ft1.c8 FROM ft1, ft2 WHERE ft1.c1 = ft2.c1 AND ft1.c1 = 1; -- ERROR
 ERROR:  invalid input syntax for integer: "foo"
 CONTEXT:  column "c8" of foreign table "ft1"
+SELECT  ft1.c1,  ft2.c2, ft1 FROM ft1, ft2 WHERE ft1.c1 = ft2.c1 AND ft1.c1 = 1; -- ERROR
+ERROR:  invalid input syntax for integer: "foo"
+CONTEXT:  whole-row reference to foreign table "ft1"
 ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE user_enum;
 -- ===================================================================
 -- subtransaction
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index ccfad1b82a3..93ebd8cab68 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -4528,6 +4528,7 @@ conversion_error_callback(void *arg)
 {
 	const char *attname = NULL;
 	const char *relname = NULL;
+	bool		is_wholerow = false;
 	ConversionLocation *errpos = (ConversionLocation *) arg;
 
 	if (errpos->rel)
@@ -4560,12 +4561,22 @@ conversion_error_callback(void *arg)
 		Assert(IsA(var, Var));
 
 		rte = rt_fetch(var->varno, estate->es_range_table);
+
+		if (var->varattno == 0)
+			is_wholerow = true;
+		else
+			attname = get_relid_attribute_name(rte->relid, var->varattno);
+
 		relname = get_rel_name(rte->relid);
-		attname = get_relid_attribute_name(rte->relid, var->varattno);
 	}
 
-	if (attname && relname)
-		errcontext("column \"%s\" of foreign table \"%s\"", attname, relname);
+	if (relname)
+	{
+		if (is_wholerow)
+			errcontext("whole-row reference to foreign table \"%s\"", relname);
+		else if (attname)
+			errcontext("column \"%s\" of foreign table \"%s\"", attname, relname);
+	}
 }
 
 /*
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql
index df4060d57d1..58c55a4d894 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -627,6 +627,7 @@ DROP FUNCTION f_test(int);
 ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE int;
 SELECT * FROM ft1 WHERE c1 = 1;  -- ERROR
 SELECT  ft1.c1,  ft2.c2, ft1.c8 FROM ft1, ft2 WHERE ft1.c1 = ft2.c1 AND ft1.c1 = 1; -- ERROR
+SELECT  ft1.c1,  ft2.c2, ft1 FROM ft1, ft2 WHERE ft1.c1 = ft2.c1 AND ft1.c1 = 1; -- ERROR
 ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE user_enum;
 
 -- ===================================================================
-- 
GitLab