PostgreSQL Source Code  git master
foreign.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * foreign.c
4  * support for foreign-data wrappers, servers and user mappings.
5  *
6  * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
7  *
8  * IDENTIFICATION
9  * src/backend/foreign/foreign.c
10  *
11  *-------------------------------------------------------------------------
12  */
13 #include "postgres.h"
14 
15 #include "access/htup_details.h"
16 #include "access/reloptions.h"
21 #include "foreign/fdwapi.h"
22 #include "foreign/foreign.h"
23 #include "funcapi.h"
24 #include "lib/stringinfo.h"
25 #include "miscadmin.h"
26 #include "utils/builtins.h"
27 #include "utils/memutils.h"
28 #include "utils/rel.h"
29 #include "utils/syscache.h"
30 
31 
32 /*
33  * GetForeignDataWrapper - look up the foreign-data wrapper by OID.
34  */
37 {
38  return GetForeignDataWrapperExtended(fdwid, 0);
39 }
40 
41 
42 /*
43  * GetForeignDataWrapperExtended - look up the foreign-data wrapper
44  * by OID. If flags uses FDW_MISSING_OK, return NULL if the object cannot
45  * be found instead of raising an error.
46  */
49 {
51  ForeignDataWrapper *fdw;
52  Datum datum;
53  HeapTuple tp;
54  bool isnull;
55 
57 
58  if (!HeapTupleIsValid(tp))
59  {
60  if ((flags & FDW_MISSING_OK) == 0)
61  elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid);
62  return NULL;
63  }
64 
66 
67  fdw = (ForeignDataWrapper *) palloc(sizeof(ForeignDataWrapper));
68  fdw->fdwid = fdwid;
69  fdw->owner = fdwform->fdwowner;
70  fdw->fdwname = pstrdup(NameStr(fdwform->fdwname));
71  fdw->fdwhandler = fdwform->fdwhandler;
72  fdw->fdwvalidator = fdwform->fdwvalidator;
73 
74  /* Extract the fdwoptions */
76  tp,
77  Anum_pg_foreign_data_wrapper_fdwoptions,
78  &isnull);
79  if (isnull)
80  fdw->options = NIL;
81  else
82  fdw->options = untransformRelOptions(datum);
83 
84  ReleaseSysCache(tp);
85 
86  return fdw;
87 }
88 
89 
90 /*
91  * GetForeignDataWrapperByName - look up the foreign-data wrapper
92  * definition by name.
93  */
95 GetForeignDataWrapperByName(const char *fdwname, bool missing_ok)
96 {
97  Oid fdwId = get_foreign_data_wrapper_oid(fdwname, missing_ok);
98 
99  if (!OidIsValid(fdwId))
100  return NULL;
101 
102  return GetForeignDataWrapper(fdwId);
103 }
104 
105 
106 /*
107  * GetForeignServer - look up the foreign server definition.
108  */
111 {
112  return GetForeignServerExtended(serverid, 0);
113 }
114 
115 
116 /*
117  * GetForeignServerExtended - look up the foreign server definition. If
118  * flags uses FSV_MISSING_OK, return NULL if the object cannot be found
119  * instead of raising an error.
120  */
123 {
124  Form_pg_foreign_server serverform;
125  ForeignServer *server;
126  HeapTuple tp;
127  Datum datum;
128  bool isnull;
129 
131 
132  if (!HeapTupleIsValid(tp))
133  {
134  if ((flags & FSV_MISSING_OK) == 0)
135  elog(ERROR, "cache lookup failed for foreign server %u", serverid);
136  return NULL;
137  }
138 
139  serverform = (Form_pg_foreign_server) GETSTRUCT(tp);
140 
141  server = (ForeignServer *) palloc(sizeof(ForeignServer));
142  server->serverid = serverid;
143  server->servername = pstrdup(NameStr(serverform->srvname));
144  server->owner = serverform->srvowner;
145  server->fdwid = serverform->srvfdw;
146 
147  /* Extract server type */
149  tp,
150  Anum_pg_foreign_server_srvtype,
151  &isnull);
152  server->servertype = isnull ? NULL : TextDatumGetCString(datum);
153 
154  /* Extract server version */
156  tp,
157  Anum_pg_foreign_server_srvversion,
158  &isnull);
159  server->serverversion = isnull ? NULL : TextDatumGetCString(datum);
160 
161  /* Extract the srvoptions */
163  tp,
164  Anum_pg_foreign_server_srvoptions,
165  &isnull);
166  if (isnull)
167  server->options = NIL;
168  else
169  server->options = untransformRelOptions(datum);
170 
171  ReleaseSysCache(tp);
172 
173  return server;
174 }
175 
176 
177 /*
178  * GetForeignServerByName - look up the foreign server definition by name.
179  */
181 GetForeignServerByName(const char *srvname, bool missing_ok)
182 {
183  Oid serverid = get_foreign_server_oid(srvname, missing_ok);
184 
185  if (!OidIsValid(serverid))
186  return NULL;
187 
188  return GetForeignServer(serverid);
189 }
190 
191 
192 /*
193  * GetUserMapping - look up the user mapping.
194  *
195  * If no mapping is found for the supplied user, we also look for
196  * PUBLIC mappings (userid == InvalidOid).
197  */
198 UserMapping *
199 GetUserMapping(Oid userid, Oid serverid)
200 {
201  Datum datum;
202  HeapTuple tp;
203  bool isnull;
204  UserMapping *um;
205 
206  tp = SearchSysCache2(USERMAPPINGUSERSERVER,
207  ObjectIdGetDatum(userid),
208  ObjectIdGetDatum(serverid));
209 
210  if (!HeapTupleIsValid(tp))
211  {
212  /* Not found for the specific user -- try PUBLIC */
213  tp = SearchSysCache2(USERMAPPINGUSERSERVER,
215  ObjectIdGetDatum(serverid));
216  }
217 
218  if (!HeapTupleIsValid(tp))
219  ereport(ERROR,
220  (errcode(ERRCODE_UNDEFINED_OBJECT),
221  errmsg("user mapping not found for \"%s\"",
222  MappingUserName(userid))));
223 
224  um = (UserMapping *) palloc(sizeof(UserMapping));
225  um->umid = ((Form_pg_user_mapping) GETSTRUCT(tp))->oid;
226  um->userid = userid;
227  um->serverid = serverid;
228 
229  /* Extract the umoptions */
230  datum = SysCacheGetAttr(USERMAPPINGUSERSERVER,
231  tp,
232  Anum_pg_user_mapping_umoptions,
233  &isnull);
234  if (isnull)
235  um->options = NIL;
236  else
237  um->options = untransformRelOptions(datum);
238 
239  ReleaseSysCache(tp);
240 
241  return um;
242 }
243 
244 
245 /*
246  * GetForeignTable - look up the foreign table definition by relation oid.
247  */
248 ForeignTable *
250 {
251  Form_pg_foreign_table tableform;
252  ForeignTable *ft;
253  HeapTuple tp;
254  Datum datum;
255  bool isnull;
256 
258  if (!HeapTupleIsValid(tp))
259  elog(ERROR, "cache lookup failed for foreign table %u", relid);
260  tableform = (Form_pg_foreign_table) GETSTRUCT(tp);
261 
262  ft = (ForeignTable *) palloc(sizeof(ForeignTable));
263  ft->relid = relid;
264  ft->serverid = tableform->ftserver;
265 
266  /* Extract the ftoptions */
268  tp,
269  Anum_pg_foreign_table_ftoptions,
270  &isnull);
271  if (isnull)
272  ft->options = NIL;
273  else
274  ft->options = untransformRelOptions(datum);
275 
276  ReleaseSysCache(tp);
277 
278  return ft;
279 }
280 
281 
282 /*
283  * GetForeignColumnOptions - Get attfdwoptions of given relation/attnum
284  * as list of DefElem.
285  */
286 List *
288 {
289  List *options;
290  HeapTuple tp;
291  Datum datum;
292  bool isnull;
293 
294  tp = SearchSysCache2(ATTNUM,
295  ObjectIdGetDatum(relid),
297  if (!HeapTupleIsValid(tp))
298  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
299  attnum, relid);
300  datum = SysCacheGetAttr(ATTNUM,
301  tp,
302  Anum_pg_attribute_attfdwoptions,
303  &isnull);
304  if (isnull)
305  options = NIL;
306  else
308 
309  ReleaseSysCache(tp);
310 
311  return options;
312 }
313 
314 
315 /*
316  * GetFdwRoutine - call the specified foreign-data wrapper handler routine
317  * to get its FdwRoutine struct.
318  */
319 FdwRoutine *
320 GetFdwRoutine(Oid fdwhandler)
321 {
322  Datum datum;
323  FdwRoutine *routine;
324 
325  datum = OidFunctionCall0(fdwhandler);
326  routine = (FdwRoutine *) DatumGetPointer(datum);
327 
328  if (routine == NULL || !IsA(routine, FdwRoutine))
329  elog(ERROR, "foreign-data wrapper handler function %u did not return an FdwRoutine struct",
330  fdwhandler);
331 
332  return routine;
333 }
334 
335 
336 /*
337  * GetForeignServerIdByRelId - look up the foreign server
338  * for the given foreign table, and return its OID.
339  */
340 Oid
342 {
343  HeapTuple tp;
344  Form_pg_foreign_table tableform;
345  Oid serverid;
346 
348  if (!HeapTupleIsValid(tp))
349  elog(ERROR, "cache lookup failed for foreign table %u", relid);
350  tableform = (Form_pg_foreign_table) GETSTRUCT(tp);
351  serverid = tableform->ftserver;
352  ReleaseSysCache(tp);
353 
354  return serverid;
355 }
356 
357 
358 /*
359  * GetFdwRoutineByServerId - look up the handler of the foreign-data wrapper
360  * for the given foreign server, and retrieve its FdwRoutine struct.
361  */
362 FdwRoutine *
364 {
365  HeapTuple tp;
367  Form_pg_foreign_server serverform;
368  Oid fdwid;
369  Oid fdwhandler;
370 
371  /* Get foreign-data wrapper OID for the server. */
373  if (!HeapTupleIsValid(tp))
374  elog(ERROR, "cache lookup failed for foreign server %u", serverid);
375  serverform = (Form_pg_foreign_server) GETSTRUCT(tp);
376  fdwid = serverform->srvfdw;
377  ReleaseSysCache(tp);
378 
379  /* Get handler function OID for the FDW. */
381  if (!HeapTupleIsValid(tp))
382  elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid);
383  fdwform = (Form_pg_foreign_data_wrapper) GETSTRUCT(tp);
384  fdwhandler = fdwform->fdwhandler;
385 
386  /* Complain if FDW has been set to NO HANDLER. */
387  if (!OidIsValid(fdwhandler))
388  ereport(ERROR,
389  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
390  errmsg("foreign-data wrapper \"%s\" has no handler",
391  NameStr(fdwform->fdwname))));
392 
393  ReleaseSysCache(tp);
394 
395  /* And finally, call the handler function. */
396  return GetFdwRoutine(fdwhandler);
397 }
398 
399 
400 /*
401  * GetFdwRoutineByRelId - look up the handler of the foreign-data wrapper
402  * for the given foreign table, and retrieve its FdwRoutine struct.
403  */
404 FdwRoutine *
406 {
407  Oid serverid;
408 
409  /* Get server OID for the foreign table. */
410  serverid = GetForeignServerIdByRelId(relid);
411 
412  /* Now retrieve server's FdwRoutine struct. */
413  return GetFdwRoutineByServerId(serverid);
414 }
415 
416 /*
417  * GetFdwRoutineForRelation - look up the handler of the foreign-data wrapper
418  * for the given foreign table, and retrieve its FdwRoutine struct.
419  *
420  * This function is preferred over GetFdwRoutineByRelId because it caches
421  * the data in the relcache entry, saving a number of catalog lookups.
422  *
423  * If makecopy is true then the returned data is freshly palloc'd in the
424  * caller's memory context. Otherwise, it's a pointer to the relcache data,
425  * which will be lost in any relcache reset --- so don't rely on it long.
426  */
427 FdwRoutine *
428 GetFdwRoutineForRelation(Relation relation, bool makecopy)
429 {
430  FdwRoutine *fdwroutine;
431  FdwRoutine *cfdwroutine;
432 
433  if (relation->rd_fdwroutine == NULL)
434  {
435  /* Get the info by consulting the catalogs and the FDW code */
436  fdwroutine = GetFdwRoutineByRelId(RelationGetRelid(relation));
437 
438  /* Save the data for later reuse in CacheMemoryContext */
440  sizeof(FdwRoutine));
441  memcpy(cfdwroutine, fdwroutine, sizeof(FdwRoutine));
442  relation->rd_fdwroutine = cfdwroutine;
443 
444  /* Give back the locally palloc'd copy regardless of makecopy */
445  return fdwroutine;
446  }
447 
448  /* We have valid cached data --- does the caller want a copy? */
449  if (makecopy)
450  {
451  fdwroutine = (FdwRoutine *) palloc(sizeof(FdwRoutine));
452  memcpy(fdwroutine, relation->rd_fdwroutine, sizeof(FdwRoutine));
453  return fdwroutine;
454  }
455 
456  /* Only a short-lived reference is needed, so just hand back cached copy */
457  return relation->rd_fdwroutine;
458 }
459 
460 
461 /*
462  * IsImportableForeignTable - filter table names for IMPORT FOREIGN SCHEMA
463  *
464  * Returns true if given table name should be imported according to the
465  * statement's import filter options.
466  */
467 bool
468 IsImportableForeignTable(const char *tablename,
470 {
471  ListCell *lc;
472 
473  switch (stmt->list_type)
474  {
476  return true;
477 
479  foreach(lc, stmt->table_list)
480  {
481  RangeVar *rv = (RangeVar *) lfirst(lc);
482 
483  if (strcmp(tablename, rv->relname) == 0)
484  return true;
485  }
486  return false;
487 
489  foreach(lc, stmt->table_list)
490  {
491  RangeVar *rv = (RangeVar *) lfirst(lc);
492 
493  if (strcmp(tablename, rv->relname) == 0)
494  return false;
495  }
496  return true;
497  }
498  return false; /* shouldn't get here */
499 }
500 
501 
502 /*
503  * pg_options_to_table - Convert options array to name/value table
504  *
505  * This is useful to provide details for information_schema and pg_dump.
506  */
507 Datum
509 {
510  Datum array = PG_GETARG_DATUM(0);
511  ListCell *cell;
512  List *options;
513  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
514 
516  rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
517 
518  /* prepare the result set */
520 
521  foreach(cell, options)
522  {
523  DefElem *def = lfirst(cell);
524  Datum values[2];
525  bool nulls[2];
526 
528  nulls[0] = false;
529  if (def->arg)
530  {
531  values[1] = CStringGetTextDatum(strVal(def->arg));
532  nulls[1] = false;
533  }
534  else
535  {
536  values[1] = (Datum) 0;
537  nulls[1] = true;
538  }
539  tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
540  values, nulls);
541  }
542 
543  return (Datum) 0;
544 }
545 
546 
547 /*
548  * Describes the valid options for postgresql FDW, server, and user mapping.
549  */
551 {
552  const char *optname;
553  Oid optcontext; /* Oid of catalog in which option may appear */
554 };
555 
556 /*
557  * Copied from fe-connect.c PQconninfoOptions.
558  *
559  * The list is small - don't bother with bsearch if it stays so.
560  */
561 static const struct ConnectionOption libpq_conninfo_options[] = {
562  {"authtype", ForeignServerRelationId},
563  {"service", ForeignServerRelationId},
564  {"user", UserMappingRelationId},
565  {"password", UserMappingRelationId},
566  {"connect_timeout", ForeignServerRelationId},
567  {"dbname", ForeignServerRelationId},
568  {"host", ForeignServerRelationId},
569  {"hostaddr", ForeignServerRelationId},
570  {"port", ForeignServerRelationId},
571  {"tty", ForeignServerRelationId},
572  {"options", ForeignServerRelationId},
573  {"requiressl", ForeignServerRelationId},
574  {"sslmode", ForeignServerRelationId},
575  {"gsslib", ForeignServerRelationId},
576  {NULL, InvalidOid}
577 };
578 
579 
580 /*
581  * Check if the provided option is one of libpq conninfo options.
582  * context is the Oid of the catalog the option came from, or 0 if we
583  * don't care.
584  */
585 static bool
586 is_conninfo_option(const char *option, Oid context)
587 {
588  const struct ConnectionOption *opt;
589 
590  for (opt = libpq_conninfo_options; opt->optname; opt++)
591  if (context == opt->optcontext && strcmp(opt->optname, option) == 0)
592  return true;
593  return false;
594 }
595 
596 
597 /*
598  * Validate the generic option given to SERVER or USER MAPPING.
599  * Raise an ERROR if the option or its value is considered invalid.
600  *
601  * Valid server options are all libpq conninfo options except
602  * user and password -- these may only appear in USER MAPPING options.
603  *
604  * Caution: this function is deprecated, and is now meant only for testing
605  * purposes, because the list of options it knows about doesn't necessarily
606  * square with those known to whichever libpq instance you might be using.
607  * Inquire of libpq itself, instead.
608  */
609 Datum
611 {
612  List *options_list = untransformRelOptions(PG_GETARG_DATUM(0));
613  Oid catalog = PG_GETARG_OID(1);
614 
615  ListCell *cell;
616 
617  foreach(cell, options_list)
618  {
619  DefElem *def = lfirst(cell);
620 
621  if (!is_conninfo_option(def->defname, catalog))
622  {
623  const struct ConnectionOption *opt;
625 
626  /*
627  * Unknown option specified, complain about it. Provide a hint
628  * with list of valid options for the object.
629  */
631  for (opt = libpq_conninfo_options; opt->optname; opt++)
632  if (catalog == opt->optcontext)
633  appendStringInfo(&buf, "%s%s", (buf.len > 0) ? ", " : "",
634  opt->optname);
635 
636  ereport(ERROR,
637  (errcode(ERRCODE_SYNTAX_ERROR),
638  errmsg("invalid option \"%s\"", def->defname),
639  buf.len > 0
640  ? errhint("Valid options in this context are: %s",
641  buf.data)
642  : errhint("There are no valid options in this context.")));
643 
644  PG_RETURN_BOOL(false);
645  }
646  }
647 
648  PG_RETURN_BOOL(true);
649 }
650 
651 
652 /*
653  * get_foreign_data_wrapper_oid - given a FDW name, look up the OID
654  *
655  * If missing_ok is false, throw an error if name not found. If true, just
656  * return InvalidOid.
657  */
658 Oid
659 get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
660 {
661  Oid oid;
662 
664  Anum_pg_foreign_data_wrapper_oid,
665  CStringGetDatum(fdwname));
666  if (!OidIsValid(oid) && !missing_ok)
667  ereport(ERROR,
668  (errcode(ERRCODE_UNDEFINED_OBJECT),
669  errmsg("foreign-data wrapper \"%s\" does not exist",
670  fdwname)));
671  return oid;
672 }
673 
674 
675 /*
676  * get_foreign_server_oid - given a server name, look up the OID
677  *
678  * If missing_ok is false, throw an error if name not found. If true, just
679  * return InvalidOid.
680  */
681 Oid
682 get_foreign_server_oid(const char *servername, bool missing_ok)
683 {
684  Oid oid;
685 
686  oid = GetSysCacheOid1(FOREIGNSERVERNAME, Anum_pg_foreign_server_oid,
687  CStringGetDatum(servername));
688  if (!OidIsValid(oid) && !missing_ok)
689  ereport(ERROR,
690  (errcode(ERRCODE_UNDEFINED_OBJECT),
691  errmsg("server \"%s\" does not exist", servername)));
692  return oid;
693 }
694 
695 /*
696  * Get a copy of an existing local path for a given join relation.
697  *
698  * This function is usually helpful to obtain an alternate local path for EPQ
699  * checks.
700  *
701  * Right now, this function only supports unparameterized foreign joins, so we
702  * only search for unparameterized path in the given list of paths. Since we
703  * are searching for a path which can be used to construct an alternative local
704  * plan for a foreign join, we look for only MergeJoin, HashJoin or NestLoop
705  * paths.
706  *
707  * If the inner or outer subpath of the chosen path is a ForeignScan, we
708  * replace it with its outer subpath. For this reason, and also because the
709  * planner might free the original path later, the path returned by this
710  * function is a shallow copy of the original. There's no need to copy
711  * the substructure, so we don't.
712  *
713  * Since the plan created using this path will presumably only be used to
714  * execute EPQ checks, efficiency of the path is not a concern. But since the
715  * path list in RelOptInfo is anyway sorted by total cost we are likely to
716  * choose the most efficient path, which is all for the best.
717  */
718 Path *
720 {
721  ListCell *lc;
722 
723  Assert(IS_JOIN_REL(joinrel));
724 
725  foreach(lc, joinrel->pathlist)
726  {
727  Path *path = (Path *) lfirst(lc);
728  JoinPath *joinpath = NULL;
729 
730  /* Skip parameterized paths. */
731  if (path->param_info != NULL)
732  continue;
733 
734  switch (path->pathtype)
735  {
736  case T_HashJoin:
737  {
738  HashPath *hash_path = makeNode(HashPath);
739 
740  memcpy(hash_path, path, sizeof(HashPath));
741  joinpath = (JoinPath *) hash_path;
742  }
743  break;
744 
745  case T_NestLoop:
746  {
747  NestPath *nest_path = makeNode(NestPath);
748 
749  memcpy(nest_path, path, sizeof(NestPath));
750  joinpath = (JoinPath *) nest_path;
751  }
752  break;
753 
754  case T_MergeJoin:
755  {
756  MergePath *merge_path = makeNode(MergePath);
757 
758  memcpy(merge_path, path, sizeof(MergePath));
759  joinpath = (JoinPath *) merge_path;
760  }
761  break;
762 
763  default:
764 
765  /*
766  * Just skip anything else. We don't know if corresponding
767  * plan would build the output row from whole-row references
768  * of base relations and execute the EPQ checks.
769  */
770  break;
771  }
772 
773  /* This path isn't good for us, check next. */
774  if (!joinpath)
775  continue;
776 
777  /*
778  * If either inner or outer path is a ForeignPath corresponding to a
779  * pushed down join, replace it with the fdw_outerpath, so that we
780  * maintain path for EPQ checks built entirely of local join
781  * strategies.
782  */
783  if (IsA(joinpath->outerjoinpath, ForeignPath))
784  {
785  ForeignPath *foreign_path;
786 
787  foreign_path = (ForeignPath *) joinpath->outerjoinpath;
788  if (IS_JOIN_REL(foreign_path->path.parent))
789  joinpath->outerjoinpath = foreign_path->fdw_outerpath;
790  }
791 
792  if (IsA(joinpath->innerjoinpath, ForeignPath))
793  {
794  ForeignPath *foreign_path;
795 
796  foreign_path = (ForeignPath *) joinpath->innerjoinpath;
797  if (IS_JOIN_REL(foreign_path->path.parent))
798  joinpath->innerjoinpath = foreign_path->fdw_outerpath;
799  }
800 
801  return (Path *) joinpath;
802  }
803  return NULL;
804 }
int16 AttrNumber
Definition: attnum.h:21
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define CStringGetTextDatum(s)
Definition: builtins.h:85
#define TextDatumGetCString(d)
Definition: builtins.h:86
#define NameStr(name)
Definition: c.h:681
uint16 bits16
Definition: c.h:449
#define OidIsValid(objectId)
Definition: c.h:710
int errhint(const char *fmt,...)
Definition: elog.c:1151
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
#define ereport(elevel,...)
Definition: elog.h:143
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define OidFunctionCall0(functionId)
Definition: fmgr.h:667
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
ForeignDataWrapper * GetForeignDataWrapper(Oid fdwid)
Definition: foreign.c:36
ForeignServer * GetForeignServerExtended(Oid serverid, bits16 flags)
Definition: foreign.c:122
static bool is_conninfo_option(const char *option, Oid context)
Definition: foreign.c:586
static const struct ConnectionOption libpq_conninfo_options[]
Definition: foreign.c:561
FdwRoutine * GetFdwRoutineByRelId(Oid relid)
Definition: foreign.c:405
ForeignTable * GetForeignTable(Oid relid)
Definition: foreign.c:249
Path * GetExistingLocalJoinPath(RelOptInfo *joinrel)
Definition: foreign.c:719
Oid get_foreign_server_oid(const char *servername, bool missing_ok)
Definition: foreign.c:682
UserMapping * GetUserMapping(Oid userid, Oid serverid)
Definition: foreign.c:199
List * GetForeignColumnOptions(Oid relid, AttrNumber attnum)
Definition: foreign.c:287
Datum pg_options_to_table(PG_FUNCTION_ARGS)
Definition: foreign.c:508
Datum postgresql_fdw_validator(PG_FUNCTION_ARGS)
Definition: foreign.c:610
FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)
Definition: foreign.c:428
FdwRoutine * GetFdwRoutine(Oid fdwhandler)
Definition: foreign.c:320
ForeignDataWrapper * GetForeignDataWrapperExtended(Oid fdwid, bits16 flags)
Definition: foreign.c:48
ForeignDataWrapper * GetForeignDataWrapperByName(const char *fdwname, bool missing_ok)
Definition: foreign.c:95
ForeignServer * GetForeignServer(Oid serverid)
Definition: foreign.c:110
ForeignServer * GetForeignServerByName(const char *srvname, bool missing_ok)
Definition: foreign.c:181
Oid GetForeignServerIdByRelId(Oid relid)
Definition: foreign.c:341
FdwRoutine * GetFdwRoutineByServerId(Oid serverid)
Definition: foreign.c:363
bool IsImportableForeignTable(const char *tablename, ImportForeignSchemaStmt *stmt)
Definition: foreign.c:468
Oid get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
Definition: foreign.c:659
#define MappingUserName(userid)
Definition: foreign.h:20
#define FSV_MISSING_OK
Definition: foreign.h:61
#define FDW_MISSING_OK
Definition: foreign.h:64
void SetSingleFuncCall(FunctionCallInfo fcinfo, bits32 flags)
Definition: funcapi.c:76
#define SRF_SINGLE_USE_EXPECTED
Definition: funcapi.h:291
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:649
Assert(fmt[strlen(fmt) - 1] !='\n')
char * pstrdup(const char *in)
Definition: mcxt.c:1305
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
MemoryContext CacheMemoryContext
Definition: mcxt.c:51
void * palloc(Size size)
Definition: mcxt.c:1068
#define IsA(nodeptr, _type_)
Definition: nodes.h:624
@ T_MergeJoin
Definition: nodes.h:75
@ T_NestLoop
Definition: nodes.h:74
@ T_HashJoin
Definition: nodes.h:76
#define makeNode(_type_)
Definition: nodes.h:621
@ FDW_IMPORT_SCHEMA_LIMIT_TO
Definition: parsenodes.h:2826
@ FDW_IMPORT_SCHEMA_ALL
Definition: parsenodes.h:2825
@ FDW_IMPORT_SCHEMA_EXCEPT
Definition: parsenodes.h:2827
#define IS_JOIN_REL(rel)
Definition: pathnodes.h:660
int16 attnum
Definition: pg_attribute.h:83
FormData_pg_foreign_data_wrapper * Form_pg_foreign_data_wrapper
FormData_pg_foreign_server * Form_pg_foreign_server
FormData_pg_foreign_table * Form_pg_foreign_table
#define lfirst(lc)
Definition: pg_list.h:169
#define NIL
Definition: pg_list.h:65
static char ** options
static char * buf
Definition: pg_test_fsync.c:67
FormData_pg_user_mapping * Form_pg_user_mapping
#define CStringGetDatum(X)
Definition: postgres.h:622
uintptr_t Datum
Definition: postgres.h:411
#define DatumGetPointer(X)
Definition: postgres.h:593
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define Int16GetDatum(X)
Definition: postgres.h:495
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationGetRelid(relation)
Definition: rel.h:489
List * untransformRelOptions(Datum options)
Definition: reloptions.c:1334
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
const char * optname
Definition: foreign.c:552
char * defname
Definition: parsenodes.h:765
Node * arg
Definition: parsenodes.h:766
char * fdwname
Definition: foreign.h:28
List * options
Definition: foreign.h:31
Path * fdw_outerpath
Definition: pathnodes.h:1411
List * options
Definition: foreign.h:42
char * serverversion
Definition: foreign.h:41
char * servername
Definition: foreign.h:39
Oid serverid
Definition: foreign.h:36
char * servertype
Definition: foreign.h:40
Oid relid
Definition: foreign.h:55
List * options
Definition: foreign.h:57
Oid serverid
Definition: foreign.h:56
ImportForeignSchemaType list_type
Definition: parsenodes.h:2836
Path * outerjoinpath
Definition: pathnodes.h:1604
Path * innerjoinpath
Definition: pathnodes.h:1605
Definition: pg_list.h:51
NodeTag pathtype
Definition: pathnodes.h:1192
RelOptInfo * parent
Definition: pathnodes.h:1194
ParamPathInfo * param_info
Definition: pathnodes.h:1197
char * relname
Definition: primnodes.h:68
List * pathlist
Definition: pathnodes.h:696
struct FdwRoutine * rd_fdwroutine
Definition: rel.h:236
TupleDesc setDesc
Definition: execnodes.h:317
Tuplestorestate * setResult
Definition: execnodes.h:316
Oid userid
Definition: foreign.h:48
Oid umid
Definition: foreign.h:47
Oid serverid
Definition: foreign.h:49
List * options
Definition: foreign.h:50
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1221
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1173
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1434
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1184
@ FOREIGNTABLEREL
Definition: syscache.h:65
@ FOREIGNSERVEROID
Definition: syscache.h:64
@ FOREIGNSERVERNAME
Definition: syscache.h:63
@ ATTNUM
Definition: syscache.h:41
@ FOREIGNDATAWRAPPEROID
Definition: syscache.h:62
@ FOREIGNDATAWRAPPERNAME
Definition: syscache.h:61
#define GetSysCacheOid1(cacheId, oidcol, key1)
Definition: syscache.h:197
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, Datum *values, bool *isnull)
Definition: tuplestore.c:750
#define strVal(v)
Definition: value.h:72