PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
option.c File Reference
Include dependency graph for option.c:

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)
 
 PG_FUNCTION_INFO_V1 (postgres_fdw_validator)
 
Datum postgres_fdw_validator (PG_FUNCTION_ARGS)
 
int ExtractConnectionOptions (List *defelems, const char **keywords, const char **values)
 
ListExtractExtensionList (const char *extensionsString, bool warnOnMissing)
 

Variables

static PgFdwOptionpostgres_fdw_options
 
static PQconninfoOptionlibpq_options
 

Typedef Documentation

Function Documentation

int ExtractConnectionOptions ( List defelems,
const char **  keywords,
const char **  values 
)

Definition at line 297 of file option.c.

References defGetString(), DefElem::defname, i, InitPgFdwOptions(), is_libpq_option(), and lfirst.

Referenced by connect_pg_server().

299 {
300  ListCell *lc;
301  int i;
302 
303  /* Build our options lists if we didn't yet. */
305 
306  i = 0;
307  foreach(lc, defelems)
308  {
309  DefElem *d = (DefElem *) lfirst(lc);
310 
311  if (is_libpq_option(d->defname))
312  {
313  keywords[i] = d->defname;
314  values[i] = defGetString(d);
315  i++;
316  }
317  }
318  return i;
319 }
char * defGetString(DefElem *def)
Definition: define.c:49
#define lfirst(lc)
Definition: pg_list.h:106
static Datum values[MAXATTR]
Definition: bootstrap.c:162
int i
static bool is_libpq_option(const char *keyword)
Definition: option.c:276
char * defname
Definition: parsenodes.h:675
static void InitPgFdwOptions(void)
Definition: option.c:155
List* ExtractExtensionList ( const char *  extensionsString,
bool  warnOnMissing 
)

Definition at line 328 of file option.c.

References ereport, errcode(), errmsg(), ERROR, get_extension_oid(), lappend_oid(), lfirst, list_free(), NIL, OidIsValid, pstrdup(), SplitIdentifierString(), and WARNING.

Referenced by postgres_fdw_validator(), and postgresGetForeignRelSize().

329 {
330  List *extensionOids = NIL;
331  List *extlist;
332  ListCell *lc;
333 
334  /* SplitIdentifierString scribbles on its input, so pstrdup first */
335  if (!SplitIdentifierString(pstrdup(extensionsString), ',', &extlist))
336  {
337  /* syntax error in name list */
338  ereport(ERROR,
339  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
340  errmsg("parameter \"%s\" must be a list of extension names",
341  "extensions")));
342  }
343 
344  foreach(lc, extlist)
345  {
346  const char *extension_name = (const char *) lfirst(lc);
347  Oid extension_oid = get_extension_oid(extension_name, true);
348 
349  if (OidIsValid(extension_oid))
350  {
351  extensionOids = lappend_oid(extensionOids, extension_oid);
352  }
353  else if (warnOnMissing)
354  {
356  (errcode(ERRCODE_UNDEFINED_OBJECT),
357  errmsg("extension \"%s\" is not installed",
358  extension_name)));
359  }
360  }
361 
362  list_free(extlist);
363  return extensionOids;
364 }
#define NIL
Definition: pg_list.h:69
char * pstrdup(const char *in)
Definition: mcxt.c:1165
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define OidIsValid(objectId)
Definition: c.h:534
#define ERROR
Definition: elog.h:43
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3129
#define ereport(elevel, rest)
Definition: elog.h:122
#define WARNING
Definition: elog.h:40
#define lfirst(lc)
Definition: pg_list.h:106
Oid get_extension_oid(const char *extname, bool missing_ok)
Definition: extension.c:134
int errmsg(const char *fmt,...)
Definition: elog.c:797
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45
static void InitPgFdwOptions ( void  )
static

Definition at line 155 of file option.c.

References AttributeRelationId, _PQconninfoOption::dispchar, ereport, errcode(), errdetail(), errmsg(), ERROR, ForeignServerRelationId, ForeignTableRelationId, InvalidOid, PgFdwOption::is_libpq_opt, PgFdwOption::keyword, _PQconninfoOption::keyword, malloc, NULL, PgFdwOption::optcontext, postgres_fdw_options, PQconndefaults(), and UserMappingRelationId.

Referenced by ExtractConnectionOptions(), and postgres_fdw_validator().

156 {
157  int num_libpq_opts;
158  PQconninfoOption *lopt;
159  PgFdwOption *popt;
160 
161  /* non-libpq FDW-specific FDW options */
162  static const PgFdwOption non_libpq_options[] = {
163  {"schema_name", ForeignTableRelationId, false},
164  {"table_name", ForeignTableRelationId, false},
165  {"column_name", AttributeRelationId, false},
166  /* use_remote_estimate is available on both server and table */
167  {"use_remote_estimate", ForeignServerRelationId, false},
168  {"use_remote_estimate", ForeignTableRelationId, false},
169  /* cost factors */
170  {"fdw_startup_cost", ForeignServerRelationId, false},
171  {"fdw_tuple_cost", ForeignServerRelationId, false},
172  /* shippable extensions */
173  {"extensions", ForeignServerRelationId, false},
174  /* updatable is available on both server and table */
175  {"updatable", ForeignServerRelationId, false},
176  {"updatable", ForeignTableRelationId, false},
177  /* fetch_size is available on both server and table */
178  {"fetch_size", ForeignServerRelationId, false},
179  {"fetch_size", ForeignTableRelationId, false},
180  {NULL, InvalidOid, false}
181  };
182 
183  /* Prevent redundant initialization. */
185  return;
186 
187  /*
188  * Get list of valid libpq options.
189  *
190  * To avoid unnecessary work, we get the list once and use it throughout
191  * the lifetime of this backend process. We don't need to care about
192  * memory context issues, because PQconndefaults allocates with malloc.
193  */
195  if (!libpq_options) /* assume reason for failure is OOM */
196  ereport(ERROR,
197  (errcode(ERRCODE_FDW_OUT_OF_MEMORY),
198  errmsg("out of memory"),
199  errdetail("could not get libpq's default connection options")));
200 
201  /* Count how many libpq options are available. */
202  num_libpq_opts = 0;
203  for (lopt = libpq_options; lopt->keyword; lopt++)
204  num_libpq_opts++;
205 
206  /*
207  * Construct an array which consists of all valid options for
208  * postgres_fdw, by appending FDW-specific options to libpq options.
209  *
210  * We use plain malloc here to allocate postgres_fdw_options because it
211  * lives as long as the backend process does. Besides, keeping
212  * libpq_options in memory allows us to avoid copying every keyword
213  * string.
214  */
216  malloc(sizeof(PgFdwOption) * num_libpq_opts +
217  sizeof(non_libpq_options));
218  if (postgres_fdw_options == NULL)
219  ereport(ERROR,
220  (errcode(ERRCODE_FDW_OUT_OF_MEMORY),
221  errmsg("out of memory")));
222 
223  popt = postgres_fdw_options;
224  for (lopt = libpq_options; lopt->keyword; lopt++)
225  {
226  /* Hide debug options, as well as settings we override internally. */
227  if (strchr(lopt->dispchar, 'D') ||
228  strcmp(lopt->keyword, "fallback_application_name") == 0 ||
229  strcmp(lopt->keyword, "client_encoding") == 0)
230  continue;
231 
232  /* We don't have to copy keyword string, as described above. */
233  popt->keyword = lopt->keyword;
234 
235  /*
236  * "user" and any secret options are allowed only on user mappings.
237  * Everything else is a server option.
238  */
239  if (strcmp(lopt->keyword, "user") == 0 || strchr(lopt->dispchar, '*'))
241  else
243  popt->is_libpq_opt = true;
244 
245  popt++;
246  }
247 
248  /* Append FDW-specific options and dummy terminator. */
249  memcpy(popt, non_libpq_options, sizeof(non_libpq_options));
250 }
const char * keyword
Definition: option.c:32
bool is_libpq_opt
Definition: option.c:34
#define AttributeRelationId
Definition: pg_attribute.h:33
int errcode(int sqlerrcode)
Definition: elog.c:575
static PgFdwOption * postgres_fdw_options
Definition: option.c:41
#define malloc(a)
Definition: header.h:45
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:873
Oid optcontext
Definition: option.c:33
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvalidOid
Definition: postgres_ext.h:36
#define ForeignServerRelationId
#define NULL
Definition: c.h:226
PQconninfoOption * PQconndefaults(void)
Definition: fe-connect.c:1108
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define UserMappingRelationId
#define ForeignTableRelationId
static PQconninfoOption * libpq_options
Definition: option.c:47
static bool is_libpq_option ( const char *  keyword)
static

Definition at line 276 of file option.c.

References Assert, PgFdwOption::is_libpq_opt, and PgFdwOption::keyword.

Referenced by ExtractConnectionOptions().

277 {
278  PgFdwOption *opt;
279 
280  Assert(postgres_fdw_options); /* must be initialized already */
281 
282  for (opt = postgres_fdw_options; opt->keyword; opt++)
283  {
284  if (opt->is_libpq_opt && strcmp(opt->keyword, keyword) == 0)
285  return true;
286  }
287 
288  return false;
289 }
const char * keyword
Definition: option.c:32
bool is_libpq_opt
Definition: option.c:34
static PgFdwOption * postgres_fdw_options
Definition: option.c:41
#define Assert(condition)
Definition: c.h:671
static bool is_valid_option ( const char *  keyword,
Oid  context 
)
static

Definition at line 257 of file option.c.

References Assert, PgFdwOption::keyword, and PgFdwOption::optcontext.

Referenced by postgres_fdw_validator().

258 {
259  PgFdwOption *opt;
260 
261  Assert(postgres_fdw_options); /* must be initialized already */
262 
263  for (opt = postgres_fdw_options; opt->keyword; opt++)
264  {
265  if (context == opt->optcontext && strcmp(opt->keyword, keyword) == 0)
266  return true;
267  }
268 
269  return false;
270 }
const char * keyword
Definition: option.c:32
static PgFdwOption * postgres_fdw_options
Definition: option.c:41
Oid optcontext
Definition: option.c:33
#define Assert(condition)
Definition: c.h:671
PG_FUNCTION_INFO_V1 ( postgres_fdw_validator  )
Datum postgres_fdw_validator ( PG_FUNCTION_ARGS  )

Definition at line 66 of file option.c.

References appendStringInfo(), buf, StringInfoData::data, defGetBoolean(), defGetString(), DefElem::defname, ereport, errcode(), errhint(), errmsg(), ERROR, ExtractExtensionList(), fetch_size, InitPgFdwOptions(), initStringInfo(), is_valid_option(), PgFdwOption::keyword, StringInfoData::len, lfirst, NULL, PgFdwOption::optcontext, PG_GETARG_DATUM, PG_GETARG_OID, PG_RETURN_VOID, untransformRelOptions(), and val.

67 {
68  List *options_list = untransformRelOptions(PG_GETARG_DATUM(0));
69  Oid catalog = PG_GETARG_OID(1);
70  ListCell *cell;
71 
72  /* Build our options lists if we didn't yet. */
74 
75  /*
76  * Check that only options supported by postgres_fdw, and allowed for the
77  * current object type, are given.
78  */
79  foreach(cell, options_list)
80  {
81  DefElem *def = (DefElem *) lfirst(cell);
82 
83  if (!is_valid_option(def->defname, catalog))
84  {
85  /*
86  * Unknown option specified, complain about it. Provide a hint
87  * with list of valid options for the object.
88  */
89  PgFdwOption *opt;
91 
92  initStringInfo(&buf);
93  for (opt = postgres_fdw_options; opt->keyword; opt++)
94  {
95  if (catalog == opt->optcontext)
96  appendStringInfo(&buf, "%s%s", (buf.len > 0) ? ", " : "",
97  opt->keyword);
98  }
99 
100  ereport(ERROR,
101  (errcode(ERRCODE_FDW_INVALID_OPTION_NAME),
102  errmsg("invalid option \"%s\"", def->defname),
103  errhint("Valid options in this context are: %s",
104  buf.data)));
105  }
106 
107  /*
108  * Validate option value, when we can do so without any context.
109  */
110  if (strcmp(def->defname, "use_remote_estimate") == 0 ||
111  strcmp(def->defname, "updatable") == 0)
112  {
113  /* these accept only boolean values */
114  (void) defGetBoolean(def);
115  }
116  else if (strcmp(def->defname, "fdw_startup_cost") == 0 ||
117  strcmp(def->defname, "fdw_tuple_cost") == 0)
118  {
119  /* these must have a non-negative numeric value */
120  double val;
121  char *endp;
122 
123  val = strtod(defGetString(def), &endp);
124  if (*endp || val < 0)
125  ereport(ERROR,
126  (errcode(ERRCODE_SYNTAX_ERROR),
127  errmsg("%s requires a non-negative numeric value",
128  def->defname)));
129  }
130  else if (strcmp(def->defname, "extensions") == 0)
131  {
132  /* check list syntax, warn about uninstalled extensions */
133  (void) ExtractExtensionList(defGetString(def), true);
134  }
135  else if (strcmp(def->defname, "fetch_size") == 0)
136  {
137  int fetch_size;
138 
139  fetch_size = strtol(defGetString(def), NULL, 10);
140  if (fetch_size <= 0)
141  ereport(ERROR,
142  (errcode(ERRCODE_SYNTAX_ERROR),
143  errmsg("%s requires a non-negative integer value",
144  def->defname)));
145  }
146  }
147 
148  PG_RETURN_VOID();
149 }
int errhint(const char *fmt,...)
Definition: elog.c:987
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
const char * keyword
Definition: option.c:32
static bool is_valid_option(const char *keyword, Oid context)
Definition: option.c:257
uint64 fetch_size
Definition: logging.c:21
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
static PgFdwOption * postgres_fdw_options
Definition: option.c:41
bool defGetBoolean(DefElem *def)
Definition: define.c:111
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
#define ERROR
Definition: elog.h:43
char * defGetString(DefElem *def)
Definition: define.c:49
List * ExtractExtensionList(const char *extensionsString, bool warnOnMissing)
Definition: option.c:328
static char * buf
Definition: pg_test_fsync.c:65
#define PG_GETARG_OID(n)
Definition: fmgr.h:231
Oid optcontext
Definition: option.c:33
#define ereport(elevel, rest)
Definition: elog.h:122
void initStringInfo(StringInfo str)
Definition: stringinfo.c:65
List * untransformRelOptions(Datum options)
Definition: reloptions.c:863
#define PG_RETURN_VOID()
Definition: fmgr.h:293
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * defname
Definition: parsenodes.h:675
Definition: pg_list.h:45
long val
Definition: informix.c:689
static void InitPgFdwOptions(void)
Definition: option.c:155

Variable Documentation

PQconninfoOption* libpq_options
static

Definition at line 47 of file option.c.

PgFdwOption* postgres_fdw_options
static

Definition at line 41 of file option.c.

Referenced by InitPgFdwOptions().