PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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-2016, 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 "lib/stringinfo.h"
24 #include "miscadmin.h"
25 #include "utils/builtins.h"
26 #include "utils/memutils.h"
27 #include "utils/rel.h"
28 #include "utils/syscache.h"
29 
30 
33 
34 static HeapTuple find_user_mapping(Oid userid, Oid serverid, bool missing_ok);
35 
36 /*
37  * GetForeignDataWrapper - look up the foreign-data wrapper by OID.
38  */
41 {
43  ForeignDataWrapper *fdw;
44  Datum datum;
45  HeapTuple tp;
46  bool isnull;
47 
49 
50  if (!HeapTupleIsValid(tp))
51  elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid);
52 
54 
55  fdw = (ForeignDataWrapper *) palloc(sizeof(ForeignDataWrapper));
56  fdw->fdwid = fdwid;
57  fdw->owner = fdwform->fdwowner;
58  fdw->fdwname = pstrdup(NameStr(fdwform->fdwname));
59  fdw->fdwhandler = fdwform->fdwhandler;
60  fdw->fdwvalidator = fdwform->fdwvalidator;
61 
62  /* Extract the fdwoptions */
64  tp,
66  &isnull);
67  if (isnull)
68  fdw->options = NIL;
69  else
70  fdw->options = untransformRelOptions(datum);
71 
72  ReleaseSysCache(tp);
73 
74  return fdw;
75 }
76 
77 
78 /*
79  * GetForeignDataWrapperByName - look up the foreign-data wrapper
80  * definition by name.
81  */
83 GetForeignDataWrapperByName(const char *fdwname, bool missing_ok)
84 {
85  Oid fdwId = get_foreign_data_wrapper_oid(fdwname, missing_ok);
86 
87  if (!OidIsValid(fdwId))
88  return NULL;
89 
90  return GetForeignDataWrapper(fdwId);
91 }
92 
93 
94 /*
95  * GetForeignServer - look up the foreign server definition.
96  */
99 {
100  Form_pg_foreign_server serverform;
101  ForeignServer *server;
102  HeapTuple tp;
103  Datum datum;
104  bool isnull;
105 
107 
108  if (!HeapTupleIsValid(tp))
109  elog(ERROR, "cache lookup failed for foreign server %u", serverid);
110 
111  serverform = (Form_pg_foreign_server) GETSTRUCT(tp);
112 
113  server = (ForeignServer *) palloc(sizeof(ForeignServer));
114  server->serverid = serverid;
115  server->servername = pstrdup(NameStr(serverform->srvname));
116  server->owner = serverform->srvowner;
117  server->fdwid = serverform->srvfdw;
118 
119  /* Extract server type */
121  tp,
123  &isnull);
124  server->servertype = isnull ? NULL : TextDatumGetCString(datum);
125 
126  /* Extract server version */
128  tp,
130  &isnull);
131  server->serverversion = isnull ? NULL : TextDatumGetCString(datum);
132 
133  /* Extract the srvoptions */
135  tp,
137  &isnull);
138  if (isnull)
139  server->options = NIL;
140  else
141  server->options = untransformRelOptions(datum);
142 
143  ReleaseSysCache(tp);
144 
145  return server;
146 }
147 
148 
149 /*
150  * GetForeignServerByName - look up the foreign server definition by name.
151  */
153 GetForeignServerByName(const char *srvname, bool missing_ok)
154 {
155  Oid serverid = get_foreign_server_oid(srvname, missing_ok);
156 
157  if (!OidIsValid(serverid))
158  return NULL;
159 
160  return GetForeignServer(serverid);
161 }
162 
163 /*
164  * GetUserMappingById - look up the user mapping by its OID.
165  */
166 UserMapping *
168 {
169  Datum datum;
170  HeapTuple tp;
171  bool isnull;
172  UserMapping *um;
173 
175  if (!HeapTupleIsValid(tp))
176  elog(ERROR, "cache lookup failed for user mapping %u", umid);
177 
178  um = (UserMapping *) palloc(sizeof(UserMapping));
179  um->umid = umid;
180 
181  /* Extract the umuser */
183  tp,
185  &isnull);
186  Assert(!isnull);
187  um->userid = DatumGetObjectId(datum);
188 
189  /* Extract the umserver */
191  tp,
193  &isnull);
194  Assert(!isnull);
195  um->serverid = DatumGetObjectId(datum);
196 
197  /* Extract the umoptions */
199  tp,
201  &isnull);
202  if (isnull)
203  um->options = NIL;
204  else
205  um->options = untransformRelOptions(datum);
206 
207  ReleaseSysCache(tp);
208 
209  return um;
210 }
211 
212 /*
213  * GetUserMapping - look up the user mapping.
214  *
215  * If no mapping is found for the supplied user, we also look for
216  * PUBLIC mappings (userid == InvalidOid).
217  */
218 UserMapping *
219 GetUserMapping(Oid userid, Oid serverid)
220 {
221  Datum datum;
222  HeapTuple tp;
223  bool isnull;
224  UserMapping *um;
225 
226  tp = find_user_mapping(userid, serverid, false);
227 
228  um = (UserMapping *) palloc(sizeof(UserMapping));
229  um->umid = HeapTupleGetOid(tp);
230  um->userid = userid;
231  um->serverid = serverid;
232 
233  /* Extract the umoptions */
235  tp,
237  &isnull);
238  if (isnull)
239  um->options = NIL;
240  else
241  um->options = untransformRelOptions(datum);
242 
243  ReleaseSysCache(tp);
244 
245  return um;
246 }
247 
248 /*
249  * GetUserMappingId - look up the user mapping, and return its OID
250  *
251  * If no mapping is found for the supplied user, we also look for
252  * PUBLIC mappings (userid == InvalidOid).
253  *
254  * If missing_ok is true, the function returns InvalidOid when it does not find
255  * required user mapping. Otherwise, find_user_mapping() throws error if it
256  * does not find required user mapping.
257  */
258 Oid
259 GetUserMappingId(Oid userid, Oid serverid, bool missing_ok)
260 {
261  HeapTuple tp;
262  Oid umid;
263 
264  tp = find_user_mapping(userid, serverid, missing_ok);
265 
266  Assert(missing_ok || tp);
267 
268  if (!tp && missing_ok)
269  return InvalidOid;
270 
271  /* Extract the Oid */
272  umid = HeapTupleGetOid(tp);
273 
274  ReleaseSysCache(tp);
275 
276  return umid;
277 }
278 
279 
280 /*
281  * find_user_mapping - Guts of GetUserMapping family.
282  *
283  * If no mapping is found for the supplied user, we also look for
284  * PUBLIC mappings (userid == InvalidOid).
285  *
286  * If missing_ok is true, the function returns NULL, if it does not find
287  * the required user mapping. Otherwise, it throws error if it does not
288  * find the required user mapping.
289  */
290 static HeapTuple
291 find_user_mapping(Oid userid, Oid serverid, bool missing_ok)
292 {
293  HeapTuple tp;
294 
296  ObjectIdGetDatum(userid),
297  ObjectIdGetDatum(serverid));
298 
299  if (HeapTupleIsValid(tp))
300  return tp;
301 
302  /* Not found for the specific user -- try PUBLIC */
305  ObjectIdGetDatum(serverid));
306 
307  if (!HeapTupleIsValid(tp))
308  {
309  if (missing_ok)
310  return NULL;
311  else
312  ereport(ERROR,
313  (errcode(ERRCODE_UNDEFINED_OBJECT),
314  errmsg("user mapping not found for \"%s\"",
315  MappingUserName(userid))));
316  }
317 
318  return tp;
319 }
320 
321 
322 /*
323  * GetForeignTable - look up the foreign table definition by relation oid.
324  */
325 ForeignTable *
327 {
328  Form_pg_foreign_table tableform;
329  ForeignTable *ft;
330  HeapTuple tp;
331  Datum datum;
332  bool isnull;
333 
335  if (!HeapTupleIsValid(tp))
336  elog(ERROR, "cache lookup failed for foreign table %u", relid);
337  tableform = (Form_pg_foreign_table) GETSTRUCT(tp);
338 
339  ft = (ForeignTable *) palloc(sizeof(ForeignTable));
340  ft->relid = relid;
341  ft->serverid = tableform->ftserver;
342 
343  /* Extract the ftoptions */
345  tp,
347  &isnull);
348  if (isnull)
349  ft->options = NIL;
350  else
351  ft->options = untransformRelOptions(datum);
352 
353  ReleaseSysCache(tp);
354 
355  return ft;
356 }
357 
358 
359 /*
360  * GetForeignColumnOptions - Get attfdwoptions of given relation/attnum
361  * as list of DefElem.
362  */
363 List *
365 {
366  List *options;
367  HeapTuple tp;
368  Datum datum;
369  bool isnull;
370 
371  tp = SearchSysCache2(ATTNUM,
372  ObjectIdGetDatum(relid),
373  Int16GetDatum(attnum));
374  if (!HeapTupleIsValid(tp))
375  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
376  attnum, relid);
377  datum = SysCacheGetAttr(ATTNUM,
378  tp,
380  &isnull);
381  if (isnull)
382  options = NIL;
383  else
384  options = untransformRelOptions(datum);
385 
386  ReleaseSysCache(tp);
387 
388  return options;
389 }
390 
391 
392 /*
393  * GetFdwRoutine - call the specified foreign-data wrapper handler routine
394  * to get its FdwRoutine struct.
395  */
396 FdwRoutine *
397 GetFdwRoutine(Oid fdwhandler)
398 {
399  Datum datum;
400  FdwRoutine *routine;
401 
402  datum = OidFunctionCall0(fdwhandler);
403  routine = (FdwRoutine *) DatumGetPointer(datum);
404 
405  if (routine == NULL || !IsA(routine, FdwRoutine))
406  elog(ERROR, "foreign-data wrapper handler function %u did not return an FdwRoutine struct",
407  fdwhandler);
408 
409  return routine;
410 }
411 
412 
413 /*
414  * GetForeignServerIdByRelId - look up the foreign server
415  * for the given foreign table, and return its OID.
416  */
417 Oid
419 {
420  HeapTuple tp;
421  Form_pg_foreign_table tableform;
422  Oid serverid;
423 
425  if (!HeapTupleIsValid(tp))
426  elog(ERROR, "cache lookup failed for foreign table %u", relid);
427  tableform = (Form_pg_foreign_table) GETSTRUCT(tp);
428  serverid = tableform->ftserver;
429  ReleaseSysCache(tp);
430 
431  return serverid;
432 }
433 
434 
435 /*
436  * GetFdwRoutineByServerId - look up the handler of the foreign-data wrapper
437  * for the given foreign server, and retrieve its FdwRoutine struct.
438  */
439 FdwRoutine *
441 {
442  HeapTuple tp;
444  Form_pg_foreign_server serverform;
445  Oid fdwid;
446  Oid fdwhandler;
447 
448  /* Get foreign-data wrapper OID for the server. */
450  if (!HeapTupleIsValid(tp))
451  elog(ERROR, "cache lookup failed for foreign server %u", serverid);
452  serverform = (Form_pg_foreign_server) GETSTRUCT(tp);
453  fdwid = serverform->srvfdw;
454  ReleaseSysCache(tp);
455 
456  /* Get handler function OID for the FDW. */
458  if (!HeapTupleIsValid(tp))
459  elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid);
460  fdwform = (Form_pg_foreign_data_wrapper) GETSTRUCT(tp);
461  fdwhandler = fdwform->fdwhandler;
462 
463  /* Complain if FDW has been set to NO HANDLER. */
464  if (!OidIsValid(fdwhandler))
465  ereport(ERROR,
466  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
467  errmsg("foreign-data wrapper \"%s\" has no handler",
468  NameStr(fdwform->fdwname))));
469 
470  ReleaseSysCache(tp);
471 
472  /* And finally, call the handler function. */
473  return GetFdwRoutine(fdwhandler);
474 }
475 
476 
477 /*
478  * GetFdwRoutineByRelId - look up the handler of the foreign-data wrapper
479  * for the given foreign table, and retrieve its FdwRoutine struct.
480  */
481 FdwRoutine *
483 {
484  Oid serverid;
485 
486  /* Get server OID for the foreign table. */
487  serverid = GetForeignServerIdByRelId(relid);
488 
489  /* Now retrieve server's FdwRoutine struct. */
490  return GetFdwRoutineByServerId(serverid);
491 }
492 
493 /*
494  * GetFdwRoutineForRelation - look up the handler of the foreign-data wrapper
495  * for the given foreign table, and retrieve its FdwRoutine struct.
496  *
497  * This function is preferred over GetFdwRoutineByRelId because it caches
498  * the data in the relcache entry, saving a number of catalog lookups.
499  *
500  * If makecopy is true then the returned data is freshly palloc'd in the
501  * caller's memory context. Otherwise, it's a pointer to the relcache data,
502  * which will be lost in any relcache reset --- so don't rely on it long.
503  */
504 FdwRoutine *
505 GetFdwRoutineForRelation(Relation relation, bool makecopy)
506 {
507  FdwRoutine *fdwroutine;
508  FdwRoutine *cfdwroutine;
509 
510  if (relation->rd_fdwroutine == NULL)
511  {
512  /* Get the info by consulting the catalogs and the FDW code */
513  fdwroutine = GetFdwRoutineByRelId(RelationGetRelid(relation));
514 
515  /* Save the data for later reuse in CacheMemoryContext */
517  sizeof(FdwRoutine));
518  memcpy(cfdwroutine, fdwroutine, sizeof(FdwRoutine));
519  relation->rd_fdwroutine = cfdwroutine;
520 
521  /* Give back the locally palloc'd copy regardless of makecopy */
522  return fdwroutine;
523  }
524 
525  /* We have valid cached data --- does the caller want a copy? */
526  if (makecopy)
527  {
528  fdwroutine = (FdwRoutine *) palloc(sizeof(FdwRoutine));
529  memcpy(fdwroutine, relation->rd_fdwroutine, sizeof(FdwRoutine));
530  return fdwroutine;
531  }
532 
533  /* Only a short-lived reference is needed, so just hand back cached copy */
534  return relation->rd_fdwroutine;
535 }
536 
537 
538 /*
539  * IsImportableForeignTable - filter table names for IMPORT FOREIGN SCHEMA
540  *
541  * Returns TRUE if given table name should be imported according to the
542  * statement's import filter options.
543  */
544 bool
545 IsImportableForeignTable(const char *tablename,
547 {
548  ListCell *lc;
549 
550  switch (stmt->list_type)
551  {
553  return true;
554 
556  foreach(lc, stmt->table_list)
557  {
558  RangeVar *rv = (RangeVar *) lfirst(lc);
559 
560  if (strcmp(tablename, rv->relname) == 0)
561  return true;
562  }
563  return false;
564 
566  foreach(lc, stmt->table_list)
567  {
568  RangeVar *rv = (RangeVar *) lfirst(lc);
569 
570  if (strcmp(tablename, rv->relname) == 0)
571  return false;
572  }
573  return true;
574  }
575  return false; /* shouldn't get here */
576 }
577 
578 
579 /*
580  * deflist_to_tuplestore - Helper function to convert DefElem list to
581  * tuplestore usable in SRF.
582  */
583 static void
585 {
586  ListCell *cell;
587  TupleDesc tupdesc;
588  Tuplestorestate *tupstore;
589  Datum values[2];
590  bool nulls[2];
591  MemoryContext per_query_ctx;
592  MemoryContext oldcontext;
593 
594  /* check to see if caller supports us returning a tuplestore */
595  if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
596  ereport(ERROR,
597  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
598  errmsg("set-valued function called in context that cannot accept a set")));
599  if (!(rsinfo->allowedModes & SFRM_Materialize) ||
600  rsinfo->expectedDesc == NULL)
601  ereport(ERROR,
602  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
603  errmsg("materialize mode required, but it is not allowed in this context")));
604 
605  per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
606  oldcontext = MemoryContextSwitchTo(per_query_ctx);
607 
608  /*
609  * Now prepare the result set.
610  */
611  tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc);
612  tupstore = tuplestore_begin_heap(true, false, work_mem);
613  rsinfo->returnMode = SFRM_Materialize;
614  rsinfo->setResult = tupstore;
615  rsinfo->setDesc = tupdesc;
616 
617  foreach(cell, options)
618  {
619  DefElem *def = lfirst(cell);
620 
621  values[0] = CStringGetTextDatum(def->defname);
622  nulls[0] = false;
623  if (def->arg)
624  {
625  values[1] = CStringGetTextDatum(((Value *) (def->arg))->val.str);
626  nulls[1] = false;
627  }
628  else
629  {
630  values[1] = (Datum) 0;
631  nulls[1] = true;
632  }
633  tuplestore_putvalues(tupstore, tupdesc, values, nulls);
634  }
635 
636  /* clean up and return the tuplestore */
637  tuplestore_donestoring(tupstore);
638 
639  MemoryContextSwitchTo(oldcontext);
640 }
641 
642 
643 /*
644  * Convert options array to name/value table. Useful for information
645  * schema and pg_dump.
646  */
647 Datum
649 {
650  Datum array = PG_GETARG_DATUM(0);
651 
652  deflist_to_tuplestore((ReturnSetInfo *) fcinfo->resultinfo,
653  untransformRelOptions(array));
654 
655  return (Datum) 0;
656 }
657 
658 
659 /*
660  * Describes the valid options for postgresql FDW, server, and user mapping.
661  */
663 {
664  const char *optname;
665  Oid optcontext; /* Oid of catalog in which option may appear */
666 };
667 
668 /*
669  * Copied from fe-connect.c PQconninfoOptions.
670  *
671  * The list is small - don't bother with bsearch if it stays so.
672  */
674  {"authtype", ForeignServerRelationId},
675  {"service", ForeignServerRelationId},
676  {"user", UserMappingRelationId},
677  {"password", UserMappingRelationId},
678  {"connect_timeout", ForeignServerRelationId},
679  {"dbname", ForeignServerRelationId},
680  {"host", ForeignServerRelationId},
681  {"hostaddr", ForeignServerRelationId},
682  {"port", ForeignServerRelationId},
683  {"tty", ForeignServerRelationId},
684  {"options", ForeignServerRelationId},
685  {"requiressl", ForeignServerRelationId},
686  {"sslmode", ForeignServerRelationId},
687  {"gsslib", ForeignServerRelationId},
688  {NULL, InvalidOid}
689 };
690 
691 
692 /*
693  * Check if the provided option is one of libpq conninfo options.
694  * context is the Oid of the catalog the option came from, or 0 if we
695  * don't care.
696  */
697 static bool
698 is_conninfo_option(const char *option, Oid context)
699 {
700  struct ConnectionOption *opt;
701 
702  for (opt = libpq_conninfo_options; opt->optname; opt++)
703  if (context == opt->optcontext && strcmp(opt->optname, option) == 0)
704  return true;
705  return false;
706 }
707 
708 
709 /*
710  * Validate the generic option given to SERVER or USER MAPPING.
711  * Raise an ERROR if the option or its value is considered invalid.
712  *
713  * Valid server options are all libpq conninfo options except
714  * user and password -- these may only appear in USER MAPPING options.
715  *
716  * Caution: this function is deprecated, and is now meant only for testing
717  * purposes, because the list of options it knows about doesn't necessarily
718  * square with those known to whichever libpq instance you might be using.
719  * Inquire of libpq itself, instead.
720  */
721 Datum
723 {
724  List *options_list = untransformRelOptions(PG_GETARG_DATUM(0));
725  Oid catalog = PG_GETARG_OID(1);
726 
727  ListCell *cell;
728 
729  foreach(cell, options_list)
730  {
731  DefElem *def = lfirst(cell);
732 
733  if (!is_conninfo_option(def->defname, catalog))
734  {
735  struct ConnectionOption *opt;
737 
738  /*
739  * Unknown option specified, complain about it. Provide a hint
740  * with list of valid options for the object.
741  */
742  initStringInfo(&buf);
743  for (opt = libpq_conninfo_options; opt->optname; opt++)
744  if (catalog == opt->optcontext)
745  appendStringInfo(&buf, "%s%s", (buf.len > 0) ? ", " : "",
746  opt->optname);
747 
748  ereport(ERROR,
749  (errcode(ERRCODE_SYNTAX_ERROR),
750  errmsg("invalid option \"%s\"", def->defname),
751  errhint("Valid options in this context are: %s",
752  buf.data)));
753 
754  PG_RETURN_BOOL(false);
755  }
756  }
757 
758  PG_RETURN_BOOL(true);
759 }
760 
761 
762 /*
763  * get_foreign_data_wrapper_oid - given a FDW name, look up the OID
764  *
765  * If missing_ok is false, throw an error if name not found. If true, just
766  * return InvalidOid.
767  */
768 Oid
769 get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
770 {
771  Oid oid;
772 
774  if (!OidIsValid(oid) && !missing_ok)
775  ereport(ERROR,
776  (errcode(ERRCODE_UNDEFINED_OBJECT),
777  errmsg("foreign-data wrapper \"%s\" does not exist",
778  fdwname)));
779  return oid;
780 }
781 
782 
783 /*
784  * get_foreign_server_oid - given a server name, look up the OID
785  *
786  * If missing_ok is false, throw an error if name not found. If true, just
787  * return InvalidOid.
788  */
789 Oid
790 get_foreign_server_oid(const char *servername, bool missing_ok)
791 {
792  Oid oid;
793 
795  if (!OidIsValid(oid) && !missing_ok)
796  ereport(ERROR,
797  (errcode(ERRCODE_UNDEFINED_OBJECT),
798  errmsg("server \"%s\" does not exist", servername)));
799  return oid;
800 }
801 
802 /*
803  * Get a copy of an existing local path for a given join relation.
804  *
805  * This function is usually helpful to obtain an alternate local path for EPQ
806  * checks.
807  *
808  * Right now, this function only supports unparameterized foreign joins, so we
809  * only search for unparameterized path in the given list of paths. Since we
810  * are searching for a path which can be used to construct an alternative local
811  * plan for a foreign join, we look for only MergeJoin, HashJoin or NestLoop
812  * paths.
813  *
814  * If the inner or outer subpath of the chosen path is a ForeignScan, we
815  * replace it with its outer subpath. For this reason, and also because the
816  * planner might free the original path later, the path returned by this
817  * function is a shallow copy of the original. There's no need to copy
818  * the substructure, so we don't.
819  *
820  * Since the plan created using this path will presumably only be used to
821  * execute EPQ checks, efficiency of the path is not a concern. But since the
822  * path list in RelOptInfo is anyway sorted by total cost we are likely to
823  * choose the most efficient path, which is all for the best.
824  */
825 extern Path *
827 {
828  ListCell *lc;
829 
830  Assert(joinrel->reloptkind == RELOPT_JOINREL);
831 
832  foreach(lc, joinrel->pathlist)
833  {
834  Path *path = (Path *) lfirst(lc);
835  JoinPath *joinpath = NULL;
836 
837  /* Skip parameterised paths. */
838  if (path->param_info != NULL)
839  continue;
840 
841  switch (path->pathtype)
842  {
843  case T_HashJoin:
844  {
845  HashPath *hash_path = makeNode(HashPath);
846 
847  memcpy(hash_path, path, sizeof(HashPath));
848  joinpath = (JoinPath *) hash_path;
849  }
850  break;
851 
852  case T_NestLoop:
853  {
854  NestPath *nest_path = makeNode(NestPath);
855 
856  memcpy(nest_path, path, sizeof(NestPath));
857  joinpath = (JoinPath *) nest_path;
858  }
859  break;
860 
861  case T_MergeJoin:
862  {
863  MergePath *merge_path = makeNode(MergePath);
864 
865  memcpy(merge_path, path, sizeof(MergePath));
866  joinpath = (JoinPath *) merge_path;
867  }
868  break;
869 
870  default:
871 
872  /*
873  * Just skip anything else. We don't know if corresponding
874  * plan would build the output row from whole-row references
875  * of base relations and execute the EPQ checks.
876  */
877  break;
878  }
879 
880  /* This path isn't good for us, check next. */
881  if (!joinpath)
882  continue;
883 
884  /*
885  * If either inner or outer path is a ForeignPath corresponding to a
886  * pushed down join, replace it with the fdw_outerpath, so that we
887  * maintain path for EPQ checks built entirely of local join
888  * strategies.
889  */
890  if (IsA(joinpath->outerjoinpath, ForeignPath))
891  {
892  ForeignPath *foreign_path;
893 
894  foreign_path = (ForeignPath *) joinpath->outerjoinpath;
895  if (foreign_path->path.parent->reloptkind == RELOPT_JOINREL)
896  joinpath->outerjoinpath = foreign_path->fdw_outerpath;
897  }
898 
899  if (IsA(joinpath->innerjoinpath, ForeignPath))
900  {
901  ForeignPath *foreign_path;
902 
903  foreign_path = (ForeignPath *) joinpath->innerjoinpath;
904  if (foreign_path->path.parent->reloptkind == RELOPT_JOINREL)
905  joinpath->innerjoinpath = foreign_path->fdw_outerpath;
906  }
907 
908  return (Path *) joinpath;
909  }
910  return NULL;
911 }
struct FdwRoutine * rd_fdwroutine
Definition: rel.h:159
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, Datum *values, bool *isnull)
Definition: tuplestore.c:735
Oid umid
Definition: foreign.h:58
#define NIL
Definition: pg_list.h:69
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:140
#define IsA(nodeptr, _type_)
Definition: nodes.h:542
Oid GetUserMappingId(Oid userid, Oid serverid, bool missing_ok)
Definition: foreign.c:259
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:631
Path * fdw_outerpath
Definition: relation.h:1045
RelOptKind reloptkind
Definition: relation.h:478
static bool is_conninfo_option(const char *option, Oid context)
Definition: foreign.c:698
#define Anum_pg_user_mapping_umuser
#define Anum_pg_user_mapping_umserver
#define Anum_pg_foreign_server_srvversion
char * fdwname
Definition: foreign.h:39
Path * innerjoinpath
Definition: relation.h:1189
static HeapTuple find_user_mapping(Oid userid, Oid serverid, bool missing_ok)
Definition: foreign.c:291
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
#define DatumGetObjectId(X)
Definition: postgres.h:508
char * pstrdup(const char *in)
Definition: mcxt.c:1168
char * serverversion
Definition: foreign.h:52
#define tuplestore_donestoring(state)
Definition: tuplestore.h:60
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define Int16GetDatum(X)
Definition: postgres.h:459
ParamPathInfo * param_info
Definition: relation.h:871
FdwRoutine * GetFdwRoutineByServerId(Oid serverid)
Definition: foreign.c:440
int errcode(int sqlerrcode)
Definition: elog.c:575
ForeignTable * GetForeignTable(Oid relid)
Definition: foreign.c:326
unsigned int Oid
Definition: postgres_ext.h:31
Datum pg_options_to_table(PG_FUNCTION_ARGS)
Definition: foreign.c:648
#define OidIsValid(objectId)
Definition: c.h:530
Oid userid
Definition: foreign.h:59
static void deflist_to_tuplestore(ReturnSetInfo *rsinfo, List *options)
Definition: foreign.c:584
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:141
#define GetSysCacheOid1(cacheId, key1)
Definition: syscache.h:168
NodeTag pathtype
Definition: relation.h:866
FdwRoutine * GetFdwRoutine(Oid fdwhandler)
Definition: foreign.c:397
char * relname
Definition: primnodes.h:74
char * servertype
Definition: foreign.h:51
Oid get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
Definition: foreign.c:769
TupleDesc expectedDesc
Definition: execnodes.h:191
ForeignDataWrapper * GetForeignDataWrapper(Oid fdwid)
Definition: foreign.c:40
List * GetForeignColumnOptions(Oid relid, AttrNumber attnum)
Definition: foreign.c:364
FormData_pg_foreign_table * Form_pg_foreign_table
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define Anum_pg_user_mapping_umoptions
RelOptInfo * parent
Definition: relation.h:868
Oid relid
Definition: foreign.h:66
bool IsImportableForeignTable(const char *tablename, ImportForeignSchemaStmt *stmt)
Definition: foreign.c:545
static char * buf
Definition: pg_test_fsync.c:65
#define PG_GETARG_OID(n)
Definition: fmgr.h:231
#define CStringGetDatum(X)
Definition: postgres.h:586
List * options
Definition: foreign.h:61
ForeignServer * GetForeignServerByName(const char *srvname, bool missing_ok)
Definition: foreign.c:153
#define ereport(elevel, rest)
Definition: elog.h:122
Node * arg
Definition: parsenodes.h:666
static char ** options
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
List * options
Definition: foreign.h:42
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:316
Path * outerjoinpath
Definition: relation.h:1188
#define TextDatumGetCString(d)
Definition: builtins.h:807
#define Anum_pg_foreign_table_ftoptions
ForeignServer * GetForeignServer(Oid serverid)
Definition: foreign.c:98
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:303
uintptr_t Datum
Definition: postgres.h:374
FdwRoutine * GetFdwRoutineByRelId(Oid relid)
Definition: foreign.c:482
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:990
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1152
int work_mem
Definition: globals.c:110
List * untransformRelOptions(Datum options)
Definition: reloptions.c:856
FormData_pg_foreign_server * Form_pg_foreign_server
#define InvalidOid
Definition: postgres_ext.h:36
int allowedModes
Definition: execnodes.h:192
SetFunctionReturnMode returnMode
Definition: execnodes.h:194
#define OidFunctionCall0(functionId)
Definition: fmgr.h:584
#define ForeignServerRelationId
#define makeNode(_type_)
Definition: nodes.h:539
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:667
#define lfirst(lc)
Definition: pg_list.h:106
Definition: value.h:42
FormData_pg_foreign_data_wrapper * Form_pg_foreign_data_wrapper
ForeignDataWrapper * GetForeignDataWrapperByName(const char *fdwname, bool missing_ok)
Definition: foreign.c:83
Path * GetExistingLocalJoinPath(RelOptInfo *joinrel)
Definition: foreign.c:826
const char * optname
Definition: foreign.c:664
Oid GetForeignServerIdByRelId(Oid relid)
Definition: foreign.c:418
Oid serverid
Definition: foreign.h:67
Oid serverid
Definition: foreign.h:60
#define Anum_pg_foreign_server_srvtype
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:127
#define Anum_pg_attribute_attfdwoptions
Definition: pg_attribute.h:212
Tuplestorestate * setResult
Definition: execnodes.h:197
#define DatumGetPointer(X)
Definition: postgres.h:557
static Datum values[MAXATTR]
Definition: bootstrap.c:160
List * options
Definition: foreign.h:68
ExprContext * econtext
Definition: execnodes.h:190
TupleDesc setDesc
Definition: execnodes.h:198
void * palloc(Size size)
Definition: mcxt.c:894
int errmsg(const char *fmt,...)
Definition: elog.c:797
FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)
Definition: foreign.c:505
#define UserMappingRelationId
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:752
char * servername
Definition: foreign.h:50
UserMapping * GetUserMappingById(Oid umid)
Definition: foreign.c:167
#define NameStr(name)
Definition: c.h:494
UserMapping * GetUserMapping(Oid userid, Oid serverid)
Definition: foreign.c:219
#define CStringGetTextDatum(s)
Definition: builtins.h:806
Datum postgresql_fdw_validator(PG_FUNCTION_ARGS)
Definition: foreign.c:722
#define PG_FUNCTION_ARGS
Definition: fmgr.h:150
char * defname
Definition: parsenodes.h:665
List * pathlist
Definition: relation.h:495
#define elog
Definition: elog.h:218
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:670
#define Anum_pg_foreign_server_srvoptions
Definition: pg_list.h:45
#define Anum_pg_foreign_data_wrapper_fdwoptions
List * options
Definition: foreign.h:53
int16 AttrNumber
Definition: attnum.h:21
#define RelationGetRelid(relation)
Definition: rel.h:341
Oid serverid
Definition: foreign.h:47
static struct ConnectionOption libpq_conninfo_options[]
Definition: foreign.c:673
Oid get_foreign_server_oid(const char *servername, bool missing_ok)
Definition: foreign.c:790
Definition: relation.h:862
#define MappingUserName(userid)
Definition: foreign.h:20
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
ImportForeignSchemaType list_type
Definition: parsenodes.h:2040
#define SearchSysCache2(cacheId, key1, key2)
Definition: syscache.h:143