On 2016/05/10 16:56, Etsuro Fujita wrote:
Here is a patch to fix this.
I found that the previous patch handles the ForeignScan's fs_relids
Bitmapset destructively. Also, I noticed that I removed some existing
comments inadvertently. So, I'm attaching the updated patch to fix
those things. I'll add this to the next CF. I think this should be
addressed in advance of the release of 9.6, though.
Best regards,
Etsuro Fujita
*** a/contrib/postgres_fdw/postgres_fdw.c
--- b/contrib/postgres_fdw/postgres_fdw.c
***************
*** 67,74 **** enum FdwScanPrivateIndex
FdwScanPrivateRetrievedAttrs,
/* Integer representing the desired fetch_size */
FdwScanPrivateFetchSize,
- /* Oid of user mapping to be used while connecting to the foreign server */
- FdwScanPrivateUserMappingOid,
/*
* String describing join i.e. names of relations being joined and types
--- 67,72 ----
***************
*** 1198,1208 **** postgresGetForeignPlan(PlannerInfo *root,
* Build the fdw_private list that will be available to the executor.
* Items in the list must match order in enum FdwScanPrivateIndex.
*/
! fdw_private = list_make5(makeString(sql.data),
remote_conds,
retrieved_attrs,
! makeInteger(fpinfo->fetch_size),
! makeInteger(foreignrel->umid));
if (foreignrel->reloptkind == RELOPT_JOINREL)
fdw_private = lappend(fdw_private,
makeString(fpinfo->relation_name->data));
--- 1196,1205 ----
* Build the fdw_private list that will be available to the executor.
* Items in the list must match order in enum FdwScanPrivateIndex.
*/
! fdw_private = list_make4(makeString(sql.data),
remote_conds,
retrieved_attrs,
! makeInteger(fpinfo->fetch_size));
if (foreignrel->reloptkind == RELOPT_JOINREL)
fdw_private = lappend(fdw_private,
makeString(fpinfo->relation_name->data));
***************
*** 1234,1240 **** postgresBeginForeignScan(ForeignScanState *node, int eflags)
--- 1231,1241 ----
ForeignScan *fsplan = (ForeignScan *) node->ss.ps.plan;
EState *estate = node->ss.ps.state;
PgFdwScanState *fsstate;
+ RangeTblEntry *rte;
+ Oid userid;
+ ForeignTable *table;
UserMapping *user;
+ int rtindex;
int numParams;
/*
***************
*** 1256,1285 **** postgresBeginForeignScan(ForeignScanState *node, int eflags)
* planning to ensure that the join is safe to pushdown. In case the
* information goes stale between planning and execution, plan will be
* invalidated and replanned.
*/
if (fsplan->scan.scanrelid > 0)
{
- ForeignTable *table;
-
/*
! * Identify which user to do the remote access as. This should match
! * what ExecCheckRTEPerms() does.
*/
! RangeTblEntry *rte = rt_fetch(fsplan->scan.scanrelid, estate->es_range_table);
! Oid userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
!
! fsstate->rel = node->ss.ss_currentRelation;
! table = GetForeignTable(RelationGetRelid(fsstate->rel));
!
! user = GetUserMapping(userid, table->serverid);
}
! else
! {
! Oid umid = intVal(list_nth(fsplan->fdw_private, FdwScanPrivateUserMappingOid));
! user = GetUserMappingById(umid);
! Assert(fsplan->fs_server == user->serverid);
! }
/*
* Get connection to the foreign server. Connection manager will
--- 1257,1283 ----
* planning to ensure that the join is safe to pushdown. In case the
* information goes stale between planning and execution, plan will be
* invalidated and replanned.
+ *
+ * This should match what ExecCheckRTEPerms() does.
*/
if (fsplan->scan.scanrelid > 0)
+ rtindex = fsplan->scan.scanrelid;
+ else
{
/*
! * It is ensured that foreign tables appearing in a foreign join
! * belong to the same server and use the same user mapping, so pick
! * the lowest-numbered one as a representative.
*/
! rtindex = -1;
! rtindex = bms_next_member(fsplan->fs_relids, rtindex);
! Assert(rtindex > 0);
}
! rte = rt_fetch(rtindex, estate->es_range_table);
! userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
! table = GetForeignTable(rte->relid);
! user = GetUserMapping(userid, table->serverid);
/*
* Get connection to the foreign server. Connection manager will
***************
*** 1316,1324 **** postgresBeginForeignScan(ForeignScanState *node, int eflags)
--- 1314,1328 ----
* into local representation and error reporting during that process.
*/
if (fsplan->scan.scanrelid > 0)
+ {
+ fsstate->rel = node->ss.ss_currentRelation;
fsstate->tupdesc = RelationGetDescr(fsstate->rel);
+ }
else
+ {
+ fsstate->rel = NULL;
fsstate->tupdesc = node->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
+ }
fsstate->attinmeta = TupleDescGetAttInMetadata(fsstate->tupdesc);
*** a/src/include/nodes/pg_list.h
--- b/src/include/nodes/pg_list.h
***************
*** 134,152 **** list_length(const List *l)
#define list_make2(x1,x2) lcons(x1, list_make1(x2))
#define list_make3(x1,x2,x3) lcons(x1, list_make2(x2, x3))
#define list_make4(x1,x2,x3,x4) lcons(x1, list_make3(x2, x3, x4))
- #define list_make5(x1,x2,x3,x4,x5) lcons(x1, list_make4(x2, x3, x4, x5))
#define list_make1_int(x1) lcons_int(x1, NIL)
#define list_make2_int(x1,x2) lcons_int(x1, list_make1_int(x2))
#define list_make3_int(x1,x2,x3) lcons_int(x1, list_make2_int(x2, x3))
#define list_make4_int(x1,x2,x3,x4) lcons_int(x1, list_make3_int(x2, x3, x4))
- #define list_make5_int(x1,x2,x3,x4,x5) lcons_int(x1, list_make4_int(x2, x3, x4, x5))
#define list_make1_oid(x1) lcons_oid(x1, NIL)
#define list_make2_oid(x1,x2) lcons_oid(x1, list_make1_oid(x2))
#define list_make3_oid(x1,x2,x3) lcons_oid(x1, list_make2_oid(x2, x3))
#define list_make4_oid(x1,x2,x3,x4) lcons_oid(x1, list_make3_oid(x2, x3, x4))
- #define list_make5_oid(x1,x2,x3,x4,x5) lcons_oid(x1, list_make4_oid(x2, x3, x4, x5))
/*
* foreach -
--- 134,149 ----
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers