1/*-------------------------------------------------------------------------
4 * foreign-data wrapper/server creation/manipulation commands
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
10 * src/backend/commands/foreigncmds.c
12 *-------------------------------------------------------------------------
49/* Internal functions */
54 * Convert a DefElem list to the text array format that is used in
55 * pg_foreign_data_wrapper, pg_foreign_server, pg_user_mapping, and
58 * Returns the array in the form of a Datum, or PointerGetDatum(NULL)
59 * if the list is empty.
61 * Note: The array is usually stored to database without further
62 * processing, hence any validation should be done before this
82 /* Insist that name not contain "=", else "a=b=c" is ambiguous */
83 if (strchr(
name,
'=') != NULL)
85 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
86 errmsg(
"invalid option name \"%s\": must not contain \"=\"",
90 /* +1 leaves room for sprintf's trailing null */
108 * Transform a list of DefElem into text array format. This is substantially
109 * the same thing as optionListToArray(), except we recognize SET/ADD/DROP
110 * actions for modifying an existing list of options, which is passed in
111 * Datum form as oldOptions. Also, if fdwvalidator isn't InvalidOid
112 * it specifies a validator function to call on the result.
114 * Returns the array in the form of a Datum, or PointerGetDatum(NULL)
115 * if the list is empty.
117 * This is used by CREATE/ALTER of FOREIGN DATA WRAPPER/SERVER/USER MAPPING/
136 * Find the element in resultOptions. We need this for validation in
139 foreach(cell, resultOptions)
148 * It is possible to perform multiple SET/DROP actions on the same
149 * option. The standard permits this, as long as the options to be
150 * added are unique. Note that an unspecified action is taken to be
158 (
errcode(ERRCODE_UNDEFINED_OBJECT),
159 errmsg(
"option \"%s\" not found",
167 (
errcode(ERRCODE_UNDEFINED_OBJECT),
168 errmsg(
"option \"%s\" not found",
178 errmsg(
"option \"%s\" provided more than once",
180 resultOptions =
lappend(resultOptions, od);
184 elog(
ERROR,
"unrecognized action %d on option \"%s\"",
194 Datum valarg = result;
197 * Pass a null options list as an empty array, so that validators
198 * don't have to be declared non-strict to handle the case.
210 * Internal workhorse for changing a data wrapper's owner.
212 * Allow this only for superusers; also the new owner must be a
219 Datum repl_val[Natts_pg_foreign_data_wrapper];
220 bool repl_null[Natts_pg_foreign_data_wrapper];
221 bool repl_repl[Natts_pg_foreign_data_wrapper];
228 /* Must be a superuser to change a FDW owner */
231 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
232 errmsg(
"permission denied to change owner of foreign-data wrapper \"%s\"",
234 errhint(
"Must be superuser to change owner of a foreign-data wrapper.")));
236 /* New owner must also be a superuser */
239 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
240 errmsg(
"permission denied to change owner of foreign-data wrapper \"%s\"",
242 errhint(
"The owner of a foreign-data wrapper must be a superuser.")));
244 if (form->fdwowner != newOwnerId)
246 memset(repl_null,
false,
sizeof(repl_null));
247 memset(repl_repl,
false,
sizeof(repl_repl));
249 repl_repl[Anum_pg_foreign_data_wrapper_fdwowner - 1] =
true;
250 repl_val[Anum_pg_foreign_data_wrapper_fdwowner - 1] =
ObjectIdGetDatum(newOwnerId);
253 Anum_pg_foreign_data_wrapper_fdwacl,
256 /* Null ACLs do not require changes */
260 form->fdwowner, newOwnerId);
261 repl_repl[Anum_pg_foreign_data_wrapper_fdwacl - 1] =
true;
262 repl_val[Anum_pg_foreign_data_wrapper_fdwacl - 1] =
PointerGetDatum(newAcl);
270 /* Update owner dependency reference */
281 * Change foreign-data wrapper owner -- by name
283 * Note restrictions in the "_internal" function, above.
301 (
errcode(ERRCODE_UNDEFINED_OBJECT),
302 errmsg(
"foreign-data wrapper \"%s\" does not exist",
name)));
319 * Change foreign-data wrapper owner -- by OID
321 * Note restrictions in the "_internal" function, above.
335 (
errcode(ERRCODE_UNDEFINED_OBJECT),
336 errmsg(
"foreign-data wrapper with OID %u does not exist", fwdId)));
346 * Internal workhorse for changing a foreign server's owner
352 Datum repl_val[Natts_pg_foreign_server];
353 bool repl_null[Natts_pg_foreign_server];
354 bool repl_repl[Natts_pg_foreign_server];
361 if (form->srvowner != newOwnerId)
363 /* Superusers can always do it */
376 /* Must be able to become new owner */
379 /* New owner must have USAGE privilege on foreign-data wrapper */
389 memset(repl_null,
false,
sizeof(repl_null));
390 memset(repl_repl,
false,
sizeof(repl_repl));
392 repl_repl[Anum_pg_foreign_server_srvowner - 1] =
true;
393 repl_val[Anum_pg_foreign_server_srvowner - 1] =
ObjectIdGetDatum(newOwnerId);
396 Anum_pg_foreign_server_srvacl,
399 /* Null ACLs do not require changes */
403 form->srvowner, newOwnerId);
404 repl_repl[Anum_pg_foreign_server_srvacl - 1] =
true;
413 /* Update owner dependency reference */
423 * Change foreign server owner -- by name
440 (
errcode(ERRCODE_UNDEFINED_OBJECT),
441 errmsg(
"server \"%s\" does not exist",
name)));
458 * Change foreign server owner -- by OID
472 (
errcode(ERRCODE_UNDEFINED_OBJECT),
473 errmsg(
"foreign server with OID %u does not exist", srvId)));
483 * Convert a handler function name passed from the parser to an Oid.
490 if (handler == NULL || handler->
arg == NULL)
493 /* handlers have no arguments */
496 /* check that handler has correct return type */
499 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
500 errmsg(
"function %s must return type %s",
507 * Convert a validator function name passed from the parser to an Oid.
514 if (validator == NULL || validator->
arg == NULL)
517 /* validators take text[], oid */
518 funcargtypes[0] = TEXTARRAYOID;
519 funcargtypes[1] = OIDOID;
522 /* validator's return value is ignored, so we don't check the type */
526 * Process function options of CREATE/ALTER FDW
530 bool *handler_given,
Oid *fdwhandler,
531 bool *validator_given,
Oid *fdwvalidator)
535 *handler_given =
false;
536 *validator_given =
false;
537 /* return InvalidOid if not given */
541 foreach(cell, func_options)
545 if (strcmp(def->
defname,
"handler") == 0)
549 *handler_given =
true;
552 else if (strcmp(def->
defname,
"validator") == 0)
554 if (*validator_given)
556 *validator_given =
true;
560 elog(
ERROR,
"option \"%s\" not recognized",
566 * Create a foreign-data wrapper
573 bool nulls[Natts_pg_foreign_data_wrapper];
577 bool validator_given;
587 /* Must be superuser */
590 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
591 errmsg(
"permission denied to create foreign-data wrapper \"%s\"",
593 errhint(
"Must be superuser to create a foreign-data wrapper.")));
595 /* For now the owner cannot be specified on create. Use effective user ID. */
599 * Check that there is no other foreign-data wrapper by this name.
604 errmsg(
"foreign-data wrapper \"%s\" already exists",
608 * Insert tuple into pg_foreign_data_wrapper.
611 memset(nulls,
false,
sizeof(nulls));
614 Anum_pg_foreign_data_wrapper_oid);
616 values[Anum_pg_foreign_data_wrapper_fdwname - 1] =
620 /* Lookup handler and validator functions, if given */
622 &handler_given, &fdwhandler,
623 &validator_given, &fdwvalidator);
628 nulls[Anum_pg_foreign_data_wrapper_fdwacl - 1] =
true;
636 values[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = fdwoptions;
638 nulls[Anum_pg_foreign_data_wrapper_fdwoptions - 1] =
true;
646 /* record dependencies */
647 myself.
classId = ForeignDataWrapperRelationId;
653 referenced.
classId = ProcedureRelationId;
661 referenced.
classId = ProcedureRelationId;
669 /* dependency on extension */
672 /* Post creation hook for new foreign data wrapper */
682 * Alter foreign-data wrapper
690 Datum repl_val[Natts_pg_foreign_data_wrapper];
691 bool repl_null[Natts_pg_foreign_data_wrapper];
692 bool repl_repl[Natts_pg_foreign_data_wrapper];
697 bool validator_given;
704 /* Must be superuser */
707 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
708 errmsg(
"permission denied to alter foreign-data wrapper \"%s\"",
710 errhint(
"Must be superuser to alter a foreign-data wrapper.")));
717 (
errcode(ERRCODE_UNDEFINED_OBJECT),
718 errmsg(
"foreign-data wrapper \"%s\" does not exist",
stmt->fdwname)));
721 fdwId = fdwForm->oid;
723 memset(repl_val, 0,
sizeof(repl_val));
724 memset(repl_null,
false,
sizeof(repl_null));
725 memset(repl_repl,
false,
sizeof(repl_repl));
728 &handler_given, &fdwhandler,
729 &validator_given, &fdwvalidator);
733 repl_val[Anum_pg_foreign_data_wrapper_fdwhandler - 1] =
ObjectIdGetDatum(fdwhandler);
734 repl_repl[Anum_pg_foreign_data_wrapper_fdwhandler - 1] =
true;
737 * It could be that the behavior of accessing foreign table changes
738 * with the new handler. Warn about this.
741 (
errmsg(
"changing the foreign-data wrapper handler can change behavior of existing foreign tables")));
746 repl_val[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] =
ObjectIdGetDatum(fdwvalidator);
747 repl_repl[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] =
true;
750 * It could be that existing options for the FDW or dependent SERVER,
751 * USER MAPPING or FOREIGN TABLE objects are no longer valid according
752 * to the new validator. Warn about this.
756 (
errmsg(
"changing the foreign-data wrapper validator can cause "
757 "the options for dependent objects to become invalid")));
762 * Validator is not changed, but we need it for validating options.
764 fdwvalidator = fdwForm->fdwvalidator;
768 * If options specified, validate and update.
772 /* Extract the current options */
775 Anum_pg_foreign_data_wrapper_fdwoptions,
780 /* Transform the options */
787 repl_val[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = datum;
789 repl_null[Anum_pg_foreign_data_wrapper_fdwoptions - 1] =
true;
791 repl_repl[Anum_pg_foreign_data_wrapper_fdwoptions - 1] =
true;
794 /* Everything looks good - update the tuple */
796 repl_val, repl_null, repl_repl);
804 /* Update function dependencies if we changed them */
805 if (handler_given || validator_given)
810 * Flush all existing dependency records of this FDW on functions; we
811 * assume there can be none other than the ones we are fixing.
818 /* And build new ones. */
822 referenced.
classId = ProcedureRelationId;
830 referenced.
classId = ProcedureRelationId;
846 * Create a foreign server
854 bool nulls[Natts_pg_foreign_server];
865 /* For now the owner cannot be specified on create. Use effective user ID. */
869 * Check that there is no other foreign server by this name. If there is
870 * one, do nothing if IF NOT EXISTS was specified.
875 if (
stmt->if_not_exists)
878 * If we are in an extension script, insist that the pre-existing
879 * object be a member of the extension, to avoid security risks.
887 errmsg(
"server \"%s\" already exists, skipping",
895 errmsg(
"server \"%s\" already exists",
900 * Check that the FDW exists and that we have USAGE on it. Also get the
901 * actual FDW for option validation etc.
910 * Insert tuple into pg_foreign_server.
913 memset(nulls,
false,
sizeof(nulls));
916 Anum_pg_foreign_server_oid);
918 values[Anum_pg_foreign_server_srvname - 1] =
923 /* Add server type if supplied */
924 if (
stmt->servertype)
925 values[Anum_pg_foreign_server_srvtype - 1] =
928 nulls[Anum_pg_foreign_server_srvtype - 1] =
true;
930 /* Add server version if supplied */
932 values[Anum_pg_foreign_server_srvversion - 1] =
935 nulls[Anum_pg_foreign_server_srvversion - 1] =
true;
937 /* Start with a blank acl */
938 nulls[Anum_pg_foreign_server_srvacl - 1] =
true;
940 /* Add server options */
947 values[Anum_pg_foreign_server_srvoptions - 1] = srvoptions;
949 nulls[Anum_pg_foreign_server_srvoptions - 1] =
true;
957 /* record dependencies */
958 myself.
classId = ForeignServerRelationId;
962 referenced.
classId = ForeignDataWrapperRelationId;
969 /* dependency on extension */
972 /* Post creation hook for new foreign server */
982 * Alter foreign server
989 Datum repl_val[Natts_pg_foreign_server];
990 bool repl_null[Natts_pg_foreign_server];
991 bool repl_repl[Natts_pg_foreign_server];
1003 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1004 errmsg(
"server \"%s\" does not exist",
stmt->servername)));
1007 srvId = srvForm->oid;
1010 * Only owner or a superuser can ALTER a SERVER.
1016 memset(repl_val, 0,
sizeof(repl_val));
1017 memset(repl_null,
false,
sizeof(repl_null));
1018 memset(repl_repl,
false,
sizeof(repl_repl));
1020 if (
stmt->has_version)
1023 * Change the server VERSION string.
1026 repl_val[Anum_pg_foreign_server_srvversion - 1] =
1029 repl_null[Anum_pg_foreign_server_srvversion - 1] =
true;
1031 repl_repl[Anum_pg_foreign_server_srvversion - 1] =
true;
1040 /* Extract the current srvoptions */
1043 Anum_pg_foreign_server_srvoptions,
1048 /* Prepare the options array */
1055 repl_val[Anum_pg_foreign_server_srvoptions - 1] = datum;
1057 repl_null[Anum_pg_foreign_server_srvoptions - 1] =
true;
1059 repl_repl[Anum_pg_foreign_server_srvoptions - 1] =
true;
1062 /* Everything looks good - update the tuple */
1064 repl_val, repl_null, repl_repl);
1081 * Common routine to check permission for user-mapping-related DDL
1082 * commands. We allow server owners to operate on any mapping, and
1083 * users to operate on their own mapping.
1092 if (umuserid == curuserid)
1108 * Create user mapping
1116 bool nulls[Natts_pg_user_mapping];
1133 /* Check that the server exists. */
1139 * Check that the user mapping is unique within server.
1141 umId =
GetSysCacheOid2(USERMAPPINGUSERSERVER, Anum_pg_user_mapping_oid,
1147 if (
stmt->if_not_exists)
1150 * Since user mappings aren't members of extensions (see comments
1151 * below), no need for checkMembershipInCurrentExtension here.
1155 errmsg(
"user mapping for \"%s\" already exists for server \"%s\", skipping",
1157 stmt->servername)));
1165 errmsg(
"user mapping for \"%s\" already exists for server \"%s\"",
1167 stmt->servername)));
1173 * Insert tuple into pg_user_mapping.
1176 memset(nulls,
false,
sizeof(nulls));
1179 Anum_pg_user_mapping_oid);
1184 /* Add user options */
1191 values[Anum_pg_user_mapping_umoptions - 1] = useoptions;
1193 nulls[Anum_pg_user_mapping_umoptions - 1] =
true;
1201 /* Add dependency on the server */
1202 myself.
classId = UserMappingRelationId;
1206 referenced.
classId = ForeignServerRelationId;
1213 /* Record the mapped user dependency */
1218 * Perhaps someday there should be a recordDependencyOnCurrentExtension
1219 * call here; but since roles aren't members of extensions, it seems like
1220 * user mappings shouldn't be either. Note that the grammar and pg_dump
1221 * would need to be extended too if we change this.
1224 /* Post creation hook for new user mapping */
1234 * Alter user mapping
1241 Datum repl_val[Natts_pg_user_mapping];
1242 bool repl_null[Natts_pg_user_mapping];
1243 bool repl_repl[Natts_pg_user_mapping];
1259 umId =
GetSysCacheOid2(USERMAPPINGUSERSERVER, Anum_pg_user_mapping_oid,
1264 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1265 errmsg(
"user mapping for \"%s\" does not exist for server \"%s\"",
1273 elog(
ERROR,
"cache lookup failed for user mapping %u", umId);
1275 memset(repl_val, 0,
sizeof(repl_val));
1276 memset(repl_null,
false,
sizeof(repl_null));
1277 memset(repl_repl,
false,
sizeof(repl_repl));
1286 * Process the options.
1293 Anum_pg_user_mapping_umoptions,
1298 /* Prepare the options array */
1305 repl_val[Anum_pg_user_mapping_umoptions - 1] = datum;
1307 repl_null[Anum_pg_user_mapping_umoptions - 1] =
true;
1309 repl_repl[Anum_pg_user_mapping_umoptions - 1] =
true;
1312 /* Everything looks good - update the tuple */
1314 repl_val, repl_null, repl_repl);
1351 * IF EXISTS specified, role not found and not public. Notice this
1354 elog(
NOTICE,
"role \"%s\" does not exist, skipping",
1364 if (!
stmt->missing_ok)
1366 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1367 errmsg(
"server \"%s\" does not exist",
1368 stmt->servername)));
1369 /* IF EXISTS, just note it */
1371 (
errmsg(
"server \"%s\" does not exist, skipping",
1372 stmt->servername)));
1376 umId =
GetSysCacheOid2(USERMAPPINGUSERSERVER, Anum_pg_user_mapping_oid,
1382 if (!
stmt->missing_ok)
1384 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1385 errmsg(
"user mapping for \"%s\" does not exist for server \"%s\"",
1388 /* IF EXISTS specified, just note it */
1390 (
errmsg(
"user mapping for \"%s\" does not exist for server \"%s\", skipping",
1400 object.classId = UserMappingRelationId;
1401 object.objectId = umId;
1402 object.objectSubId = 0;
1411 * Create a foreign table
1412 * call after DefineRelation().
1420 bool nulls[Natts_pg_foreign_table];
1430 * Advance command counter to ensure the pg_attribute tuple is visible;
1431 * the tuple might be updated to add constraints in previous step.
1438 * For now the owner cannot be specified on create. Use effective user ID.
1443 * Check that the foreign server exists and that we have USAGE on it. Also
1444 * get the actual FDW for option validation etc.
1454 * Insert tuple into pg_foreign_table.
1457 memset(nulls,
false,
sizeof(nulls));
1461 /* Add table generic options */
1468 values[Anum_pg_foreign_table_ftoptions - 1] = ftoptions;
1470 nulls[Anum_pg_foreign_table_ftoptions - 1] =
true;
1478 /* Add pg_class dependency on the server */
1479 myself.
classId = RelationRelationId;
1483 referenced.
classId = ForeignServerRelationId;
1492 * Import a foreign schema
1504 /* Check that the foreign server exists and that we have USAGE on it */
1510 /* Check that the schema exists and we have CREATE permissions on it */
1513 /* Get the FDW and check it supports IMPORT */
1517 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1518 errmsg(
"foreign-data wrapper \"%s\" has no handler",
1523 (
errcode(ERRCODE_FDW_NO_SCHEMAS),
1524 errmsg(
"foreign-data wrapper \"%s\" does not support IMPORT FOREIGN SCHEMA",
1527 /* Call FDW to get a list of commands */
1530 /* Parse and execute each command */
1531 foreach(lc, cmd_list)
1533 char *cmd = (
char *)
lfirst(lc);
1536 List *raw_parsetree_list;
1540 * Setup error traceback support for ereport(). This is so that any
1541 * error in the generated SQL will be displayed nicely.
1543 callback_arg.
tablename = NULL;
/* not known yet */
1544 callback_arg.
cmd = cmd;
1546 sqlerrcontext.
arg = &callback_arg;
1551 * Parse the SQL string into a list of raw parse trees.
1556 * Process each parse tree (we allow the FDW to put more than one
1557 * command per string, though this isn't really advised).
1559 foreach(lc2, raw_parsetree_list)
1566 * Because we only allow CreateForeignTableStmt, we can skip parse
1567 * analysis, rewrite, and planning steps here.
1571 "foreign-data wrapper \"%s\" returned incorrect statement type %d",
1574 /* Ignore commands for tables excluded by filter options */
1578 /* Enable reporting of current table's name on error */
1581 /* Ensure creation schema is the one given in IMPORT statement */
1584 /* No planning needed, just make a wrapper PlannedStmt */
1587 pstmt->canSetTag =
false;
1588 pstmt->utilityStmt = (
Node *) cstmt;
1593 /* Execute statement */
1598 /* Be sure to advance the command counter between subcommands */
1609 * error context callback to let us supply the failing SQL statement's text
1615 int syntaxerrposition;
1617 /* If it's a syntax error, convert to internal syntax error report */
1619 if (syntaxerrposition > 0)
Acl * aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
void check_can_set_role(Oid member, Oid role)
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
ArrayType * construct_empty_array(Oid elmtype)
Datum makeArrayResult(ArrayBuildState *astate, MemoryContext rcontext)
static Datum values[MAXATTR]
#define CStringGetTextDatum(s)
#define OidIsValid(objectId)
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
char * defGetString(DefElem *def)
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
DestReceiver * None_Receiver
int internalerrquery(const char *query)
int internalerrposition(int cursorpos)
ErrorContextCallback * error_context_stack
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
int errposition(int cursorpos)
#define ereport(elevel,...)
#define DirectFunctionCall1(func, arg1)
#define OidFunctionCall2(functionId, arg1, arg2)
ForeignDataWrapper * GetForeignDataWrapper(Oid fdwid)
ForeignServer * GetForeignServerByName(const char *srvname, bool missing_ok)
Oid get_foreign_server_oid(const char *servername, bool missing_ok)
ForeignDataWrapper * GetForeignDataWrapperByName(const char *fdwname, bool missing_ok)
bool IsImportableForeignTable(const char *tablename, ImportForeignSchemaStmt *stmt)
FdwRoutine * GetFdwRoutine(Oid fdwhandler)
#define MappingUserName(userid)
static void AlterForeignServerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
static Oid lookup_fdw_handler_func(DefElem *handler)
ObjectAddress AlterForeignServerOwner(const char *name, Oid newOwnerId)
static void import_error_callback(void *arg)
void AlterForeignServerOwner_oid(Oid srvId, Oid newOwnerId)
void ImportForeignSchema(ImportForeignSchemaStmt *stmt)
ObjectAddress AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId)
ObjectAddress AlterForeignServer(AlterForeignServerStmt *stmt)
static Datum optionListToArray(List *options)
static void AlterForeignDataWrapperOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
static Oid lookup_fdw_validator_func(DefElem *validator)
void AlterForeignDataWrapperOwner_oid(Oid fwdId, Oid newOwnerId)
static void user_mapping_ddl_aclcheck(Oid umuserid, Oid serverid, const char *servername)
ObjectAddress AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt)
ObjectAddress CreateForeignServer(CreateForeignServerStmt *stmt)
Oid RemoveUserMapping(DropUserMappingStmt *stmt)
ObjectAddress CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt)
static void parse_func_options(ParseState *pstate, List *func_options, bool *handler_given, Oid *fdwhandler, bool *validator_given, Oid *fdwvalidator)
ObjectAddress AlterUserMapping(AlterUserMappingStmt *stmt)
void CreateForeignTable(CreateForeignTableStmt *stmt, Oid relid)
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
ObjectAddress CreateUserMapping(CreateUserMappingStmt *stmt)
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
void heap_freetuple(HeapTuple htup)
#define HeapTupleIsValid(tuple)
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
static void * GETSTRUCT(const HeapTupleData *tuple)
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
if(TABLE==NULL||TABLE_index==NULL)
List * lappend(List *list, void *datum)
List * list_delete_cell(List *list, ListCell *cell)
Oid get_func_rettype(Oid funcid)
char * pstrdup(const char *in)
MemoryContext CurrentMemoryContext
Datum namein(PG_FUNCTION_ARGS)
char * NameListToString(const List *names)
Oid LookupCreationNamespace(const char *nspname)
#define IsA(nodeptr, _type_)
#define InvokeObjectPostCreateHook(classId, objectId, subId)
#define InvokeObjectPostAlterHook(classId, objectId, subId)
const ObjectAddress InvalidObjectAddress
#define ObjectAddressSet(addr, class_id, object_id)
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
void checkMembershipInCurrentExtension(const ObjectAddress *object)
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
FormData_pg_foreign_data_wrapper * Form_pg_foreign_data_wrapper
FormData_pg_foreign_server * Form_pg_foreign_server
#define lfirst_node(type, lc)
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
List * pg_parse_query(const char *query_string)
static Datum PointerGetDatum(const void *X)
static Datum ObjectIdGetDatum(Oid X)
static Pointer DatumGetPointer(Datum X)
static Datum CStringGetDatum(const char *X)
#define RelationGetDescr(relation)
List * untransformRelOptions(Datum options)
#define ERRCODE_DUPLICATE_OBJECT
struct ErrorContextCallback * previous
void(* callback)(void *arg)
ImportForeignSchema_function ImportForeignSchema
bool superuser_arg(Oid roleid)
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
#define SearchSysCacheCopy1(cacheId, key1)
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
void ProcessUtility(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
@ PROCESS_UTILITY_SUBCOMMAND
static char * VARDATA(const void *PTR)
static void SET_VARSIZE(void *PTR, Size len)
void CommandCounterIncrement(void)