PostgreSQL Source Code  git master
foreigncmds.c File Reference
#include "postgres.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "access/reloptions.h"
#include "access/xact.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_server.h"
#include "catalog/pg_foreign_table.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "catalog/pg_user_mapping.h"
#include "commands/defrem.h"
#include "foreign/fdwapi.h"
#include "foreign/foreign.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
#include "tcop/utility.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"
Include dependency graph for foreigncmds.c:

Go to the source code of this file.

Data Structures

struct  import_error_callback_arg
 

Functions

static void import_error_callback (void *arg)
 
static Datum optionListToArray (List *options)
 
Datum transformGenericOptions (Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
 
static void AlterForeignDataWrapperOwner_internal (Relation rel, HeapTuple tup, Oid newOwnerId)
 
ObjectAddress AlterForeignDataWrapperOwner (const char *name, Oid newOwnerId)
 
void AlterForeignDataWrapperOwner_oid (Oid fwdId, Oid newOwnerId)
 
static void AlterForeignServerOwner_internal (Relation rel, HeapTuple tup, Oid newOwnerId)
 
ObjectAddress AlterForeignServerOwner (const char *name, Oid newOwnerId)
 
void AlterForeignServerOwner_oid (Oid srvId, Oid newOwnerId)
 
static Oid lookup_fdw_handler_func (DefElem *handler)
 
static Oid lookup_fdw_validator_func (DefElem *validator)
 
static void parse_func_options (List *func_options, bool *handler_given, Oid *fdwhandler, bool *validator_given, Oid *fdwvalidator)
 
ObjectAddress CreateForeignDataWrapper (CreateFdwStmt *stmt)
 
ObjectAddress AlterForeignDataWrapper (AlterFdwStmt *stmt)
 
void RemoveForeignDataWrapperById (Oid fdwId)
 
ObjectAddress CreateForeignServer (CreateForeignServerStmt *stmt)
 
ObjectAddress AlterForeignServer (AlterForeignServerStmt *stmt)
 
void RemoveForeignServerById (Oid srvId)
 
static void user_mapping_ddl_aclcheck (Oid umuserid, Oid serverid, const char *servername)
 
ObjectAddress CreateUserMapping (CreateUserMappingStmt *stmt)
 
ObjectAddress AlterUserMapping (AlterUserMappingStmt *stmt)
 
Oid RemoveUserMapping (DropUserMappingStmt *stmt)
 
void RemoveUserMappingById (Oid umId)
 
void CreateForeignTable (CreateForeignTableStmt *stmt, Oid relid)
 
void ImportForeignSchema (ImportForeignSchemaStmt *stmt)
 

Function Documentation

◆ AlterForeignDataWrapper()

ObjectAddress AlterForeignDataWrapper ( AlterFdwStmt stmt)

Definition at line 673 of file foreigncmds.c.

References Anum_pg_foreign_data_wrapper_fdwhandler, Anum_pg_foreign_data_wrapper_fdwoptions, Anum_pg_foreign_data_wrapper_fdwvalidator, CatalogTupleUpdate(), ObjectAddress::classId, CStringGetDatum, DatumGetPointer, deleteDependencyRecordsForClass(), DEPENDENCY_NORMAL, ereport, errcode(), errhint(), errmsg(), ERROR, AlterFdwStmt::fdwname, FOREIGNDATAWRAPPERNAME, FOREIGNDATAWRAPPEROID, ForeignDataWrapperRelationId, AlterFdwStmt::func_options, GETSTRUCT, heap_close, heap_freetuple(), heap_modify_tuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, InvokeObjectPostAlterHook, Natts_pg_foreign_data_wrapper, ObjectAddressSet, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, AlterFdwStmt::options, parse_func_options(), PointerGetDatum, PointerIsValid, ProcedureRelationId, recordDependencyOn(), RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy1, superuser(), SysCacheGetAttr(), HeapTupleData::t_self, transformGenericOptions(), and WARNING.

Referenced by ProcessUtilitySlow().

674 {
675  Relation rel;
676  HeapTuple tp;
679  bool repl_null[Natts_pg_foreign_data_wrapper];
680  bool repl_repl[Natts_pg_foreign_data_wrapper];
681  Oid fdwId;
682  bool isnull;
683  Datum datum;
684  bool handler_given;
685  bool validator_given;
686  Oid fdwhandler;
687  Oid fdwvalidator;
688  ObjectAddress myself;
689 
691 
692  /* Must be super user */
693  if (!superuser())
694  ereport(ERROR,
695  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
696  errmsg("permission denied to alter foreign-data wrapper \"%s\"",
697  stmt->fdwname),
698  errhint("Must be superuser to alter a foreign-data wrapper.")));
699 
701  CStringGetDatum(stmt->fdwname));
702 
703  if (!HeapTupleIsValid(tp))
704  ereport(ERROR,
705  (errcode(ERRCODE_UNDEFINED_OBJECT),
706  errmsg("foreign-data wrapper \"%s\" does not exist", stmt->fdwname)));
707 
708  fdwForm = (Form_pg_foreign_data_wrapper) GETSTRUCT(tp);
709  fdwId = HeapTupleGetOid(tp);
710 
711  memset(repl_val, 0, sizeof(repl_val));
712  memset(repl_null, false, sizeof(repl_null));
713  memset(repl_repl, false, sizeof(repl_repl));
714 
716  &handler_given, &fdwhandler,
717  &validator_given, &fdwvalidator);
718 
719  if (handler_given)
720  {
721  repl_val[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = ObjectIdGetDatum(fdwhandler);
722  repl_repl[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = true;
723 
724  /*
725  * It could be that the behavior of accessing foreign table changes
726  * with the new handler. Warn about this.
727  */
729  (errmsg("changing the foreign-data wrapper handler can change behavior of existing foreign tables")));
730  }
731 
732  if (validator_given)
733  {
734  repl_val[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = ObjectIdGetDatum(fdwvalidator);
735  repl_repl[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = true;
736 
737  /*
738  * It could be that existing options for the FDW or dependent SERVER,
739  * USER MAPPING or FOREIGN TABLE objects are no longer valid according
740  * to the new validator. Warn about this.
741  */
742  if (OidIsValid(fdwvalidator))
744  (errmsg("changing the foreign-data wrapper validator can cause "
745  "the options for dependent objects to become invalid")));
746  }
747  else
748  {
749  /*
750  * Validator is not changed, but we need it for validating options.
751  */
752  fdwvalidator = fdwForm->fdwvalidator;
753  }
754 
755  /*
756  * If options specified, validate and update.
757  */
758  if (stmt->options)
759  {
760  /* Extract the current options */
762  tp,
764  &isnull);
765  if (isnull)
766  datum = PointerGetDatum(NULL);
767 
768  /* Transform the options */
770  datum,
771  stmt->options,
772  fdwvalidator);
773 
774  if (PointerIsValid(DatumGetPointer(datum)))
775  repl_val[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = datum;
776  else
777  repl_null[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = true;
778 
779  repl_repl[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = true;
780  }
781 
782  /* Everything looks good - update the tuple */
783  tp = heap_modify_tuple(tp, RelationGetDescr(rel),
784  repl_val, repl_null, repl_repl);
785 
786  CatalogTupleUpdate(rel, &tp->t_self, tp);
787 
788  heap_freetuple(tp);
789 
791 
792  /* Update function dependencies if we changed them */
793  if (handler_given || validator_given)
794  {
795  ObjectAddress referenced;
796 
797  /*
798  * Flush all existing dependency records of this FDW on functions; we
799  * assume there can be none other than the ones we are fixing.
800  */
802  fdwId,
805 
806  /* And build new ones. */
807 
808  if (OidIsValid(fdwhandler))
809  {
810  referenced.classId = ProcedureRelationId;
811  referenced.objectId = fdwhandler;
812  referenced.objectSubId = 0;
813  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
814  }
815 
816  if (OidIsValid(fdwvalidator))
817  {
818  referenced.classId = ProcedureRelationId;
819  referenced.objectId = fdwvalidator;
820  referenced.objectSubId = 0;
821  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
822  }
823  }
824 
826 
828 
829  return myself;
830 }
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
static void parse_func_options(List *func_options, bool *handler_given, Oid *fdwhandler, bool *validator_given, Oid *fdwvalidator)
Definition: foreigncmds.c:516
#define RelationGetDescr(relation)
Definition: rel.h:437
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:109
#define PointerGetDatum(X)
Definition: postgres.h:562
#define ProcedureRelationId
Definition: pg_proc.h:33
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
#define Anum_pg_foreign_data_wrapper_fdwhandler
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:586
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:584
char * fdwname
Definition: parsenodes.h:2221
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
List * func_options
Definition: parsenodes.h:2222
#define WARNING
Definition: elog.h:40
uintptr_t Datum
Definition: postgres.h:372
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:241
#define Anum_pg_foreign_data_wrapper_fdwvalidator
#define Natts_pg_foreign_data_wrapper
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
FormData_pg_foreign_data_wrapper * Form_pg_foreign_data_wrapper
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define ForeignDataWrapperRelationId
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define DatumGetPointer(X)
Definition: postgres.h:555
List * options
Definition: parsenodes.h:2223
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
#define PointerIsValid(pointer)
Definition: c.h:574
#define Anum_pg_foreign_data_wrapper_fdwoptions

◆ AlterForeignDataWrapperOwner()

ObjectAddress AlterForeignDataWrapperOwner ( const char *  name,
Oid  newOwnerId 
)

Definition at line 277 of file foreigncmds.c.

References AlterForeignDataWrapperOwner_internal(), CStringGetDatum, ereport, errcode(), errmsg(), ERROR, FOREIGNDATAWRAPPERNAME, ForeignDataWrapperRelationId, heap_close, heap_freetuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, ObjectAddressSet, RowExclusiveLock, and SearchSysCacheCopy1.

Referenced by ExecAlterOwnerStmt().

278 {
279  Oid fdwId;
280  HeapTuple tup;
281  Relation rel;
282  ObjectAddress address;
283 
285 
287 
288  if (!HeapTupleIsValid(tup))
289  ereport(ERROR,
290  (errcode(ERRCODE_UNDEFINED_OBJECT),
291  errmsg("foreign-data wrapper \"%s\" does not exist", name)));
292 
293  fdwId = HeapTupleGetOid(tup);
294 
295  AlterForeignDataWrapperOwner_internal(rel, tup, newOwnerId);
296 
298 
299  heap_freetuple(tup);
300 
302 
303  return address;
304 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:584
#define ereport(elevel, rest)
Definition: elog.h:122
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define ForeignDataWrapperRelationId
const char * name
Definition: encode.c:521
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void AlterForeignDataWrapperOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
Definition: foreigncmds.c:207
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700

◆ AlterForeignDataWrapperOwner_internal()

static void AlterForeignDataWrapperOwner_internal ( Relation  rel,
HeapTuple  tup,
Oid  newOwnerId 
)
static

Definition at line 207 of file foreigncmds.c.

References aclnewowner(), Anum_pg_foreign_data_wrapper_fdwacl, Anum_pg_foreign_data_wrapper_fdwowner, CatalogTupleUpdate(), changeDependencyOnOwner(), DatumGetAclP, ereport, errcode(), errhint(), errmsg(), ERROR, ForeignDataWrapperRelationId, GETSTRUCT, heap_getattr, heap_modify_tuple(), HeapTupleGetOid, InvokeObjectPostAlterHook, NameStr, Natts_pg_foreign_data_wrapper, ObjectIdGetDatum, PointerGetDatum, RelationGetDescr, superuser(), superuser_arg(), and HeapTupleData::t_self.

Referenced by AlterForeignDataWrapperOwner(), and AlterForeignDataWrapperOwner_oid().

208 {
211  bool repl_null[Natts_pg_foreign_data_wrapper];
212  bool repl_repl[Natts_pg_foreign_data_wrapper];
213  Acl *newAcl;
214  Datum aclDatum;
215  bool isNull;
216 
218 
219  /* Must be a superuser to change a FDW owner */
220  if (!superuser())
221  ereport(ERROR,
222  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
223  errmsg("permission denied to change owner of foreign-data wrapper \"%s\"",
224  NameStr(form->fdwname)),
225  errhint("Must be superuser to change owner of a foreign-data wrapper.")));
226 
227  /* New owner must also be a superuser */
228  if (!superuser_arg(newOwnerId))
229  ereport(ERROR,
230  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
231  errmsg("permission denied to change owner of foreign-data wrapper \"%s\"",
232  NameStr(form->fdwname)),
233  errhint("The owner of a foreign-data wrapper must be a superuser.")));
234 
235  if (form->fdwowner != newOwnerId)
236  {
237  memset(repl_null, false, sizeof(repl_null));
238  memset(repl_repl, false, sizeof(repl_repl));
239 
240  repl_repl[Anum_pg_foreign_data_wrapper_fdwowner - 1] = true;
241  repl_val[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(newOwnerId);
242 
243  aclDatum = heap_getattr(tup,
245  RelationGetDescr(rel),
246  &isNull);
247  /* Null ACLs do not require changes */
248  if (!isNull)
249  {
250  newAcl = aclnewowner(DatumGetAclP(aclDatum),
251  form->fdwowner, newOwnerId);
252  repl_repl[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
254  }
255 
256  tup = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null,
257  repl_repl);
258 
259  CatalogTupleUpdate(rel, &tup->t_self, tup);
260 
261  /* Update owner dependency reference */
263  HeapTupleGetOid(tup),
264  newOwnerId);
265  }
266 
268  HeapTupleGetOid(tup), 0);
269 }
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define Anum_pg_foreign_data_wrapper_fdwowner
#define RelationGetDescr(relation)
Definition: rel.h:437
#define DatumGetAclP(X)
Definition: acl.h:121
#define PointerGetDatum(X)
Definition: postgres.h:562
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
#define Anum_pg_foreign_data_wrapper_fdwacl
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
Definition: pg_shdepend.c:304
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
bool superuser_arg(Oid roleid)
Definition: superuser.c:57
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:774
uintptr_t Datum
Definition: postgres.h:372
#define Natts_pg_foreign_data_wrapper
FormData_pg_foreign_data_wrapper * Form_pg_foreign_data_wrapper
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define ForeignDataWrapperRelationId
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:557
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
Acl * aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
Definition: acl.c:1052

◆ AlterForeignDataWrapperOwner_oid()

void AlterForeignDataWrapperOwner_oid ( Oid  fwdId,
Oid  newOwnerId 
)

Definition at line 312 of file foreigncmds.c.

References AlterForeignDataWrapperOwner_internal(), ereport, errcode(), errmsg(), ERROR, FOREIGNDATAWRAPPEROID, ForeignDataWrapperRelationId, heap_close, heap_freetuple(), heap_open(), HeapTupleIsValid, ObjectIdGetDatum, RowExclusiveLock, and SearchSysCacheCopy1.

Referenced by shdepReassignOwned().

313 {
314  HeapTuple tup;
315  Relation rel;
316 
318 
320 
321  if (!HeapTupleIsValid(tup))
322  ereport(ERROR,
323  (errcode(ERRCODE_UNDEFINED_OBJECT),
324  errmsg("foreign-data wrapper with OID %u does not exist", fwdId)));
325 
326  AlterForeignDataWrapperOwner_internal(rel, tup, newOwnerId);
327 
328  heap_freetuple(tup);
329 
331 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define ForeignDataWrapperRelationId
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void AlterForeignDataWrapperOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
Definition: foreigncmds.c:207

◆ AlterForeignServer()

ObjectAddress AlterForeignServer ( AlterForeignServerStmt stmt)

Definition at line 985 of file foreigncmds.c.

References ACL_KIND_FOREIGN_SERVER, aclcheck_error(), ACLCHECK_NOT_OWNER, Anum_pg_foreign_server_srvoptions, Anum_pg_foreign_server_srvversion, CatalogTupleUpdate(), CStringGetDatum, CStringGetTextDatum, DatumGetPointer, ereport, errcode(), errmsg(), ERROR, ForeignDataWrapper::fdwvalidator, FOREIGNSERVERNAME, FOREIGNSERVEROID, ForeignServerRelationId, GetForeignDataWrapper(), GETSTRUCT, GetUserId(), AlterForeignServerStmt::has_version, heap_close, heap_freetuple(), heap_modify_tuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, InvokeObjectPostAlterHook, Natts_pg_foreign_server, ObjectAddressSet, AlterForeignServerStmt::options, pg_foreign_server_ownercheck(), PointerGetDatum, PointerIsValid, RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy1, AlterForeignServerStmt::servername, SysCacheGetAttr(), HeapTupleData::t_self, transformGenericOptions(), and AlterForeignServerStmt::version.

Referenced by ProcessUtilitySlow().

986 {
987  Relation rel;
988  HeapTuple tp;
989  Datum repl_val[Natts_pg_foreign_server];
990  bool repl_null[Natts_pg_foreign_server];
991  bool repl_repl[Natts_pg_foreign_server];
992  Oid srvId;
993  Form_pg_foreign_server srvForm;
994  ObjectAddress address;
995 
997 
999  CStringGetDatum(stmt->servername));
1000 
1001  if (!HeapTupleIsValid(tp))
1002  ereport(ERROR,
1003  (errcode(ERRCODE_UNDEFINED_OBJECT),
1004  errmsg("server \"%s\" does not exist", stmt->servername)));
1005 
1006  srvId = HeapTupleGetOid(tp);
1007  srvForm = (Form_pg_foreign_server) GETSTRUCT(tp);
1008 
1009  /*
1010  * Only owner or a superuser can ALTER a SERVER.
1011  */
1012  if (!pg_foreign_server_ownercheck(srvId, GetUserId()))
1014  stmt->servername);
1015 
1016  memset(repl_val, 0, sizeof(repl_val));
1017  memset(repl_null, false, sizeof(repl_null));
1018  memset(repl_repl, false, sizeof(repl_repl));
1019 
1020  if (stmt->has_version)
1021  {
1022  /*
1023  * Change the server VERSION string.
1024  */
1025  if (stmt->version)
1026  repl_val[Anum_pg_foreign_server_srvversion - 1] =
1028  else
1029  repl_null[Anum_pg_foreign_server_srvversion - 1] = true;
1030 
1031  repl_repl[Anum_pg_foreign_server_srvversion - 1] = true;
1032  }
1033 
1034  if (stmt->options)
1035  {
1036  ForeignDataWrapper *fdw = GetForeignDataWrapper(srvForm->srvfdw);
1037  Datum datum;
1038  bool isnull;
1039 
1040  /* Extract the current srvoptions */
1042  tp,
1044  &isnull);
1045  if (isnull)
1046  datum = PointerGetDatum(NULL);
1047 
1048  /* Prepare the options array */
1050  datum,
1051  stmt->options,
1052  fdw->fdwvalidator);
1053 
1054  if (PointerIsValid(DatumGetPointer(datum)))
1055  repl_val[Anum_pg_foreign_server_srvoptions - 1] = datum;
1056  else
1057  repl_null[Anum_pg_foreign_server_srvoptions - 1] = true;
1058 
1059  repl_repl[Anum_pg_foreign_server_srvoptions - 1] = true;
1060  }
1061 
1062  /* Everything looks good - update the tuple */
1063  tp = heap_modify_tuple(tp, RelationGetDescr(rel),
1064  repl_val, repl_null, repl_repl);
1065 
1066  CatalogTupleUpdate(rel, &tp->t_self, tp);
1067 
1069 
1070  ObjectAddressSet(address, ForeignServerRelationId, srvId);
1071 
1072  heap_freetuple(tp);
1073 
1075 
1076  return address;
1077 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define RelationGetDescr(relation)
Definition: rel.h:437
Oid GetUserId(void)
Definition: miscinit.c:284
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:109
#define Anum_pg_foreign_server_srvversion
#define PointerGetDatum(X)
Definition: postgres.h:562
bool pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid)
Definition: aclchk.c:4968
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
ForeignDataWrapper * GetForeignDataWrapper(Oid fdwid)
Definition: foreign.c:35
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:584
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
#define Natts_pg_foreign_server
uintptr_t Datum
Definition: postgres.h:372
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
FormData_pg_foreign_server * Form_pg_foreign_server
#define ForeignServerRelationId
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define DatumGetPointer(X)
Definition: postgres.h:555
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define CStringGetTextDatum(s)
Definition: builtins.h:91
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
#define Anum_pg_foreign_server_srvoptions
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
#define PointerIsValid(pointer)
Definition: c.h:574

◆ AlterForeignServerOwner()

ObjectAddress AlterForeignServerOwner ( const char *  name,
Oid  newOwnerId 
)

Definition at line 414 of file foreigncmds.c.

References AlterForeignServerOwner_internal(), CStringGetDatum, ereport, errcode(), errmsg(), ERROR, FOREIGNSERVERNAME, ForeignServerRelationId, heap_close, heap_freetuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, ObjectAddressSet, RowExclusiveLock, and SearchSysCacheCopy1.

Referenced by ExecAlterOwnerStmt().

415 {
416  Oid servOid;
417  HeapTuple tup;
418  Relation rel;
419  ObjectAddress address;
420 
422 
424 
425  if (!HeapTupleIsValid(tup))
426  ereport(ERROR,
427  (errcode(ERRCODE_UNDEFINED_OBJECT),
428  errmsg("server \"%s\" does not exist", name)));
429 
430  servOid = HeapTupleGetOid(tup);
431 
432  AlterForeignServerOwner_internal(rel, tup, newOwnerId);
433 
434  ObjectAddressSet(address, ForeignServerRelationId, servOid);
435 
436  heap_freetuple(tup);
437 
439 
440  return address;
441 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:584
#define ereport(elevel, rest)
Definition: elog.h:122
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define ForeignServerRelationId
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
static void AlterForeignServerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
Definition: foreigncmds.c:337
const char * name
Definition: encode.c:521
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700

◆ AlterForeignServerOwner_internal()

static void AlterForeignServerOwner_internal ( Relation  rel,
HeapTuple  tup,
Oid  newOwnerId 
)
static

Definition at line 337 of file foreigncmds.c.

References ACL_KIND_FDW, ACL_KIND_FOREIGN_SERVER, ACL_USAGE, aclcheck_error(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, aclnewowner(), Anum_pg_foreign_server_srvacl, Anum_pg_foreign_server_srvowner, CatalogTupleUpdate(), changeDependencyOnOwner(), check_is_member_of_role(), DatumGetAclP, ForeignDataWrapper::fdwname, ForeignServerRelationId, GetForeignDataWrapper(), GETSTRUCT, GetUserId(), heap_getattr, heap_modify_tuple(), HeapTupleGetOid, InvokeObjectPostAlterHook, NameStr, Natts_pg_foreign_server, ObjectIdGetDatum, pg_foreign_data_wrapper_aclcheck(), pg_foreign_server_ownercheck(), PointerGetDatum, RelationGetDescr, superuser(), and HeapTupleData::t_self.

Referenced by AlterForeignServerOwner(), and AlterForeignServerOwner_oid().

338 {
340  Datum repl_val[Natts_pg_foreign_server];
341  bool repl_null[Natts_pg_foreign_server];
342  bool repl_repl[Natts_pg_foreign_server];
343  Acl *newAcl;
344  Datum aclDatum;
345  bool isNull;
346 
347  form = (Form_pg_foreign_server) GETSTRUCT(tup);
348 
349  if (form->srvowner != newOwnerId)
350  {
351  /* Superusers can always do it */
352  if (!superuser())
353  {
354  Oid srvId;
355  AclResult aclresult;
356 
357  srvId = HeapTupleGetOid(tup);
358 
359  /* Must be owner */
362  NameStr(form->srvname));
363 
364  /* Must be able to become new owner */
365  check_is_member_of_role(GetUserId(), newOwnerId);
366 
367  /* New owner must have USAGE privilege on foreign-data wrapper */
368  aclresult = pg_foreign_data_wrapper_aclcheck(form->srvfdw, newOwnerId, ACL_USAGE);
369  if (aclresult != ACLCHECK_OK)
370  {
371  ForeignDataWrapper *fdw = GetForeignDataWrapper(form->srvfdw);
372 
373  aclcheck_error(aclresult, ACL_KIND_FDW, fdw->fdwname);
374  }
375  }
376 
377  memset(repl_null, false, sizeof(repl_null));
378  memset(repl_repl, false, sizeof(repl_repl));
379 
380  repl_repl[Anum_pg_foreign_server_srvowner - 1] = true;
381  repl_val[Anum_pg_foreign_server_srvowner - 1] = ObjectIdGetDatum(newOwnerId);
382 
383  aclDatum = heap_getattr(tup,
385  RelationGetDescr(rel),
386  &isNull);
387  /* Null ACLs do not require changes */
388  if (!isNull)
389  {
390  newAcl = aclnewowner(DatumGetAclP(aclDatum),
391  form->srvowner, newOwnerId);
392  repl_repl[Anum_pg_foreign_server_srvacl - 1] = true;
393  repl_val[Anum_pg_foreign_server_srvacl - 1] = PointerGetDatum(newAcl);
394  }
395 
396  tup = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null,
397  repl_repl);
398 
399  CatalogTupleUpdate(rel, &tup->t_self, tup);
400 
401  /* Update owner dependency reference */
403  newOwnerId);
404  }
405 
407  HeapTupleGetOid(tup), 0);
408 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define RelationGetDescr(relation)
Definition: rel.h:437
Oid GetUserId(void)
Definition: miscinit.c:284
char * fdwname
Definition: foreign.h:39
#define DatumGetAclP(X)
Definition: acl.h:121
#define PointerGetDatum(X)
Definition: postgres.h:562
AclResult pg_foreign_data_wrapper_aclcheck(Oid fdw_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4567
bool pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid)
Definition: aclchk.c:4968
bool superuser(void)
Definition: superuser.c:47
unsigned int Oid
Definition: postgres_ext.h:31
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
Definition: pg_shdepend.c:304
ForeignDataWrapper * GetForeignDataWrapper(Oid fdwid)
Definition: foreign.c:35
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
ItemPointerData t_self
Definition: htup.h:65
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457
#define ACL_USAGE
Definition: parsenodes.h:80
void check_is_member_of_role(Oid member, Oid role)
Definition: acl.c:4879
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
#define Anum_pg_foreign_server_srvacl
#define Natts_pg_foreign_server
#define Anum_pg_foreign_server_srvowner
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:774
AclResult
Definition: acl.h:178
uintptr_t Datum
Definition: postgres.h:372
FormData_pg_foreign_server * Form_pg_foreign_server
#define ForeignServerRelationId
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define NameStr(name)
Definition: c.h:557
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
Acl * aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
Definition: acl.c:1052

◆ AlterForeignServerOwner_oid()

void AlterForeignServerOwner_oid ( Oid  srvId,
Oid  newOwnerId 
)

Definition at line 447 of file foreigncmds.c.

References AlterForeignServerOwner_internal(), ereport, errcode(), errmsg(), ERROR, FOREIGNSERVEROID, ForeignServerRelationId, heap_close, heap_freetuple(), heap_open(), HeapTupleIsValid, ObjectIdGetDatum, RowExclusiveLock, and SearchSysCacheCopy1.

Referenced by shdepReassignOwned().

448 {
449  HeapTuple tup;
450  Relation rel;
451 
453 
455 
456  if (!HeapTupleIsValid(tup))
457  ereport(ERROR,
458  (errcode(ERRCODE_UNDEFINED_OBJECT),
459  errmsg("foreign server with OID %u does not exist", srvId)));
460 
461  AlterForeignServerOwner_internal(rel, tup, newOwnerId);
462 
463  heap_freetuple(tup);
464 
466 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define ForeignServerRelationId
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
static void AlterForeignServerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
Definition: foreigncmds.c:337
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ AlterUserMapping()

ObjectAddress AlterUserMapping ( AlterUserMappingStmt stmt)

Definition at line 1250 of file foreigncmds.c.

References ACL_ID_PUBLIC, Anum_pg_user_mapping_umoptions, CatalogTupleUpdate(), DatumGetPointer, elog, ereport, errcode(), errmsg(), ERROR, ForeignServer::fdwid, ForeignDataWrapper::fdwvalidator, get_rolespec_oid(), GetForeignDataWrapper(), GetForeignServerByName(), GetSysCacheOid2, heap_close, heap_freetuple(), heap_modify_tuple(), heap_open(), HeapTupleIsValid, MappingUserName, Natts_pg_user_mapping, ObjectAddressSet, ObjectIdGetDatum, OidIsValid, AlterUserMappingStmt::options, PointerGetDatum, PointerIsValid, RelationGetDescr, ROLESPEC_PUBLIC, RoleSpec::roletype, RowExclusiveLock, SearchSysCacheCopy1, ForeignServer::serverid, AlterUserMappingStmt::servername, SysCacheGetAttr(), HeapTupleData::t_self, transformGenericOptions(), AlterUserMappingStmt::user, user_mapping_ddl_aclcheck(), USERMAPPINGOID, and UserMappingRelationId.

Referenced by ProcessUtilitySlow().

1251 {
1252  Relation rel;
1253  HeapTuple tp;
1254  Datum repl_val[Natts_pg_user_mapping];
1255  bool repl_null[Natts_pg_user_mapping];
1256  bool repl_repl[Natts_pg_user_mapping];
1257  Oid useId;
1258  Oid umId;
1259  ForeignServer *srv;
1260  ObjectAddress address;
1261  RoleSpec *role = (RoleSpec *) stmt->user;
1262 
1264 
1265  if (role->roletype == ROLESPEC_PUBLIC)
1266  useId = ACL_ID_PUBLIC;
1267  else
1268  useId = get_rolespec_oid(stmt->user, false);
1269 
1270  srv = GetForeignServerByName(stmt->servername, false);
1271 
1272  umId = GetSysCacheOid2(USERMAPPINGUSERSERVER,
1273  ObjectIdGetDatum(useId),
1274  ObjectIdGetDatum(srv->serverid));
1275  if (!OidIsValid(umId))
1276  ereport(ERROR,
1277  (errcode(ERRCODE_UNDEFINED_OBJECT),
1278  errmsg("user mapping for \"%s\" does not exist for the server",
1279  MappingUserName(useId))));
1280 
1281  user_mapping_ddl_aclcheck(useId, srv->serverid, stmt->servername);
1282 
1284 
1285  if (!HeapTupleIsValid(tp))
1286  elog(ERROR, "cache lookup failed for user mapping %u", umId);
1287 
1288  memset(repl_val, 0, sizeof(repl_val));
1289  memset(repl_null, false, sizeof(repl_null));
1290  memset(repl_repl, false, sizeof(repl_repl));
1291 
1292  if (stmt->options)
1293  {
1294  ForeignDataWrapper *fdw;
1295  Datum datum;
1296  bool isnull;
1297 
1298  /*
1299  * Process the options.
1300  */
1301 
1302  fdw = GetForeignDataWrapper(srv->fdwid);
1303 
1304  datum = SysCacheGetAttr(USERMAPPINGUSERSERVER,
1305  tp,
1307  &isnull);
1308  if (isnull)
1309  datum = PointerGetDatum(NULL);
1310 
1311  /* Prepare the options array */
1313  datum,
1314  stmt->options,
1315  fdw->fdwvalidator);
1316 
1317  if (PointerIsValid(DatumGetPointer(datum)))
1318  repl_val[Anum_pg_user_mapping_umoptions - 1] = datum;
1319  else
1320  repl_null[Anum_pg_user_mapping_umoptions - 1] = true;
1321 
1322  repl_repl[Anum_pg_user_mapping_umoptions - 1] = true;
1323  }
1324 
1325  /* Everything looks good - update the tuple */
1326  tp = heap_modify_tuple(tp, RelationGetDescr(rel),
1327  repl_val, repl_null, repl_repl);
1328 
1329  CatalogTupleUpdate(rel, &tp->t_self, tp);
1330 
1331  ObjectAddressSet(address, UserMappingRelationId, umId);
1332 
1333  heap_freetuple(tp);
1334 
1336 
1337  return address;
1338 }
#define RelationGetDescr(relation)
Definition: rel.h:437
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:109
#define PointerGetDatum(X)
Definition: postgres.h:562
int errcode(int sqlerrcode)
Definition: elog.c:575
static void user_mapping_ddl_aclcheck(Oid umuserid, Oid serverid, const char *servername)
Definition: foreigncmds.c:1110
#define heap_close(r, l)
Definition: heapam.h:97
#define Natts_pg_user_mapping
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:586
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:193
ForeignDataWrapper * GetForeignDataWrapper(Oid fdwid)
Definition: foreign.c:35
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define Anum_pg_user_mapping_umoptions
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
ForeignServer * GetForeignServerByName(const char *srvname, bool missing_ok)
Definition: foreign.c:148
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
RoleSpecType roletype
Definition: parsenodes.h:327
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5149
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define DatumGetPointer(X)
Definition: postgres.h:555
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define UserMappingRelationId
#define ACL_ID_PUBLIC
Definition: acl.h:47
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
#define PointerIsValid(pointer)
Definition: c.h:574
Oid serverid
Definition: foreign.h:47
#define MappingUserName(userid)
Definition: foreign.h:20

◆ CreateForeignDataWrapper()

ObjectAddress CreateForeignDataWrapper ( CreateFdwStmt stmt)

Definition at line 560 of file foreigncmds.c.

References Anum_pg_foreign_data_wrapper_fdwacl, Anum_pg_foreign_data_wrapper_fdwhandler, Anum_pg_foreign_data_wrapper_fdwname, Anum_pg_foreign_data_wrapper_fdwoptions, Anum_pg_foreign_data_wrapper_fdwowner, Anum_pg_foreign_data_wrapper_fdwvalidator, CatalogTupleInsert(), ObjectAddress::classId, CStringGetDatum, DatumGetPointer, DEPENDENCY_NORMAL, DirectFunctionCall1, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errhint(), errmsg(), ERROR, CreateFdwStmt::fdwname, ForeignDataWrapperRelationId, CreateFdwStmt::func_options, GetForeignDataWrapperByName(), GetUserId(), heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), InvokeObjectPostCreateHook, namein(), Natts_pg_foreign_data_wrapper, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, CreateFdwStmt::options, parse_func_options(), PointerGetDatum, PointerIsValid, ProcedureRelationId, RelationData::rd_att, recordDependencyOn(), recordDependencyOnCurrentExtension(), recordDependencyOnOwner(), RowExclusiveLock, superuser(), transformGenericOptions(), and values.

Referenced by ProcessUtilitySlow().

561 {
562  Relation rel;
564  bool nulls[Natts_pg_foreign_data_wrapper];
565  HeapTuple tuple;
566  Oid fdwId;
567  bool handler_given;
568  bool validator_given;
569  Oid fdwhandler;
570  Oid fdwvalidator;
571  Datum fdwoptions;
572  Oid ownerId;
573  ObjectAddress myself;
574  ObjectAddress referenced;
575 
577 
578  /* Must be super user */
579  if (!superuser())
580  ereport(ERROR,
581  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
582  errmsg("permission denied to create foreign-data wrapper \"%s\"",
583  stmt->fdwname),
584  errhint("Must be superuser to create a foreign-data wrapper.")));
585 
586  /* For now the owner cannot be specified on create. Use effective user ID. */
587  ownerId = GetUserId();
588 
589  /*
590  * Check that there is no other foreign-data wrapper by this name.
591  */
592  if (GetForeignDataWrapperByName(stmt->fdwname, true) != NULL)
593  ereport(ERROR,
595  errmsg("foreign-data wrapper \"%s\" already exists",
596  stmt->fdwname)));
597 
598  /*
599  * Insert tuple into pg_foreign_data_wrapper.
600  */
601  memset(values, 0, sizeof(values));
602  memset(nulls, false, sizeof(nulls));
603 
607 
608  /* Lookup handler and validator functions, if given */
610  &handler_given, &fdwhandler,
611  &validator_given, &fdwvalidator);
612 
615 
616  nulls[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
617 
619  PointerGetDatum(NULL),
620  stmt->options,
621  fdwvalidator);
622 
623  if (PointerIsValid(DatumGetPointer(fdwoptions)))
624  values[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = fdwoptions;
625  else
626  nulls[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = true;
627 
628  tuple = heap_form_tuple(rel->rd_att, values, nulls);
629 
630  fdwId = CatalogTupleInsert(rel, tuple);
631 
632  heap_freetuple(tuple);
633 
634  /* record dependencies */
636  myself.objectId = fdwId;
637  myself.objectSubId = 0;
638 
639  if (OidIsValid(fdwhandler))
640  {
641  referenced.classId = ProcedureRelationId;
642  referenced.objectId = fdwhandler;
643  referenced.objectSubId = 0;
644  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
645  }
646 
647  if (OidIsValid(fdwvalidator))
648  {
649  referenced.classId = ProcedureRelationId;
650  referenced.objectId = fdwvalidator;
651  referenced.objectSubId = 0;
652  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
653  }
654 
656 
657  /* dependency on extension */
658  recordDependencyOnCurrentExtension(&myself, false);
659 
660  /* Post creation hook for new foreign data wrapper */
662 
664 
665  return myself;
666 }
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:46
int errhint(const char *fmt,...)
Definition: elog.c:987
static void parse_func_options(List *func_options, bool *handler_given, Oid *fdwhandler, bool *validator_given, Oid *fdwvalidator)
Definition: foreigncmds.c:516
#define Anum_pg_foreign_data_wrapper_fdwowner
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
Oid GetUserId(void)
Definition: miscinit.c:284
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:109
#define PointerGetDatum(X)
Definition: postgres.h:562
#define ProcedureRelationId
Definition: pg_proc.h:33
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
#define Anum_pg_foreign_data_wrapper_fdwhandler
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
#define heap_close(r, l)
Definition: heapam.h:97
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:159
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:586
#define Anum_pg_foreign_data_wrapper_fdwacl
List * options
Definition: parsenodes.h:2215
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
#define RowExclusiveLock
Definition: lockdefs.h:38
char * fdwname
Definition: parsenodes.h:2213
#define CStringGetDatum(X)
Definition: postgres.h:584
#define Anum_pg_foreign_data_wrapper_fdwname
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
TupleDesc rd_att
Definition: rel.h:115
#define Anum_pg_foreign_data_wrapper_fdwvalidator
#define Natts_pg_foreign_data_wrapper
ForeignDataWrapper * GetForeignDataWrapperByName(const char *fdwname, bool missing_ok)
Definition: foreign.c:78
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:139
#define ForeignDataWrapperRelationId
#define DatumGetPointer(X)
Definition: postgres.h:555
static Datum values[MAXATTR]
Definition: bootstrap.c:164
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
#define PointerIsValid(pointer)
Definition: c.h:574
#define Anum_pg_foreign_data_wrapper_fdwoptions
List * func_options
Definition: parsenodes.h:2214

◆ CreateForeignServer()

ObjectAddress CreateForeignServer ( CreateForeignServerStmt stmt)

Definition at line 861 of file foreigncmds.c.

References ACL_KIND_FDW, ACL_USAGE, aclcheck_error(), ACLCHECK_OK, Anum_pg_foreign_server_srvacl, Anum_pg_foreign_server_srvfdw, Anum_pg_foreign_server_srvname, Anum_pg_foreign_server_srvoptions, Anum_pg_foreign_server_srvowner, Anum_pg_foreign_server_srvtype, Anum_pg_foreign_server_srvversion, CatalogTupleInsert(), ObjectAddress::classId, CStringGetDatum, CStringGetTextDatum, DatumGetPointer, DEPENDENCY_NORMAL, DirectFunctionCall1, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, ForeignDataWrapper::fdwid, ForeignDataWrapper::fdwname, CreateForeignServerStmt::fdwname, ForeignDataWrapper::fdwvalidator, ForeignDataWrapperRelationId, ForeignServerRelationId, GetForeignDataWrapperByName(), GetForeignServerByName(), GetUserId(), heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), CreateForeignServerStmt::if_not_exists, InvalidObjectAddress, InvokeObjectPostCreateHook, namein(), Natts_pg_foreign_server, NOTICE, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, CreateForeignServerStmt::options, pg_foreign_data_wrapper_aclcheck(), PointerGetDatum, PointerIsValid, RelationData::rd_att, recordDependencyOn(), recordDependencyOnCurrentExtension(), recordDependencyOnOwner(), RowExclusiveLock, CreateForeignServerStmt::servername, CreateForeignServerStmt::servertype, transformGenericOptions(), values, and CreateForeignServerStmt::version.

Referenced by ProcessUtilitySlow().

862 {
863  Relation rel;
864  Datum srvoptions;
866  bool nulls[Natts_pg_foreign_server];
867  HeapTuple tuple;
868  Oid srvId;
869  Oid ownerId;
870  AclResult aclresult;
871  ObjectAddress myself;
872  ObjectAddress referenced;
873  ForeignDataWrapper *fdw;
874 
876 
877  /* For now the owner cannot be specified on create. Use effective user ID. */
878  ownerId = GetUserId();
879 
880  /*
881  * Check that there is no other foreign server by this name. Do nothing if
882  * IF NOT EXISTS was enforced.
883  */
884  if (GetForeignServerByName(stmt->servername, true) != NULL)
885  {
886  if (stmt->if_not_exists)
887  {
888  ereport(NOTICE,
890  errmsg("server \"%s\" already exists, skipping",
891  stmt->servername)));
893  return InvalidObjectAddress;
894  }
895  else
896  ereport(ERROR,
898  errmsg("server \"%s\" already exists",
899  stmt->servername)));
900  }
901 
902  /*
903  * Check that the FDW exists and that we have USAGE on it. Also get the
904  * actual FDW for option validation etc.
905  */
906  fdw = GetForeignDataWrapperByName(stmt->fdwname, false);
907 
908  aclresult = pg_foreign_data_wrapper_aclcheck(fdw->fdwid, ownerId, ACL_USAGE);
909  if (aclresult != ACLCHECK_OK)
910  aclcheck_error(aclresult, ACL_KIND_FDW, fdw->fdwname);
911 
912  /*
913  * Insert tuple into pg_foreign_server.
914  */
915  memset(values, 0, sizeof(values));
916  memset(nulls, false, sizeof(nulls));
917 
918  values[Anum_pg_foreign_server_srvname - 1] =
920  values[Anum_pg_foreign_server_srvowner - 1] = ObjectIdGetDatum(ownerId);
922 
923  /* Add server type if supplied */
924  if (stmt->servertype)
925  values[Anum_pg_foreign_server_srvtype - 1] =
927  else
928  nulls[Anum_pg_foreign_server_srvtype - 1] = true;
929 
930  /* Add server version if supplied */
931  if (stmt->version)
934  else
935  nulls[Anum_pg_foreign_server_srvversion - 1] = true;
936 
937  /* Start with a blank acl */
938  nulls[Anum_pg_foreign_server_srvacl - 1] = true;
939 
940  /* Add server options */
942  PointerGetDatum(NULL),
943  stmt->options,
944  fdw->fdwvalidator);
945 
946  if (PointerIsValid(DatumGetPointer(srvoptions)))
947  values[Anum_pg_foreign_server_srvoptions - 1] = srvoptions;
948  else
949  nulls[Anum_pg_foreign_server_srvoptions - 1] = true;
950 
951  tuple = heap_form_tuple(rel->rd_att, values, nulls);
952 
953  srvId = CatalogTupleInsert(rel, tuple);
954 
955  heap_freetuple(tuple);
956 
957  /* record dependencies */
959  myself.objectId = srvId;
960  myself.objectSubId = 0;
961 
963  referenced.objectId = fdw->fdwid;
964  referenced.objectSubId = 0;
965  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
966 
968 
969  /* dependency on extension */
970  recordDependencyOnCurrentExtension(&myself, false);
971 
972  /* Post creation hook for new foreign server */
974 
976 
977  return myself;
978 }
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:46
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
Oid GetUserId(void)
Definition: miscinit.c:284
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:109
#define Anum_pg_foreign_server_srvversion
char * fdwname
Definition: foreign.h:39
#define PointerGetDatum(X)
Definition: postgres.h:562
AclResult pg_foreign_data_wrapper_aclcheck(Oid fdw_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4567
int errcode(int sqlerrcode)
Definition: elog.c:575
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
#define heap_close(r, l)
Definition: heapam.h:97
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:159
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
#define Anum_pg_foreign_server_srvname
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:584
#define ACL_USAGE
Definition: parsenodes.h:80
ForeignServer * GetForeignServerByName(const char *srvname, bool missing_ok)
Definition: foreign.c:148
#define ereport(elevel, rest)
Definition: elog.h:122
#define Anum_pg_foreign_server_srvacl
#define Natts_pg_foreign_server
#define Anum_pg_foreign_server_srvowner
#define Anum_pg_foreign_server_srvfdw
AclResult
Definition: acl.h:178
uintptr_t Datum
Definition: postgres.h:372
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
TupleDesc rd_att
Definition: rel.h:115
#define NOTICE
Definition: elog.h:37
#define ForeignServerRelationId
ForeignDataWrapper * GetForeignDataWrapperByName(const char *fdwname, bool missing_ok)
Definition: foreign.c:78
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:139
#define ForeignDataWrapperRelationId
#define Anum_pg_foreign_server_srvtype
#define DatumGetPointer(X)
Definition: postgres.h:555
static Datum values[MAXATTR]
Definition: bootstrap.c:164
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define CStringGetTextDatum(s)
Definition: builtins.h:91
#define Anum_pg_foreign_server_srvoptions
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
#define PointerIsValid(pointer)
Definition: c.h:574

◆ CreateForeignTable()

void CreateForeignTable ( CreateForeignTableStmt stmt,
Oid  relid 
)

Definition at line 1446 of file foreigncmds.c.

References ACL_KIND_FOREIGN_SERVER, ACL_USAGE, aclcheck_error(), ACLCHECK_OK, Anum_pg_foreign_table_ftoptions, Anum_pg_foreign_table_ftrelid, Anum_pg_foreign_table_ftserver, CatalogTupleInsert(), ObjectAddress::classId, CommandCounterIncrement(), DatumGetPointer, DEPENDENCY_NORMAL, ForeignServer::fdwid, ForeignDataWrapper::fdwvalidator, ForeignServerRelationId, ForeignTableRelationId, GetForeignDataWrapper(), GetForeignServerByName(), GetUserId(), heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), Natts_pg_foreign_table, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, CreateForeignTableStmt::options, pg_foreign_server_aclcheck(), PointerGetDatum, PointerIsValid, RelationData::rd_att, recordDependencyOn(), RelationRelationId, RowExclusiveLock, ForeignServer::serverid, ForeignServer::servername, CreateForeignTableStmt::servername, transformGenericOptions(), and values.

Referenced by ProcessUtilitySlow().

1447 {
1448  Relation ftrel;
1449  Datum ftoptions;
1451  bool nulls[Natts_pg_foreign_table];
1452  HeapTuple tuple;
1453  AclResult aclresult;
1454  ObjectAddress myself;
1455  ObjectAddress referenced;
1456  Oid ownerId;
1457  ForeignDataWrapper *fdw;
1458  ForeignServer *server;
1459 
1460  /*
1461  * Advance command counter to ensure the pg_attribute tuple is visible;
1462  * the tuple might be updated to add constraints in previous step.
1463  */
1465 
1467 
1468  /*
1469  * For now the owner cannot be specified on create. Use effective user ID.
1470  */
1471  ownerId = GetUserId();
1472 
1473  /*
1474  * Check that the foreign server exists and that we have USAGE on it. Also
1475  * get the actual FDW for option validation etc.
1476  */
1477  server = GetForeignServerByName(stmt->servername, false);
1478  aclresult = pg_foreign_server_aclcheck(server->serverid, ownerId, ACL_USAGE);
1479  if (aclresult != ACLCHECK_OK)
1480  aclcheck_error(aclresult, ACL_KIND_FOREIGN_SERVER, server->servername);
1481 
1482  fdw = GetForeignDataWrapper(server->fdwid);
1483 
1484  /*
1485  * Insert tuple into pg_foreign_table.
1486  */
1487  memset(values, 0, sizeof(values));
1488  memset(nulls, false, sizeof(nulls));
1489 
1490  values[Anum_pg_foreign_table_ftrelid - 1] = ObjectIdGetDatum(relid);
1492  /* Add table generic options */
1494  PointerGetDatum(NULL),
1495  stmt->options,
1496  fdw->fdwvalidator);
1497 
1498  if (PointerIsValid(DatumGetPointer(ftoptions)))
1499  values[Anum_pg_foreign_table_ftoptions - 1] = ftoptions;
1500  else
1501  nulls[Anum_pg_foreign_table_ftoptions - 1] = true;
1502 
1503  tuple = heap_form_tuple(ftrel->rd_att, values, nulls);
1504 
1505  CatalogTupleInsert(ftrel, tuple);
1506 
1507  heap_freetuple(tuple);
1508 
1509  /* Add pg_class dependency on the server */
1510  myself.classId = RelationRelationId;
1511  myself.objectId = relid;
1512  myself.objectSubId = 0;
1513 
1514  referenced.classId = ForeignServerRelationId;
1515  referenced.objectId = server->serverid;
1516  referenced.objectSubId = 0;
1517  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1518 
1519  heap_close(ftrel, RowExclusiveLock);
1520 }
Oid GetUserId(void)
Definition: miscinit.c:284
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:109
#define PointerGetDatum(X)
Definition: postgres.h:562
#define RelationRelationId
Definition: pg_class.h:29
#define Natts_pg_foreign_table
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
#define Anum_pg_foreign_table_ftserver
ForeignDataWrapper * GetForeignDataWrapper(Oid fdwid)
Definition: foreign.c:35
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
AclResult pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4580
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ACL_USAGE
Definition: parsenodes.h:80
ForeignServer * GetForeignServerByName(const char *srvname, bool missing_ok)
Definition: foreign.c:148
#define Anum_pg_foreign_table_ftrelid
#define Anum_pg_foreign_table_ftoptions
AclResult
Definition: acl.h:178
uintptr_t Datum
Definition: postgres.h:372
void CommandCounterIncrement(void)
Definition: xact.c:915
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
TupleDesc rd_att
Definition: rel.h:115
#define ForeignServerRelationId
#define DatumGetPointer(X)
Definition: postgres.h:555
static Datum values[MAXATTR]
Definition: bootstrap.c:164
char * servername
Definition: foreign.h:50
#define ForeignTableRelationId
#define PointerIsValid(pointer)
Definition: c.h:574
Oid serverid
Definition: foreign.h:47

◆ CreateUserMapping()

ObjectAddress CreateUserMapping ( CreateUserMappingStmt stmt)

Definition at line 1135 of file foreigncmds.c.

References ACL_ID_PUBLIC, Anum_pg_user_mapping_umoptions, Anum_pg_user_mapping_umserver, Anum_pg_user_mapping_umuser, CatalogTupleInsert(), ObjectAddress::classId, DatumGetPointer, DEPENDENCY_NORMAL, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, ForeignServer::fdwid, ForeignDataWrapper::fdwvalidator, ForeignServerRelationId, get_rolespec_oid(), GetForeignDataWrapper(), GetForeignServerByName(), GetSysCacheOid2, heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), CreateUserMappingStmt::if_not_exists, InvalidObjectAddress, InvokeObjectPostCreateHook, MappingUserName, Natts_pg_user_mapping, NOTICE, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, CreateUserMappingStmt::options, PointerGetDatum, PointerIsValid, RelationData::rd_att, recordDependencyOn(), recordDependencyOnCurrentExtension(), recordDependencyOnOwner(), ROLESPEC_PUBLIC, RoleSpec::roletype, RowExclusiveLock, ForeignServer::serverid, CreateUserMappingStmt::servername, transformGenericOptions(), CreateUserMappingStmt::user, user_mapping_ddl_aclcheck(), UserMappingRelationId, and values.

Referenced by ProcessUtilitySlow().

1136 {
1137  Relation rel;
1138  Datum useoptions;
1140  bool nulls[Natts_pg_user_mapping];
1141  HeapTuple tuple;
1142  Oid useId;
1143  Oid umId;
1144  ObjectAddress myself;
1145  ObjectAddress referenced;
1146  ForeignServer *srv;
1147  ForeignDataWrapper *fdw;
1148  RoleSpec *role = (RoleSpec *) stmt->user;
1149 
1151 
1152  if (role->roletype == ROLESPEC_PUBLIC)
1153  useId = ACL_ID_PUBLIC;
1154  else
1155  useId = get_rolespec_oid(stmt->user, false);
1156 
1157  /* Check that the server exists. */
1158  srv = GetForeignServerByName(stmt->servername, false);
1159 
1160  user_mapping_ddl_aclcheck(useId, srv->serverid, stmt->servername);
1161 
1162  /*
1163  * Check that the user mapping is unique within server.
1164  */
1165  umId = GetSysCacheOid2(USERMAPPINGUSERSERVER,
1166  ObjectIdGetDatum(useId),
1167  ObjectIdGetDatum(srv->serverid));
1168 
1169  if (OidIsValid(umId))
1170  {
1171  if (stmt->if_not_exists)
1172  {
1173  ereport(NOTICE,
1175  errmsg("user mapping for \"%s\" already exists for server %s, skipping",
1176  MappingUserName(useId),
1177  stmt->servername)));
1178 
1180  return InvalidObjectAddress;
1181  }
1182  else
1183  ereport(ERROR,
1185  errmsg("user mapping for \"%s\" already exists for server %s",
1186  MappingUserName(useId),
1187  stmt->servername)));
1188  }
1189 
1190  fdw = GetForeignDataWrapper(srv->fdwid);
1191 
1192  /*
1193  * Insert tuple into pg_user_mapping.
1194  */
1195  memset(values, 0, sizeof(values));
1196  memset(nulls, false, sizeof(nulls));
1197 
1198  values[Anum_pg_user_mapping_umuser - 1] = ObjectIdGetDatum(useId);
1200 
1201  /* Add user options */
1203  PointerGetDatum(NULL),
1204  stmt->options,
1205  fdw->fdwvalidator);
1206 
1207  if (PointerIsValid(DatumGetPointer(useoptions)))
1208  values[Anum_pg_user_mapping_umoptions - 1] = useoptions;
1209  else
1210  nulls[Anum_pg_user_mapping_umoptions - 1] = true;
1211 
1212  tuple = heap_form_tuple(rel->rd_att, values, nulls);
1213 
1214  umId = CatalogTupleInsert(rel, tuple);
1215 
1216  heap_freetuple(tuple);
1217 
1218  /* Add dependency on the server */
1219  myself.classId = UserMappingRelationId;
1220  myself.objectId = umId;
1221  myself.objectSubId = 0;
1222 
1223  referenced.classId = ForeignServerRelationId;
1224  referenced.objectId = srv->serverid;
1225  referenced.objectSubId = 0;
1226  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1227 
1228  if (OidIsValid(useId))
1229  {
1230  /* Record the mapped user dependency */
1232  }
1233 
1234  /* dependency on extension */
1235  recordDependencyOnCurrentExtension(&myself, false);
1236 
1237  /* Post creation hook for new user mapping */
1239 
1241 
1242  return myself;
1243 }
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
#define Anum_pg_user_mapping_umuser
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:109
#define Anum_pg_user_mapping_umserver
#define PointerGetDatum(X)
Definition: postgres.h:562
int errcode(int sqlerrcode)
Definition: elog.c:575
static void user_mapping_ddl_aclcheck(Oid umuserid, Oid serverid, const char *servername)
Definition: foreigncmds.c:1110
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
#define heap_close(r, l)
Definition: heapam.h:97
#define Natts_pg_user_mapping
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:159
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:586
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:193
ForeignDataWrapper * GetForeignDataWrapper(Oid fdwid)
Definition: foreign.c:35
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
#define Anum_pg_user_mapping_umoptions
#define RowExclusiveLock
Definition: lockdefs.h:38
ForeignServer * GetForeignServerByName(const char *srvname, bool missing_ok)
Definition: foreign.c:148
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
RoleSpecType roletype
Definition: parsenodes.h:327
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5149
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
TupleDesc rd_att
Definition: rel.h:115
#define NOTICE
Definition: elog.h:37
#define ForeignServerRelationId
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:139
#define DatumGetPointer(X)
Definition: postgres.h:555
static Datum values[MAXATTR]
Definition: bootstrap.c:164
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define UserMappingRelationId
#define ACL_ID_PUBLIC
Definition: acl.h:47
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
#define PointerIsValid(pointer)
Definition: c.h:574
Oid serverid
Definition: foreign.h:47
#define MappingUserName(userid)
Definition: foreign.h:20

◆ import_error_callback()

static void import_error_callback ( void *  arg)
static

Definition at line 1643 of file foreigncmds.c.

References import_error_callback_arg::cmd, errcontext, errposition(), geterrposition(), internalerrposition(), internalerrquery(), and import_error_callback_arg::tablename.

Referenced by ImportForeignSchema().

1644 {
1646  int syntaxerrposition;
1647 
1648  /* If it's a syntax error, convert to internal syntax error report */
1649  syntaxerrposition = geterrposition();
1650  if (syntaxerrposition > 0)
1651  {
1652  errposition(0);
1653  internalerrposition(syntaxerrposition);
1654  internalerrquery(callback_arg->cmd);
1655  }
1656 
1657  if (callback_arg->tablename)
1658  errcontext("importing foreign table \"%s\"",
1659  callback_arg->tablename);
1660 }
int geterrposition(void)
Definition: elog.c:1257
int internalerrquery(const char *query)
Definition: elog.c:1161
#define errcontext
Definition: elog.h:164
void * arg
int errposition(int cursorpos)
Definition: elog.c:1125
int internalerrposition(int cursorpos)
Definition: elog.c:1141

◆ ImportForeignSchema()

void ImportForeignSchema ( ImportForeignSchemaStmt stmt)

Definition at line 1526 of file foreigncmds.c.

References ACL_KIND_FOREIGN_SERVER, ACL_USAGE, aclcheck_error(), ACLCHECK_OK, ErrorContextCallback::arg, CreateForeignTableStmt::base, ErrorContextCallback::callback, import_error_callback_arg::cmd, CMD_UTILITY, CommandCounterIncrement(), elog, ereport, errcode(), errmsg(), ERROR, error_context_stack, ForeignDataWrapper::fdwhandler, ForeignServer::fdwid, ForeignDataWrapper::fdwname, GetFdwRoutine(), GetForeignDataWrapper(), GetForeignServerByName(), GetUserId(), import_error_callback(), FdwRoutine::ImportForeignSchema, IsA, IsImportableForeignTable(), lfirst, lfirst_node, ImportForeignSchemaStmt::local_schema, LookupCreationNamespace(), makeNode, nodeTag, None_Receiver, OidIsValid, pg_foreign_server_aclcheck(), pg_parse_query(), ErrorContextCallback::previous, PROCESS_UTILITY_SUBCOMMAND, ProcessUtility(), pstrdup(), CreateStmt::relation, RangeVar::relname, RangeVar::schemaname, ImportForeignSchemaStmt::server_name, ForeignServer::serverid, ForeignServer::servername, RawStmt::stmt, RawStmt::stmt_len, RawStmt::stmt_location, and import_error_callback_arg::tablename.

Referenced by ProcessUtilitySlow().

1527 {
1528  ForeignServer *server;
1529  ForeignDataWrapper *fdw;
1530  FdwRoutine *fdw_routine;
1531  AclResult aclresult;
1532  List *cmd_list;
1533  ListCell *lc;
1534 
1535  /* Check that the foreign server exists and that we have USAGE on it */
1536  server = GetForeignServerByName(stmt->server_name, false);
1537  aclresult = pg_foreign_server_aclcheck(server->serverid, GetUserId(), ACL_USAGE);
1538  if (aclresult != ACLCHECK_OK)
1539  aclcheck_error(aclresult, ACL_KIND_FOREIGN_SERVER, server->servername);
1540 
1541  /* Check that the schema exists and we have CREATE permissions on it */
1542  (void) LookupCreationNamespace(stmt->local_schema);
1543 
1544  /* Get the FDW and check it supports IMPORT */
1545  fdw = GetForeignDataWrapper(server->fdwid);
1546  if (!OidIsValid(fdw->fdwhandler))
1547  ereport(ERROR,
1548  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1549  errmsg("foreign-data wrapper \"%s\" has no handler",
1550  fdw->fdwname)));
1551  fdw_routine = GetFdwRoutine(fdw->fdwhandler);
1552  if (fdw_routine->ImportForeignSchema == NULL)
1553  ereport(ERROR,
1554  (errcode(ERRCODE_FDW_NO_SCHEMAS),
1555  errmsg("foreign-data wrapper \"%s\" does not support IMPORT FOREIGN SCHEMA",
1556  fdw->fdwname)));
1557 
1558  /* Call FDW to get a list of commands */
1559  cmd_list = fdw_routine->ImportForeignSchema(stmt, server->serverid);
1560 
1561  /* Parse and execute each command */
1562  foreach(lc, cmd_list)
1563  {
1564  char *cmd = (char *) lfirst(lc);
1565  import_error_callback_arg callback_arg;
1566  ErrorContextCallback sqlerrcontext;
1567  List *raw_parsetree_list;
1568  ListCell *lc2;
1569 
1570  /*
1571  * Setup error traceback support for ereport(). This is so that any
1572  * error in the generated SQL will be displayed nicely.
1573  */
1574  callback_arg.tablename = NULL; /* not known yet */
1575  callback_arg.cmd = cmd;
1576  sqlerrcontext.callback = import_error_callback;
1577  sqlerrcontext.arg = (void *) &callback_arg;
1578  sqlerrcontext.previous = error_context_stack;
1579  error_context_stack = &sqlerrcontext;
1580 
1581  /*
1582  * Parse the SQL string into a list of raw parse trees.
1583  */
1584  raw_parsetree_list = pg_parse_query(cmd);
1585 
1586  /*
1587  * Process each parse tree (we allow the FDW to put more than one
1588  * command per string, though this isn't really advised).
1589  */
1590  foreach(lc2, raw_parsetree_list)
1591  {
1592  RawStmt *rs = lfirst_node(RawStmt, lc2);
1594  PlannedStmt *pstmt;
1595 
1596  /*
1597  * Because we only allow CreateForeignTableStmt, we can skip parse
1598  * analysis, rewrite, and planning steps here.
1599  */
1600  if (!IsA(cstmt, CreateForeignTableStmt))
1601  elog(ERROR,
1602  "foreign-data wrapper \"%s\" returned incorrect statement type %d",
1603  fdw->fdwname, (int) nodeTag(cstmt));
1604 
1605  /* Ignore commands for tables excluded by filter options */
1606  if (!IsImportableForeignTable(cstmt->base.relation->relname, stmt))
1607  continue;
1608 
1609  /* Enable reporting of current table's name on error */
1610  callback_arg.tablename = cstmt->base.relation->relname;
1611 
1612  /* Ensure creation schema is the one given in IMPORT statement */
1613  cstmt->base.relation->schemaname = pstrdup(stmt->local_schema);
1614 
1615  /* No planning needed, just make a wrapper PlannedStmt */
1616  pstmt = makeNode(PlannedStmt);
1617  pstmt->commandType = CMD_UTILITY;
1618  pstmt->canSetTag = false;
1619  pstmt->utilityStmt = (Node *) cstmt;
1620  pstmt->stmt_location = rs->stmt_location;
1621  pstmt->stmt_len = rs->stmt_len;
1622 
1623  /* Execute statement */
1624  ProcessUtility(pstmt,
1625  cmd,
1626  PROCESS_UTILITY_SUBCOMMAND, NULL, NULL,
1627  None_Receiver, NULL);
1628 
1629  /* Be sure to advance the command counter between subcommands */
1631 
1632  callback_arg.tablename = NULL;
1633  }
1634 
1635  error_context_stack = sqlerrcontext.previous;
1636  }
1637 }
RangeVar * relation
Definition: parsenodes.h:2014
#define IsA(nodeptr, _type_)
Definition: nodes.h:563
Oid GetUserId(void)
Definition: miscinit.c:284
char * fdwname
Definition: foreign.h:39
Oid LookupCreationNamespace(const char *nspname)
Definition: namespace.c:2896
char * pstrdup(const char *in)
Definition: mcxt.c:1063
Definition: nodes.h:512
void ProcessUtility(PlannedStmt *pstmt, const char *queryString, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, char *completionTag)
Definition: utility.c:335
int errcode(int sqlerrcode)
Definition: elog.c:575
DestReceiver * None_Receiver
Definition: dest.c:91
void(* callback)(void *arg)
Definition: elog.h:239
struct ErrorContextCallback * previous
Definition: elog.h:238
#define OidIsValid(objectId)
Definition: c.h:586
char * schemaname
Definition: primnodes.h:67
ErrorContextCallback * error_context_stack
Definition: elog.c:88
FdwRoutine * GetFdwRoutine(Oid fdwhandler)
Definition: foreign.c:287
char * relname
Definition: primnodes.h:68
ForeignDataWrapper * GetForeignDataWrapper(Oid fdwid)
Definition: foreign.c:35
#define ERROR
Definition: elog.h:43
List * pg_parse_query(const char *query_string)
Definition: postgres.c:607
#define lfirst_node(type, lc)
Definition: pg_list.h:109
AclResult pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4580
bool IsImportableForeignTable(const char *tablename, ImportForeignSchemaStmt *stmt)
Definition: foreign.c:435
Node * stmt
Definition: parsenodes.h:1431
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457
#define ACL_USAGE
Definition: parsenodes.h:80
ForeignServer * GetForeignServerByName(const char *srvname, bool missing_ok)
Definition: foreign.c:148
ImportForeignSchema_function ImportForeignSchema
Definition: fdwapi.h:227
#define ereport(elevel, rest)
Definition: elog.h:122
AclResult
Definition: acl.h:178
void CommandCounterIncrement(void)
Definition: xact.c:915
int stmt_len
Definition: parsenodes.h:1433
int stmt_location
Definition: parsenodes.h:1432
#define makeNode(_type_)
Definition: nodes.h:560
#define lfirst(lc)
Definition: pg_list.h:106
#define nodeTag(nodeptr)
Definition: nodes.h:517
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * servername
Definition: foreign.h:50
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
Oid serverid
Definition: foreign.h:47
static void import_error_callback(void *arg)
Definition: foreigncmds.c:1643

◆ lookup_fdw_handler_func()

static Oid lookup_fdw_handler_func ( DefElem handler)
static

Definition at line 472 of file foreigncmds.c.

References DefElem::arg, ereport, errcode(), errmsg(), ERROR, FDW_HANDLEROID, get_func_rettype(), InvalidOid, LookupFuncName(), and NameListToString().

Referenced by parse_func_options().

473 {
474  Oid handlerOid;
475  Oid funcargtypes[1]; /* dummy */
476 
477  if (handler == NULL || handler->arg == NULL)
478  return InvalidOid;
479 
480  /* handlers have no arguments */
481  handlerOid = LookupFuncName((List *) handler->arg, 0, funcargtypes, false);
482 
483  /* check that handler has correct return type */
484  if (get_func_rettype(handlerOid) != FDW_HANDLEROID)
485  ereport(ERROR,
486  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
487  errmsg("function %s must return type %s",
488  NameListToString((List *) handler->arg), "fdw_handler")));
489 
490  return handlerOid;
491 }
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1459
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
Node * arg
Definition: parsenodes.h:720
char * NameListToString(List *names)
Definition: namespace.c:3063
#define InvalidOid
Definition: postgres_ext.h:36
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
Definition: parse_func.c:1961
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: pg_list.h:45
#define FDW_HANDLEROID
Definition: pg_type.h:708

◆ lookup_fdw_validator_func()

static Oid lookup_fdw_validator_func ( DefElem validator)
static

Definition at line 497 of file foreigncmds.c.

References DefElem::arg, InvalidOid, LookupFuncName(), OIDOID, and TEXTARRAYOID.

Referenced by parse_func_options().

498 {
499  Oid funcargtypes[2];
500 
501  if (validator == NULL || validator->arg == NULL)
502  return InvalidOid;
503 
504  /* validators take text[], oid */
505  funcargtypes[0] = TEXTARRAYOID;
506  funcargtypes[1] = OIDOID;
507 
508  return LookupFuncName((List *) validator->arg, 2, funcargtypes, false);
509  /* validator's return value is ignored, so we don't check the type */
510 }
#define OIDOID
Definition: pg_type.h:328
unsigned int Oid
Definition: postgres_ext.h:31
#define TEXTARRAYOID
Definition: pg_type.h:470
Node * arg
Definition: parsenodes.h:720
#define InvalidOid
Definition: postgres_ext.h:36
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
Definition: parse_func.c:1961
Definition: pg_list.h:45

◆ optionListToArray()

static Datum optionListToArray ( List options)
static

Definition at line 65 of file foreigncmds.c.

References accumArrayResult(), CurrentMemoryContext, defGetString(), DefElem::defname, lfirst, makeArrayResult(), palloc(), PointerGetDatum, SET_VARSIZE, TEXTOID, value, VARDATA, and VARHDRSZ.

Referenced by transformGenericOptions().

66 {
67  ArrayBuildState *astate = NULL;
68  ListCell *cell;
69 
70  foreach(cell, options)
71  {
72  DefElem *def = lfirst(cell);
73  const char *value;
74  Size len;
75  text *t;
76 
77  value = defGetString(def);
78  len = VARHDRSZ + strlen(def->defname) + 1 + strlen(value);
79  t = palloc(len + 1);
80  SET_VARSIZE(t, len);
81  sprintf(VARDATA(t), "%s=%s", def->defname, value);
82 
83  astate = accumArrayResult(astate, PointerGetDatum(t),
84  false, TEXTOID,
86  }
87 
88  if (astate)
89  return makeArrayResult(astate, CurrentMemoryContext);
90 
91  return PointerGetDatum(NULL);
92 }
#define VARDATA(PTR)
Definition: postgres.h:303
#define TEXTOID
Definition: pg_type.h:324
#define PointerGetDatum(X)
Definition: postgres.h:562
#define VARHDRSZ
Definition: c.h:503
char * defGetString(DefElem *def)
Definition: define.c:49
static struct @121 value
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
Datum makeArrayResult(ArrayBuildState *astate, MemoryContext rcontext)
Definition: arrayfuncs.c:5106
#define lfirst(lc)
Definition: pg_list.h:106
size_t Size
Definition: c.h:414
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5042
void * palloc(Size size)
Definition: mcxt.c:835
Definition: c.h:497
char * defname
Definition: parsenodes.h:719
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328

◆ parse_func_options()

static void parse_func_options ( List func_options,
bool handler_given,
Oid fdwhandler,
bool validator_given,
Oid fdwvalidator 
)
static

Definition at line 516 of file foreigncmds.c.

References DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, InvalidOid, lfirst, lookup_fdw_handler_func(), and lookup_fdw_validator_func().

Referenced by AlterForeignDataWrapper(), and CreateForeignDataWrapper().

519 {
520  ListCell *cell;
521 
522  *handler_given = false;
523  *validator_given = false;
524  /* return InvalidOid if not given */
525  *fdwhandler = InvalidOid;
526  *fdwvalidator = InvalidOid;
527 
528  foreach(cell, func_options)
529  {
530  DefElem *def = (DefElem *) lfirst(cell);
531 
532  if (strcmp(def->defname, "handler") == 0)
533  {
534  if (*handler_given)
535  ereport(ERROR,
536  (errcode(ERRCODE_SYNTAX_ERROR),
537  errmsg("conflicting or redundant options")));
538  *handler_given = true;
539  *fdwhandler = lookup_fdw_handler_func(def);
540  }
541  else if (strcmp(def->defname, "validator") == 0)
542  {
543  if (*validator_given)
544  ereport(ERROR,
545  (errcode(ERRCODE_SYNTAX_ERROR),
546  errmsg("conflicting or redundant options")));
547  *validator_given = true;
548  *fdwvalidator = lookup_fdw_validator_func(def);
549  }
550  else
551  elog(ERROR, "option \"%s\" not recognized",
552  def->defname);
553  }
554 }
int errcode(int sqlerrcode)
Definition: elog.c:575
static Oid lookup_fdw_validator_func(DefElem *validator)
Definition: foreigncmds.c:497
static Oid lookup_fdw_handler_func(DefElem *handler)
Definition: foreigncmds.c:472
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvalidOid
Definition: postgres_ext.h:36
#define lfirst(lc)
Definition: pg_list.h:106
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * defname
Definition: parsenodes.h:719
#define elog
Definition: elog.h:219

◆ RemoveForeignDataWrapperById()

void RemoveForeignDataWrapperById ( Oid  fdwId)

Definition at line 837 of file foreigncmds.c.

References CatalogTupleDelete(), elog, ERROR, FOREIGNDATAWRAPPEROID, ForeignDataWrapperRelationId, heap_close, heap_open(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), and HeapTupleData::t_self.

Referenced by doDeletion().

838 {
839  HeapTuple tp;
840  Relation rel;
841 
843 
845 
846  if (!HeapTupleIsValid(tp))
847  elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwId);
848 
849  CatalogTupleDelete(rel, &tp->t_self);
850 
851  ReleaseSysCache(tp);
852 
854 }
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define ForeignDataWrapperRelationId
#define elog
Definition: elog.h:219

◆ RemoveForeignServerById()

void RemoveForeignServerById ( Oid  srvId)

Definition at line 1084 of file foreigncmds.c.

References CatalogTupleDelete(), elog, ERROR, FOREIGNSERVEROID, ForeignServerRelationId, heap_close, heap_open(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), and HeapTupleData::t_self.

Referenced by doDeletion().

1085 {
1086  HeapTuple tp;
1087  Relation rel;
1088 
1090 
1092 
1093  if (!HeapTupleIsValid(tp))
1094  elog(ERROR, "cache lookup failed for foreign server %u", srvId);
1095 
1096  CatalogTupleDelete(rel, &tp->t_self);
1097 
1098  ReleaseSysCache(tp);
1099 
1101 }
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define ForeignServerRelationId
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define elog
Definition: elog.h:219

◆ RemoveUserMapping()

Oid RemoveUserMapping ( DropUserMappingStmt stmt)

Definition at line 1345 of file foreigncmds.c.

References ACL_ID_PUBLIC, DROP_CASCADE, elog, ereport, errcode(), errmsg(), ERROR, get_rolespec_oid(), GetForeignServerByName(), GetSysCacheOid2, InvalidOid, MappingUserName, DropUserMappingStmt::missing_ok, NOTICE, ObjectIdGetDatum, OidIsValid, performDeletion(), RoleSpec::rolename, ROLESPEC_PUBLIC, RoleSpec::roletype, ForeignServer::serverid, ForeignServer::servername, DropUserMappingStmt::servername, DropUserMappingStmt::user, user_mapping_ddl_aclcheck(), and UserMappingRelationId.

Referenced by ProcessUtilitySlow().

1346 {
1347  ObjectAddress object;
1348  Oid useId;
1349  Oid umId;
1350  ForeignServer *srv;
1351  RoleSpec *role = (RoleSpec *) stmt->user;
1352 
1353  if (role->roletype == ROLESPEC_PUBLIC)
1354  useId = ACL_ID_PUBLIC;
1355  else
1356  {
1357  useId = get_rolespec_oid(stmt->user, stmt->missing_ok);
1358  if (!OidIsValid(useId))
1359  {
1360  /*
1361  * IF EXISTS specified, role not found and not public. Notice this
1362  * and leave.
1363  */
1364  elog(NOTICE, "role \"%s\" does not exist, skipping",
1365  role->rolename);
1366  return InvalidOid;
1367  }
1368  }
1369 
1370  srv = GetForeignServerByName(stmt->servername, true);
1371 
1372  if (!srv)
1373  {
1374  if (!stmt->missing_ok)
1375  ereport(ERROR,
1376  (errcode(ERRCODE_UNDEFINED_OBJECT),
1377  errmsg("server \"%s\" does not exist",
1378  stmt->servername)));
1379  /* IF EXISTS, just note it */
1380  ereport(NOTICE, (errmsg("server does not exist, skipping")));
1381  return InvalidOid;
1382  }
1383 
1384  umId = GetSysCacheOid2(USERMAPPINGUSERSERVER,
1385  ObjectIdGetDatum(useId),
1386  ObjectIdGetDatum(srv->serverid));
1387 
1388  if (!OidIsValid(umId))
1389  {
1390  if (!stmt->missing_ok)
1391  ereport(ERROR,
1392  (errcode(ERRCODE_UNDEFINED_OBJECT),
1393  errmsg("user mapping for \"%s\" does not exist for the server",
1394  MappingUserName(useId))));
1395 
1396  /* IF EXISTS specified, just note it */
1397  ereport(NOTICE,
1398  (errmsg("user mapping for \"%s\" does not exist for the server, skipping",
1399  MappingUserName(useId))));
1400  return InvalidOid;
1401  }
1402 
1403  user_mapping_ddl_aclcheck(useId, srv->serverid, srv->servername);
1404 
1405  /*
1406  * Do the deletion
1407  */
1408  object.classId = UserMappingRelationId;
1409  object.objectId = umId;
1410  object.objectSubId = 0;
1411 
1412  performDeletion(&object, DROP_CASCADE, 0);
1413 
1414  return umId;
1415 }
int errcode(int sqlerrcode)
Definition: elog.c:575
static void user_mapping_ddl_aclcheck(Oid umuserid, Oid serverid, const char *servername)
Definition: foreigncmds.c:1110
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:586
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:193
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:303
ForeignServer * GetForeignServerByName(const char *srvname, bool missing_ok)
Definition: foreign.c:148
#define ereport(elevel, rest)
Definition: elog.h:122
RoleSpecType roletype
Definition: parsenodes.h:327
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5149
#define InvalidOid
Definition: postgres_ext.h:36
#define NOTICE
Definition: elog.h:37
char * rolename
Definition: parsenodes.h:328
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define UserMappingRelationId
char * servername
Definition: foreign.h:50
#define ACL_ID_PUBLIC
Definition: acl.h:47
#define elog
Definition: elog.h:219
Oid serverid
Definition: foreign.h:47
#define MappingUserName(userid)
Definition: foreign.h:20

◆ RemoveUserMappingById()

void RemoveUserMappingById ( Oid  umId)

Definition at line 1422 of file foreigncmds.c.

References CatalogTupleDelete(), elog, ERROR, heap_close, heap_open(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), HeapTupleData::t_self, USERMAPPINGOID, and UserMappingRelationId.

Referenced by doDeletion().

1423 {
1424  HeapTuple tp;
1425  Relation rel;
1426 
1428 
1430 
1431  if (!HeapTupleIsValid(tp))
1432  elog(ERROR, "cache lookup failed for user mapping %u", umId);
1433 
1434  CatalogTupleDelete(rel, &tp->t_self);
1435 
1436  ReleaseSysCache(tp);
1437 
1439 }
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define UserMappingRelationId
#define elog
Definition: elog.h:219

◆ transformGenericOptions()

Datum transformGenericOptions ( Oid  catalogId,
Datum  oldOptions,
List options,
Oid  fdwvalidator 
)

Definition at line 109 of file foreigncmds.c.

References construct_empty_array(), DatumGetPointer, DefElem::defaction, DEFELEM_ADD, DEFELEM_DROP, DEFELEM_SET, DEFELEM_UNSPEC, DefElem::defname, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, lappend(), lfirst, list_delete_cell(), ObjectIdGetDatum, OidFunctionCall2, OidIsValid, optionListToArray(), PointerGetDatum, TEXTOID, and untransformRelOptions().

Referenced by AlterForeignDataWrapper(), AlterForeignServer(), AlterUserMapping(), ATExecAlterColumnGenericOptions(), ATExecGenericOptions(), CreateForeignDataWrapper(), CreateForeignServer(), CreateForeignTable(), and CreateUserMapping().

113 {
114  List *resultOptions = untransformRelOptions(oldOptions);
115  ListCell *optcell;
116  Datum result;
117 
118  foreach(optcell, options)
119  {
120  DefElem *od = lfirst(optcell);
121  ListCell *cell;
122  ListCell *prev = NULL;
123 
124  /*
125  * Find the element in resultOptions. We need this for validation in
126  * all cases. Also identify the previous element.
127  */
128  foreach(cell, resultOptions)
129  {
130  DefElem *def = lfirst(cell);
131 
132  if (strcmp(def->defname, od->defname) == 0)
133  break;
134  else
135  prev = cell;
136  }
137 
138  /*
139  * It is possible to perform multiple SET/DROP actions on the same
140  * option. The standard permits this, as long as the options to be
141  * added are unique. Note that an unspecified action is taken to be
142  * ADD.
143  */
144  switch (od->defaction)
145  {
146  case DEFELEM_DROP:
147  if (!cell)
148  ereport(ERROR,
149  (errcode(ERRCODE_UNDEFINED_OBJECT),
150  errmsg("option \"%s\" not found",
151  od->defname)));
152  resultOptions = list_delete_cell(resultOptions, cell, prev);
153  break;
154 
155  case DEFELEM_SET:
156  if (!cell)
157  ereport(ERROR,
158  (errcode(ERRCODE_UNDEFINED_OBJECT),
159  errmsg("option \"%s\" not found",
160  od->defname)));
161  lfirst(cell) = od;
162  break;
163 
164  case DEFELEM_ADD:
165  case DEFELEM_UNSPEC:
166  if (cell)
167  ereport(ERROR,
169  errmsg("option \"%s\" provided more than once",
170  od->defname)));
171  resultOptions = lappend(resultOptions, od);
172  break;
173 
174  default:
175  elog(ERROR, "unrecognized action %d on option \"%s\"",
176  (int) od->defaction, od->defname);
177  break;
178  }
179  }
180 
181  result = optionListToArray(resultOptions);
182 
183  if (OidIsValid(fdwvalidator))
184  {
185  Datum valarg = result;
186 
187  /*
188  * Pass a null options list as an empty array, so that validators
189  * don't have to be declared non-strict to handle the case.
190  */
191  if (DatumGetPointer(valarg) == NULL)
193  OidFunctionCall2(fdwvalidator, valarg, ObjectIdGetDatum(catalogId));
194  }
195 
196  return result;
197 }
#define TEXTOID
Definition: pg_type.h:324
#define PointerGetDatum(X)
Definition: postgres.h:562
DefElemAction defaction
Definition: parsenodes.h:721
int errcode(int sqlerrcode)
Definition: elog.c:575
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3398
#define OidIsValid(objectId)
Definition: c.h:586
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
List * lappend(List *list, void *datum)
Definition: list.c:128
List * list_delete_cell(List *list, ListCell *cell, ListCell *prev)
Definition: list.c:528
uintptr_t Datum
Definition: postgres.h:372
List * untransformRelOptions(Datum options)
Definition: reloptions.c:917
#define lfirst(lc)
Definition: pg_list.h:106
#define DatumGetPointer(X)
Definition: postgres.h:555
#define OidFunctionCall2(functionId, arg1, arg2)
Definition: fmgr.h:625
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * defname
Definition: parsenodes.h:719
#define elog
Definition: elog.h:219
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
Definition: pg_list.h:45
static Datum optionListToArray(List *options)
Definition: foreigncmds.c:65

◆ user_mapping_ddl_aclcheck()

static void user_mapping_ddl_aclcheck ( Oid  umuserid,
Oid  serverid,
const char *  servername 
)
static

Definition at line 1110 of file foreigncmds.c.

References ACL_KIND_FOREIGN_SERVER, ACL_USAGE, aclcheck_error(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, GetUserId(), pg_foreign_server_aclcheck(), and pg_foreign_server_ownercheck().

Referenced by AlterUserMapping(), CreateUserMapping(), and RemoveUserMapping().

1111 {
1112  Oid curuserid = GetUserId();
1113 
1114  if (!pg_foreign_server_ownercheck(serverid, curuserid))
1115  {
1116  if (umuserid == curuserid)
1117  {
1118  AclResult aclresult;
1119 
1120  aclresult = pg_foreign_server_aclcheck(serverid, curuserid, ACL_USAGE);
1121  if (aclresult != ACLCHECK_OK)
1122  aclcheck_error(aclresult, ACL_KIND_FOREIGN_SERVER, servername);
1123  }
1124  else
1126  servername);
1127  }
1128 }
Oid GetUserId(void)
Definition: miscinit.c:284
bool pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid)
Definition: aclchk.c:4968
unsigned int Oid
Definition: postgres_ext.h:31
AclResult pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4580
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457
#define ACL_USAGE
Definition: parsenodes.h:80
AclResult
Definition: acl.h:178