Hi,
On 2016/02/09 14:09, Ashutosh Bapat wrote:
Sorry, I was wrong. For public user mapping userid is 0 (InvalidOid),
which is returned as is in UserMapping object. I confused InvalidOid
with -1.
I think the following umid handling in postgresGetForeignPlan has the
same issue:
/*
* 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),
retrieved_attrs,
makeInteger(fpinfo->fetch_size),
makeInteger(foreignrel->umid));
I don't think it's correct to use makeInteger for the foreignrel's umid.
You store the umid in the fdw_private list here and extract it from the
list in postgresBeginForeignScan, to get the user mapping. But we
really need that? We have a validated plan when getting called from
postgresBeginForeignScan, so if foreign join, we can simply pick any of
the plan's fs_relids and use it to identify which user to do the remote
access as, in the same way as for foreign tables.
Attached is a patch for that.
Best regards,
Etsuro Fujita
*** a/contrib/postgres_fdw/postgres_fdw.c
--- b/contrib/postgres_fdw/postgres_fdw.c
***************
*** 65,72 **** 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
--- 65,70 ----
***************
*** 1133,1142 **** 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_make4(makeString(sql.data),
retrieved_attrs,
! makeInteger(fpinfo->fetch_size),
! makeInteger(foreignrel->umid));
if (foreignrel->reloptkind == RELOPT_JOINREL)
fdw_private = lappend(fdw_private,
makeString(fpinfo->relation_name->data));
--- 1131,1139 ----
* 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_make3(makeString(sql.data),
retrieved_attrs,
! makeInteger(fpinfo->fetch_size));
if (foreignrel->reloptkind == RELOPT_JOINREL)
fdw_private = lappend(fdw_private,
makeString(fpinfo->relation_name->data));
***************
*** 1168,1174 **** postgresBeginForeignScan(ForeignScanState *node, int eflags)
--- 1165,1175 ----
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;
int i;
ListCell *lc;
***************
*** 1193,1221 **** postgresBeginForeignScan(ForeignScanState *node, int eflags)
* 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
--- 1194,1217 ----
* information goes stale between planning and execution, plan will be
* invalidated and replanned.
*/
! /*
! * Identify which user to do the remote access as. This should match what
! * ExecCheckRTEPerms() does.
! */
! if (fsplan->scan.scanrelid > 0)
! rtindex = fsplan->scan.scanrelid;
else
{
! /* Pick the lowest-numbered one as a representative */
! rtindex = bms_first_member(fsplan->fs_relids);
}
+ rte = rt_fetch(rtindex, estate->es_range_table);
+ userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
+
+ /* Get info about foreign table */
+ table = GetForeignTable(rte->relid);
+ user = GetUserMapping(userid, table->serverid);
/*
* Get connection to the foreign server. Connection manager will
***************
*** 1252,1260 **** postgresBeginForeignScan(ForeignScanState *node, int eflags)
--- 1248,1262 ----
* 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);
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers