PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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-2024, 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 "miscadmin.h"
25#include "tcop/tcopprot.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{
53 Datum datum;
54 HeapTuple tp;
55 bool isnull;
56
57 tp = SearchSysCache1(FOREIGNDATAWRAPPEROID, ObjectIdGetDatum(fdwid));
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
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 */
76 datum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID,
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
86
87 return fdw;
88}
89
90
91/*
92 * GetForeignDataWrapperByName - look up the foreign-data wrapper
93 * definition by name.
94 */
96GetForeignDataWrapperByName(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
131 tp = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(serverid));
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 */
149 datum = SysCacheGetAttr(FOREIGNSERVEROID,
150 tp,
151 Anum_pg_foreign_server_srvtype,
152 &isnull);
153 server->servertype = isnull ? NULL : TextDatumGetCString(datum);
154
155 /* Extract server version */
156 datum = SysCacheGetAttr(FOREIGNSERVEROID,
157 tp,
158 Anum_pg_foreign_server_srvversion,
159 &isnull);
160 server->serverversion = isnull ? NULL : TextDatumGetCString(datum);
161
162 /* Extract the srvoptions */
163 datum = SysCacheGetAttr(FOREIGNSERVEROID,
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 */
182GetForeignServerByName(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 */
200GetUserMapping(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 {
221 ForeignServer *server = GetForeignServer(serverid);
222
224 (errcode(ERRCODE_UNDEFINED_OBJECT),
225 errmsg("user mapping not found for user \"%s\", server \"%s\"",
226 MappingUserName(userid), server->servername)));
227 }
228
229 um = (UserMapping *) palloc(sizeof(UserMapping));
230 um->umid = ((Form_pg_user_mapping) GETSTRUCT(tp))->oid;
231 um->userid = userid;
232 um->serverid = serverid;
233
234 /* Extract the umoptions */
235 datum = SysCacheGetAttr(USERMAPPINGUSERSERVER,
236 tp,
237 Anum_pg_user_mapping_umoptions,
238 &isnull);
239 if (isnull)
240 um->options = NIL;
241 else
242 um->options = untransformRelOptions(datum);
243
244 ReleaseSysCache(tp);
245
246 return um;
247}
248
249
250/*
251 * GetForeignTable - look up the foreign table definition by relation oid.
252 */
255{
256 Form_pg_foreign_table tableform;
257 ForeignTable *ft;
258 HeapTuple tp;
259 Datum datum;
260 bool isnull;
261
262 tp = SearchSysCache1(FOREIGNTABLEREL, ObjectIdGetDatum(relid));
263 if (!HeapTupleIsValid(tp))
264 elog(ERROR, "cache lookup failed for foreign table %u", relid);
265 tableform = (Form_pg_foreign_table) GETSTRUCT(tp);
266
267 ft = (ForeignTable *) palloc(sizeof(ForeignTable));
268 ft->relid = relid;
269 ft->serverid = tableform->ftserver;
270
271 /* Extract the ftoptions */
272 datum = SysCacheGetAttr(FOREIGNTABLEREL,
273 tp,
274 Anum_pg_foreign_table_ftoptions,
275 &isnull);
276 if (isnull)
277 ft->options = NIL;
278 else
279 ft->options = untransformRelOptions(datum);
280
281 ReleaseSysCache(tp);
282
283 return ft;
284}
285
286
287/*
288 * GetForeignColumnOptions - Get attfdwoptions of given relation/attnum
289 * as list of DefElem.
290 */
291List *
293{
294 List *options;
295 HeapTuple tp;
296 Datum datum;
297 bool isnull;
298
299 tp = SearchSysCache2(ATTNUM,
300 ObjectIdGetDatum(relid),
302 if (!HeapTupleIsValid(tp))
303 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
304 attnum, relid);
305 datum = SysCacheGetAttr(ATTNUM,
306 tp,
307 Anum_pg_attribute_attfdwoptions,
308 &isnull);
309 if (isnull)
310 options = NIL;
311 else
313
314 ReleaseSysCache(tp);
315
316 return options;
317}
318
319
320/*
321 * GetFdwRoutine - call the specified foreign-data wrapper handler routine
322 * to get its FdwRoutine struct.
323 */
326{
327 Datum datum;
328 FdwRoutine *routine;
329
330 /* Check if the access to foreign tables is restricted */
332 {
333 /* there must not be built-in FDW handler */
335 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
336 errmsg("access to non-system foreign table is restricted")));
337 }
338
339 datum = OidFunctionCall0(fdwhandler);
340 routine = (FdwRoutine *) DatumGetPointer(datum);
341
342 if (routine == NULL || !IsA(routine, FdwRoutine))
343 elog(ERROR, "foreign-data wrapper handler function %u did not return an FdwRoutine struct",
344 fdwhandler);
345
346 return routine;
347}
348
349
350/*
351 * GetForeignServerIdByRelId - look up the foreign server
352 * for the given foreign table, and return its OID.
353 */
354Oid
356{
357 HeapTuple tp;
358 Form_pg_foreign_table tableform;
359 Oid serverid;
360
361 tp = SearchSysCache1(FOREIGNTABLEREL, ObjectIdGetDatum(relid));
362 if (!HeapTupleIsValid(tp))
363 elog(ERROR, "cache lookup failed for foreign table %u", relid);
364 tableform = (Form_pg_foreign_table) GETSTRUCT(tp);
365 serverid = tableform->ftserver;
366 ReleaseSysCache(tp);
367
368 return serverid;
369}
370
371
372/*
373 * GetFdwRoutineByServerId - look up the handler of the foreign-data wrapper
374 * for the given foreign server, and retrieve its FdwRoutine struct.
375 */
378{
379 HeapTuple tp;
381 Form_pg_foreign_server serverform;
382 Oid fdwid;
383 Oid fdwhandler;
384
385 /* Get foreign-data wrapper OID for the server. */
386 tp = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(serverid));
387 if (!HeapTupleIsValid(tp))
388 elog(ERROR, "cache lookup failed for foreign server %u", serverid);
389 serverform = (Form_pg_foreign_server) GETSTRUCT(tp);
390 fdwid = serverform->srvfdw;
391 ReleaseSysCache(tp);
392
393 /* Get handler function OID for the FDW. */
394 tp = SearchSysCache1(FOREIGNDATAWRAPPEROID, ObjectIdGetDatum(fdwid));
395 if (!HeapTupleIsValid(tp))
396 elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid);
398 fdwhandler = fdwform->fdwhandler;
399
400 /* Complain if FDW has been set to NO HANDLER. */
401 if (!OidIsValid(fdwhandler))
403 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
404 errmsg("foreign-data wrapper \"%s\" has no handler",
405 NameStr(fdwform->fdwname))));
406
407 ReleaseSysCache(tp);
408
409 /* And finally, call the handler function. */
410 return GetFdwRoutine(fdwhandler);
411}
412
413
414/*
415 * GetFdwRoutineByRelId - look up the handler of the foreign-data wrapper
416 * for the given foreign table, and retrieve its FdwRoutine struct.
417 */
420{
421 Oid serverid;
422
423 /* Get server OID for the foreign table. */
424 serverid = GetForeignServerIdByRelId(relid);
425
426 /* Now retrieve server's FdwRoutine struct. */
427 return GetFdwRoutineByServerId(serverid);
428}
429
430/*
431 * GetFdwRoutineForRelation - look up the handler of the foreign-data wrapper
432 * for the given foreign table, and retrieve its FdwRoutine struct.
433 *
434 * This function is preferred over GetFdwRoutineByRelId because it caches
435 * the data in the relcache entry, saving a number of catalog lookups.
436 *
437 * If makecopy is true then the returned data is freshly palloc'd in the
438 * caller's memory context. Otherwise, it's a pointer to the relcache data,
439 * which will be lost in any relcache reset --- so don't rely on it long.
440 */
442GetFdwRoutineForRelation(Relation relation, bool makecopy)
443{
444 FdwRoutine *fdwroutine;
445 FdwRoutine *cfdwroutine;
446
447 if (relation->rd_fdwroutine == NULL)
448 {
449 /* Get the info by consulting the catalogs and the FDW code */
450 fdwroutine = GetFdwRoutineByRelId(RelationGetRelid(relation));
451
452 /* Save the data for later reuse in CacheMemoryContext */
454 sizeof(FdwRoutine));
455 memcpy(cfdwroutine, fdwroutine, sizeof(FdwRoutine));
456 relation->rd_fdwroutine = cfdwroutine;
457
458 /* Give back the locally palloc'd copy regardless of makecopy */
459 return fdwroutine;
460 }
461
462 /* We have valid cached data --- does the caller want a copy? */
463 if (makecopy)
464 {
465 fdwroutine = (FdwRoutine *) palloc(sizeof(FdwRoutine));
466 memcpy(fdwroutine, relation->rd_fdwroutine, sizeof(FdwRoutine));
467 return fdwroutine;
468 }
469
470 /* Only a short-lived reference is needed, so just hand back cached copy */
471 return relation->rd_fdwroutine;
472}
473
474
475/*
476 * IsImportableForeignTable - filter table names for IMPORT FOREIGN SCHEMA
477 *
478 * Returns true if given table name should be imported according to the
479 * statement's import filter options.
480 */
481bool
482IsImportableForeignTable(const char *tablename,
484{
485 ListCell *lc;
486
487 switch (stmt->list_type)
488 {
490 return true;
491
493 foreach(lc, stmt->table_list)
494 {
495 RangeVar *rv = (RangeVar *) lfirst(lc);
496
497 if (strcmp(tablename, rv->relname) == 0)
498 return true;
499 }
500 return false;
501
503 foreach(lc, stmt->table_list)
504 {
505 RangeVar *rv = (RangeVar *) lfirst(lc);
506
507 if (strcmp(tablename, rv->relname) == 0)
508 return false;
509 }
510 return true;
511 }
512 return false; /* shouldn't get here */
513}
514
515
516/*
517 * pg_options_to_table - Convert options array to name/value table
518 *
519 * This is useful to provide details for information_schema and pg_dump.
520 */
521Datum
523{
524 Datum array = PG_GETARG_DATUM(0);
525 ListCell *cell;
526 List *options;
527 ReturnSetInfo *rsinfo;
528
530 rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
531
532 /* prepare the result set */
534
535 foreach(cell, options)
536 {
537 DefElem *def = lfirst(cell);
538 Datum values[2];
539 bool nulls[2];
540
542 nulls[0] = false;
543 if (def->arg)
544 {
546 nulls[1] = false;
547 }
548 else
549 {
550 values[1] = (Datum) 0;
551 nulls[1] = true;
552 }
553 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
554 values, nulls);
555 }
556
557 return (Datum) 0;
558}
559
560
561/*
562 * Describes the valid options for postgresql FDW, server, and user mapping.
563 */
565{
566 const char *optname;
567 Oid optcontext; /* Oid of catalog in which option may appear */
568};
569
570/*
571 * Copied from fe-connect.c PQconninfoOptions.
572 *
573 * The list is small - don't bother with bsearch if it stays so.
574 */
576 {"authtype", ForeignServerRelationId},
577 {"service", ForeignServerRelationId},
578 {"user", UserMappingRelationId},
579 {"password", UserMappingRelationId},
580 {"connect_timeout", ForeignServerRelationId},
581 {"dbname", ForeignServerRelationId},
582 {"host", ForeignServerRelationId},
583 {"hostaddr", ForeignServerRelationId},
584 {"port", ForeignServerRelationId},
585 {"tty", ForeignServerRelationId},
586 {"options", ForeignServerRelationId},
587 {"requiressl", ForeignServerRelationId},
588 {"sslmode", ForeignServerRelationId},
589 {"gsslib", ForeignServerRelationId},
590 {"gssdelegation", ForeignServerRelationId},
591 {NULL, InvalidOid}
592};
593
594
595/*
596 * Check if the provided option is one of libpq conninfo options.
597 * context is the Oid of the catalog the option came from, or 0 if we
598 * don't care.
599 */
600static bool
602{
603 const struct ConnectionOption *opt;
604
605 for (opt = libpq_conninfo_options; opt->optname; opt++)
606 if (context == opt->optcontext && strcmp(opt->optname, option) == 0)
607 return true;
608 return false;
609}
610
611
612/*
613 * Validate the generic option given to SERVER or USER MAPPING.
614 * Raise an ERROR if the option or its value is considered invalid.
615 *
616 * Valid server options are all libpq conninfo options except
617 * user and password -- these may only appear in USER MAPPING options.
618 *
619 * Caution: this function is deprecated, and is now meant only for testing
620 * purposes, because the list of options it knows about doesn't necessarily
621 * square with those known to whichever libpq instance you might be using.
622 * Inquire of libpq itself, instead.
623 */
624Datum
626{
627 List *options_list = untransformRelOptions(PG_GETARG_DATUM(0));
628 Oid catalog = PG_GETARG_OID(1);
629
630 ListCell *cell;
631
632 foreach(cell, options_list)
633 {
634 DefElem *def = lfirst(cell);
635
636 if (!is_conninfo_option(def->defname, catalog))
637 {
638 const struct ConnectionOption *opt;
639 const char *closest_match;
641 bool has_valid_options = false;
642
643 /*
644 * Unknown option specified, complain about it. Provide a hint
645 * with a valid option that looks similar, if there is one.
646 */
648 for (opt = libpq_conninfo_options; opt->optname; opt++)
649 {
650 if (catalog == opt->optcontext)
651 {
652 has_valid_options = true;
654 }
655 }
656
657 closest_match = getClosestMatch(&match_state);
659 (errcode(ERRCODE_SYNTAX_ERROR),
660 errmsg("invalid option \"%s\"", def->defname),
661 has_valid_options ? closest_match ?
662 errhint("Perhaps you meant the option \"%s\".",
663 closest_match) : 0 :
664 errhint("There are no valid options in this context.")));
665
666 PG_RETURN_BOOL(false);
667 }
668 }
669
670 PG_RETURN_BOOL(true);
671}
672
673
674/*
675 * get_foreign_data_wrapper_oid - given a FDW name, look up the OID
676 *
677 * If missing_ok is false, throw an error if name not found. If true, just
678 * return InvalidOid.
679 */
680Oid
681get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
682{
683 Oid oid;
684
685 oid = GetSysCacheOid1(FOREIGNDATAWRAPPERNAME,
686 Anum_pg_foreign_data_wrapper_oid,
687 CStringGetDatum(fdwname));
688 if (!OidIsValid(oid) && !missing_ok)
690 (errcode(ERRCODE_UNDEFINED_OBJECT),
691 errmsg("foreign-data wrapper \"%s\" does not exist",
692 fdwname)));
693 return oid;
694}
695
696
697/*
698 * get_foreign_server_oid - given a server name, look up the OID
699 *
700 * If missing_ok is false, throw an error if name not found. If true, just
701 * return InvalidOid.
702 */
703Oid
704get_foreign_server_oid(const char *servername, bool missing_ok)
705{
706 Oid oid;
707
708 oid = GetSysCacheOid1(FOREIGNSERVERNAME, Anum_pg_foreign_server_oid,
709 CStringGetDatum(servername));
710 if (!OidIsValid(oid) && !missing_ok)
712 (errcode(ERRCODE_UNDEFINED_OBJECT),
713 errmsg("server \"%s\" does not exist", servername)));
714 return oid;
715}
716
717/*
718 * Get a copy of an existing local path for a given join relation.
719 *
720 * This function is usually helpful to obtain an alternate local path for EPQ
721 * checks.
722 *
723 * Right now, this function only supports unparameterized foreign joins, so we
724 * only search for unparameterized path in the given list of paths. Since we
725 * are searching for a path which can be used to construct an alternative local
726 * plan for a foreign join, we look for only MergeJoin, HashJoin or NestLoop
727 * paths.
728 *
729 * If the inner or outer subpath of the chosen path is a ForeignScan, we
730 * replace it with its outer subpath. For this reason, and also because the
731 * planner might free the original path later, the path returned by this
732 * function is a shallow copy of the original. There's no need to copy
733 * the substructure, so we don't.
734 *
735 * Since the plan created using this path will presumably only be used to
736 * execute EPQ checks, efficiency of the path is not a concern. But since the
737 * path list in RelOptInfo is anyway sorted by total cost we are likely to
738 * choose the most efficient path, which is all for the best.
739 */
740Path *
742{
743 ListCell *lc;
744
745 Assert(IS_JOIN_REL(joinrel));
746
747 foreach(lc, joinrel->pathlist)
748 {
749 Path *path = (Path *) lfirst(lc);
750 JoinPath *joinpath = NULL;
751
752 /* Skip parameterized paths. */
753 if (path->param_info != NULL)
754 continue;
755
756 switch (path->pathtype)
757 {
758 case T_HashJoin:
759 {
760 HashPath *hash_path = makeNode(HashPath);
761
762 memcpy(hash_path, path, sizeof(HashPath));
763 joinpath = (JoinPath *) hash_path;
764 }
765 break;
766
767 case T_NestLoop:
768 {
769 NestPath *nest_path = makeNode(NestPath);
770
771 memcpy(nest_path, path, sizeof(NestPath));
772 joinpath = (JoinPath *) nest_path;
773 }
774 break;
775
776 case T_MergeJoin:
777 {
778 MergePath *merge_path = makeNode(MergePath);
779
780 memcpy(merge_path, path, sizeof(MergePath));
781 joinpath = (JoinPath *) merge_path;
782 }
783 break;
784
785 default:
786
787 /*
788 * Just skip anything else. We don't know if corresponding
789 * plan would build the output row from whole-row references
790 * of base relations and execute the EPQ checks.
791 */
792 break;
793 }
794
795 /* This path isn't good for us, check next. */
796 if (!joinpath)
797 continue;
798
799 /*
800 * If either inner or outer path is a ForeignPath corresponding to a
801 * pushed down join, replace it with the fdw_outerpath, so that we
802 * maintain path for EPQ checks built entirely of local join
803 * strategies.
804 */
805 if (IsA(joinpath->outerjoinpath, ForeignPath))
806 {
807 ForeignPath *foreign_path;
808
809 foreign_path = (ForeignPath *) joinpath->outerjoinpath;
810 if (IS_JOIN_REL(foreign_path->path.parent))
811 joinpath->outerjoinpath = foreign_path->fdw_outerpath;
812 }
813
814 if (IsA(joinpath->innerjoinpath, ForeignPath))
815 {
816 ForeignPath *foreign_path;
817
818 foreign_path = (ForeignPath *) joinpath->innerjoinpath;
819 if (IS_JOIN_REL(foreign_path->path.parent))
820 joinpath->innerjoinpath = foreign_path->fdw_outerpath;
821 }
822
823 return (Path *) joinpath;
824 }
825 return NULL;
826}
int16 AttrNumber
Definition: attnum.h:21
static Datum values[MAXATTR]
Definition: bootstrap.c:151
#define CStringGetTextDatum(s)
Definition: builtins.h:97
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define NameStr(name)
Definition: c.h:700
uint16 bits16
Definition: c.h:493
#define Assert(condition)
Definition: c.h:812
#define unlikely(x)
Definition: c.h:330
#define OidIsValid(objectId)
Definition: c.h:729
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define OidFunctionCall0(functionId)
Definition: fmgr.h:677
#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
static bool is_conninfo_option(const char *option, Oid context)
Definition: foreign.c:601
static const struct ConnectionOption libpq_conninfo_options[]
Definition: foreign.c:575
ForeignDataWrapper * GetForeignDataWrapper(Oid fdwid)
Definition: foreign.c:37
ForeignServer * GetForeignServerByName(const char *srvname, bool missing_ok)
Definition: foreign.c:182
FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)
Definition: foreign.c:442
FdwRoutine * GetFdwRoutineByServerId(Oid serverid)
Definition: foreign.c:377
ForeignTable * GetForeignTable(Oid relid)
Definition: foreign.c:254
Path * GetExistingLocalJoinPath(RelOptInfo *joinrel)
Definition: foreign.c:741
UserMapping * GetUserMapping(Oid userid, Oid serverid)
Definition: foreign.c:200
Oid get_foreign_server_oid(const char *servername, bool missing_ok)
Definition: foreign.c:704
ForeignServer * GetForeignServer(Oid serverid)
Definition: foreign.c:111
Datum pg_options_to_table(PG_FUNCTION_ARGS)
Definition: foreign.c:522
ForeignDataWrapper * GetForeignDataWrapperExtended(Oid fdwid, bits16 flags)
Definition: foreign.c:49
Datum postgresql_fdw_validator(PG_FUNCTION_ARGS)
Definition: foreign.c:625
FdwRoutine * GetFdwRoutineByRelId(Oid relid)
Definition: foreign.c:419
ForeignDataWrapper * GetForeignDataWrapperByName(const char *fdwname, bool missing_ok)
Definition: foreign.c:96
Oid GetForeignServerIdByRelId(Oid relid)
Definition: foreign.c:355
bool IsImportableForeignTable(const char *tablename, ImportForeignSchemaStmt *stmt)
Definition: foreign.c:482
ForeignServer * GetForeignServerExtended(Oid serverid, bits16 flags)
Definition: foreign.c:123
FdwRoutine * GetFdwRoutine(Oid fdwhandler)
Definition: foreign.c:325
List * GetForeignColumnOptions(Oid relid, AttrNumber attnum)
Definition: foreign.c:292
Oid get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
Definition: foreign.c:681
#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:76
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1181
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void * palloc(Size size)
Definition: mcxt.c:1317
MemoryContext CacheMemoryContext
Definition: mcxt.c:152
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define makeNode(_type_)
Definition: nodes.h:155
@ FDW_IMPORT_SCHEMA_LIMIT_TO
Definition: parsenodes.h:2966
@ FDW_IMPORT_SCHEMA_ALL
Definition: parsenodes.h:2965
@ FDW_IMPORT_SCHEMA_EXCEPT
Definition: parsenodes.h:2967
#define IS_JOIN_REL(rel)
Definition: pathnodes.h:844
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
int restrict_nonsystem_relation_kind
Definition: postgres.c:104
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
tree context
Definition: radixtree.h:1837
#define RelationGetRelid(relation)
Definition: rel.h:505
List * untransformRelOptions(Datum options)
Definition: reloptions.c:1331
const char * optname
Definition: foreign.c:566
char * defname
Definition: parsenodes.h:817
Node * arg
Definition: parsenodes.h:818
char * fdwname
Definition: foreign.h:28
List * options
Definition: foreign.h:31
Path * fdw_outerpath
Definition: pathnodes.h:1882
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:2086
Path * innerjoinpath
Definition: pathnodes.h:2087
Definition: pg_list.h:54
NodeTag pathtype
Definition: pathnodes.h:1637
char * relname
Definition: primnodes.h:82
List * pathlist
Definition: pathnodes.h:898
struct FdwRoutine * rd_fdwroutine
Definition: rel.h:240
TupleDesc setDesc
Definition: execnodes.h:343
Tuplestorestate * setResult
Definition: execnodes.h:342
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:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:600
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:232
#define GetSysCacheOid1(cacheId, oidcol, key1)
Definition: syscache.h:109
#define RESTRICT_RELKIND_FOREIGN_TABLE
Definition: tcopprot.h:44
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition: tuplestore.c:784
#define strVal(v)
Definition: value.h:82
const char * getClosestMatch(ClosestMatchState *state)
Definition: varlena.c:6256
void initClosestMatch(ClosestMatchState *state, const char *source, int max_d)
Definition: varlena.c:6201
void updateClosestMatch(ClosestMatchState *state, const char *candidate)
Definition: varlena.c:6221