diff options
author | Robert Haas <rhaas@postgresql.org> | 2016-03-28 21:50:28 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2016-03-28 21:50:28 -0400 |
commit | 5d4171d1c70edfe3e9be1de9e66603af28e3afe1 (patch) | |
tree | e74ee89c0af8ea0662fc001ba9ce965d6a2890c8 /src | |
parent | 868628e4fd44d75987d6c099ac63613cc5417629 (diff) | |
download | postgresql-5d4171d1c70edfe3e9be1de9e66603af28e3afe1.tar.gz postgresql-5d4171d1c70edfe3e9be1de9e66603af28e3afe1.zip |
Don't require a user mapping for FDWs to work.
Commit fbe5a3fb73102c2cfec11aaaa4a67943f4474383 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.
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/foreign/foreign.c | 36 | ||||
-rw-r--r-- | src/backend/optimizer/util/relnode.c | 12 | ||||
-rw-r--r-- | src/include/foreign/foreign.h | 2 |
3 files changed, 38 insertions, 12 deletions
diff --git a/src/backend/foreign/foreign.c b/src/backend/foreign/foreign.c index 239849bb0b0..f1feb85c551 100644 --- a/src/backend/foreign/foreign.c +++ b/src/backend/foreign/foreign.c @@ -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; } diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c index 7e37edf5f5d..6f24b031e44 100644 --- a/src/backend/optimizer/util/relnode.c +++ b/src/backend/optimizer/util/relnode.c @@ -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; diff --git a/src/include/foreign/foreign.h b/src/include/foreign/foreign.h index 71f8e55b0e9..fb945e9ffd8 100644 --- a/src/include/foreign/foreign.h +++ b/src/include/foreign/foreign.h @@ -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, |