From 7132313f42c71b75405e34cdac3db6126229b549 Mon Sep 17 00:00:00 2001 From: Masahiko Sawada Date: Fri, 31 Aug 2018 16:55:16 +0900 Subject: [PATCH 2/2] Poc: postgres_fdw support routine mappings. --- contrib/postgres_fdw/deparse.c | 68 +++++++++++++++++++++++++++++++++--------- contrib/postgres_fdw/option.c | 4 +++ 2 files changed, 58 insertions(+), 14 deletions(-) diff --git a/contrib/postgres_fdw/deparse.c b/contrib/postgres_fdw/deparse.c index 6001f4d..d5a673a 100644 --- a/contrib/postgres_fdw/deparse.c +++ b/contrib/postgres_fdw/deparse.c @@ -185,6 +185,8 @@ static void appendAggOrderBy(List *orderList, List *targetList, static void appendFunctionName(Oid funcid, deparse_expr_cxt *context); static Node *deparseSortGroupClause(Index ref, List *tlist, bool force_colno, deparse_expr_cxt *context); +static void ExtractRoutineMappingOptions(List *defelems, char **remote_func_schema, + char **remote_func_name); /* * Helper functions @@ -3177,30 +3179,51 @@ appendOrderByClause(List *pathkeys, deparse_expr_cxt *context) static void appendFunctionName(Oid funcid, deparse_expr_cxt *context) { + PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) context->foreignrel->fdw_private; + ForeignServer *server = fpinfo->server; StringInfo buf = context->buf; - HeapTuple proctup; + HeapTuple proctup = NULL; Form_pg_proc procform; - const char *proname; + char *proname = NULL; + char *schemaname = NULL; + Oid rmId; - proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid)); - if (!HeapTupleIsValid(proctup)) - elog(ERROR, "cache lookup failed for function %u", funcid); - procform = (Form_pg_proc) GETSTRUCT(proctup); + rmId = GetSysCacheOid2(ROUTINEMAPPINGPROCSERVER, + ObjectIdGetDatum(funcid), + ObjectIdGetDatum(server->serverid)); - /* Print schema name only if it's not pg_catalog */ - if (procform->pronamespace != PG_CATALOG_NAMESPACE) + /* This function is mapped, get remote schema and function name */ + if (OidIsValid(rmId)) { - const char *schemaname; + RoutineMapping *rm; - schemaname = get_namespace_name(procform->pronamespace); - appendStringInfo(buf, "%s.", quote_identifier(schemaname)); + rm = GetRoutineMapping(rmId); + ExtractRoutineMappingOptions(rm->options, &schemaname, &proname); } + if (!schemaname || !proname) + { + proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid)); + if (!HeapTupleIsValid(proctup)) + elog(ERROR, "cache lookup failed for function %u", funcid); + procform = (Form_pg_proc) GETSTRUCT(proctup); + + /* Print schema name only if it's not pg_catalog */ + if (!schemaname && procform->pronamespace != PG_CATALOG_NAMESPACE) + schemaname = get_namespace_name(procform->pronamespace); + + if (!proname) + proname = NameStr(procform->proname); + } + + if (schemaname) + appendStringInfo(buf, "%s.", quote_identifier(schemaname)); + /* Always print the function name */ - proname = NameStr(procform->proname); - appendStringInfoString(buf, quote_identifier(proname)); + appendStringInfo(buf, "%s", quote_identifier(proname)); - ReleaseSysCache(proctup); + if (HeapTupleIsValid(proctup)) + ReleaseSysCache(proctup); } /* @@ -3342,3 +3365,20 @@ get_relation_column_alias_ids(Var *node, RelOptInfo *foreignrel, /* Shouldn't get here */ elog(ERROR, "unexpected expression in subquery output"); } + +static void +ExtractRoutineMappingOptions(List *defelems, char **remote_func_schema, + char **remote_func_name) +{ + ListCell *lc; + + foreach(lc, defelems) + { + DefElem *d = (DefElem *) lfirst(lc); + + if (strcmp(d->defname, "remote_func_schema") == 0) + *remote_func_schema = defGetString(d); + else if (strcmp(d->defname, "remote_func_name") == 0) + *remote_func_name = defGetString(d); + } +} diff --git a/contrib/postgres_fdw/option.c b/contrib/postgres_fdw/option.c index 6854f1b..2d5e21c 100644 --- a/contrib/postgres_fdw/option.c +++ b/contrib/postgres_fdw/option.c @@ -17,6 +17,7 @@ #include "access/reloptions.h" #include "catalog/pg_foreign_server.h" #include "catalog/pg_foreign_table.h" +#include "catalog/pg_routine_mapping.h" #include "catalog/pg_user_mapping.h" #include "commands/defrem.h" #include "commands/extension.h" @@ -177,6 +178,9 @@ InitPgFdwOptions(void) /* fetch_size is available on both server and table */ {"fetch_size", ForeignServerRelationId, false}, {"fetch_size", ForeignTableRelationId, false}, + /* Routine mapping */ + {"remote_func_name", RoutineMappingRelationId, false}, + {"remote_func_schema", RoutineMappingRelationId, false}, {NULL, InvalidOid, false} }; -- 2.10.5