#include "postgres.h"#include "postgres_fdw.h"#include "access/reloptions.h"#include "catalog/pg_foreign_server.h"#include "catalog/pg_foreign_table.h"#include "catalog/pg_user_mapping.h"#include "commands/defrem.h"
Go to the source code of this file.
Data Structures | |
| struct | PgFdwOption |
Typedefs | |
| typedef struct PgFdwOption | PgFdwOption |
Functions | |
| static void | InitPgFdwOptions (void) |
| static bool | is_valid_option (const char *keyword, Oid context) |
| static bool | is_libpq_option (const char *keyword) |
| Datum | postgres_fdw_validator (PG_FUNCTION_ARGS) |
| PG_FUNCTION_INFO_V1 (postgres_fdw_validator) | |
| int | ExtractConnectionOptions (List *defelems, const char **keywords, const char **values) |
Variables | |
| static PgFdwOption * | postgres_fdw_options |
| static PQconninfoOption * | libpq_options |
| typedef struct PgFdwOption PgFdwOption |
| int ExtractConnectionOptions | ( | List * | defelems, | |
| const char ** | keywords, | |||
| const char ** | values | |||
| ) |
Definition at line 271 of file option.c.
References defGetString(), DefElem::defname, i, InitPgFdwOptions(), is_libpq_option(), and lfirst.
Referenced by connect_pg_server().
{
ListCell *lc;
int i;
/* Build our options lists if we didn't yet. */
InitPgFdwOptions();
i = 0;
foreach(lc, defelems)
{
DefElem *d = (DefElem *) lfirst(lc);
if (is_libpq_option(d->defname))
{
keywords[i] = d->defname;
values[i] = defGetString(d);
i++;
}
}
return i;
}
| static void InitPgFdwOptions | ( | void | ) | [static] |
Definition at line 137 of file option.c.
References _PQconninfoOption::dispchar, ereport, errcode(), errdetail(), errmsg(), ERROR, PgFdwOption::is_libpq_opt, PgFdwOption::keyword, _PQconninfoOption::keyword, malloc, NULL, PgFdwOption::optcontext, and PQconndefaults().
Referenced by ExtractConnectionOptions(), and postgres_fdw_validator().
{
int num_libpq_opts;
PQconninfoOption *lopt;
PgFdwOption *popt;
/* non-libpq FDW-specific FDW options */
static const PgFdwOption non_libpq_options[] = {
{"schema_name", ForeignTableRelationId, false},
{"table_name", ForeignTableRelationId, false},
{"column_name", AttributeRelationId, false},
/* use_remote_estimate is available on both server and table */
{"use_remote_estimate", ForeignServerRelationId, false},
{"use_remote_estimate", ForeignTableRelationId, false},
/* cost factors */
{"fdw_startup_cost", ForeignServerRelationId, false},
{"fdw_tuple_cost", ForeignServerRelationId, false},
{NULL, InvalidOid, false}
};
/* Prevent redundant initialization. */
if (postgres_fdw_options)
return;
/*
* Get list of valid libpq options.
*
* To avoid unnecessary work, we get the list once and use it throughout
* the lifetime of this backend process. We don't need to care about
* memory context issues, because PQconndefaults allocates with malloc.
*/
libpq_options = PQconndefaults();
if (!libpq_options) /* assume reason for failure is OOM */
ereport(ERROR,
(errcode(ERRCODE_FDW_OUT_OF_MEMORY),
errmsg("out of memory"),
errdetail("could not get libpq's default connection options")));
/* Count how many libpq options are available. */
num_libpq_opts = 0;
for (lopt = libpq_options; lopt->keyword; lopt++)
num_libpq_opts++;
/*
* Construct an array which consists of all valid options for
* postgres_fdw, by appending FDW-specific options to libpq options.
*
* We use plain malloc here to allocate postgres_fdw_options because it
* lives as long as the backend process does. Besides, keeping
* libpq_options in memory allows us to avoid copying every keyword
* string.
*/
postgres_fdw_options = (PgFdwOption *)
malloc(sizeof(PgFdwOption) * num_libpq_opts +
sizeof(non_libpq_options));
if (postgres_fdw_options == NULL)
ereport(ERROR,
(errcode(ERRCODE_FDW_OUT_OF_MEMORY),
errmsg("out of memory")));
popt = postgres_fdw_options;
for (lopt = libpq_options; lopt->keyword; lopt++)
{
/* Hide debug options, as well as settings we override internally. */
if (strchr(lopt->dispchar, 'D') ||
strcmp(lopt->keyword, "fallback_application_name") == 0 ||
strcmp(lopt->keyword, "client_encoding") == 0)
continue;
/* We don't have to copy keyword string, as described above. */
popt->keyword = lopt->keyword;
/*
* "user" and any secret options are allowed only on user mappings.
* Everything else is a server option.
*/
if (strcmp(lopt->keyword, "user") == 0 || strchr(lopt->dispchar, '*'))
popt->optcontext = UserMappingRelationId;
else
popt->optcontext = ForeignServerRelationId;
popt->is_libpq_opt = true;
popt++;
}
/* Append FDW-specific options and dummy terminator. */
memcpy(popt, non_libpq_options, sizeof(non_libpq_options));
}
| static bool is_libpq_option | ( | const char * | keyword | ) | [static] |
Definition at line 250 of file option.c.
References Assert, PgFdwOption::is_libpq_opt, and PgFdwOption::keyword.
Referenced by ExtractConnectionOptions().
{
PgFdwOption *opt;
Assert(postgres_fdw_options); /* must be initialized already */
for (opt = postgres_fdw_options; opt->keyword; opt++)
{
if (opt->is_libpq_opt && strcmp(opt->keyword, keyword) == 0)
return true;
}
return false;
}
Definition at line 231 of file option.c.
References Assert, PgFdwOption::keyword, and PgFdwOption::optcontext.
Referenced by postgres_fdw_validator().
{
PgFdwOption *opt;
Assert(postgres_fdw_options); /* must be initialized already */
for (opt = postgres_fdw_options; opt->keyword; opt++)
{
if (context == opt->optcontext && strcmp(opt->keyword, keyword) == 0)
return true;
}
return false;
}
| PG_FUNCTION_INFO_V1 | ( | postgres_fdw_validator | ) |
| Datum postgres_fdw_validator | ( | PG_FUNCTION_ARGS | ) |
Definition at line 65 of file option.c.
References appendStringInfo(), buf, StringInfoData::data, defGetBoolean(), defGetString(), DefElem::defname, ereport, errcode(), errhint(), errmsg(), ERROR, InitPgFdwOptions(), initStringInfo(), is_valid_option(), PgFdwOption::keyword, StringInfoData::len, lfirst, PgFdwOption::optcontext, PG_GETARG_DATUM, PG_GETARG_OID, PG_RETURN_VOID, untransformRelOptions(), and val.
{
List *options_list = untransformRelOptions(PG_GETARG_DATUM(0));
Oid catalog = PG_GETARG_OID(1);
ListCell *cell;
/* Build our options lists if we didn't yet. */
InitPgFdwOptions();
/*
* Check that only options supported by postgres_fdw, and allowed for the
* current object type, are given.
*/
foreach(cell, options_list)
{
DefElem *def = (DefElem *) lfirst(cell);
if (!is_valid_option(def->defname, catalog))
{
/*
* Unknown option specified, complain about it. Provide a hint
* with list of valid options for the object.
*/
PgFdwOption *opt;
StringInfoData buf;
initStringInfo(&buf);
for (opt = postgres_fdw_options; opt->keyword; opt++)
{
if (catalog == opt->optcontext)
appendStringInfo(&buf, "%s%s", (buf.len > 0) ? ", " : "",
opt->keyword);
}
ereport(ERROR,
(errcode(ERRCODE_FDW_INVALID_OPTION_NAME),
errmsg("invalid option \"%s\"", def->defname),
errhint("Valid options in this context are: %s",
buf.data)));
}
/*
* Validate option value, when we can do so without any context.
*/
if (strcmp(def->defname, "use_remote_estimate") == 0)
{
/* use_remote_estimate accepts only boolean values */
(void) defGetBoolean(def);
}
else if (strcmp(def->defname, "fdw_startup_cost") == 0 ||
strcmp(def->defname, "fdw_tuple_cost") == 0)
{
/* these must have a non-negative numeric value */
double val;
char *endp;
val = strtod(defGetString(def), &endp);
if (*endp || val < 0)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("%s requires a non-negative numeric value",
def->defname)));
}
}
PG_RETURN_VOID();
}
PQconninfoOption* libpq_options [static] |
PgFdwOption* postgres_fdw_options [static] |
1.7.1