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-2023, 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  {"gssdelegation", ForeignServerRelationId},
578  {NULL, InvalidOid}
579 };
580 
581 
582 /*
583  * Check if the provided option is one of libpq conninfo options.
584  * context is the Oid of the catalog the option came from, or 0 if we
585  * don't care.
586  */
587 static bool
588 is_conninfo_option(const char *option, Oid context)
589 {
590  const struct ConnectionOption *opt;
591 
592  for (opt = libpq_conninfo_options; opt->optname; opt++)
593  if (context == opt->optcontext && strcmp(opt->optname, option) == 0)
594  return true;
595  return false;
596 }
597 
598 
599 /*
600  * Validate the generic option given to SERVER or USER MAPPING.
601  * Raise an ERROR if the option or its value is considered invalid.
602  *
603  * Valid server options are all libpq conninfo options except
604  * user and password -- these may only appear in USER MAPPING options.
605  *
606  * Caution: this function is deprecated, and is now meant only for testing
607  * purposes, because the list of options it knows about doesn't necessarily
608  * square with those known to whichever libpq instance you might be using.
609  * Inquire of libpq itself, instead.
610  */
611 Datum
613 {
614  List *options_list = untransformRelOptions(PG_GETARG_DATUM(0));
615  Oid catalog = PG_GETARG_OID(1);
616 
617  ListCell *cell;
618 
619  foreach(cell, options_list)
620  {
621  DefElem *def = lfirst(cell);
622 
623  if (!is_conninfo_option(def->defname, catalog))
624  {
625  const struct ConnectionOption *opt;
626  const char *closest_match;
628  bool has_valid_options = false;
629 
630  /*
631  * Unknown option specified, complain about it. Provide a hint
632  * with a valid option that looks similar, if there is one.
633  */
635  for (opt = libpq_conninfo_options; opt->optname; opt++)
636  {
637  if (catalog == opt->optcontext)
638  {
639  has_valid_options = true;
641  }
642  }
643 
644  closest_match = getClosestMatch(&match_state);
645  ereport(ERROR,
646  (errcode(ERRCODE_SYNTAX_ERROR),
647  errmsg("invalid option \"%s\"", def->defname),
648  has_valid_options ? closest_match ?
649  errhint("Perhaps you meant the option \"%s\".",
650  closest_match) : 0 :
651  errhint("There are no valid options in this context.")));
652 
653  PG_RETURN_BOOL(false);
654  }
655  }
656 
657  PG_RETURN_BOOL(true);
658 }
659 
660 
661 /*
662  * get_foreign_data_wrapper_oid - given a FDW name, look up the OID
663  *
664  * If missing_ok is false, throw an error if name not found. If true, just
665  * return InvalidOid.
666  */
667 Oid
668 get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
669 {
670  Oid oid;
671 
673  Anum_pg_foreign_data_wrapper_oid,
674  CStringGetDatum(fdwname));
675  if (!OidIsValid(oid) && !missing_ok)
676  ereport(ERROR,
677  (errcode(ERRCODE_UNDEFINED_OBJECT),
678  errmsg("foreign-data wrapper \"%s\" does not exist",
679  fdwname)));
680  return oid;
681 }
682 
683 
684 /*
685  * get_foreign_server_oid - given a server name, look up the OID
686  *
687  * If missing_ok is false, throw an error if name not found. If true, just
688  * return InvalidOid.
689  */
690 Oid
691 get_foreign_server_oid(const char *servername, bool missing_ok)
692 {
693  Oid oid;
694 
695  oid = GetSysCacheOid1(FOREIGNSERVERNAME, Anum_pg_foreign_server_oid,
696  CStringGetDatum(servername));
697  if (!OidIsValid(oid) && !missing_ok)
698  ereport(ERROR,
699  (errcode(ERRCODE_UNDEFINED_OBJECT),
700  errmsg("server \"%s\" does not exist", servername)));
701  return oid;
702 }
703 
704 /*
705  * Get a copy of an existing local path for a given join relation.
706  *
707  * This function is usually helpful to obtain an alternate local path for EPQ
708  * checks.
709  *
710  * Right now, this function only supports unparameterized foreign joins, so we
711  * only search for unparameterized path in the given list of paths. Since we
712  * are searching for a path which can be used to construct an alternative local
713  * plan for a foreign join, we look for only MergeJoin, HashJoin or NestLoop
714  * paths.
715  *
716  * If the inner or outer subpath of the chosen path is a ForeignScan, we
717  * replace it with its outer subpath. For this reason, and also because the
718  * planner might free the original path later, the path returned by this
719  * function is a shallow copy of the original. There's no need to copy
720  * the substructure, so we don't.
721  *
722  * Since the plan created using this path will presumably only be used to
723  * execute EPQ checks, efficiency of the path is not a concern. But since the
724  * path list in RelOptInfo is anyway sorted by total cost we are likely to
725  * choose the most efficient path, which is all for the best.
726  */
727 Path *
729 {
730  ListCell *lc;
731 
732  Assert(IS_JOIN_REL(joinrel));
733 
734  foreach(lc, joinrel->pathlist)
735  {
736  Path *path = (Path *) lfirst(lc);
737  JoinPath *joinpath = NULL;
738 
739  /* Skip parameterized paths. */
740  if (path->param_info != NULL)
741  continue;
742 
743  switch (path->pathtype)
744  {
745  case T_HashJoin:
746  {
747  HashPath *hash_path = makeNode(HashPath);
748 
749  memcpy(hash_path, path, sizeof(HashPath));
750  joinpath = (JoinPath *) hash_path;
751  }
752  break;
753 
754  case T_NestLoop:
755  {
756  NestPath *nest_path = makeNode(NestPath);
757 
758  memcpy(nest_path, path, sizeof(NestPath));
759  joinpath = (JoinPath *) nest_path;
760  }
761  break;
762 
763  case T_MergeJoin:
764  {
765  MergePath *merge_path = makeNode(MergePath);
766 
767  memcpy(merge_path, path, sizeof(MergePath));
768  joinpath = (JoinPath *) merge_path;
769  }
770  break;
771 
772  default:
773 
774  /*
775  * Just skip anything else. We don't know if corresponding
776  * plan would build the output row from whole-row references
777  * of base relations and execute the EPQ checks.
778  */
779  break;
780  }
781 
782  /* This path isn't good for us, check next. */
783  if (!joinpath)
784  continue;
785 
786  /*
787  * If either inner or outer path is a ForeignPath corresponding to a
788  * pushed down join, replace it with the fdw_outerpath, so that we
789  * maintain path for EPQ checks built entirely of local join
790  * strategies.
791  */
792  if (IsA(joinpath->outerjoinpath, ForeignPath))
793  {
794  ForeignPath *foreign_path;
795 
796  foreign_path = (ForeignPath *) joinpath->outerjoinpath;
797  if (IS_JOIN_REL(foreign_path->path.parent))
798  joinpath->outerjoinpath = foreign_path->fdw_outerpath;
799  }
800 
801  if (IsA(joinpath->innerjoinpath, ForeignPath))
802  {
803  ForeignPath *foreign_path;
804 
805  foreign_path = (ForeignPath *) joinpath->innerjoinpath;
806  if (IS_JOIN_REL(foreign_path->path.parent))
807  joinpath->innerjoinpath = foreign_path->fdw_outerpath;
808  }
809 
810  return (Path *) joinpath;
811  }
812  return NULL;
813 }
int16 AttrNumber
Definition: attnum.h:21
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define CStringGetTextDatum(s)
Definition: builtins.h:94
#define TextDatumGetCString(d)
Definition: builtins.h:95
#define NameStr(name)
Definition: c.h:735
uint16 bits16
Definition: c.h:503
#define OidIsValid(objectId)
Definition: c.h:764
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:588
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:728
Oid get_foreign_server_oid(const char *servername, bool missing_ok)
Definition: foreign.c:691
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:612
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:668
#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:296
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
#define stmt
Definition: indent_codes.h:59
struct parser_state match_state[5]
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
Assert(fmt[strlen(fmt) - 1] !='\n')
char * pstrdup(const char *in)
Definition: mcxt.c:1644
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1021
MemoryContext CacheMemoryContext
Definition: mcxt.c:144
void * palloc(Size size)
Definition: mcxt.c:1226
#define IsA(nodeptr, _type_)
Definition: nodes.h:179
#define makeNode(_type_)
Definition: nodes.h:176
@ FDW_IMPORT_SCHEMA_LIMIT_TO
Definition: parsenodes.h:2814
@ FDW_IMPORT_SCHEMA_ALL
Definition: parsenodes.h:2813
@ FDW_IMPORT_SCHEMA_EXCEPT
Definition: parsenodes.h:2815
#define IS_JOIN_REL(rel)
Definition: pathnodes.h:829
int16 attnum
Definition: pg_attribute.h:74
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:172
#define NIL
Definition: pg_list.h:68
static char ** options
FormData_pg_user_mapping * Form_pg_user_mapping
uintptr_t Datum
Definition: postgres.h:64
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:172
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationGetRelid(relation)
Definition: rel.h:504
List * untransformRelOptions(Datum options)
Definition: reloptions.c:1333
const char * optname
Definition: foreign.c:553
char * defname
Definition: parsenodes.h:809
Node * arg
Definition: parsenodes.h:810
char * fdwname
Definition: foreign.h:28
List * options
Definition: foreign.h:31
Path * fdw_outerpath
Definition: pathnodes.h:1838
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
Path * outerjoinpath
Definition: pathnodes.h:2042
Path * innerjoinpath
Definition: pathnodes.h:2043
Definition: pg_list.h:54
NodeTag pathtype
Definition: pathnodes.h:1594
char * relname
Definition: primnodes.h:74
List * pathlist
Definition: pathnodes.h:883
struct FdwRoutine * rd_fdwroutine
Definition: rel.h:239
TupleDesc setDesc
Definition: execnodes.h:334
Tuplestorestate * setResult
Definition: execnodes.h:333
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:868
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:820
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1081
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:831
@ 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:200
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:6201
void initClosestMatch(ClosestMatchState *state, const char *source, int max_d)
Definition: varlena.c:6146
void updateClosestMatch(ClosestMatchState *state, const char *candidate)
Definition: varlena.c:6166