1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-27 12:41:57 +03:00

Don't require a user mapping for FDWs to work.

Commit fbe5a3fb73 accidentally changed
this behavior; put things back the way they were, and add some
regression tests.

Report by Andres Freund; patch by Ashutosh Bapat, with a bit of
kibitzing by me.
This commit is contained in:
Robert Haas
2016-03-28 21:50:28 -04:00
parent 868628e4fd
commit 5d4171d1c7
8 changed files with 125 additions and 22 deletions

View File

@ -31,7 +31,7 @@
extern Datum pg_options_to_table(PG_FUNCTION_ARGS);
extern Datum postgresql_fdw_validator(PG_FUNCTION_ARGS);
static HeapTuple find_user_mapping(Oid userid, Oid serverid);
static HeapTuple find_user_mapping(Oid userid, Oid serverid, bool missing_ok);
/*
* GetForeignDataWrapper - look up the foreign-data wrapper by OID.
@ -223,7 +223,7 @@ GetUserMapping(Oid userid, Oid serverid)
bool isnull;
UserMapping *um;
tp = find_user_mapping(userid, serverid);
tp = find_user_mapping(userid, serverid, false);
um = (UserMapping *) palloc(sizeof(UserMapping));
um->umid = HeapTupleGetOid(tp);
@ -250,14 +250,23 @@ GetUserMapping(Oid userid, Oid serverid)
*
* If no mapping is found for the supplied user, we also look for
* PUBLIC mappings (userid == InvalidOid).
*
* If missing_ok is true, the function returns InvalidOid when it does not find
* required user mapping. Otherwise, find_user_mapping() throws error if it
* does not find required user mapping.
*/
Oid
GetUserMappingId(Oid userid, Oid serverid)
GetUserMappingId(Oid userid, Oid serverid, bool missing_ok)
{
HeapTuple tp;
Oid umid;
tp = find_user_mapping(userid, serverid);
tp = find_user_mapping(userid, serverid, missing_ok);
Assert(missing_ok || tp);
if (!tp && missing_ok)
return InvalidOid;
/* Extract the Oid */
umid = HeapTupleGetOid(tp);
@ -273,9 +282,13 @@ GetUserMappingId(Oid userid, Oid serverid)
*
* If no mapping is found for the supplied user, we also look for
* PUBLIC mappings (userid == InvalidOid).
*
* If missing_ok is true, the function returns NULL, if it does not find
* the required user mapping. Otherwise, it throws error if it does not
* find the required user mapping.
*/
static HeapTuple
find_user_mapping(Oid userid, Oid serverid)
find_user_mapping(Oid userid, Oid serverid, bool missing_ok)
{
HeapTuple tp;
@ -292,10 +305,15 @@ find_user_mapping(Oid userid, Oid serverid)
ObjectIdGetDatum(serverid));
if (!HeapTupleIsValid(tp))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("user mapping not found for \"%s\"",
MappingUserName(userid))));
{
if (missing_ok)
return NULL;
else
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("user mapping not found for \"%s\"",
MappingUserName(userid))));
}
return tp;
}

View File

@ -180,11 +180,15 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
* ensure that it gets invalidated in the case of a user OID change.
* See RevalidateCachedQuery and more generally the hasForeignJoin
* flags in PlannerGlobal and PlannedStmt.
*
* It's possible, and not necessarily an error, for rel->umid to be
* InvalidOid even though rel->serverid is set. That just means there
* is a server with no user mapping.
*/
Oid userid;
userid = OidIsValid(rte->checkAsUser) ? rte->checkAsUser : GetUserId();
rel->umid = GetUserMappingId(userid, rel->serverid);
rel->umid = GetUserMappingId(userid, rel->serverid, true);
}
else
rel->umid = InvalidOid;
@ -435,12 +439,16 @@ build_join_rel(PlannerInfo *root,
*
* Otherwise those fields are left invalid, so FDW API will not be called
* for the join relation.
*
* For FDWs like file_fdw, which ignore user mapping, the user mapping id
* associated with the joining relation may be invalid. A valid serverid
* distinguishes between a pushed down join with no user mapping and
* a join which can not be pushed down because of user mapping mismatch.
*/
if (OidIsValid(outer_rel->serverid) &&
inner_rel->serverid == outer_rel->serverid &&
inner_rel->umid == outer_rel->umid)
{
Assert(OidIsValid(outer_rel->umid));
joinrel->serverid = outer_rel->serverid;
joinrel->umid = outer_rel->umid;
joinrel->fdwroutine = outer_rel->fdwroutine;

View File

@ -72,7 +72,7 @@ typedef struct ForeignTable
extern ForeignServer *GetForeignServer(Oid serverid);
extern ForeignServer *GetForeignServerByName(const char *name, bool missing_ok);
extern UserMapping *GetUserMapping(Oid userid, Oid serverid);
extern Oid GetUserMappingId(Oid userid, Oid serverid);
extern Oid GetUserMappingId(Oid userid, Oid serverid, bool missing_ok);
extern UserMapping *GetUserMappingById(Oid umid);
extern ForeignDataWrapper *GetForeignDataWrapper(Oid fdwid);
extern ForeignDataWrapper *GetForeignDataWrapperByName(const char *name,