Header And Logo

PostgreSQL
| The world's most advanced open source database.

Data Structures | Functions | Variables

foreign.c File Reference

#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"
Include dependency graph for foreign.c:

Go to the source code of this file.

Data Structures

struct  ConnectionOption

Functions

Datum pg_options_to_table (PG_FUNCTION_ARGS)
Datum postgresql_fdw_validator (PG_FUNCTION_ARGS)
ForeignDataWrapperGetForeignDataWrapper (Oid fdwid)
ForeignDataWrapperGetForeignDataWrapperByName (const char *fdwname, bool missing_ok)
ForeignServerGetForeignServer (Oid serverid)
ForeignServerGetForeignServerByName (const char *srvname, bool missing_ok)
UserMappingGetUserMapping (Oid userid, Oid serverid)
ForeignTableGetForeignTable (Oid relid)
ListGetForeignColumnOptions (Oid relid, AttrNumber attnum)
FdwRoutineGetFdwRoutine (Oid fdwhandler)
FdwRoutineGetFdwRoutineByRelId (Oid relid)
FdwRoutineGetFdwRoutineForRelation (Relation relation, bool makecopy)
static void deflist_to_tuplestore (ReturnSetInfo *rsinfo, List *options)
static bool is_conninfo_option (const char *option, Oid context)
Oid get_foreign_data_wrapper_oid (const char *fdwname, bool missing_ok)
Oid get_foreign_server_oid (const char *servername, bool missing_ok)

Variables

static struct ConnectionOption libpq_conninfo_options []

Function Documentation

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);
}

Oid get_foreign_data_wrapper_oid ( const char *  fdwname,
bool  missing_ok 
)

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;
}

Oid get_foreign_server_oid ( const char *  servername,
bool  missing_ok 
)

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  ) 
UserMapping* GetUserMapping ( Oid  userid,
Oid  serverid 
)
static bool is_conninfo_option ( const char *  option,
Oid  context 
) [static]

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);
}


Variable Documentation

Initial value:
 {
    {"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}
}

Definition at line 496 of file foreign.c.