On 2016/03/16 16:25, Etsuro Fujita wrote:
> PG9.5 allows us to add an oid system column to foreign tables, using
> ALTER FOREIGN TABLE SET WITH OIDS, but currently, that column reads as
> zeroes in postgres_fdw.  That seems to me like a bug.  So, I'd like to
> propose to fix that, by retrieving that column from the remote server
> when requested.  I'm attaching a proposed patch for that.

I rebased the patch against HEAD.  Updated patch attached.  I don't
think this is a 9.6 issue, but I think this is somewhat related to the
9.6 issue [1] that postgres_fdw join pushdown incorrectly retrieves
system columns other than ctid and oid from the remote server, so ISTM
that it's better to address this in conjunction with [1].

Best regards,
Etsuro Fujita

[1] http://www.postgresql.org/message-id/57035dfc.3050...@lab.ntt.co.jp
*** a/contrib/postgres_fdw/deparse.c
--- b/contrib/postgres_fdw/deparse.c
***************
*** 287,299 **** foreign_expr_walker(Node *node,
  					/* Var belongs to foreign table */
  
  					/*
! 					 * System columns other than ctid should not be sent to
! 					 * the remote, since we don't make any effort to ensure
! 					 * that local and remote values match (tableoid, in
  					 * particular, almost certainly doesn't match).
  					 */
  					if (var->varattno < 0 &&
! 						var->varattno != SelfItemPointerAttributeNumber)
  						return false;
  
  					/* Else check the collation */
--- 287,300 ----
  					/* Var belongs to foreign table */
  
  					/*
! 					 * System columns other than ctid and oid should not be
! 					 * sent to the remote, since we don't make any effort to
! 					 * ensure that local and remote values match (tableoid, in
  					 * particular, almost certainly doesn't match).
  					 */
  					if (var->varattno < 0 &&
! 						var->varattno != SelfItemPointerAttributeNumber &&
! 						var->varattno != ObjectIdAttributeNumber)
  						return false;
  
  					/* Else check the collation */
***************
*** 911,918 **** deparseTargetList(StringInfo buf,
  	}
  
  	/*
! 	 * Add ctid if needed.  We currently don't support retrieving any other
! 	 * system columns.
  	 */
  	if (bms_is_member(SelfItemPointerAttributeNumber - FirstLowInvalidHeapAttributeNumber,
  					  attrs_used))
--- 912,919 ----
  	}
  
  	/*
! 	 * Add ctid and oid if needed.  We currently don't support retrieving any
! 	 * other system columns.
  	 */
  	if (bms_is_member(SelfItemPointerAttributeNumber - FirstLowInvalidHeapAttributeNumber,
  					  attrs_used))
***************
*** 930,935 **** deparseTargetList(StringInfo buf,
--- 931,952 ----
  		*retrieved_attrs = lappend_int(*retrieved_attrs,
  									   SelfItemPointerAttributeNumber);
  	}
+ 	if (bms_is_member(ObjectIdAttributeNumber - FirstLowInvalidHeapAttributeNumber,
+ 					  attrs_used))
+ 	{
+ 		if (!first)
+ 			appendStringInfoString(buf, ", ");
+ 		else if (is_returning)
+ 			appendStringInfoString(buf, " RETURNING ");
+ 		first = false;
+ 
+ 		if (qualify_col)
+ 			ADD_REL_QUALIFIER(buf, rtindex);
+ 		appendStringInfoString(buf, "oid");
+ 
+ 		*retrieved_attrs = lappend_int(*retrieved_attrs,
+ 									   ObjectIdAttributeNumber);
+ 	}
  
  	/* Don't generate bad syntax if no undropped columns */
  	if (first && !is_returning)
***************
*** 1571,1583 **** deparseColumnRef(StringInfo buf, int varno, int varattno, PlannerInfo *root,
  {
  	RangeTblEntry *rte;
  
! 	/* varattno can be a whole-row reference, ctid or a regular table column */
  	if (varattno == SelfItemPointerAttributeNumber)
  	{
  		if (qualify_col)
  			ADD_REL_QUALIFIER(buf, varno);
  		appendStringInfoString(buf, "ctid");
  	}
  	else if (varattno == 0)
  	{
  		/* Whole row reference */
--- 1588,1609 ----
  {
  	RangeTblEntry *rte;
  
! 	/*
! 	 * varattno can be a ctid, an oid, a whole-row reference, or a regular
! 	 * table column
! 	 */
  	if (varattno == SelfItemPointerAttributeNumber)
  	{
  		if (qualify_col)
  			ADD_REL_QUALIFIER(buf, varno);
  		appendStringInfoString(buf, "ctid");
  	}
+ 	else if (varattno == ObjectIdAttributeNumber)
+ 	{
+ 		if (qualify_col)
+ 			ADD_REL_QUALIFIER(buf, varno);
+ 		appendStringInfoString(buf, "oid");
+ 	}
  	else if (varattno == 0)
  	{
  		/* Whole row reference */
*** a/contrib/postgres_fdw/expected/postgres_fdw.out
--- b/contrib/postgres_fdw/expected/postgres_fdw.out
***************
*** 2286,2292 **** DEALLOCATE st2;
  DEALLOCATE st3;
  DEALLOCATE st4;
  DEALLOCATE st5;
! -- System columns, except ctid, should not be sent to remote
  EXPLAIN (VERBOSE, COSTS false)
  SELECT * FROM ft1 t1 WHERE t1.tableoid = 'pg_class'::regclass LIMIT 1;
                                    QUERY PLAN                                   
--- 2286,2292 ----
  DEALLOCATE st3;
  DEALLOCATE st4;
  DEALLOCATE st5;
! -- System columns, except ctid and oid, should not be sent to remote
  EXPLAIN (VERBOSE, COSTS false)
  SELECT * FROM ft1 t1 WHERE t1.tableoid = 'pg_class'::regclass LIMIT 1;
                                    QUERY PLAN                                   
*** a/contrib/postgres_fdw/postgres_fdw.c
--- b/contrib/postgres_fdw/postgres_fdw.c
***************
*** 4298,4303 **** make_tuple_from_result_row(PGresult *res,
--- 4298,4304 ----
  	Datum	   *values;
  	bool	   *nulls;
  	ItemPointer ctid = NULL;
+ 	Oid			oid = InvalidOid;
  	ConversionLocation errpos;
  	ErrorContextCallback errcallback;
  	MemoryContext oldcontext;
***************
*** 4355,4361 **** make_tuple_from_result_row(PGresult *res,
  		else
  			valstr = PQgetvalue(res, row, j);
  
! 		/* convert value to internal representation */
  		errpos.cur_attno = i;
  		if (i > 0)
  		{
--- 4356,4366 ----
  		else
  			valstr = PQgetvalue(res, row, j);
  
! 		/*
! 		 * convert value to internal representation
! 		 *
! 		 * Note: we ignore system columns other than ctid and oid in result
! 		 */
  		errpos.cur_attno = i;
  		if (i > 0)
  		{
***************
*** 4370,4376 **** make_tuple_from_result_row(PGresult *res,
  		}
  		else if (i == SelfItemPointerAttributeNumber)
  		{
! 			/* ctid --- note we ignore any other system column in result */
  			if (valstr != NULL)
  			{
  				Datum		datum;
--- 4375,4381 ----
  		}
  		else if (i == SelfItemPointerAttributeNumber)
  		{
! 			/* ctid */
  			if (valstr != NULL)
  			{
  				Datum		datum;
***************
*** 4379,4384 **** make_tuple_from_result_row(PGresult *res,
--- 4384,4400 ----
  				ctid = (ItemPointer) DatumGetPointer(datum);
  			}
  		}
+ 		else if (i == ObjectIdAttributeNumber)
+ 		{
+ 			/* oid */
+ 			if (valstr != NULL)
+ 			{
+ 				Datum		datum;
+ 
+ 				datum = DirectFunctionCall1(oidin, CStringGetDatum(valstr));
+ 				oid = DatumGetObjectId(datum);
+ 			}
+ 		}
  		errpos.cur_attno = 0;
  
  		j++;
***************
*** 4410,4415 **** make_tuple_from_result_row(PGresult *res,
--- 4426,4437 ----
  	if (ctid)
  		tuple->t_self = tuple->t_data->t_ctid = *ctid;
  
+ 	/*
+ 	 * If we have an OID to return, install it.
+ 	 */
+ 	if (OidIsValid(oid))
+ 		HeapTupleSetOid(tuple, oid);
+ 
  	/* Clean up */
  	MemoryContextReset(temp_context);
  
***************
*** 4436,4441 **** conversion_error_callback(void *arg)
--- 4458,4465 ----
  			attname = NameStr(tupdesc->attrs[errpos->cur_attno - 1]->attname);
  		else if (errpos->cur_attno == SelfItemPointerAttributeNumber)
  			attname = "ctid";
+ 		else if (errpos->cur_attno == ObjectIdAttributeNumber)
+ 			attname = "oid";
  
  		relname = RelationGetRelationName(errpos->rel);
  	}
*** a/contrib/postgres_fdw/sql/postgres_fdw.sql
--- b/contrib/postgres_fdw/sql/postgres_fdw.sql
***************
*** 557,563 **** DEALLOCATE st3;
  DEALLOCATE st4;
  DEALLOCATE st5;
  
! -- System columns, except ctid, should not be sent to remote
  EXPLAIN (VERBOSE, COSTS false)
  SELECT * FROM ft1 t1 WHERE t1.tableoid = 'pg_class'::regclass LIMIT 1;
  SELECT * FROM ft1 t1 WHERE t1.tableoid = 'ft1'::regclass LIMIT 1;
--- 557,563 ----
  DEALLOCATE st4;
  DEALLOCATE st5;
  
! -- System columns, except ctid and oid, should not be sent to remote
  EXPLAIN (VERBOSE, COSTS false)
  SELECT * FROM ft1 t1 WHERE t1.tableoid = 'pg_class'::regclass LIMIT 1;
  SELECT * FROM ft1 t1 WHERE t1.tableoid = 'ft1'::regclass LIMIT 1;
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to