#include "postgres.h"
#include "access/htup_details.h"
#include "access/reloptions.h"
#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_server.h"
#include "catalog/pg_foreign_table.h"
#include "catalog/pg_user_mapping.h"
#include "foreign/fdwapi.h"
#include "foreign/foreign.h"
#include "lib/stringinfo.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/syscache.h"
Go to the source code of this file.
static void deflist_to_tuplestore | ( | ReturnSetInfo * | rsinfo, | |
List * | options | |||
) | [static] |
Definition at line 407 of file foreign.c.
References ReturnSetInfo::allowedModes, DefElem::arg, CreateTupleDescCopy(), CStringGetTextDatum, DefElem::defname, ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, ereport, errcode(), errmsg(), ERROR, ReturnSetInfo::expectedDesc, IsA, lfirst, MemoryContextSwitchTo(), NULL, ReturnSetInfo::returnMode, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, tuplestore_begin_heap(), tuplestore_donestoring, tuplestore_putvalues(), values, and work_mem.
Referenced by pg_options_to_table().
{ ListCell *cell; TupleDesc tupdesc; Tuplestorestate *tupstore; Datum values[2]; bool nulls[2]; MemoryContext per_query_ctx; MemoryContext oldcontext; /* check to see if caller supports us returning a tuplestore */ if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("set-valued function called in context that cannot accept a set"))); if (!(rsinfo->allowedModes & SFRM_Materialize) || rsinfo->expectedDesc == NULL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("materialize mode required, but it is not allowed in this context"))); per_query_ctx = rsinfo->econtext->ecxt_per_query_memory; oldcontext = MemoryContextSwitchTo(per_query_ctx); /* * Now prepare the result set. */ tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc); tupstore = tuplestore_begin_heap(true, false, work_mem); rsinfo->returnMode = SFRM_Materialize; rsinfo->setResult = tupstore; rsinfo->setDesc = tupdesc; foreach(cell, options) { DefElem *def = lfirst(cell); values[0] = CStringGetTextDatum(def->defname); nulls[0] = false; if (def->arg) { values[1] = CStringGetTextDatum(((Value *) (def->arg))->val.str); nulls[1] = false; } else { values[1] = (Datum) 0; nulls[1] = true; } tuplestore_putvalues(tupstore, tupdesc, values, nulls); } /* clean up and return the tuplestore */ tuplestore_donestoring(tupstore); MemoryContextSwitchTo(oldcontext); }
Definition at line 592 of file foreign.c.
References CStringGetDatum, ereport, errcode(), errmsg(), ERROR, FOREIGNDATAWRAPPERNAME, GetSysCacheOid1, and OidIsValid.
Referenced by convert_foreign_data_wrapper_name(), get_object_address_unqualified(), GetForeignDataWrapperByName(), and objectNamesToOids().
{ Oid oid; oid = GetSysCacheOid1(FOREIGNDATAWRAPPERNAME, CStringGetDatum(fdwname)); if (!OidIsValid(oid) && !missing_ok) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("foreign-data wrapper \"%s\" does not exist", fdwname))); return oid; }
Definition at line 613 of file foreign.c.
References CStringGetDatum, ereport, errcode(), errmsg(), ERROR, FOREIGNSERVERNAME, GetSysCacheOid1, and OidIsValid.
Referenced by convert_server_name(), get_object_address_unqualified(), GetForeignServerByName(), and objectNamesToOids().
{ Oid oid; oid = GetSysCacheOid1(FOREIGNSERVERNAME, CStringGetDatum(servername)); if (!OidIsValid(oid) && !missing_ok) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("server \"%s\" does not exist", servername))); return oid; }
FdwRoutine* GetFdwRoutine | ( | Oid | fdwhandler | ) |
Definition at line 290 of file foreign.c.
References DatumGetPointer, elog, ERROR, IsA, NULL, and OidFunctionCall0.
Referenced by GetFdwRoutineByRelId().
{ Datum datum; FdwRoutine *routine; datum = OidFunctionCall0(fdwhandler); routine = (FdwRoutine *) DatumGetPointer(datum); if (routine == NULL || !IsA(routine, FdwRoutine)) elog(ERROR, "foreign-data wrapper handler function %u did not return an FdwRoutine struct", fdwhandler); return routine; }
FdwRoutine* GetFdwRoutineByRelId | ( | Oid | relid | ) |
Definition at line 311 of file foreign.c.
References elog, ereport, errcode(), errmsg(), ERROR, FOREIGNDATAWRAPPEROID, FOREIGNSERVEROID, FOREIGNTABLEREL, GetFdwRoutine(), GETSTRUCT, HeapTupleIsValid, NameStr, ObjectIdGetDatum, OidIsValid, ReleaseSysCache(), and SearchSysCache1.
Referenced by GetFdwRoutineForRelation(), and make_modifytable().
{ HeapTuple tp; Form_pg_foreign_data_wrapper fdwform; Form_pg_foreign_server serverform; Form_pg_foreign_table tableform; Oid serverid; Oid fdwid; Oid fdwhandler; /* Get server OID for the foreign table. */ tp = SearchSysCache1(FOREIGNTABLEREL, ObjectIdGetDatum(relid)); if (!HeapTupleIsValid(tp)) elog(ERROR, "cache lookup failed for foreign table %u", relid); tableform = (Form_pg_foreign_table) GETSTRUCT(tp); serverid = tableform->ftserver; ReleaseSysCache(tp); /* Get foreign-data wrapper OID for the server. */ tp = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(serverid)); if (!HeapTupleIsValid(tp)) elog(ERROR, "cache lookup failed for foreign server %u", serverid); serverform = (Form_pg_foreign_server) GETSTRUCT(tp); fdwid = serverform->srvfdw; ReleaseSysCache(tp); /* Get handler function OID for the FDW. */ tp = SearchSysCache1(FOREIGNDATAWRAPPEROID, ObjectIdGetDatum(fdwid)); if (!HeapTupleIsValid(tp)) elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid); fdwform = (Form_pg_foreign_data_wrapper) GETSTRUCT(tp); fdwhandler = fdwform->fdwhandler; /* Complain if FDW has been set to NO HANDLER. */ if (!OidIsValid(fdwhandler)) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("foreign-data wrapper \"%s\" has no handler", NameStr(fdwform->fdwname)))); ReleaseSysCache(tp); /* And finally, call the handler function. */ return GetFdwRoutine(fdwhandler); }
FdwRoutine* GetFdwRoutineForRelation | ( | Relation | relation, | |
bool | makecopy | |||
) |
Definition at line 369 of file foreign.c.
References CacheMemoryContext, GetFdwRoutineByRelId(), MemoryContextAlloc(), NULL, palloc(), RelationData::rd_fdwroutine, and RelationGetRelid.
Referenced by analyze_rel(), CheckValidResultRel(), ExecInitForeignScan(), get_relation_info(), InitResultRelInfo(), and rewriteTargetListUD().
{ FdwRoutine *fdwroutine; FdwRoutine *cfdwroutine; if (relation->rd_fdwroutine == NULL) { /* Get the info by consulting the catalogs and the FDW code */ fdwroutine = GetFdwRoutineByRelId(RelationGetRelid(relation)); /* Save the data for later reuse in CacheMemoryContext */ cfdwroutine = (FdwRoutine *) MemoryContextAlloc(CacheMemoryContext, sizeof(FdwRoutine)); memcpy(cfdwroutine, fdwroutine, sizeof(FdwRoutine)); relation->rd_fdwroutine = cfdwroutine; /* Give back the locally palloc'd copy regardless of makecopy */ return fdwroutine; } /* We have valid cached data --- does the caller want a copy? */ if (makecopy) { fdwroutine = (FdwRoutine *) palloc(sizeof(FdwRoutine)); memcpy(fdwroutine, relation->rd_fdwroutine, sizeof(FdwRoutine)); return fdwroutine; } /* Only a short-lived reference is needed, so just hand back cached copy */ return relation->rd_fdwroutine; }
List* GetForeignColumnOptions | ( | Oid | relid, | |
AttrNumber | attnum | |||
) |
Definition at line 257 of file foreign.c.
References Anum_pg_attribute_attfdwoptions, ATTNUM, elog, ERROR, HeapTupleIsValid, Int16GetDatum, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache2, SysCacheGetAttr(), and untransformRelOptions().
Referenced by deparseAnalyzeSql(), deparseColumnRef(), and get_file_fdw_attribute_options().
{ List *options; HeapTuple tp; Datum datum; bool isnull; tp = SearchSysCache2(ATTNUM, ObjectIdGetDatum(relid), Int16GetDatum(attnum)); if (!HeapTupleIsValid(tp)) elog(ERROR, "cache lookup failed for attribute %d of relation %u", attnum, relid); datum = SysCacheGetAttr(ATTNUM, tp, Anum_pg_attribute_attfdwoptions, &isnull); if (isnull) options = NIL; else options = untransformRelOptions(datum); ReleaseSysCache(tp); return options; }
ForeignDataWrapper* GetForeignDataWrapper | ( | Oid | fdwid | ) |
Definition at line 39 of file foreign.c.
References Anum_pg_foreign_data_wrapper_fdwoptions, elog, ERROR, ForeignDataWrapper::fdwhandler, ForeignDataWrapper::fdwid, ForeignDataWrapper::fdwname, ForeignDataWrapper::fdwvalidator, FOREIGNDATAWRAPPEROID, GETSTRUCT, HeapTupleIsValid, NameStr, ObjectIdGetDatum, ForeignDataWrapper::options, ForeignDataWrapper::owner, palloc(), pstrdup(), ReleaseSysCache(), SearchSysCache1, SysCacheGetAttr(), and untransformRelOptions().
Referenced by AlterForeignServer(), AlterForeignServerOwner_internal(), AlterUserMapping(), ATExecAlterColumnGenericOptions(), ATExecGenericOptions(), CreateForeignTable(), CreateUserMapping(), fileGetOptions(), get_connect_string(), GetForeignDataWrapperByName(), getObjectDescription(), and getObjectIdentity().
{ Form_pg_foreign_data_wrapper fdwform; ForeignDataWrapper *fdw; Datum datum; HeapTuple tp; bool isnull; tp = SearchSysCache1(FOREIGNDATAWRAPPEROID, ObjectIdGetDatum(fdwid)); if (!HeapTupleIsValid(tp)) elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid); fdwform = (Form_pg_foreign_data_wrapper) GETSTRUCT(tp); fdw = (ForeignDataWrapper *) palloc(sizeof(ForeignDataWrapper)); fdw->fdwid = fdwid; fdw->owner = fdwform->fdwowner; fdw->fdwname = pstrdup(NameStr(fdwform->fdwname)); fdw->fdwhandler = fdwform->fdwhandler; fdw->fdwvalidator = fdwform->fdwvalidator; /* Extract the fdwoptions */ datum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tp, Anum_pg_foreign_data_wrapper_fdwoptions, &isnull); if (isnull) fdw->options = NIL; else fdw->options = untransformRelOptions(datum); ReleaseSysCache(tp); return fdw; }
ForeignDataWrapper* GetForeignDataWrapperByName | ( | const char * | fdwname, | |
bool | missing_ok | |||
) |
Definition at line 82 of file foreign.c.
References get_foreign_data_wrapper_oid(), GetForeignDataWrapper(), and OidIsValid.
Referenced by CreateForeignDataWrapper(), and CreateForeignServer().
{ Oid fdwId = get_foreign_data_wrapper_oid(fdwname, missing_ok); if (!OidIsValid(fdwId)) return NULL; return GetForeignDataWrapper(fdwId); }
ForeignServer* GetForeignServer | ( | Oid | serverid | ) |
Definition at line 97 of file foreign.c.
References Anum_pg_foreign_server_srvoptions, Anum_pg_foreign_server_srvtype, Anum_pg_foreign_server_srvversion, elog, ERROR, ForeignServer::fdwid, FOREIGNSERVEROID, GETSTRUCT, HeapTupleIsValid, NameStr, NULL, ObjectIdGetDatum, ForeignServer::options, ForeignServer::owner, palloc(), pstrdup(), ReleaseSysCache(), SearchSysCache1, ForeignServer::serverid, ForeignServer::servername, ForeignServer::servertype, ForeignServer::serverversion, SysCacheGetAttr(), TextDatumGetCString, and untransformRelOptions().
Referenced by ATExecAlterColumnGenericOptions(), ATExecGenericOptions(), fileGetOptions(), GetForeignServerByName(), getObjectDescription(), getObjectIdentity(), postgresAcquireSampleRowsFunc(), postgresAnalyzeForeignTable(), postgresBeginForeignModify(), postgresBeginForeignScan(), and postgresGetForeignRelSize().
{ Form_pg_foreign_server serverform; ForeignServer *server; HeapTuple tp; Datum datum; bool isnull; tp = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(serverid)); if (!HeapTupleIsValid(tp)) elog(ERROR, "cache lookup failed for foreign server %u", serverid); serverform = (Form_pg_foreign_server) GETSTRUCT(tp); server = (ForeignServer *) palloc(sizeof(ForeignServer)); server->serverid = serverid; server->servername = pstrdup(NameStr(serverform->srvname)); server->owner = serverform->srvowner; server->fdwid = serverform->srvfdw; /* Extract server type */ datum = SysCacheGetAttr(FOREIGNSERVEROID, tp, Anum_pg_foreign_server_srvtype, &isnull); server->servertype = isnull ? NULL : pstrdup(TextDatumGetCString(datum)); /* Extract server version */ datum = SysCacheGetAttr(FOREIGNSERVEROID, tp, Anum_pg_foreign_server_srvversion, &isnull); server->serverversion = isnull ? NULL : pstrdup(TextDatumGetCString(datum)); /* Extract the srvoptions */ datum = SysCacheGetAttr(FOREIGNSERVEROID, tp, Anum_pg_foreign_server_srvoptions, &isnull); if (isnull) server->options = NIL; else server->options = untransformRelOptions(datum); ReleaseSysCache(tp); return server; }
ForeignServer* GetForeignServerByName | ( | const char * | srvname, | |
bool | missing_ok | |||
) |
Definition at line 152 of file foreign.c.
References get_foreign_server_oid(), GetForeignServer(), and OidIsValid.
Referenced by AlterUserMapping(), CreateForeignServer(), CreateForeignTable(), CreateUserMapping(), get_connect_string(), and RemoveUserMapping().
{ Oid serverid = get_foreign_server_oid(srvname, missing_ok); if (!OidIsValid(serverid)) return NULL; return GetForeignServer(serverid); }
ForeignTable* GetForeignTable | ( | Oid | relid | ) |
Definition at line 219 of file foreign.c.
References Anum_pg_foreign_table_ftoptions, elog, ERROR, FOREIGNTABLEREL, GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum, ForeignTable::options, palloc(), ReleaseSysCache(), ForeignTable::relid, SearchSysCache1, ForeignTable::serverid, SysCacheGetAttr(), and untransformRelOptions().
Referenced by check_selective_binary_conversion(), deparseRelation(), fileGetOptions(), postgresAcquireSampleRowsFunc(), postgresAnalyzeForeignTable(), postgresBeginForeignModify(), postgresBeginForeignScan(), and postgresGetForeignRelSize().
{ Form_pg_foreign_table tableform; ForeignTable *ft; HeapTuple tp; Datum datum; bool isnull; tp = SearchSysCache1(FOREIGNTABLEREL, ObjectIdGetDatum(relid)); if (!HeapTupleIsValid(tp)) elog(ERROR, "cache lookup failed for foreign table %u", relid); tableform = (Form_pg_foreign_table) GETSTRUCT(tp); ft = (ForeignTable *) palloc(sizeof(ForeignTable)); ft->relid = relid; ft->serverid = tableform->ftserver; /* Extract the ftoptions */ datum = SysCacheGetAttr(FOREIGNTABLEREL, tp, Anum_pg_foreign_table_ftoptions, &isnull); if (isnull) ft->options = NIL; else ft->options = untransformRelOptions(datum); ReleaseSysCache(tp); return ft; }
UserMapping* GetUserMapping | ( | Oid | userid, | |
Oid | serverid | |||
) |
Definition at line 170 of file foreign.c.
References Anum_pg_user_mapping_umoptions, ereport, errcode(), errmsg(), ERROR, HeapTupleIsValid, InvalidOid, MappingUserName, ObjectIdGetDatum, UserMapping::options, palloc(), ReleaseSysCache(), SearchSysCache2, UserMapping::serverid, SysCacheGetAttr(), untransformRelOptions(), UserMapping::userid, and USERMAPPINGUSERSERVER.
Referenced by get_connect_string(), postgresAcquireSampleRowsFunc(), postgresAnalyzeForeignTable(), postgresBeginForeignModify(), postgresBeginForeignScan(), and postgresGetForeignRelSize().
{ Datum datum; HeapTuple tp; bool isnull; UserMapping *um; tp = SearchSysCache2(USERMAPPINGUSERSERVER, ObjectIdGetDatum(userid), ObjectIdGetDatum(serverid)); if (!HeapTupleIsValid(tp)) { /* Not found for the specific user -- try PUBLIC */ tp = SearchSysCache2(USERMAPPINGUSERSERVER, ObjectIdGetDatum(InvalidOid), ObjectIdGetDatum(serverid)); } if (!HeapTupleIsValid(tp)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("user mapping not found for \"%s\"", MappingUserName(userid)))); um = (UserMapping *) palloc(sizeof(UserMapping)); um->userid = userid; um->serverid = serverid; /* Extract the umoptions */ datum = SysCacheGetAttr(USERMAPPINGUSERSERVER, tp, Anum_pg_user_mapping_umoptions, &isnull); if (isnull) um->options = NIL; else um->options = untransformRelOptions(datum); ReleaseSysCache(tp); return um; }
Definition at line 521 of file foreign.c.
References ConnectionOption::optcontext, and ConnectionOption::optname.
Referenced by postgresql_fdw_validator().
{ struct ConnectionOption *opt; for (opt = libpq_conninfo_options; opt->optname; opt++) if (context == opt->optcontext && strcmp(opt->optname, option) == 0) return true; return false; }
Datum pg_options_to_table | ( | PG_FUNCTION_ARGS | ) |
Definition at line 471 of file foreign.c.
References deflist_to_tuplestore(), PG_GETARG_DATUM, and untransformRelOptions().
{ Datum array = PG_GETARG_DATUM(0); deflist_to_tuplestore((ReturnSetInfo *) fcinfo->resultinfo, untransformRelOptions(array)); return (Datum) 0; }
Datum postgresql_fdw_validator | ( | PG_FUNCTION_ARGS | ) |
Definition at line 545 of file foreign.c.
References appendStringInfo(), buf, StringInfoData::data, DefElem::defname, ereport, errcode(), errhint(), errmsg(), ERROR, initStringInfo(), is_conninfo_option(), StringInfoData::len, lfirst, ConnectionOption::optcontext, ConnectionOption::optname, PG_GETARG_DATUM, PG_GETARG_OID, PG_RETURN_BOOL, and untransformRelOptions().
{ List *options_list = untransformRelOptions(PG_GETARG_DATUM(0)); Oid catalog = PG_GETARG_OID(1); ListCell *cell; foreach(cell, options_list) { DefElem *def = lfirst(cell); if (!is_conninfo_option(def->defname, catalog)) { struct ConnectionOption *opt; StringInfoData buf; /* * Unknown option specified, complain about it. Provide a hint * with list of valid options for the object. */ initStringInfo(&buf); for (opt = libpq_conninfo_options; opt->optname; opt++) if (catalog == opt->optcontext) appendStringInfo(&buf, "%s%s", (buf.len > 0) ? ", " : "", opt->optname); ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("invalid option \"%s\"", def->defname), errhint("Valid options in this context are: %s", buf.data))); PG_RETURN_BOOL(false); } } PG_RETURN_BOOL(true); }
struct ConnectionOption libpq_conninfo_options[] [static] |
{ {"authtype", ForeignServerRelationId}, {"service", ForeignServerRelationId}, {"user", UserMappingRelationId}, {"password", UserMappingRelationId}, {"connect_timeout", ForeignServerRelationId}, {"dbname", ForeignServerRelationId}, {"host", ForeignServerRelationId}, {"hostaddr", ForeignServerRelationId}, {"port", ForeignServerRelationId}, {"tty", ForeignServerRelationId}, {"options", ForeignServerRelationId}, {"requiressl", ForeignServerRelationId}, {"sslmode", ForeignServerRelationId}, {"gsslib", ForeignServerRelationId}, {NULL, InvalidOid} }