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 (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers