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