PostgreSQL Source Code  git master
foreigncmds.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/reloptions.h"
#include "access/table.h"
#include "access/xact.h"
#include "catalog/catalog.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 679 of file foreigncmds.c.

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

Referenced by ProcessUtilitySlow().

680 {
681  Relation rel;
682  HeapTuple tp;
684  Datum repl_val[Natts_pg_foreign_data_wrapper];
685  bool repl_null[Natts_pg_foreign_data_wrapper];
686  bool repl_repl[Natts_pg_foreign_data_wrapper];
687  Oid fdwId;
688  bool isnull;
689  Datum datum;
690  bool handler_given;
691  bool validator_given;
692  Oid fdwhandler;
693  Oid fdwvalidator;
694  ObjectAddress myself;
695 
696  rel = table_open(ForeignDataWrapperRelationId, RowExclusiveLock);
697 
698  /* Must be super user */
699  if (!superuser())
700  ereport(ERROR,
701  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
702  errmsg("permission denied to alter foreign-data wrapper \"%s\"",
703  stmt->fdwname),
704  errhint("Must be superuser to alter a foreign-data wrapper.")));
705 
707  CStringGetDatum(stmt->fdwname));
708 
709  if (!HeapTupleIsValid(tp))
710  ereport(ERROR,
711  (errcode(ERRCODE_UNDEFINED_OBJECT),
712  errmsg("foreign-data wrapper \"%s\" does not exist", stmt->fdwname)));
713 
714  fdwForm = (Form_pg_foreign_data_wrapper) GETSTRUCT(tp);
715  fdwId = fdwForm->oid;
716 
717  memset(repl_val, 0, sizeof(repl_val));
718  memset(repl_null, false, sizeof(repl_null));
719  memset(repl_repl, false, sizeof(repl_repl));
720 
722  &handler_given, &fdwhandler,
723  &validator_given, &fdwvalidator);
724 
725  if (handler_given)
726  {
727  repl_val[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = ObjectIdGetDatum(fdwhandler);
728  repl_repl[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = true;
729 
730  /*
731  * It could be that the behavior of accessing foreign table changes
732  * with the new handler. Warn about this.
733  */
735  (errmsg("changing the foreign-data wrapper handler can change behavior of existing foreign tables")));
736  }
737 
738  if (validator_given)
739  {
740  repl_val[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = ObjectIdGetDatum(fdwvalidator);
741  repl_repl[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = true;
742 
743  /*
744  * It could be that existing options for the FDW or dependent SERVER,
745  * USER MAPPING or FOREIGN TABLE objects are no longer valid according
746  * to the new validator. Warn about this.
747  */
748  if (OidIsValid(fdwvalidator))
750  (errmsg("changing the foreign-data wrapper validator can cause "
751  "the options for dependent objects to become invalid")));
752  }
753  else
754  {
755  /*
756  * Validator is not changed, but we need it for validating options.
757  */
758  fdwvalidator = fdwForm->fdwvalidator;
759  }
760 
761  /*
762  * If options specified, validate and update.
763  */
764  if (stmt->options)
765  {
766  /* Extract the current options */
768  tp,
769  Anum_pg_foreign_data_wrapper_fdwoptions,
770  &isnull);
771  if (isnull)
772  datum = PointerGetDatum(NULL);
773 
774  /* Transform the options */
775  datum = transformGenericOptions(ForeignDataWrapperRelationId,
776  datum,
777  stmt->options,
778  fdwvalidator);
779 
780  if (PointerIsValid(DatumGetPointer(datum)))
781  repl_val[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = datum;
782  else
783  repl_null[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = true;
784 
785  repl_repl[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = true;
786  }
787 
788  /* Everything looks good - update the tuple */
789  tp = heap_modify_tuple(tp, RelationGetDescr(rel),
790  repl_val, repl_null, repl_repl);
791 
792  CatalogTupleUpdate(rel, &tp->t_self, tp);
793 
794  heap_freetuple(tp);
795 
796  ObjectAddressSet(myself, ForeignDataWrapperRelationId, fdwId);
797 
798  /* Update function dependencies if we changed them */
799  if (handler_given || validator_given)
800  {
801  ObjectAddress referenced;
802 
803  /*
804  * Flush all existing dependency records of this FDW on functions; we
805  * assume there can be none other than the ones we are fixing.
806  */
807  deleteDependencyRecordsForClass(ForeignDataWrapperRelationId,
808  fdwId,
809  ProcedureRelationId,
811 
812  /* And build new ones. */
813 
814  if (OidIsValid(fdwhandler))
815  {
816  referenced.classId = ProcedureRelationId;
817  referenced.objectId = fdwhandler;
818  referenced.objectSubId = 0;
819  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
820  }
821 
822  if (OidIsValid(fdwvalidator))
823  {
824  referenced.classId = ProcedureRelationId;
825  referenced.objectId = fdwvalidator;
826  referenced.objectSubId = 0;
827  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
828  }
829  }
830 
831  InvokeObjectPostAlterHook(ForeignDataWrapperRelationId, fdwId, 0);
832 
834 
835  return myself;
836 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
int errhint(const char *fmt,...)
Definition: elog.c:974
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
static void parse_func_options(List *func_options, bool *handler_given, Oid *fdwhandler, bool *validator_given, Oid *fdwvalidator)
Definition: foreigncmds.c:519
#define RelationGetDescr(relation)
Definition: rel.h:442
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:110
#define PointerGetDatum(X)
Definition: postgres.h:556
int errcode(int sqlerrcode)
Definition: elog.c:570
bool superuser(void)
Definition: superuser.c:47
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#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:578
char * fdwname
Definition: parsenodes.h:2263
#define ereport(elevel, rest)
Definition: elog.h:141
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
List * func_options
Definition: parsenodes.h:2264
#define WARNING
Definition: elog.h:40
uintptr_t Datum
Definition: postgres.h:367
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1385
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:240
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_foreign_data_wrapper * Form_pg_foreign_data_wrapper
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define DatumGetPointer(X)
Definition: postgres.h:549
List * options
Definition: parsenodes.h:2265
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
int errmsg(const char *fmt,...)
Definition: elog.c:784
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define PointerIsValid(pointer)
Definition: c.h:626

◆ AlterForeignDataWrapperOwner()

ObjectAddress AlterForeignDataWrapperOwner ( const char *  name,
Oid  newOwnerId 
)

Definition at line 275 of file foreigncmds.c.

References AlterForeignDataWrapperOwner_internal(), CStringGetDatum, ereport, errcode(), errmsg(), ERROR, FOREIGNDATAWRAPPERNAME, GETSTRUCT, heap_freetuple(), HeapTupleIsValid, ObjectAddressSet, RowExclusiveLock, SearchSysCacheCopy1, table_close(), and table_open().

Referenced by ExecAlterOwnerStmt().

276 {
277  Oid fdwId;
278  HeapTuple tup;
279  Relation rel;
280  ObjectAddress address;
282 
283 
284  rel = table_open(ForeignDataWrapperRelationId, RowExclusiveLock);
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 
294  fdwId = form->oid;
295 
296  AlterForeignDataWrapperOwner_internal(rel, tup, newOwnerId);
297 
298  ObjectAddressSet(address, ForeignDataWrapperRelationId, fdwId);
299 
300  heap_freetuple(tup);
301 
303 
304  return address;
305 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
int errcode(int sqlerrcode)
Definition: elog.c:570
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
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:578
#define ereport(elevel, rest)
Definition: elog.h:141
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_foreign_data_wrapper * Form_pg_foreign_data_wrapper
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:174
int errmsg(const char *fmt,...)
Definition: elog.c:784
static void AlterForeignDataWrapperOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
Definition: foreigncmds.c:205
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ AlterForeignDataWrapperOwner_internal()

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

Definition at line 205 of file foreigncmds.c.

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

Referenced by AlterForeignDataWrapperOwner(), and AlterForeignDataWrapperOwner_oid().

206 {
208  Datum repl_val[Natts_pg_foreign_data_wrapper];
209  bool repl_null[Natts_pg_foreign_data_wrapper];
210  bool repl_repl[Natts_pg_foreign_data_wrapper];
211  Acl *newAcl;
212  Datum aclDatum;
213  bool isNull;
214 
216 
217  /* Must be a superuser to change a FDW owner */
218  if (!superuser())
219  ereport(ERROR,
220  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
221  errmsg("permission denied to change owner of foreign-data wrapper \"%s\"",
222  NameStr(form->fdwname)),
223  errhint("Must be superuser to change owner of a foreign-data wrapper.")));
224 
225  /* New owner must also be a superuser */
226  if (!superuser_arg(newOwnerId))
227  ereport(ERROR,
228  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
229  errmsg("permission denied to change owner of foreign-data wrapper \"%s\"",
230  NameStr(form->fdwname)),
231  errhint("The owner of a foreign-data wrapper must be a superuser.")));
232 
233  if (form->fdwowner != newOwnerId)
234  {
235  memset(repl_null, false, sizeof(repl_null));
236  memset(repl_repl, false, sizeof(repl_repl));
237 
238  repl_repl[Anum_pg_foreign_data_wrapper_fdwowner - 1] = true;
239  repl_val[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(newOwnerId);
240 
241  aclDatum = heap_getattr(tup,
242  Anum_pg_foreign_data_wrapper_fdwacl,
243  RelationGetDescr(rel),
244  &isNull);
245  /* Null ACLs do not require changes */
246  if (!isNull)
247  {
248  newAcl = aclnewowner(DatumGetAclP(aclDatum),
249  form->fdwowner, newOwnerId);
250  repl_repl[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
251  repl_val[Anum_pg_foreign_data_wrapper_fdwacl - 1] = PointerGetDatum(newAcl);
252  }
253 
254  tup = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null,
255  repl_repl);
256 
257  CatalogTupleUpdate(rel, &tup->t_self, tup);
258 
259  /* Update owner dependency reference */
260  changeDependencyOnOwner(ForeignDataWrapperRelationId,
261  form->oid,
262  newOwnerId);
263  }
264 
265  InvokeObjectPostAlterHook(ForeignDataWrapperRelationId,
266  form->oid, 0);
267 }
int errhint(const char *fmt,...)
Definition: elog.c:974
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:442
#define DatumGetAclP(X)
Definition: acl.h:120
#define PointerGetDatum(X)
Definition: postgres.h:556
int errcode(int sqlerrcode)
Definition: elog.c:570
bool superuser(void)
Definition: superuser.c:47
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
Definition: pg_shdepend.c:310
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define ereport(elevel, rest)
Definition: elog.h:141
#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:762
uintptr_t Datum
Definition: postgres.h:367
FormData_pg_foreign_data_wrapper * Form_pg_foreign_data_wrapper
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define NameStr(name)
Definition: c.h:609
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
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 313 of file foreigncmds.c.

References AlterForeignDataWrapperOwner_internal(), ereport, errcode(), errmsg(), ERROR, FOREIGNDATAWRAPPEROID, heap_freetuple(), HeapTupleIsValid, ObjectIdGetDatum, RowExclusiveLock, SearchSysCacheCopy1, table_close(), and table_open().

Referenced by shdepReassignOwned().

314 {
315  HeapTuple tup;
316  Relation rel;
317 
318  rel = table_open(ForeignDataWrapperRelationId, RowExclusiveLock);
319 
321 
322  if (!HeapTupleIsValid(tup))
323  ereport(ERROR,
324  (errcode(ERRCODE_UNDEFINED_OBJECT),
325  errmsg("foreign-data wrapper with OID %u does not exist", fwdId)));
326 
327  AlterForeignDataWrapperOwner_internal(rel, tup, newOwnerId);
328 
329  heap_freetuple(tup);
330 
332 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
int errcode(int sqlerrcode)
Definition: elog.c:570
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:141
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
int errmsg(const char *fmt,...)
Definition: elog.c:784
static void AlterForeignDataWrapperOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
Definition: foreigncmds.c:205
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ AlterForeignServer()

ObjectAddress AlterForeignServer ( AlterForeignServerStmt stmt)

Definition at line 994 of file foreigncmds.c.

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

Referenced by ProcessUtilitySlow().

995 {
996  Relation rel;
997  HeapTuple tp;
998  Datum repl_val[Natts_pg_foreign_server];
999  bool repl_null[Natts_pg_foreign_server];
1000  bool repl_repl[Natts_pg_foreign_server];
1001  Oid srvId;
1002  Form_pg_foreign_server srvForm;
1003  ObjectAddress address;
1004 
1005  rel = table_open(ForeignServerRelationId, RowExclusiveLock);
1006 
1008  CStringGetDatum(stmt->servername));
1009 
1010  if (!HeapTupleIsValid(tp))
1011  ereport(ERROR,
1012  (errcode(ERRCODE_UNDEFINED_OBJECT),
1013  errmsg("server \"%s\" does not exist", stmt->servername)));
1014 
1015  srvForm = (Form_pg_foreign_server) GETSTRUCT(tp);
1016  srvId = srvForm->oid;
1017 
1018  /*
1019  * Only owner or a superuser can ALTER a SERVER.
1020  */
1021  if (!pg_foreign_server_ownercheck(srvId, GetUserId()))
1023  stmt->servername);
1024 
1025  memset(repl_val, 0, sizeof(repl_val));
1026  memset(repl_null, false, sizeof(repl_null));
1027  memset(repl_repl, false, sizeof(repl_repl));
1028 
1029  if (stmt->has_version)
1030  {
1031  /*
1032  * Change the server VERSION string.
1033  */
1034  if (stmt->version)
1035  repl_val[Anum_pg_foreign_server_srvversion - 1] =
1037  else
1038  repl_null[Anum_pg_foreign_server_srvversion - 1] = true;
1039 
1040  repl_repl[Anum_pg_foreign_server_srvversion - 1] = true;
1041  }
1042 
1043  if (stmt->options)
1044  {
1045  ForeignDataWrapper *fdw = GetForeignDataWrapper(srvForm->srvfdw);
1046  Datum datum;
1047  bool isnull;
1048 
1049  /* Extract the current srvoptions */
1051  tp,
1052  Anum_pg_foreign_server_srvoptions,
1053  &isnull);
1054  if (isnull)
1055  datum = PointerGetDatum(NULL);
1056 
1057  /* Prepare the options array */
1058  datum = transformGenericOptions(ForeignServerRelationId,
1059  datum,
1060  stmt->options,
1061  fdw->fdwvalidator);
1062 
1063  if (PointerIsValid(DatumGetPointer(datum)))
1064  repl_val[Anum_pg_foreign_server_srvoptions - 1] = datum;
1065  else
1066  repl_null[Anum_pg_foreign_server_srvoptions - 1] = true;
1067 
1068  repl_repl[Anum_pg_foreign_server_srvoptions - 1] = true;
1069  }
1070 
1071  /* Everything looks good - update the tuple */
1072  tp = heap_modify_tuple(tp, RelationGetDescr(rel),
1073  repl_val, repl_null, repl_repl);
1074 
1075  CatalogTupleUpdate(rel, &tp->t_self, tp);
1076 
1077  InvokeObjectPostAlterHook(ForeignServerRelationId, srvId, 0);
1078 
1079  ObjectAddressSet(address, ForeignServerRelationId, srvId);
1080 
1081  heap_freetuple(tp);
1082 
1084 
1085  return address;
1086 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:442
Oid GetUserId(void)
Definition: miscinit.c:380
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:110
#define PointerGetDatum(X)
Definition: postgres.h:556
bool pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid)
Definition: aclchk.c:5119
int errcode(int sqlerrcode)
Definition: elog.c:570
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3353
ForeignDataWrapper * GetForeignDataWrapper(Oid fdwid)
Definition: foreign.c:35
#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:578
#define ereport(elevel, rest)
Definition: elog.h:141
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
uintptr_t Datum
Definition: postgres.h:367
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1385
FormData_pg_foreign_server * Form_pg_foreign_server
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define DatumGetPointer(X)
Definition: postgres.h:549
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define CStringGetTextDatum(s)
Definition: builtins.h:83
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define PointerIsValid(pointer)
Definition: c.h:626

◆ AlterForeignServerOwner()

ObjectAddress AlterForeignServerOwner ( const char *  name,
Oid  newOwnerId 
)

Definition at line 415 of file foreigncmds.c.

References AlterForeignServerOwner_internal(), CStringGetDatum, ereport, errcode(), errmsg(), ERROR, FOREIGNSERVERNAME, GETSTRUCT, heap_freetuple(), HeapTupleIsValid, ObjectAddressSet, RowExclusiveLock, SearchSysCacheCopy1, table_close(), and table_open().

Referenced by ExecAlterOwnerStmt().

416 {
417  Oid servOid;
418  HeapTuple tup;
419  Relation rel;
420  ObjectAddress address;
422 
423  rel = table_open(ForeignServerRelationId, RowExclusiveLock);
424 
426 
427  if (!HeapTupleIsValid(tup))
428  ereport(ERROR,
429  (errcode(ERRCODE_UNDEFINED_OBJECT),
430  errmsg("server \"%s\" does not exist", name)));
431 
432  form = (Form_pg_foreign_server) GETSTRUCT(tup);
433  servOid = form->oid;
434 
435  AlterForeignServerOwner_internal(rel, tup, newOwnerId);
436 
437  ObjectAddressSet(address, ForeignServerRelationId, servOid);
438 
439  heap_freetuple(tup);
440 
442 
443  return address;
444 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
int errcode(int sqlerrcode)
Definition: elog.c:570
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
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:578
#define ereport(elevel, rest)
Definition: elog.h:141
FormData_pg_foreign_server * Form_pg_foreign_server
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static void AlterForeignServerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
Definition: foreigncmds.c:338
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:174
int errmsg(const char *fmt,...)
Definition: elog.c:784
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ AlterForeignServerOwner_internal()

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

Definition at line 338 of file foreigncmds.c.

References ACL_USAGE, aclcheck_error(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, aclnewowner(), CatalogTupleUpdate(), changeDependencyOnOwner(), check_is_member_of_role(), DatumGetAclP, ForeignDataWrapper::fdwname, GetForeignDataWrapper(), GETSTRUCT, GetUserId(), heap_getattr, heap_modify_tuple(), InvokeObjectPostAlterHook, NameStr, OBJECT_FDW, OBJECT_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().

339 {
341  Datum repl_val[Natts_pg_foreign_server];
342  bool repl_null[Natts_pg_foreign_server];
343  bool repl_repl[Natts_pg_foreign_server];
344  Acl *newAcl;
345  Datum aclDatum;
346  bool isNull;
347 
348  form = (Form_pg_foreign_server) GETSTRUCT(tup);
349 
350  if (form->srvowner != newOwnerId)
351  {
352  /* Superusers can always do it */
353  if (!superuser())
354  {
355  Oid srvId;
356  AclResult aclresult;
357 
358  srvId = form->oid;
359 
360  /* Must be owner */
363  NameStr(form->srvname));
364 
365  /* Must be able to become new owner */
366  check_is_member_of_role(GetUserId(), newOwnerId);
367 
368  /* New owner must have USAGE privilege on foreign-data wrapper */
369  aclresult = pg_foreign_data_wrapper_aclcheck(form->srvfdw, newOwnerId, ACL_USAGE);
370  if (aclresult != ACLCHECK_OK)
371  {
372  ForeignDataWrapper *fdw = GetForeignDataWrapper(form->srvfdw);
373 
374  aclcheck_error(aclresult, OBJECT_FDW, fdw->fdwname);
375  }
376  }
377 
378  memset(repl_null, false, sizeof(repl_null));
379  memset(repl_repl, false, sizeof(repl_repl));
380 
381  repl_repl[Anum_pg_foreign_server_srvowner - 1] = true;
382  repl_val[Anum_pg_foreign_server_srvowner - 1] = ObjectIdGetDatum(newOwnerId);
383 
384  aclDatum = heap_getattr(tup,
385  Anum_pg_foreign_server_srvacl,
386  RelationGetDescr(rel),
387  &isNull);
388  /* Null ACLs do not require changes */
389  if (!isNull)
390  {
391  newAcl = aclnewowner(DatumGetAclP(aclDatum),
392  form->srvowner, newOwnerId);
393  repl_repl[Anum_pg_foreign_server_srvacl - 1] = true;
394  repl_val[Anum_pg_foreign_server_srvacl - 1] = PointerGetDatum(newAcl);
395  }
396 
397  tup = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null,
398  repl_repl);
399 
400  CatalogTupleUpdate(rel, &tup->t_self, tup);
401 
402  /* Update owner dependency reference */
403  changeDependencyOnOwner(ForeignServerRelationId, form->oid,
404  newOwnerId);
405  }
406 
407  InvokeObjectPostAlterHook(ForeignServerRelationId,
408  form->oid, 0);
409 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:442
Oid GetUserId(void)
Definition: miscinit.c:380
char * fdwname
Definition: foreign.h:28
#define DatumGetAclP(X)
Definition: acl.h:120
#define PointerGetDatum(X)
Definition: postgres.h:556
AclResult pg_foreign_data_wrapper_aclcheck(Oid fdw_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4718
bool pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid)
Definition: aclchk.c:5119
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:310
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3353
ForeignDataWrapper * GetForeignDataWrapper(Oid fdwid)
Definition: foreign.c:35
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
ItemPointerData t_self
Definition: htup.h:65
#define ACL_USAGE
Definition: parsenodes.h:82
void check_is_member_of_role(Oid member, Oid role)
Definition: acl.c:4954
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:367
FormData_pg_foreign_server * Form_pg_foreign_server
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
#define NameStr(name)
Definition: c.h:609
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
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 450 of file foreigncmds.c.

References AlterForeignServerOwner_internal(), ereport, errcode(), errmsg(), ERROR, FOREIGNSERVEROID, heap_freetuple(), HeapTupleIsValid, ObjectIdGetDatum, RowExclusiveLock, SearchSysCacheCopy1, table_close(), and table_open().

Referenced by shdepReassignOwned().

451 {
452  HeapTuple tup;
453  Relation rel;
454 
455  rel = table_open(ForeignServerRelationId, RowExclusiveLock);
456 
458 
459  if (!HeapTupleIsValid(tup))
460  ereport(ERROR,
461  (errcode(ERRCODE_UNDEFINED_OBJECT),
462  errmsg("foreign server with OID %u does not exist", srvId)));
463 
464  AlterForeignServerOwner_internal(rel, tup, newOwnerId);
465 
466  heap_freetuple(tup);
467 
469 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
int errcode(int sqlerrcode)
Definition: elog.c:570
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:141
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static void AlterForeignServerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
Definition: foreigncmds.c:338
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
int errmsg(const char *fmt,...)
Definition: elog.c:784
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ AlterUserMapping()

ObjectAddress AlterUserMapping ( AlterUserMappingStmt stmt)

Definition at line 1266 of file foreigncmds.c.

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

Referenced by ProcessUtilitySlow().

1267 {
1268  Relation rel;
1269  HeapTuple tp;
1270  Datum repl_val[Natts_pg_user_mapping];
1271  bool repl_null[Natts_pg_user_mapping];
1272  bool repl_repl[Natts_pg_user_mapping];
1273  Oid useId;
1274  Oid umId;
1275  ForeignServer *srv;
1276  ObjectAddress address;
1277  RoleSpec *role = (RoleSpec *) stmt->user;
1278 
1279  rel = table_open(UserMappingRelationId, RowExclusiveLock);
1280 
1281  if (role->roletype == ROLESPEC_PUBLIC)
1282  useId = ACL_ID_PUBLIC;
1283  else
1284  useId = get_rolespec_oid(stmt->user, false);
1285 
1286  srv = GetForeignServerByName(stmt->servername, false);
1287 
1288  umId = GetSysCacheOid2(USERMAPPINGUSERSERVER, Anum_pg_user_mapping_oid,
1289  ObjectIdGetDatum(useId),
1290  ObjectIdGetDatum(srv->serverid));
1291  if (!OidIsValid(umId))
1292  ereport(ERROR,
1293  (errcode(ERRCODE_UNDEFINED_OBJECT),
1294  errmsg("user mapping for \"%s\" does not exist for server \"%s\"",
1295  MappingUserName(useId), stmt->servername)));
1296 
1297  user_mapping_ddl_aclcheck(useId, srv->serverid, stmt->servername);
1298 
1300 
1301  if (!HeapTupleIsValid(tp))
1302  elog(ERROR, "cache lookup failed for user mapping %u", umId);
1303 
1304  memset(repl_val, 0, sizeof(repl_val));
1305  memset(repl_null, false, sizeof(repl_null));
1306  memset(repl_repl, false, sizeof(repl_repl));
1307 
1308  if (stmt->options)
1309  {
1310  ForeignDataWrapper *fdw;
1311  Datum datum;
1312  bool isnull;
1313 
1314  /*
1315  * Process the options.
1316  */
1317 
1318  fdw = GetForeignDataWrapper(srv->fdwid);
1319 
1320  datum = SysCacheGetAttr(USERMAPPINGUSERSERVER,
1321  tp,
1322  Anum_pg_user_mapping_umoptions,
1323  &isnull);
1324  if (isnull)
1325  datum = PointerGetDatum(NULL);
1326 
1327  /* Prepare the options array */
1328  datum = transformGenericOptions(UserMappingRelationId,
1329  datum,
1330  stmt->options,
1331  fdw->fdwvalidator);
1332 
1333  if (PointerIsValid(DatumGetPointer(datum)))
1334  repl_val[Anum_pg_user_mapping_umoptions - 1] = datum;
1335  else
1336  repl_null[Anum_pg_user_mapping_umoptions - 1] = true;
1337 
1338  repl_repl[Anum_pg_user_mapping_umoptions - 1] = true;
1339  }
1340 
1341  /* Everything looks good - update the tuple */
1342  tp = heap_modify_tuple(tp, RelationGetDescr(rel),
1343  repl_val, repl_null, repl_repl);
1344 
1345  CatalogTupleUpdate(rel, &tp->t_self, tp);
1346 
1347  ObjectAddressSet(address, UserMappingRelationId, umId);
1348 
1349  heap_freetuple(tp);
1350 
1352 
1353  return address;
1354 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define RelationGetDescr(relation)
Definition: rel.h:442
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:110
#define PointerGetDatum(X)
Definition: postgres.h:556
int errcode(int sqlerrcode)
Definition: elog.c:570
static void user_mapping_ddl_aclcheck(Oid umuserid, Oid serverid, const char *servername)
Definition: foreigncmds.c:1119
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
ForeignDataWrapper * GetForeignDataWrapper(Oid fdwid)
Definition: foreign.c:35
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
ForeignServer * GetForeignServerByName(const char *srvname, bool missing_ok)
Definition: foreign.c:180
#define ereport(elevel, rest)
Definition: elog.h:141
uintptr_t Datum
Definition: postgres.h:367
RoleSpecType roletype
Definition: parsenodes.h:328
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1385
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5225
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:194
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define DatumGetPointer(X)
Definition: postgres.h:549
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define elog(elevel,...)
Definition: elog.h:226
#define ACL_ID_PUBLIC
Definition: acl.h:46
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define PointerIsValid(pointer)
Definition: c.h:626
Oid serverid
Definition: foreign.h:36
#define MappingUserName(userid)
Definition: foreign.h:20

◆ CreateForeignDataWrapper()

ObjectAddress CreateForeignDataWrapper ( CreateFdwStmt stmt)

Definition at line 563 of file foreigncmds.c.

References CatalogTupleInsert(), ObjectAddress::classId, CStringGetDatum, DatumGetPointer, DEPENDENCY_NORMAL, DirectFunctionCall1, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errhint(), errmsg(), ERROR, CreateFdwStmt::fdwname, ForeignDataWrapperOidIndexId, CreateFdwStmt::func_options, GetForeignDataWrapperByName(), GetNewOidWithIndex(), GetUserId(), heap_form_tuple(), heap_freetuple(), InvokeObjectPostCreateHook, namein(), ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, CreateFdwStmt::options, parse_func_options(), PointerGetDatum, PointerIsValid, RelationData::rd_att, recordDependencyOn(), recordDependencyOnCurrentExtension(), recordDependencyOnOwner(), RowExclusiveLock, superuser(), table_close(), table_open(), transformGenericOptions(), and values.

Referenced by ProcessUtilitySlow().

564 {
565  Relation rel;
566  Datum values[Natts_pg_foreign_data_wrapper];
567  bool nulls[Natts_pg_foreign_data_wrapper];
568  HeapTuple tuple;
569  Oid fdwId;
570  bool handler_given;
571  bool validator_given;
572  Oid fdwhandler;
573  Oid fdwvalidator;
574  Datum fdwoptions;
575  Oid ownerId;
576  ObjectAddress myself;
577  ObjectAddress referenced;
578 
579  rel = table_open(ForeignDataWrapperRelationId, RowExclusiveLock);
580 
581  /* Must be super user */
582  if (!superuser())
583  ereport(ERROR,
584  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
585  errmsg("permission denied to create foreign-data wrapper \"%s\"",
586  stmt->fdwname),
587  errhint("Must be superuser to create a foreign-data wrapper.")));
588 
589  /* For now the owner cannot be specified on create. Use effective user ID. */
590  ownerId = GetUserId();
591 
592  /*
593  * Check that there is no other foreign-data wrapper by this name.
594  */
595  if (GetForeignDataWrapperByName(stmt->fdwname, true) != NULL)
596  ereport(ERROR,
598  errmsg("foreign-data wrapper \"%s\" already exists",
599  stmt->fdwname)));
600 
601  /*
602  * Insert tuple into pg_foreign_data_wrapper.
603  */
604  memset(values, 0, sizeof(values));
605  memset(nulls, false, sizeof(nulls));
606 
608  Anum_pg_foreign_data_wrapper_oid);
609  values[Anum_pg_foreign_data_wrapper_oid - 1] = ObjectIdGetDatum(fdwId);
610  values[Anum_pg_foreign_data_wrapper_fdwname - 1] =
612  values[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(ownerId);
613 
614  /* Lookup handler and validator functions, if given */
616  &handler_given, &fdwhandler,
617  &validator_given, &fdwvalidator);
618 
619  values[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = ObjectIdGetDatum(fdwhandler);
620  values[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = ObjectIdGetDatum(fdwvalidator);
621 
622  nulls[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
623 
624  fdwoptions = transformGenericOptions(ForeignDataWrapperRelationId,
625  PointerGetDatum(NULL),
626  stmt->options,
627  fdwvalidator);
628 
629  if (PointerIsValid(DatumGetPointer(fdwoptions)))
630  values[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = fdwoptions;
631  else
632  nulls[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = true;
633 
634  tuple = heap_form_tuple(rel->rd_att, values, nulls);
635 
636  CatalogTupleInsert(rel, tuple);
637 
638  heap_freetuple(tuple);
639 
640  /* record dependencies */
641  myself.classId = ForeignDataWrapperRelationId;
642  myself.objectId = fdwId;
643  myself.objectSubId = 0;
644 
645  if (OidIsValid(fdwhandler))
646  {
647  referenced.classId = ProcedureRelationId;
648  referenced.objectId = fdwhandler;
649  referenced.objectSubId = 0;
650  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
651  }
652 
653  if (OidIsValid(fdwvalidator))
654  {
655  referenced.classId = ProcedureRelationId;
656  referenced.objectId = fdwvalidator;
657  referenced.objectSubId = 0;
658  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
659  }
660 
661  recordDependencyOnOwner(ForeignDataWrapperRelationId, fdwId, ownerId);
662 
663  /* dependency on extension */
664  recordDependencyOnCurrentExtension(&myself, false);
665 
666  /* Post creation hook for new foreign data wrapper */
667  InvokeObjectPostCreateHook(ForeignDataWrapperRelationId, fdwId, 0);
668 
670 
671  return myself;
672 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:323
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
int errhint(const char *fmt,...)
Definition: elog.c:974
static void parse_func_options(List *func_options, bool *handler_given, Oid *fdwhandler, bool *validator_given, Oid *fdwvalidator)
Definition: foreigncmds.c:519
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
Oid GetUserId(void)
Definition: miscinit.c:380
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:110
#define PointerGetDatum(X)
Definition: postgres.h:556
int errcode(int sqlerrcode)
Definition: elog.c:570
bool superuser(void)
Definition: superuser.c:47
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:617
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:165
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
List * options
Definition: parsenodes.h:2257
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
char * fdwname
Definition: parsenodes.h:2255
#define CStringGetDatum(X)
Definition: postgres.h:578
#define ereport(elevel, rest)
Definition: elog.h:141
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:84
#define ForeignDataWrapperOidIndexId
Definition: indexing.h:294
ForeignDataWrapper * GetForeignDataWrapperByName(const char *fdwname, bool missing_ok)
Definition: foreign.c:94
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:138
#define DatumGetPointer(X)
Definition: postgres.h:549
static Datum values[MAXATTR]
Definition: bootstrap.c:167
int errmsg(const char *fmt,...)
Definition: elog.c:784
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:33
#define PointerIsValid(pointer)
Definition: c.h:626
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183
List * func_options
Definition: parsenodes.h:2256

◆ CreateForeignServer()

ObjectAddress CreateForeignServer ( CreateForeignServerStmt stmt)

Definition at line 867 of file foreigncmds.c.

References ACL_USAGE, aclcheck_error(), ACLCHECK_OK, CatalogTupleInsert(), ObjectAddress::classId, CStringGetDatum, CStringGetTextDatum, DatumGetPointer, DEPENDENCY_NORMAL, DirectFunctionCall1, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, ForeignDataWrapper::fdwid, ForeignDataWrapper::fdwname, CreateForeignServerStmt::fdwname, ForeignDataWrapper::fdwvalidator, ForeignServerOidIndexId, GetForeignDataWrapperByName(), GetForeignServerByName(), GetNewOidWithIndex(), GetUserId(), heap_form_tuple(), heap_freetuple(), CreateForeignServerStmt::if_not_exists, InvalidObjectAddress, InvokeObjectPostCreateHook, namein(), NOTICE, OBJECT_FDW, 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, table_close(), table_open(), transformGenericOptions(), values, and CreateForeignServerStmt::version.

Referenced by ProcessUtilitySlow().

868 {
869  Relation rel;
870  Datum srvoptions;
871  Datum values[Natts_pg_foreign_server];
872  bool nulls[Natts_pg_foreign_server];
873  HeapTuple tuple;
874  Oid srvId;
875  Oid ownerId;
876  AclResult aclresult;
877  ObjectAddress myself;
878  ObjectAddress referenced;
879  ForeignDataWrapper *fdw;
880 
881  rel = table_open(ForeignServerRelationId, RowExclusiveLock);
882 
883  /* For now the owner cannot be specified on create. Use effective user ID. */
884  ownerId = GetUserId();
885 
886  /*
887  * Check that there is no other foreign server by this name. Do nothing if
888  * IF NOT EXISTS was enforced.
889  */
890  if (GetForeignServerByName(stmt->servername, true) != NULL)
891  {
892  if (stmt->if_not_exists)
893  {
894  ereport(NOTICE,
896  errmsg("server \"%s\" already exists, skipping",
897  stmt->servername)));
899  return InvalidObjectAddress;
900  }
901  else
902  ereport(ERROR,
904  errmsg("server \"%s\" already exists",
905  stmt->servername)));
906  }
907 
908  /*
909  * Check that the FDW exists and that we have USAGE on it. Also get the
910  * actual FDW for option validation etc.
911  */
912  fdw = GetForeignDataWrapperByName(stmt->fdwname, false);
913 
914  aclresult = pg_foreign_data_wrapper_aclcheck(fdw->fdwid, ownerId, ACL_USAGE);
915  if (aclresult != ACLCHECK_OK)
916  aclcheck_error(aclresult, OBJECT_FDW, fdw->fdwname);
917 
918  /*
919  * Insert tuple into pg_foreign_server.
920  */
921  memset(values, 0, sizeof(values));
922  memset(nulls, false, sizeof(nulls));
923 
925  Anum_pg_foreign_server_oid);
926  values[Anum_pg_foreign_server_oid - 1] = ObjectIdGetDatum(srvId);
927  values[Anum_pg_foreign_server_srvname - 1] =
929  values[Anum_pg_foreign_server_srvowner - 1] = ObjectIdGetDatum(ownerId);
930  values[Anum_pg_foreign_server_srvfdw - 1] = ObjectIdGetDatum(fdw->fdwid);
931 
932  /* Add server type if supplied */
933  if (stmt->servertype)
934  values[Anum_pg_foreign_server_srvtype - 1] =
936  else
937  nulls[Anum_pg_foreign_server_srvtype - 1] = true;
938 
939  /* Add server version if supplied */
940  if (stmt->version)
941  values[Anum_pg_foreign_server_srvversion - 1] =
943  else
944  nulls[Anum_pg_foreign_server_srvversion - 1] = true;
945 
946  /* Start with a blank acl */
947  nulls[Anum_pg_foreign_server_srvacl - 1] = true;
948 
949  /* Add server options */
950  srvoptions = transformGenericOptions(ForeignServerRelationId,
951  PointerGetDatum(NULL),
952  stmt->options,
953  fdw->fdwvalidator);
954 
955  if (PointerIsValid(DatumGetPointer(srvoptions)))
956  values[Anum_pg_foreign_server_srvoptions - 1] = srvoptions;
957  else
958  nulls[Anum_pg_foreign_server_srvoptions - 1] = true;
959 
960  tuple = heap_form_tuple(rel->rd_att, values, nulls);
961 
962  CatalogTupleInsert(rel, tuple);
963 
964  heap_freetuple(tuple);
965 
966  /* record dependencies */
967  myself.classId = ForeignServerRelationId;
968  myself.objectId = srvId;
969  myself.objectSubId = 0;
970 
971  referenced.classId = ForeignDataWrapperRelationId;
972  referenced.objectId = fdw->fdwid;
973  referenced.objectSubId = 0;
974  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
975 
976  recordDependencyOnOwner(ForeignServerRelationId, srvId, ownerId);
977 
978  /* dependency on extension */
979  recordDependencyOnCurrentExtension(&myself, false);
980 
981  /* Post creation hook for new foreign server */
982  InvokeObjectPostCreateHook(ForeignServerRelationId, srvId, 0);
983 
985 
986  return myself;
987 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:323
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
Oid GetUserId(void)
Definition: miscinit.c:380
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:110
char * fdwname
Definition: foreign.h:28
#define PointerGetDatum(X)
Definition: postgres.h:556
AclResult pg_foreign_data_wrapper_aclcheck(Oid fdw_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4718
int errcode(int sqlerrcode)
Definition: elog.c:570
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:617
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:165
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3353
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:578
#define ACL_USAGE
Definition: parsenodes.h:82
ForeignServer * GetForeignServerByName(const char *srvname, bool missing_ok)
Definition: foreign.c:180
#define ereport(elevel, rest)
Definition: elog.h:141
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:84
#define NOTICE
Definition: elog.h:37
ForeignDataWrapper * GetForeignDataWrapperByName(const char *fdwname, bool missing_ok)
Definition: foreign.c:94
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:138
#define DatumGetPointer(X)
Definition: postgres.h:549
static Datum values[MAXATTR]
Definition: bootstrap.c:167
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define CStringGetTextDatum(s)
Definition: builtins.h:83
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:33
#define PointerIsValid(pointer)
Definition: c.h:626
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183
#define ForeignServerOidIndexId
Definition: indexing.h:299

◆ CreateForeignTable()

void CreateForeignTable ( CreateForeignTableStmt stmt,
Oid  relid 
)

Definition at line 1464 of file foreigncmds.c.

References ACL_USAGE, aclcheck_error(), ACLCHECK_OK, CatalogTupleInsert(), ObjectAddress::classId, CommandCounterIncrement(), DatumGetPointer, DEPENDENCY_NORMAL, ForeignServer::fdwid, ForeignDataWrapper::fdwvalidator, GetForeignDataWrapper(), GetForeignServerByName(), GetUserId(), heap_form_tuple(), heap_freetuple(), OBJECT_FOREIGN_SERVER, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, CreateForeignTableStmt::options, pg_foreign_server_aclcheck(), PointerGetDatum, PointerIsValid, RelationData::rd_att, recordDependencyOn(), RowExclusiveLock, ForeignServer::serverid, ForeignServer::servername, CreateForeignTableStmt::servername, table_close(), table_open(), transformGenericOptions(), and values.

Referenced by ProcessUtilitySlow().

1465 {
1466  Relation ftrel;
1467  Datum ftoptions;
1468  Datum values[Natts_pg_foreign_table];
1469  bool nulls[Natts_pg_foreign_table];
1470  HeapTuple tuple;
1471  AclResult aclresult;
1472  ObjectAddress myself;
1473  ObjectAddress referenced;
1474  Oid ownerId;
1475  ForeignDataWrapper *fdw;
1476  ForeignServer *server;
1477 
1478  /*
1479  * Advance command counter to ensure the pg_attribute tuple is visible;
1480  * the tuple might be updated to add constraints in previous step.
1481  */
1483 
1484  ftrel = table_open(ForeignTableRelationId, RowExclusiveLock);
1485 
1486  /*
1487  * For now the owner cannot be specified on create. Use effective user ID.
1488  */
1489  ownerId = GetUserId();
1490 
1491  /*
1492  * Check that the foreign server exists and that we have USAGE on it. Also
1493  * get the actual FDW for option validation etc.
1494  */
1495  server = GetForeignServerByName(stmt->servername, false);
1496  aclresult = pg_foreign_server_aclcheck(server->serverid, ownerId, ACL_USAGE);
1497  if (aclresult != ACLCHECK_OK)
1498  aclcheck_error(aclresult, OBJECT_FOREIGN_SERVER, server->servername);
1499 
1500  fdw = GetForeignDataWrapper(server->fdwid);
1501 
1502  /*
1503  * Insert tuple into pg_foreign_table.
1504  */
1505  memset(values, 0, sizeof(values));
1506  memset(nulls, false, sizeof(nulls));
1507 
1508  values[Anum_pg_foreign_table_ftrelid - 1] = ObjectIdGetDatum(relid);
1509  values[Anum_pg_foreign_table_ftserver - 1] = ObjectIdGetDatum(server->serverid);
1510  /* Add table generic options */
1511  ftoptions = transformGenericOptions(ForeignTableRelationId,
1512  PointerGetDatum(NULL),
1513  stmt->options,
1514  fdw->fdwvalidator);
1515 
1516  if (PointerIsValid(DatumGetPointer(ftoptions)))
1517  values[Anum_pg_foreign_table_ftoptions - 1] = ftoptions;
1518  else
1519  nulls[Anum_pg_foreign_table_ftoptions - 1] = true;
1520 
1521  tuple = heap_form_tuple(ftrel->rd_att, values, nulls);
1522 
1523  CatalogTupleInsert(ftrel, tuple);
1524 
1525  heap_freetuple(tuple);
1526 
1527  /* Add pg_class dependency on the server */
1528  myself.classId = RelationRelationId;
1529  myself.objectId = relid;
1530  myself.objectSubId = 0;
1531 
1532  referenced.classId = ForeignServerRelationId;
1533  referenced.objectId = server->serverid;
1534  referenced.objectSubId = 0;
1535  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1536 
1537  table_close(ftrel, RowExclusiveLock);
1538 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
Oid GetUserId(void)
Definition: miscinit.c:380
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:110
#define PointerGetDatum(X)
Definition: postgres.h:556
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3353
ForeignDataWrapper * GetForeignDataWrapper(Oid fdwid)
Definition: foreign.c:35
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
AclResult pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4731
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ACL_USAGE
Definition: parsenodes.h:82
ForeignServer * GetForeignServerByName(const char *srvname, bool missing_ok)
Definition: foreign.c:180
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:367
void CommandCounterIncrement(void)
Definition: xact.c:1003
TupleDesc rd_att
Definition: rel.h:84
#define DatumGetPointer(X)
Definition: postgres.h:549
static Datum values[MAXATTR]
Definition: bootstrap.c:167
char * servername
Definition: foreign.h:39
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define PointerIsValid(pointer)
Definition: c.h:626
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183
Oid serverid
Definition: foreign.h:36

◆ CreateUserMapping()

ObjectAddress CreateUserMapping ( CreateUserMappingStmt stmt)

Definition at line 1144 of file foreigncmds.c.

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

Referenced by ProcessUtilitySlow().

1145 {
1146  Relation rel;
1147  Datum useoptions;
1148  Datum values[Natts_pg_user_mapping];
1149  bool nulls[Natts_pg_user_mapping];
1150  HeapTuple tuple;
1151  Oid useId;
1152  Oid umId;
1153  ObjectAddress myself;
1154  ObjectAddress referenced;
1155  ForeignServer *srv;
1156  ForeignDataWrapper *fdw;
1157  RoleSpec *role = (RoleSpec *) stmt->user;
1158 
1159  rel = table_open(UserMappingRelationId, RowExclusiveLock);
1160 
1161  if (role->roletype == ROLESPEC_PUBLIC)
1162  useId = ACL_ID_PUBLIC;
1163  else
1164  useId = get_rolespec_oid(stmt->user, false);
1165 
1166  /* Check that the server exists. */
1167  srv = GetForeignServerByName(stmt->servername, false);
1168 
1169  user_mapping_ddl_aclcheck(useId, srv->serverid, stmt->servername);
1170 
1171  /*
1172  * Check that the user mapping is unique within server.
1173  */
1174  umId = GetSysCacheOid2(USERMAPPINGUSERSERVER, Anum_pg_user_mapping_oid,
1175  ObjectIdGetDatum(useId),
1176  ObjectIdGetDatum(srv->serverid));
1177 
1178  if (OidIsValid(umId))
1179  {
1180  if (stmt->if_not_exists)
1181  {
1182  ereport(NOTICE,
1184  errmsg("user mapping for \"%s\" already exists for server \"%s\", skipping",
1185  MappingUserName(useId),
1186  stmt->servername)));
1187 
1189  return InvalidObjectAddress;
1190  }
1191  else
1192  ereport(ERROR,
1194  errmsg("user mapping for \"%s\" already exists for server \"%s\"",
1195  MappingUserName(useId),
1196  stmt->servername)));
1197  }
1198 
1199  fdw = GetForeignDataWrapper(srv->fdwid);
1200 
1201  /*
1202  * Insert tuple into pg_user_mapping.
1203  */
1204  memset(values, 0, sizeof(values));
1205  memset(nulls, false, sizeof(nulls));
1206 
1208  Anum_pg_user_mapping_oid);
1209  values[Anum_pg_user_mapping_oid - 1] = ObjectIdGetDatum(umId);
1210  values[Anum_pg_user_mapping_umuser - 1] = ObjectIdGetDatum(useId);
1211  values[Anum_pg_user_mapping_umserver - 1] = ObjectIdGetDatum(srv->serverid);
1212 
1213  /* Add user options */
1214  useoptions = transformGenericOptions(UserMappingRelationId,
1215  PointerGetDatum(NULL),
1216  stmt->options,
1217  fdw->fdwvalidator);
1218 
1219  if (PointerIsValid(DatumGetPointer(useoptions)))
1220  values[Anum_pg_user_mapping_umoptions - 1] = useoptions;
1221  else
1222  nulls[Anum_pg_user_mapping_umoptions - 1] = true;
1223 
1224  tuple = heap_form_tuple(rel->rd_att, values, nulls);
1225 
1226  CatalogTupleInsert(rel, tuple);
1227 
1228  heap_freetuple(tuple);
1229 
1230  /* Add dependency on the server */
1231  myself.classId = UserMappingRelationId;
1232  myself.objectId = umId;
1233  myself.objectSubId = 0;
1234 
1235  referenced.classId = ForeignServerRelationId;
1236  referenced.objectId = srv->serverid;
1237  referenced.objectSubId = 0;
1238  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1239 
1240  if (OidIsValid(useId))
1241  {
1242  /* Record the mapped user dependency */
1243  recordDependencyOnOwner(UserMappingRelationId, umId, useId);
1244  }
1245 
1246  /*
1247  * Perhaps someday there should be a recordDependencyOnCurrentExtension
1248  * call here; but since roles aren't members of extensions, it seems like
1249  * user mappings shouldn't be either. Note that the grammar and pg_dump
1250  * would need to be extended too if we change this.
1251  */
1252 
1253  /* Post creation hook for new user mapping */
1254  InvokeObjectPostCreateHook(UserMappingRelationId, umId, 0);
1255 
1257 
1258  return myself;
1259 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:323
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:110
#define PointerGetDatum(X)
Definition: postgres.h:556
int errcode(int sqlerrcode)
Definition: elog.c:570
static void user_mapping_ddl_aclcheck(Oid umuserid, Oid serverid, const char *servername)
Definition: foreigncmds.c:1119
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:165
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
ForeignDataWrapper * GetForeignDataWrapper(Oid fdwid)
Definition: foreign.c:35
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
ForeignServer * GetForeignServerByName(const char *srvname, bool missing_ok)
Definition: foreign.c:180
#define ereport(elevel, rest)
Definition: elog.h:141
uintptr_t Datum
Definition: postgres.h:367
RoleSpecType roletype
Definition: parsenodes.h:328
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5225
TupleDesc rd_att
Definition: rel.h:84
#define NOTICE
Definition: elog.h:37
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:194
#define UserMappingOidIndexId
Definition: indexing.h:304
#define DatumGetPointer(X)
Definition: postgres.h:549
static Datum values[MAXATTR]
Definition: bootstrap.c:167
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define ACL_ID_PUBLIC
Definition: acl.h:46
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:33
#define PointerIsValid(pointer)
Definition: c.h:626
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183
Oid serverid
Definition: foreign.h:36
#define MappingUserName(userid)
Definition: foreign.h:20

◆ import_error_callback()

static void import_error_callback ( void *  arg)
static

Definition at line 1661 of file foreigncmds.c.

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

Referenced by ImportForeignSchema().

1662 {
1664  int syntaxerrposition;
1665 
1666  /* If it's a syntax error, convert to internal syntax error report */
1667  syntaxerrposition = geterrposition();
1668  if (syntaxerrposition > 0)
1669  {
1670  errposition(0);
1671  internalerrposition(syntaxerrposition);
1672  internalerrquery(callback_arg->cmd);
1673  }
1674 
1675  if (callback_arg->tablename)
1676  errcontext("importing foreign table \"%s\"",
1677  callback_arg->tablename);
1678 }
int geterrposition(void)
Definition: elog.c:1244
int internalerrquery(const char *query)
Definition: elog.c:1148
#define errcontext
Definition: elog.h:183
void * arg
int errposition(int cursorpos)
Definition: elog.c:1112
int internalerrposition(int cursorpos)
Definition: elog.c:1128

◆ ImportForeignSchema()

void ImportForeignSchema ( ImportForeignSchemaStmt stmt)

Definition at line 1544 of file foreigncmds.c.

References 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, OBJECT_FOREIGN_SERVER, 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().

1545 {
1546  ForeignServer *server;
1547  ForeignDataWrapper *fdw;
1548  FdwRoutine *fdw_routine;
1549  AclResult aclresult;
1550  List *cmd_list;
1551  ListCell *lc;
1552 
1553  /* Check that the foreign server exists and that we have USAGE on it */
1554  server = GetForeignServerByName(stmt->server_name, false);
1555  aclresult = pg_foreign_server_aclcheck(server->serverid, GetUserId(), ACL_USAGE);
1556  if (aclresult != ACLCHECK_OK)
1557  aclcheck_error(aclresult, OBJECT_FOREIGN_SERVER, server->servername);
1558 
1559  /* Check that the schema exists and we have CREATE permissions on it */
1560  (void) LookupCreationNamespace(stmt->local_schema);
1561 
1562  /* Get the FDW and check it supports IMPORT */
1563  fdw = GetForeignDataWrapper(server->fdwid);
1564  if (!OidIsValid(fdw->fdwhandler))
1565  ereport(ERROR,
1566  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1567  errmsg("foreign-data wrapper \"%s\" has no handler",
1568  fdw->fdwname)));
1569  fdw_routine = GetFdwRoutine(fdw->fdwhandler);
1570  if (fdw_routine->ImportForeignSchema == NULL)
1571  ereport(ERROR,
1572  (errcode(ERRCODE_FDW_NO_SCHEMAS),
1573  errmsg("foreign-data wrapper \"%s\" does not support IMPORT FOREIGN SCHEMA",
1574  fdw->fdwname)));
1575 
1576  /* Call FDW to get a list of commands */
1577  cmd_list = fdw_routine->ImportForeignSchema(stmt, server->serverid);
1578 
1579  /* Parse and execute each command */
1580  foreach(lc, cmd_list)
1581  {
1582  char *cmd = (char *) lfirst(lc);
1583  import_error_callback_arg callback_arg;
1584  ErrorContextCallback sqlerrcontext;
1585  List *raw_parsetree_list;
1586  ListCell *lc2;
1587 
1588  /*
1589  * Setup error traceback support for ereport(). This is so that any
1590  * error in the generated SQL will be displayed nicely.
1591  */
1592  callback_arg.tablename = NULL; /* not known yet */
1593  callback_arg.cmd = cmd;
1594  sqlerrcontext.callback = import_error_callback;
1595  sqlerrcontext.arg = (void *) &callback_arg;
1596  sqlerrcontext.previous = error_context_stack;
1597  error_context_stack = &sqlerrcontext;
1598 
1599  /*
1600  * Parse the SQL string into a list of raw parse trees.
1601  */
1602  raw_parsetree_list = pg_parse_query(cmd);
1603 
1604  /*
1605  * Process each parse tree (we allow the FDW to put more than one
1606  * command per string, though this isn't really advised).
1607  */
1608  foreach(lc2, raw_parsetree_list)
1609  {
1610  RawStmt *rs = lfirst_node(RawStmt, lc2);
1612  PlannedStmt *pstmt;
1613 
1614  /*
1615  * Because we only allow CreateForeignTableStmt, we can skip parse
1616  * analysis, rewrite, and planning steps here.
1617  */
1618  if (!IsA(cstmt, CreateForeignTableStmt))
1619  elog(ERROR,
1620  "foreign-data wrapper \"%s\" returned incorrect statement type %d",
1621  fdw->fdwname, (int) nodeTag(cstmt));
1622 
1623  /* Ignore commands for tables excluded by filter options */
1624  if (!IsImportableForeignTable(cstmt->base.relation->relname, stmt))
1625  continue;
1626 
1627  /* Enable reporting of current table's name on error */
1628  callback_arg.tablename = cstmt->base.relation->relname;
1629 
1630  /* Ensure creation schema is the one given in IMPORT statement */
1631  cstmt->base.relation->schemaname = pstrdup(stmt->local_schema);
1632 
1633  /* No planning needed, just make a wrapper PlannedStmt */
1634  pstmt = makeNode(PlannedStmt);
1635  pstmt->commandType = CMD_UTILITY;
1636  pstmt->canSetTag = false;
1637  pstmt->utilityStmt = (Node *) cstmt;
1638  pstmt->stmt_location = rs->stmt_location;
1639  pstmt->stmt_len = rs->stmt_len;
1640 
1641  /* Execute statement */
1642  ProcessUtility(pstmt,
1643  cmd,
1644  PROCESS_UTILITY_SUBCOMMAND, NULL, NULL,
1645  None_Receiver, NULL);
1646 
1647  /* Be sure to advance the command counter between subcommands */
1649 
1650  callback_arg.tablename = NULL;
1651  }
1652 
1653  error_context_stack = sqlerrcontext.previous;
1654  }
1655 }
RangeVar * relation
Definition: parsenodes.h:2049
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
Oid GetUserId(void)
Definition: miscinit.c:380
char * fdwname
Definition: foreign.h:28
Oid LookupCreationNamespace(const char *nspname)
Definition: namespace.c:2928
char * pstrdup(const char *in)
Definition: mcxt.c:1161
Definition: nodes.h:525
void ProcessUtility(PlannedStmt *pstmt, const char *queryString, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, char *completionTag)
Definition: utility.c:338
int errcode(int sqlerrcode)
Definition: elog.c:570
DestReceiver * None_Receiver
Definition: dest.c:96
void(* callback)(void *arg)
Definition: elog.h:254
struct ErrorContextCallback * previous
Definition: elog.h:253
#define OidIsValid(objectId)
Definition: c.h:638
char * schemaname
Definition: primnodes.h:67
ErrorContextCallback * error_context_stack
Definition: elog.c:88
FdwRoutine * GetFdwRoutine(Oid fdwhandler)
Definition: foreign.c:319
char * relname
Definition: primnodes.h:68
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3353
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:632
#define lfirst_node(type, lc)
Definition: pg_list.h:193
AclResult pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4731
bool IsImportableForeignTable(const char *tablename, ImportForeignSchemaStmt *stmt)
Definition: foreign.c:467
Node * stmt
Definition: parsenodes.h:1485
#define ACL_USAGE
Definition: parsenodes.h:82
ForeignServer * GetForeignServerByName(const char *srvname, bool missing_ok)
Definition: foreign.c:180
ImportForeignSchema_function ImportForeignSchema
Definition: fdwapi.h:237
#define ereport(elevel, rest)
Definition: elog.h:141
AclResult
Definition: acl.h:177
void CommandCounterIncrement(void)
Definition: xact.c:1003
int stmt_len
Definition: parsenodes.h:1487
int stmt_location
Definition: parsenodes.h:1486
#define makeNode(_type_)
Definition: nodes.h:573
#define lfirst(lc)
Definition: pg_list.h:190
#define nodeTag(nodeptr)
Definition: nodes.h:530
int errmsg(const char *fmt,...)
Definition: elog.c:784
char * servername
Definition: foreign.h:39
#define elog(elevel,...)
Definition: elog.h:226
Definition: pg_list.h:50
Oid serverid
Definition: foreign.h:36
static void import_error_callback(void *arg)
Definition: foreigncmds.c:1661

◆ lookup_fdw_handler_func()

static Oid lookup_fdw_handler_func ( DefElem handler)
static

Definition at line 475 of file foreigncmds.c.

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

Referenced by parse_func_options().

476 {
477  Oid handlerOid;
478  Oid funcargtypes[1]; /* dummy */
479 
480  if (handler == NULL || handler->arg == NULL)
481  return InvalidOid;
482 
483  /* handlers have no arguments */
484  handlerOid = LookupFuncName((List *) handler->arg, 0, funcargtypes, false);
485 
486  /* check that handler has correct return type */
487  if (get_func_rettype(handlerOid) != FDW_HANDLEROID)
488  ereport(ERROR,
489  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
490  errmsg("function %s must return type %s",
491  NameListToString((List *) handler->arg), "fdw_handler")));
492 
493  return handlerOid;
494 }
int errcode(int sqlerrcode)
Definition: elog.c:570
unsigned int Oid
Definition: postgres_ext.h:31
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1457
#define ERROR
Definition: elog.h:43
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
Definition: parse_func.c:2100
#define ereport(elevel, rest)
Definition: elog.h:141
Node * arg
Definition: parsenodes.h:731
char * NameListToString(List *names)
Definition: namespace.c:3094
#define InvalidOid
Definition: postgres_ext.h:36
int errmsg(const char *fmt,...)
Definition: elog.c:784
Definition: pg_list.h:50

◆ lookup_fdw_validator_func()

static Oid lookup_fdw_validator_func ( DefElem validator)
static

Definition at line 500 of file foreigncmds.c.

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

Referenced by parse_func_options().

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

◆ optionListToArray()

static Datum optionListToArray ( List options)
static

Definition at line 66 of file foreigncmds.c.

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

Referenced by transformGenericOptions().

67 {
68  ArrayBuildState *astate = NULL;
69  ListCell *cell;
70 
71  foreach(cell, options)
72  {
73  DefElem *def = lfirst(cell);
74  const char *value;
75  Size len;
76  text *t;
77 
78  value = defGetString(def);
79  len = VARHDRSZ + strlen(def->defname) + 1 + strlen(value);
80  t = palloc(len + 1);
81  SET_VARSIZE(t, len);
82  sprintf(VARDATA(t), "%s=%s", def->defname, value);
83 
84  astate = accumArrayResult(astate, PointerGetDatum(t),
85  false, TEXTOID,
87  }
88 
89  if (astate)
90  return makeArrayResult(astate, CurrentMemoryContext);
91 
92  return PointerGetDatum(NULL);
93 }
#define VARDATA(PTR)
Definition: postgres.h:302
#define PointerGetDatum(X)
Definition: postgres.h:556
#define VARHDRSZ
Definition: c.h:555
static struct @144 value
#define sprintf
Definition: port.h:194
char * defGetString(DefElem *def)
Definition: define.c:49
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
Datum makeArrayResult(ArrayBuildState *astate, MemoryContext rcontext)
Definition: arrayfuncs.c:5117
#define lfirst(lc)
Definition: pg_list.h:190
size_t Size
Definition: c.h:466
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5053
void * palloc(Size size)
Definition: mcxt.c:924
Definition: c.h:549
char * defname
Definition: parsenodes.h:730
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329

◆ 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 519 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().

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

◆ RemoveForeignDataWrapperById()

void RemoveForeignDataWrapperById ( Oid  fdwId)

Definition at line 843 of file foreigncmds.c.

References CatalogTupleDelete(), elog, ERROR, FOREIGNDATAWRAPPEROID, HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by doDeletion().

844 {
845  HeapTuple tp;
846  Relation rel;
847 
848  rel = table_open(ForeignDataWrapperRelationId, RowExclusiveLock);
849 
851 
852  if (!HeapTupleIsValid(tp))
853  elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwId);
854 
855  CatalogTupleDelete(rel, &tp->t_self);
856 
857  ReleaseSysCache(tp);
858 
860 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#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:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:226
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ RemoveForeignServerById()

void RemoveForeignServerById ( Oid  srvId)

Definition at line 1093 of file foreigncmds.c.

References CatalogTupleDelete(), elog, ERROR, FOREIGNSERVEROID, HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by doDeletion().

1094 {
1095  HeapTuple tp;
1096  Relation rel;
1097 
1098  rel = table_open(ForeignServerRelationId, RowExclusiveLock);
1099 
1101 
1102  if (!HeapTupleIsValid(tp))
1103  elog(ERROR, "cache lookup failed for foreign server %u", srvId);
1104 
1105  CatalogTupleDelete(rel, &tp->t_self);
1106 
1107  ReleaseSysCache(tp);
1108 
1110 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#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:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:226
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ RemoveUserMapping()

Oid RemoveUserMapping ( DropUserMappingStmt stmt)

Definition at line 1361 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, and user_mapping_ddl_aclcheck().

Referenced by ProcessUtilitySlow().

1362 {
1363  ObjectAddress object;
1364  Oid useId;
1365  Oid umId;
1366  ForeignServer *srv;
1367  RoleSpec *role = (RoleSpec *) stmt->user;
1368 
1369  if (role->roletype == ROLESPEC_PUBLIC)
1370  useId = ACL_ID_PUBLIC;
1371  else
1372  {
1373  useId = get_rolespec_oid(stmt->user, stmt->missing_ok);
1374  if (!OidIsValid(useId))
1375  {
1376  /*
1377  * IF EXISTS specified, role not found and not public. Notice this
1378  * and leave.
1379  */
1380  elog(NOTICE, "role \"%s\" does not exist, skipping",
1381  role->rolename);
1382  return InvalidOid;
1383  }
1384  }
1385 
1386  srv = GetForeignServerByName(stmt->servername, true);
1387 
1388  if (!srv)
1389  {
1390  if (!stmt->missing_ok)
1391  ereport(ERROR,
1392  (errcode(ERRCODE_UNDEFINED_OBJECT),
1393  errmsg("server \"%s\" does not exist",
1394  stmt->servername)));
1395  /* IF EXISTS, just note it */
1396  ereport(NOTICE,
1397  (errmsg("server \"%s\" does not exist, skipping",
1398  stmt->servername)));
1399  return InvalidOid;
1400  }
1401 
1402  umId = GetSysCacheOid2(USERMAPPINGUSERSERVER, Anum_pg_user_mapping_oid,
1403  ObjectIdGetDatum(useId),
1404  ObjectIdGetDatum(srv->serverid));
1405 
1406  if (!OidIsValid(umId))
1407  {
1408  if (!stmt->missing_ok)
1409  ereport(ERROR,
1410  (errcode(ERRCODE_UNDEFINED_OBJECT),
1411  errmsg("user mapping for \"%s\" does not exist for server \"%s\"",
1412  MappingUserName(useId), stmt->servername)));
1413 
1414  /* IF EXISTS specified, just note it */
1415  ereport(NOTICE,
1416  (errmsg("user mapping for \"%s\" does not exist for server \"%s\", skipping",
1417  MappingUserName(useId), stmt->servername)));
1418  return InvalidOid;
1419  }
1420 
1421  user_mapping_ddl_aclcheck(useId, srv->serverid, srv->servername);
1422 
1423  /*
1424  * Do the deletion
1425  */
1426  object.classId = UserMappingRelationId;
1427  object.objectId = umId;
1428  object.objectSubId = 0;
1429 
1430  performDeletion(&object, DROP_CASCADE, 0);
1431 
1432  return umId;
1433 }
int errcode(int sqlerrcode)
Definition: elog.c:570
static void user_mapping_ddl_aclcheck(Oid umuserid, Oid serverid, const char *servername)
Definition: foreigncmds.c:1119
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:315
ForeignServer * GetForeignServerByName(const char *srvname, bool missing_ok)
Definition: foreign.c:180
#define ereport(elevel, rest)
Definition: elog.h:141
RoleSpecType roletype
Definition: parsenodes.h:328
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5225
#define InvalidOid
Definition: postgres_ext.h:36
#define NOTICE
Definition: elog.h:37
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:194
char * rolename
Definition: parsenodes.h:329
int errmsg(const char *fmt,...)
Definition: elog.c:784
char * servername
Definition: foreign.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define ACL_ID_PUBLIC
Definition: acl.h:46
Oid serverid
Definition: foreign.h:36
#define MappingUserName(userid)
Definition: foreign.h:20

◆ RemoveUserMappingById()

void RemoveUserMappingById ( Oid  umId)

Definition at line 1440 of file foreigncmds.c.

References CatalogTupleDelete(), elog, ERROR, HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), HeapTupleData::t_self, table_close(), table_open(), and USERMAPPINGOID.

Referenced by doDeletion().

1441 {
1442  HeapTuple tp;
1443  Relation rel;
1444 
1445  rel = table_open(UserMappingRelationId, RowExclusiveLock);
1446 
1448 
1449  if (!HeapTupleIsValid(tp))
1450  elog(ERROR, "cache lookup failed for user mapping %u", umId);
1451 
1452  CatalogTupleDelete(rel, &tp->t_self);
1453 
1454  ReleaseSysCache(tp);
1455 
1457 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#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:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:226
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ transformGenericOptions()

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

Definition at line 110 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, and untransformRelOptions().

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

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

◆ user_mapping_ddl_aclcheck()

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

Definition at line 1119 of file foreigncmds.c.

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

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

1120 {
1121  Oid curuserid = GetUserId();
1122 
1123  if (!pg_foreign_server_ownercheck(serverid, curuserid))
1124  {
1125  if (umuserid == curuserid)
1126  {
1127  AclResult aclresult;
1128 
1129  aclresult = pg_foreign_server_aclcheck(serverid, curuserid, ACL_USAGE);
1130  if (aclresult != ACLCHECK_OK)
1131  aclcheck_error(aclresult, OBJECT_FOREIGN_SERVER, servername);
1132  }
1133  else
1135  servername);
1136  }
1137 }
Oid GetUserId(void)
Definition: miscinit.c:380
bool pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid)
Definition: aclchk.c:5119
unsigned int Oid
Definition: postgres_ext.h:31
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3353
AclResult pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4731
#define ACL_USAGE
Definition: parsenodes.h:82
AclResult
Definition: acl.h:177