PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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-2026, 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 "optimizer/paths.h"
26#include "tcop/tcopprot.h"
27#include "utils/builtins.h"
28#include "utils/memutils.h"
29#include "utils/rel.h"
30#include "utils/syscache.h"
31#include "utils/tuplestore.h"
32#include "utils/varlena.h"
33
34
35/*
36 * GetForeignDataWrapper - look up the foreign-data wrapper by OID.
37 */
40{
41 return GetForeignDataWrapperExtended(fdwid, 0);
42}
43
44
45/*
46 * GetForeignDataWrapperExtended - look up the foreign-data wrapper
47 * by OID. If flags uses FDW_MISSING_OK, return NULL if the object cannot
48 * be found instead of raising an error.
49 */
52{
55 Datum datum;
56 HeapTuple tp;
57 bool isnull;
58
60
61 if (!HeapTupleIsValid(tp))
62 {
63 if ((flags & FDW_MISSING_OK) == 0)
64 elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid);
65 return NULL;
66 }
67
69
71 fdw->fdwid = fdwid;
72 fdw->owner = fdwform->fdwowner;
73 fdw->fdwname = pstrdup(NameStr(fdwform->fdwname));
74 fdw->fdwhandler = fdwform->fdwhandler;
75 fdw->fdwvalidator = fdwform->fdwvalidator;
76 fdw->fdwconnection = fdwform->fdwconnection;
77
78 /* Extract the fdwoptions */
80 tp,
82 &isnull);
83 if (isnull)
84 fdw->options = NIL;
85 else
86 fdw->options = untransformRelOptions(datum);
87
89
90 return fdw;
91}
92
93
94/*
95 * GetForeignDataWrapperByName - look up the foreign-data wrapper
96 * definition by name.
97 */
99GetForeignDataWrapperByName(const char *fdwname, bool missing_ok)
100{
101 Oid fdwId = get_foreign_data_wrapper_oid(fdwname, missing_ok);
102
103 if (!OidIsValid(fdwId))
104 return NULL;
105
107}
108
109
110/*
111 * GetForeignServer - look up the foreign server definition.
112 */
115{
116 return GetForeignServerExtended(serverid, 0);
117}
118
119
120/*
121 * GetForeignServerExtended - look up the foreign server definition. If
122 * flags uses FSV_MISSING_OK, return NULL if the object cannot be found
123 * instead of raising an error.
124 */
127{
129 ForeignServer *server;
130 HeapTuple tp;
131 Datum datum;
132 bool isnull;
133
135
136 if (!HeapTupleIsValid(tp))
137 {
138 if ((flags & FSV_MISSING_OK) == 0)
139 elog(ERROR, "cache lookup failed for foreign server %u", serverid);
140 return NULL;
141 }
142
144
146 server->serverid = serverid;
147 server->servername = pstrdup(NameStr(serverform->srvname));
148 server->owner = serverform->srvowner;
149 server->fdwid = serverform->srvfdw;
150
151 /* Extract server type */
153 tp,
155 &isnull);
156 server->servertype = isnull ? NULL : TextDatumGetCString(datum);
157
158 /* Extract server version */
160 tp,
162 &isnull);
163 server->serverversion = isnull ? NULL : TextDatumGetCString(datum);
164
165 /* Extract the srvoptions */
167 tp,
169 &isnull);
170 if (isnull)
171 server->options = NIL;
172 else
173 server->options = untransformRelOptions(datum);
174
175 ReleaseSysCache(tp);
176
177 return server;
178}
179
180
181/*
182 * GetForeignServerByName - look up the foreign server definition by name.
183 */
185GetForeignServerByName(const char *srvname, bool missing_ok)
186{
187 Oid serverid = get_foreign_server_oid(srvname, missing_ok);
188
189 if (!OidIsValid(serverid))
190 return NULL;
191
192 return GetForeignServer(serverid);
193}
194
195
196/*
197 * Retrieve connection string from server's FDW.
198 *
199 * NB: leaks into CurrentMemoryContext.
200 */
201char *
203{
206
208
209 if (!OidIsValid(fdw->fdwconnection))
212 errmsg("foreign data wrapper \"%s\" does not support subscription connections",
213 fdw->fdwname),
214 errdetail("Foreign data wrapper must be defined with CONNECTION specified.")));
215
216 connection_datum = OidFunctionCall3(fdw->fdwconnection,
217 ObjectIdGetDatum(userid),
218 ObjectIdGetDatum(server->serverid),
220
222}
223
224
225/*
226 * GetUserMapping - look up the user mapping.
227 *
228 * If no mapping is found for the supplied user, we also look for
229 * PUBLIC mappings (userid == InvalidOid).
230 */
232GetUserMapping(Oid userid, Oid serverid)
233{
234 Datum datum;
235 HeapTuple tp;
236 bool isnull;
238
240 ObjectIdGetDatum(userid),
241 ObjectIdGetDatum(serverid));
242
243 if (!HeapTupleIsValid(tp))
244 {
245 /* Not found for the specific user -- try PUBLIC */
248 ObjectIdGetDatum(serverid));
249 }
250
251 if (!HeapTupleIsValid(tp))
252 {
253 ForeignServer *server = GetForeignServer(serverid);
254
257 errmsg("user mapping not found for user \"%s\", server \"%s\"",
258 MappingUserName(userid), server->servername)));
259 }
260
262 um->umid = ((Form_pg_user_mapping) GETSTRUCT(tp))->oid;
263 um->userid = userid;
264 um->serverid = serverid;
265
266 /* Extract the umoptions */
268 tp,
270 &isnull);
271 if (isnull)
272 um->options = NIL;
273 else
274 um->options = untransformRelOptions(datum);
275
276 ReleaseSysCache(tp);
277
278 return um;
279}
280
281
282/*
283 * GetForeignTable - look up the foreign table definition by relation oid.
284 */
287{
290 HeapTuple tp;
291 Datum datum;
292 bool isnull;
293
295 if (!HeapTupleIsValid(tp))
296 elog(ERROR, "cache lookup failed for foreign table %u", relid);
298
300 ft->relid = relid;
301 ft->serverid = tableform->ftserver;
302
303 /* Extract the ftoptions */
305 tp,
307 &isnull);
308 if (isnull)
309 ft->options = NIL;
310 else
311 ft->options = untransformRelOptions(datum);
312
313 ReleaseSysCache(tp);
314
315 return ft;
316}
317
318
319/*
320 * GetForeignColumnOptions - Get attfdwoptions of given relation/attnum
321 * as list of DefElem.
322 */
323List *
325{
326 List *options;
327 HeapTuple tp;
328 Datum datum;
329 bool isnull;
330
332 ObjectIdGetDatum(relid),
334 if (!HeapTupleIsValid(tp))
335 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
336 attnum, relid);
337 datum = SysCacheGetAttr(ATTNUM,
338 tp,
340 &isnull);
341 if (isnull)
342 options = NIL;
343 else
345
346 ReleaseSysCache(tp);
347
348 return options;
349}
350
351
352/*
353 * GetFdwRoutine - call the specified foreign-data wrapper handler routine
354 * to get its FdwRoutine struct.
355 */
358{
359 Datum datum;
360 FdwRoutine *routine;
361
362 /* Check if the access to foreign tables is restricted */
364 {
365 /* there must not be built-in FDW handler */
368 errmsg("access to non-system foreign table is restricted")));
369 }
370
371 datum = OidFunctionCall0(fdwhandler);
372 routine = (FdwRoutine *) DatumGetPointer(datum);
373
374 if (routine == NULL || !IsA(routine, FdwRoutine))
375 elog(ERROR, "foreign-data wrapper handler function %u did not return an FdwRoutine struct",
376 fdwhandler);
377
378 return routine;
379}
380
381
382/*
383 * GetForeignServerIdByRelId - look up the foreign server
384 * for the given foreign table, and return its OID.
385 */
386Oid
388{
389 HeapTuple tp;
391 Oid serverid;
392
394 if (!HeapTupleIsValid(tp))
395 elog(ERROR, "cache lookup failed for foreign table %u", relid);
397 serverid = tableform->ftserver;
398 ReleaseSysCache(tp);
399
400 return serverid;
401}
402
403
404/*
405 * GetFdwRoutineByServerId - look up the handler of the foreign-data wrapper
406 * for the given foreign server, and retrieve its FdwRoutine struct.
407 */
410{
411 HeapTuple tp;
414 Oid fdwid;
415 Oid fdwhandler;
416
417 /* Get foreign-data wrapper OID for the server. */
419 if (!HeapTupleIsValid(tp))
420 elog(ERROR, "cache lookup failed for foreign server %u", serverid);
422 fdwid = serverform->srvfdw;
423 ReleaseSysCache(tp);
424
425 /* Get handler function OID for the FDW. */
427 if (!HeapTupleIsValid(tp))
428 elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid);
430 fdwhandler = fdwform->fdwhandler;
431
432 /* Complain if FDW has been set to NO HANDLER. */
433 if (!OidIsValid(fdwhandler))
436 errmsg("foreign-data wrapper \"%s\" has no handler",
437 NameStr(fdwform->fdwname))));
438
439 ReleaseSysCache(tp);
440
441 /* And finally, call the handler function. */
442 return GetFdwRoutine(fdwhandler);
443}
444
445
446/*
447 * GetFdwRoutineByRelId - look up the handler of the foreign-data wrapper
448 * for the given foreign table, and retrieve its FdwRoutine struct.
449 */
452{
453 Oid serverid;
454
455 /* Get server OID for the foreign table. */
456 serverid = GetForeignServerIdByRelId(relid);
457
458 /* Now retrieve server's FdwRoutine struct. */
459 return GetFdwRoutineByServerId(serverid);
460}
461
462/*
463 * GetFdwRoutineForRelation - look up the handler of the foreign-data wrapper
464 * for the given foreign table, and retrieve its FdwRoutine struct.
465 *
466 * This function is preferred over GetFdwRoutineByRelId because it caches
467 * the data in the relcache entry, saving a number of catalog lookups.
468 *
469 * If makecopy is true then the returned data is freshly palloc'd in the
470 * caller's memory context. Otherwise, it's a pointer to the relcache data,
471 * which will be lost in any relcache reset --- so don't rely on it long.
472 */
475{
476 FdwRoutine *fdwroutine;
478
479 if (relation->rd_fdwroutine == NULL)
480 {
481 /* Get the info by consulting the catalogs and the FDW code */
482 fdwroutine = GetFdwRoutineByRelId(RelationGetRelid(relation));
483
484 /* Save the data for later reuse in CacheMemoryContext */
486 sizeof(FdwRoutine));
487 memcpy(cfdwroutine, fdwroutine, sizeof(FdwRoutine));
488 relation->rd_fdwroutine = cfdwroutine;
489
490 /* Give back the locally palloc'd copy regardless of makecopy */
491 return fdwroutine;
492 }
493
494 /* We have valid cached data --- does the caller want a copy? */
495 if (makecopy)
496 {
497 fdwroutine = palloc_object(FdwRoutine);
498 memcpy(fdwroutine, relation->rd_fdwroutine, sizeof(FdwRoutine));
499 return fdwroutine;
500 }
501
502 /* Only a short-lived reference is needed, so just hand back cached copy */
503 return relation->rd_fdwroutine;
504}
505
506
507/*
508 * IsImportableForeignTable - filter table names for IMPORT FOREIGN SCHEMA
509 *
510 * Returns true if given table name should be imported according to the
511 * statement's import filter options.
512 */
513bool
514IsImportableForeignTable(const char *tablename,
516{
517 ListCell *lc;
518
519 switch (stmt->list_type)
520 {
522 return true;
523
525 foreach(lc, stmt->table_list)
526 {
527 RangeVar *rv = (RangeVar *) lfirst(lc);
528
529 if (strcmp(tablename, rv->relname) == 0)
530 return true;
531 }
532 return false;
533
535 foreach(lc, stmt->table_list)
536 {
537 RangeVar *rv = (RangeVar *) lfirst(lc);
538
539 if (strcmp(tablename, rv->relname) == 0)
540 return false;
541 }
542 return true;
543 }
544 return false; /* shouldn't get here */
545}
546
547
548/*
549 * pg_options_to_table - Convert options array to name/value table
550 *
551 * This is useful to provide details for information_schema and pg_dump.
552 */
553Datum
555{
556 Datum array = PG_GETARG_DATUM(0);
557 ListCell *cell;
558 List *options;
560
562 rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
563
564 /* prepare the result set */
566
567 foreach(cell, options)
568 {
569 DefElem *def = lfirst(cell);
570 Datum values[2];
571 bool nulls[2];
572
574 nulls[0] = false;
575 if (def->arg)
576 {
578 nulls[1] = false;
579 }
580 else
581 {
582 values[1] = (Datum) 0;
583 nulls[1] = true;
584 }
585 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
586 values, nulls);
587 }
588
589 return (Datum) 0;
590}
591
592
593/*
594 * Describes the valid options for postgresql FDW, server, and user mapping.
595 */
597{
598 const char *optname;
599 Oid optcontext; /* Oid of catalog in which option may appear */
600};
601
602/*
603 * Copied from fe-connect.c PQconninfoOptions.
604 *
605 * The list is small - don't bother with bsearch if it stays so.
606 */
608 {"authtype", ForeignServerRelationId},
609 {"service", ForeignServerRelationId},
610 {"user", UserMappingRelationId},
611 {"password", UserMappingRelationId},
612 {"connect_timeout", ForeignServerRelationId},
613 {"dbname", ForeignServerRelationId},
614 {"host", ForeignServerRelationId},
615 {"hostaddr", ForeignServerRelationId},
616 {"port", ForeignServerRelationId},
618 {"options", ForeignServerRelationId},
619 {"requiressl", ForeignServerRelationId},
620 {"sslmode", ForeignServerRelationId},
621 {"gsslib", ForeignServerRelationId},
622 {"gssdelegation", ForeignServerRelationId},
624};
625
626
627/*
628 * Check if the provided option is one of libpq conninfo options.
629 * context is the Oid of the catalog the option came from, or 0 if we
630 * don't care.
631 */
632static bool
633is_conninfo_option(const char *option, Oid context)
634{
635 const struct ConnectionOption *opt;
636
637 for (opt = libpq_conninfo_options; opt->optname; opt++)
638 if (context == opt->optcontext && strcmp(opt->optname, option) == 0)
639 return true;
640 return false;
641}
642
643
644/*
645 * Validate the generic option given to SERVER or USER MAPPING.
646 * Raise an ERROR if the option or its value is considered invalid.
647 *
648 * Valid server options are all libpq conninfo options except
649 * user and password -- these may only appear in USER MAPPING options.
650 *
651 * Caution: this function is deprecated, and is now meant only for testing
652 * purposes, because the list of options it knows about doesn't necessarily
653 * square with those known to whichever libpq instance you might be using.
654 * Inquire of libpq itself, instead.
655 */
656Datum
658{
661
662 ListCell *cell;
663
664 foreach(cell, options_list)
665 {
666 DefElem *def = lfirst(cell);
667
669 {
670 const struct ConnectionOption *opt;
671 const char *closest_match;
673 bool has_valid_options = false;
674
675 /*
676 * Unknown option specified, complain about it. Provide a hint
677 * with a valid option that looks similar, if there is one.
678 */
680 for (opt = libpq_conninfo_options; opt->optname; opt++)
681 {
682 if (catalog == opt->optcontext)
683 {
684 has_valid_options = true;
686 }
687 }
688
692 errmsg("invalid option \"%s\"", def->defname),
694 errhint("Perhaps you meant the option \"%s\".",
695 closest_match) : 0 :
696 errhint("There are no valid options in this context.")));
697
698 PG_RETURN_BOOL(false);
699 }
700 }
701
702 PG_RETURN_BOOL(true);
703}
704
705
706/*
707 * get_foreign_data_wrapper_oid - given a FDW name, look up the OID
708 *
709 * If missing_ok is false, throw an error if name not found. If true, just
710 * return InvalidOid.
711 */
712Oid
713get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
714{
715 Oid oid;
716
719 CStringGetDatum(fdwname));
720 if (!OidIsValid(oid) && !missing_ok)
723 errmsg("foreign-data wrapper \"%s\" does not exist",
724 fdwname)));
725 return oid;
726}
727
728
729/*
730 * get_foreign_server_oid - given a server name, look up the OID
731 *
732 * If missing_ok is false, throw an error if name not found. If true, just
733 * return InvalidOid.
734 */
735Oid
736get_foreign_server_oid(const char *servername, bool missing_ok)
737{
738 Oid oid;
739
741 CStringGetDatum(servername));
742 if (!OidIsValid(oid) && !missing_ok)
745 errmsg("server \"%s\" does not exist", servername)));
746 return oid;
747}
748
749/*
750 * Get a copy of an existing local path for a given join relation.
751 *
752 * This function is usually helpful to obtain an alternate local path for EPQ
753 * checks.
754 *
755 * Right now, this function only supports unparameterized foreign joins, so we
756 * only search for unparameterized path in the given list of paths. Since we
757 * are searching for a path which can be used to construct an alternative local
758 * plan for a foreign join, we look for only MergeJoin, HashJoin or NestLoop
759 * paths.
760 *
761 * If the inner or outer subpath of the chosen path is a ForeignScan, we
762 * replace it with its outer subpath. For this reason, and also because the
763 * planner might free the original path later, the path returned by this
764 * function is a shallow copy of the original. There's no need to copy
765 * the substructure, so we don't.
766 *
767 * Since the plan created using this path will presumably only be used to
768 * execute EPQ checks, efficiency of the path is not a concern. But since the
769 * path list in RelOptInfo is anyway sorted by total cost we are likely to
770 * choose the most efficient path, which is all for the best.
771 */
772Path *
774{
775 ListCell *lc;
776
777 Assert(IS_JOIN_REL(joinrel));
778
779 foreach(lc, joinrel->pathlist)
780 {
781 Path *path = (Path *) lfirst(lc);
783
784 /* Skip parameterized paths. */
785 if (path->param_info != NULL)
786 continue;
787
788 switch (path->pathtype)
789 {
790 case T_HashJoin:
791 {
793
794 memcpy(hash_path, path, sizeof(HashPath));
796 }
797 break;
798
799 case T_NestLoop:
800 {
802
803 memcpy(nest_path, path, sizeof(NestPath));
805 }
806 break;
807
808 case T_MergeJoin:
809 {
811
812 memcpy(merge_path, path, sizeof(MergePath));
814 }
815 break;
816
817 default:
818
819 /*
820 * Just skip anything else. We don't know if corresponding
821 * plan would build the output row from whole-row references
822 * of base relations and execute the EPQ checks.
823 */
824 break;
825 }
826
827 /* This path isn't good for us, check next. */
828 if (!joinpath)
829 continue;
830
831 /*
832 * If either inner or outer path is a ForeignPath corresponding to a
833 * pushed down join, replace it with the fdw_outerpath, so that we
834 * maintain path for EPQ checks built entirely of local join
835 * strategies.
836 */
837 if (IsA(joinpath->outerjoinpath, ForeignPath))
838 {
840
841 foreign_path = (ForeignPath *) joinpath->outerjoinpath;
842 if (IS_JOIN_REL(foreign_path->path.parent))
843 {
844 joinpath->outerjoinpath = foreign_path->fdw_outerpath;
845
846 if (joinpath->path.pathtype == T_MergeJoin)
847 {
849
850 /*
851 * If the new outer path is already well enough ordered
852 * for the mergejoin, we can skip doing an explicit sort.
853 */
854 if (merge_path->outersortkeys &&
856 joinpath->outerjoinpath->pathkeys,
857 &merge_path->outer_presorted_keys))
859 }
860 }
861 }
862
863 if (IsA(joinpath->innerjoinpath, ForeignPath))
864 {
866
867 foreign_path = (ForeignPath *) joinpath->innerjoinpath;
868 if (IS_JOIN_REL(foreign_path->path.parent))
869 {
870 joinpath->innerjoinpath = foreign_path->fdw_outerpath;
871
872 if (joinpath->path.pathtype == T_MergeJoin)
873 {
875
876 /*
877 * If the new inner path is already well enough ordered
878 * for the mergejoin, we can skip doing an explicit sort.
879 */
880 if (merge_path->innersortkeys &&
881 pathkeys_contained_in(merge_path->innersortkeys,
882 joinpath->innerjoinpath->pathkeys))
884 }
885 }
886 }
887
888 return (Path *) joinpath;
889 }
890 return NULL;
891}
int16 AttrNumber
Definition attnum.h:21
static Datum values[MAXATTR]
Definition bootstrap.c:190
#define CStringGetTextDatum(s)
Definition builtins.h:98
#define TextDatumGetCString(d)
Definition builtins.h:99
#define NameStr(name)
Definition c.h:835
#define Assert(condition)
Definition c.h:943
uint16_t uint16
Definition c.h:623
#define unlikely(x)
Definition c.h:438
#define OidIsValid(objectId)
Definition c.h:858
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
int errcode(int sqlerrcode)
Definition elog.c:874
int errhint(const char *fmt,...) pg_attribute_printf(1
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
#define palloc_object(type)
Definition fe_memutils.h:74
#define PG_GETARG_OID(n)
Definition fmgr.h:275
#define DatumGetTextPP(X)
Definition fmgr.h:293
#define OidFunctionCall0(functionId)
Definition fmgr.h:720
#define PG_GETARG_DATUM(n)
Definition fmgr.h:268
#define OidFunctionCall3(functionId, arg1, arg2, arg3)
Definition fmgr.h:726
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition fmgr.h:360
static bool is_conninfo_option(const char *option, Oid context)
Definition foreign.c:633
static const struct ConnectionOption libpq_conninfo_options[]
Definition foreign.c:607
ForeignDataWrapper * GetForeignDataWrapper(Oid fdwid)
Definition foreign.c:39
ForeignServer * GetForeignServerByName(const char *srvname, bool missing_ok)
Definition foreign.c:185
ForeignDataWrapper * GetForeignDataWrapperExtended(Oid fdwid, uint16 flags)
Definition foreign.c:51
FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)
Definition foreign.c:474
FdwRoutine * GetFdwRoutineByServerId(Oid serverid)
Definition foreign.c:409
char * ForeignServerConnectionString(Oid userid, ForeignServer *server)
Definition foreign.c:202
ForeignTable * GetForeignTable(Oid relid)
Definition foreign.c:286
Path * GetExistingLocalJoinPath(RelOptInfo *joinrel)
Definition foreign.c:773
UserMapping * GetUserMapping(Oid userid, Oid serverid)
Definition foreign.c:232
Oid get_foreign_server_oid(const char *servername, bool missing_ok)
Definition foreign.c:736
ForeignServer * GetForeignServer(Oid serverid)
Definition foreign.c:114
Datum pg_options_to_table(PG_FUNCTION_ARGS)
Definition foreign.c:554
Datum postgresql_fdw_validator(PG_FUNCTION_ARGS)
Definition foreign.c:657
FdwRoutine * GetFdwRoutineByRelId(Oid relid)
Definition foreign.c:451
ForeignDataWrapper * GetForeignDataWrapperByName(const char *fdwname, bool missing_ok)
Definition foreign.c:99
Oid GetForeignServerIdByRelId(Oid relid)
Definition foreign.c:387
bool IsImportableForeignTable(const char *tablename, ImportForeignSchemaStmt *stmt)
Definition foreign.c:514
ForeignServer * GetForeignServerExtended(Oid serverid, uint16 flags)
Definition foreign.c:126
FdwRoutine * GetFdwRoutine(Oid fdwhandler)
Definition foreign.c:357
List * GetForeignColumnOptions(Oid relid, AttrNumber attnum)
Definition foreign.c:324
Oid get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
Definition foreign.c:713
#define MappingUserName(userid)
Definition foreign.h:20
#define FSV_MISSING_OK
Definition foreign.h:62
#define FDW_MISSING_OK
Definition foreign.h:65
void InitMaterializedSRF(FunctionCallInfo fcinfo, uint32 flags)
Definition funcapi.c:76
#define MAT_SRF_USE_EXPECTED_DESC
Definition funcapi.h:296
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
#define stmt
struct parser_state match_state[5]
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition mcxt.c:1232
char * pstrdup(const char *in)
Definition mcxt.c:1781
MemoryContext CacheMemoryContext
Definition mcxt.c:169
#define IsA(nodeptr, _type_)
Definition nodes.h:164
#define makeNode(_type_)
Definition nodes.h:161
static char * errmsg
@ FDW_IMPORT_SCHEMA_LIMIT_TO
@ FDW_IMPORT_SCHEMA_ALL
@ FDW_IMPORT_SCHEMA_EXCEPT
bool pathkeys_count_contained_in(List *keys1, List *keys2, int *n_common)
Definition pathkeys.c:558
bool pathkeys_contained_in(List *keys1, List *keys2)
Definition pathkeys.c:343
#define IS_JOIN_REL(rel)
Definition pathnodes.h:994
int16 attnum
END_CATALOG_STRUCT typedef FormData_pg_foreign_data_wrapper * Form_pg_foreign_data_wrapper
END_CATALOG_STRUCT typedef FormData_pg_foreign_server * Form_pg_foreign_server
END_CATALOG_STRUCT typedef FormData_pg_foreign_table * Form_pg_foreign_table
#define lfirst(lc)
Definition pg_list.h:172
#define NIL
Definition pg_list.h:68
END_CATALOG_STRUCT typedef FormData_pg_user_mapping * Form_pg_user_mapping
int restrict_nonsystem_relation_kind
Definition postgres.c:111
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
static Datum Int16GetDatum(int16 X)
Definition postgres.h:172
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
uint64_t Datum
Definition postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
static Datum CStringGetDatum(const char *X)
Definition postgres.h:370
#define InvalidOid
unsigned int Oid
static int fb(int x)
#define RelationGetRelid(relation)
Definition rel.h:516
List * untransformRelOptions(Datum options)
const char * optname
Definition foreign.c:598
char * defname
Definition parsenodes.h:860
Node * arg
Definition parsenodes.h:861
List * options
Definition foreign.h:43
char * serverversion
Definition foreign.h:42
char * servername
Definition foreign.h:40
char * servertype
Definition foreign.h:41
Definition pg_list.h:54
List * outersortkeys
Definition pathnodes.h:2470
List * innersortkeys
Definition pathnodes.h:2471
NodeTag pathtype
Definition pathnodes.h:1971
char * relname
Definition primnodes.h:84
List * pathlist
Definition pathnodes.h:1050
struct FdwRoutine * rd_fdwroutine
Definition rel.h:240
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache2(SysCacheIdentifier cacheId, Datum key1, Datum key2)
Definition syscache.c:231
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:221
Datum SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:596
#define GetSysCacheOid1(cacheId, oidcol, key1)
Definition syscache.h:109
#define RESTRICT_RELKIND_FOREIGN_TABLE
Definition tcopprot.h:45
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition tuplestore.c:785
#define strVal(v)
Definition value.h:82
const char * getClosestMatch(ClosestMatchState *state)
Definition varlena.c:5386
void initClosestMatch(ClosestMatchState *state, const char *source, int max_d)
Definition varlena.c:5331
void updateClosestMatch(ClosestMatchState *state, const char *candidate)
Definition varlena.c:5351
char * text_to_cstring(const text *t)
Definition varlena.c:217