PostgreSQL Source Code  git master
defrem.h File Reference
#include "catalog/objectaddress.h"
#include "nodes/params.h"
#include "parser/parse_node.h"
#include "tcop/dest.h"
#include "utils/array.h"
Include dependency graph for defrem.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void RemoveObjects (DropStmt *stmt)
 
ObjectAddress DefineIndex (Oid relationId, IndexStmt *stmt, Oid indexRelationId, Oid parentIndexId, Oid parentConstraintId, bool is_alter_table, bool check_rights, bool check_not_in_use, bool skip_build, bool quiet)
 
void ExecReindex (ParseState *pstate, ReindexStmt *stmt, bool isTopLevel)
 
char * makeObjectName (const char *name1, const char *name2, const char *label)
 
char * ChooseRelationName (const char *name1, const char *name2, const char *label, Oid namespaceid, bool isconstraint)
 
bool CheckIndexCompatible (Oid oldId, const char *accessMethodName, List *attributeList, List *exclusionOpNames)
 
Oid GetDefaultOpClass (Oid type_id, Oid am_id)
 
Oid ResolveOpClass (List *opclass, Oid attrType, const char *accessMethodName, Oid accessMethodId)
 
ObjectAddress CreateFunction (ParseState *pstate, CreateFunctionStmt *stmt)
 
void RemoveFunctionById (Oid funcOid)
 
ObjectAddress AlterFunction (ParseState *pstate, AlterFunctionStmt *stmt)
 
ObjectAddress CreateCast (CreateCastStmt *stmt)
 
ObjectAddress CreateTransform (CreateTransformStmt *stmt)
 
void IsThereFunctionInNamespace (const char *proname, int pronargs, oidvector *proargtypes, Oid nspOid)
 
void ExecuteDoStmt (DoStmt *stmt, bool atomic)
 
void ExecuteCallStmt (CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest)
 
TupleDesc CallStmtResultDesc (CallStmt *stmt)
 
Oid get_transform_oid (Oid type_id, Oid lang_id, bool missing_ok)
 
void interpret_function_parameter_list (ParseState *pstate, List *parameters, Oid languageOid, ObjectType objtype, oidvector **parameterTypes, List **parameterTypes_list, ArrayType **allParameterTypes, ArrayType **parameterModes, ArrayType **parameterNames, List **inParameterNames_list, List **parameterDefaults, Oid *variadicArgType, Oid *requiredResultType)
 
ObjectAddress DefineOperator (List *names, List *parameters)
 
void RemoveOperatorById (Oid operOid)
 
ObjectAddress AlterOperator (AlterOperatorStmt *stmt)
 
ObjectAddress CreateStatistics (CreateStatsStmt *stmt)
 
ObjectAddress AlterStatistics (AlterStatsStmt *stmt)
 
void RemoveStatisticsById (Oid statsOid)
 
Oid StatisticsGetRelation (Oid statId, bool missing_ok)
 
ObjectAddress DefineAggregate (ParseState *pstate, List *name, List *args, bool oldstyle, List *parameters, bool replace)
 
ObjectAddress DefineOpClass (CreateOpClassStmt *stmt)
 
ObjectAddress DefineOpFamily (CreateOpFamilyStmt *stmt)
 
Oid AlterOpFamily (AlterOpFamilyStmt *stmt)
 
void IsThereOpClassInNamespace (const char *opcname, Oid opcmethod, Oid opcnamespace)
 
void IsThereOpFamilyInNamespace (const char *opfname, Oid opfmethod, Oid opfnamespace)
 
Oid get_opclass_oid (Oid amID, List *opclassname, bool missing_ok)
 
Oid get_opfamily_oid (Oid amID, List *opfamilyname, bool missing_ok)
 
ObjectAddress DefineTSParser (List *names, List *parameters)
 
ObjectAddress DefineTSDictionary (List *names, List *parameters)
 
ObjectAddress AlterTSDictionary (AlterTSDictionaryStmt *stmt)
 
ObjectAddress DefineTSTemplate (List *names, List *parameters)
 
ObjectAddress DefineTSConfiguration (List *names, List *parameters, ObjectAddress *copied)
 
void RemoveTSConfigurationById (Oid cfgId)
 
ObjectAddress AlterTSConfiguration (AlterTSConfigurationStmt *stmt)
 
textserialize_deflist (List *deflist)
 
Listdeserialize_deflist (Datum txt)
 
ObjectAddress AlterForeignServerOwner (const char *name, Oid newOwnerId)
 
void AlterForeignServerOwner_oid (Oid, Oid newOwnerId)
 
ObjectAddress AlterForeignDataWrapperOwner (const char *name, Oid newOwnerId)
 
void AlterForeignDataWrapperOwner_oid (Oid fwdId, Oid newOwnerId)
 
ObjectAddress CreateForeignDataWrapper (CreateFdwStmt *stmt)
 
ObjectAddress AlterForeignDataWrapper (AlterFdwStmt *stmt)
 
ObjectAddress CreateForeignServer (CreateForeignServerStmt *stmt)
 
ObjectAddress AlterForeignServer (AlterForeignServerStmt *stmt)
 
ObjectAddress CreateUserMapping (CreateUserMappingStmt *stmt)
 
ObjectAddress AlterUserMapping (AlterUserMappingStmt *stmt)
 
Oid RemoveUserMapping (DropUserMappingStmt *stmt)
 
void CreateForeignTable (CreateForeignTableStmt *stmt, Oid relid)
 
void ImportForeignSchema (ImportForeignSchemaStmt *stmt)
 
Datum transformGenericOptions (Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
 
ObjectAddress CreateAccessMethod (CreateAmStmt *stmt)
 
Oid get_index_am_oid (const char *amname, bool missing_ok)
 
Oid get_table_am_oid (const char *amname, bool missing_ok)
 
Oid get_am_oid (const char *amname, bool missing_ok)
 
char * get_am_name (Oid amOid)
 
char * defGetString (DefElem *def)
 
double defGetNumeric (DefElem *def)
 
bool defGetBoolean (DefElem *def)
 
int32 defGetInt32 (DefElem *def)
 
int64 defGetInt64 (DefElem *def)
 
ListdefGetQualifiedName (DefElem *def)
 
TypeNamedefGetTypeName (DefElem *def)
 
int defGetTypeLength (DefElem *def)
 
ListdefGetStringList (DefElem *def)
 

Function Documentation

◆ AlterForeignDataWrapper()

ObjectAddress AlterForeignDataWrapper ( AlterFdwStmt stmt)

Definition at line 678 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().

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

◆ 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:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
int errcode(int sqlerrcode)
Definition: elog.c:698
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define ERROR
Definition: elog.h:46
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:622
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_foreign_data_wrapper * Form_pg_foreign_data_wrapper
const char * name
Definition: encode.c:515
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:175
int errmsg(const char *fmt,...)
Definition: elog.c:909
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_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:167
int errcode(int sqlerrcode)
Definition: elog.c:698
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:175
int errmsg(const char *fmt,...)
Definition: elog.c:909
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 969 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().

970 {
971  Relation rel;
972  HeapTuple tp;
973  Datum repl_val[Natts_pg_foreign_server];
974  bool repl_null[Natts_pg_foreign_server];
975  bool repl_repl[Natts_pg_foreign_server];
976  Oid srvId;
977  Form_pg_foreign_server srvForm;
978  ObjectAddress address;
979 
980  rel = table_open(ForeignServerRelationId, RowExclusiveLock);
981 
983  CStringGetDatum(stmt->servername));
984 
985  if (!HeapTupleIsValid(tp))
986  ereport(ERROR,
987  (errcode(ERRCODE_UNDEFINED_OBJECT),
988  errmsg("server \"%s\" does not exist", stmt->servername)));
989 
990  srvForm = (Form_pg_foreign_server) GETSTRUCT(tp);
991  srvId = srvForm->oid;
992 
993  /*
994  * Only owner or a superuser can ALTER a SERVER.
995  */
998  stmt->servername);
999 
1000  memset(repl_val, 0, sizeof(repl_val));
1001  memset(repl_null, false, sizeof(repl_null));
1002  memset(repl_repl, false, sizeof(repl_repl));
1003 
1004  if (stmt->has_version)
1005  {
1006  /*
1007  * Change the server VERSION string.
1008  */
1009  if (stmt->version)
1010  repl_val[Anum_pg_foreign_server_srvversion - 1] =
1012  else
1013  repl_null[Anum_pg_foreign_server_srvversion - 1] = true;
1014 
1015  repl_repl[Anum_pg_foreign_server_srvversion - 1] = true;
1016  }
1017 
1018  if (stmt->options)
1019  {
1020  ForeignDataWrapper *fdw = GetForeignDataWrapper(srvForm->srvfdw);
1021  Datum datum;
1022  bool isnull;
1023 
1024  /* Extract the current srvoptions */
1026  tp,
1027  Anum_pg_foreign_server_srvoptions,
1028  &isnull);
1029  if (isnull)
1030  datum = PointerGetDatum(NULL);
1031 
1032  /* Prepare the options array */
1033  datum = transformGenericOptions(ForeignServerRelationId,
1034  datum,
1035  stmt->options,
1036  fdw->fdwvalidator);
1037 
1038  if (PointerIsValid(DatumGetPointer(datum)))
1039  repl_val[Anum_pg_foreign_server_srvoptions - 1] = datum;
1040  else
1041  repl_null[Anum_pg_foreign_server_srvoptions - 1] = true;
1042 
1043  repl_repl[Anum_pg_foreign_server_srvoptions - 1] = true;
1044  }
1045 
1046  /* Everything looks good - update the tuple */
1047  tp = heap_modify_tuple(tp, RelationGetDescr(rel),
1048  repl_val, repl_null, repl_repl);
1049 
1050  CatalogTupleUpdate(rel, &tp->t_self, tp);
1051 
1052  InvokeObjectPostAlterHook(ForeignServerRelationId, srvId, 0);
1053 
1054  ObjectAddressSet(address, ForeignServerRelationId, srvId);
1055 
1056  heap_freetuple(tp);
1057 
1059 
1060  return address;
1061 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetDescr(relation)
Definition: rel.h:495
Oid GetUserId(void)
Definition: miscinit.c:478
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:110
#define PointerGetDatum(X)
Definition: postgres.h:600
bool pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid)
Definition: aclchk.c:5187
int errcode(int sqlerrcode)
Definition: elog.c:698
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:3313
ForeignDataWrapper * GetForeignDataWrapper(Oid fdwid)
Definition: foreign.c:35
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:622
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
uintptr_t Datum
Definition: postgres.h:411
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
FormData_pg_foreign_server * Form_pg_foreign_server
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define DatumGetPointer(X)
Definition: postgres.h:593
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:175
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define CStringGetTextDatum(s)
Definition: builtins.h:82
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:698

◆ 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:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
int errcode(int sqlerrcode)
Definition: elog.c:698
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define ERROR
Definition: elog.h:46
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:622
FormData_pg_foreign_server * Form_pg_foreign_server
#define ereport(elevel,...)
Definition: elog.h:157
#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:515
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:175
int errmsg(const char *fmt,...)
Definition: elog.c:909
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ AlterForeignServerOwner_oid()

void AlterForeignServerOwner_oid ( Oid  ,
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:167
int errcode(int sqlerrcode)
Definition: elog.c:698
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel,...)
Definition: elog.h:157
#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:175
int errmsg(const char *fmt,...)
Definition: elog.c:909
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ AlterFunction()

ObjectAddress AlterFunction ( ParseState pstate,
AlterFunctionStmt stmt 
)

Definition at line 1345 of file functioncmds.c.

References aclcheck_error(), ACLCHECK_NOT_OWNER, AlterFunctionStmt::actions, DefElem::arg, CatalogTupleUpdate(), changeDependencyFor(), ObjectAddress::classId, compute_common_attribute(), DatumGetArrayTypeP, defGetNumeric(), DefElem::defname, DEPENDENCY_NORMAL, elog, ereport, errcode(), errmsg(), ERROR, AlterFunctionStmt::func, GETSTRUCT, GetUserId(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, interpret_func_parallel(), interpret_func_support(), interpret_func_volatility(), intVal, InvokeObjectPostAlterHook, lfirst, LookupFuncWithArgs(), NameListToString(), NIL, NoLock, ObjectAddressSet, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, ObjectWithArgs::objname, AlterFunctionStmt::objtype, OidIsValid, pg_proc_ownercheck(), PointerGetDatum, PROCOID, recordDependencyOn(), RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy1, superuser(), SysCacheGetAttr(), HeapTupleData::t_self, table_close(), table_open(), and update_proconfig_value().

Referenced by ProcessUtilitySlow().

1346 {
1347  HeapTuple tup;
1348  Oid funcOid;
1349  Form_pg_proc procForm;
1350  bool is_procedure;
1351  Relation rel;
1352  ListCell *l;
1353  DefElem *volatility_item = NULL;
1354  DefElem *strict_item = NULL;
1355  DefElem *security_def_item = NULL;
1356  DefElem *leakproof_item = NULL;
1357  List *set_items = NIL;
1358  DefElem *cost_item = NULL;
1359  DefElem *rows_item = NULL;
1360  DefElem *support_item = NULL;
1361  DefElem *parallel_item = NULL;
1362  ObjectAddress address;
1363 
1364  rel = table_open(ProcedureRelationId, RowExclusiveLock);
1365 
1366  funcOid = LookupFuncWithArgs(stmt->objtype, stmt->func, false);
1367 
1368  ObjectAddressSet(address, ProcedureRelationId, funcOid);
1369 
1370  tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1371  if (!HeapTupleIsValid(tup)) /* should not happen */
1372  elog(ERROR, "cache lookup failed for function %u", funcOid);
1373 
1374  procForm = (Form_pg_proc) GETSTRUCT(tup);
1375 
1376  /* Permission check: must own function */
1377  if (!pg_proc_ownercheck(funcOid, GetUserId()))
1379  NameListToString(stmt->func->objname));
1380 
1381  if (procForm->prokind == PROKIND_AGGREGATE)
1382  ereport(ERROR,
1383  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1384  errmsg("\"%s\" is an aggregate function",
1385  NameListToString(stmt->func->objname))));
1386 
1387  is_procedure = (procForm->prokind == PROKIND_PROCEDURE);
1388 
1389  /* Examine requested actions. */
1390  foreach(l, stmt->actions)
1391  {
1392  DefElem *defel = (DefElem *) lfirst(l);
1393 
1394  if (compute_common_attribute(pstate,
1395  is_procedure,
1396  defel,
1397  &volatility_item,
1398  &strict_item,
1399  &security_def_item,
1400  &leakproof_item,
1401  &set_items,
1402  &cost_item,
1403  &rows_item,
1404  &support_item,
1405  &parallel_item) == false)
1406  elog(ERROR, "option \"%s\" not recognized", defel->defname);
1407  }
1408 
1409  if (volatility_item)
1410  procForm->provolatile = interpret_func_volatility(volatility_item);
1411  if (strict_item)
1412  procForm->proisstrict = intVal(strict_item->arg);
1413  if (security_def_item)
1414  procForm->prosecdef = intVal(security_def_item->arg);
1415  if (leakproof_item)
1416  {
1417  procForm->proleakproof = intVal(leakproof_item->arg);
1418  if (procForm->proleakproof && !superuser())
1419  ereport(ERROR,
1420  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1421  errmsg("only superuser can define a leakproof function")));
1422  }
1423  if (cost_item)
1424  {
1425  procForm->procost = defGetNumeric(cost_item);
1426  if (procForm->procost <= 0)
1427  ereport(ERROR,
1428  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1429  errmsg("COST must be positive")));
1430  }
1431  if (rows_item)
1432  {
1433  procForm->prorows = defGetNumeric(rows_item);
1434  if (procForm->prorows <= 0)
1435  ereport(ERROR,
1436  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1437  errmsg("ROWS must be positive")));
1438  if (!procForm->proretset)
1439  ereport(ERROR,
1440  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1441  errmsg("ROWS is not applicable when function does not return a set")));
1442  }
1443  if (support_item)
1444  {
1445  /* interpret_func_support handles the privilege check */
1446  Oid newsupport = interpret_func_support(support_item);
1447 
1448  /* Add or replace dependency on support function */
1449  if (OidIsValid(procForm->prosupport))
1450  changeDependencyFor(ProcedureRelationId, funcOid,
1451  ProcedureRelationId, procForm->prosupport,
1452  newsupport);
1453  else
1454  {
1455  ObjectAddress referenced;
1456 
1457  referenced.classId = ProcedureRelationId;
1458  referenced.objectId = newsupport;
1459  referenced.objectSubId = 0;
1460  recordDependencyOn(&address, &referenced, DEPENDENCY_NORMAL);
1461  }
1462 
1463  procForm->prosupport = newsupport;
1464  }
1465  if (set_items)
1466  {
1467  Datum datum;
1468  bool isnull;
1469  ArrayType *a;
1470  Datum repl_val[Natts_pg_proc];
1471  bool repl_null[Natts_pg_proc];
1472  bool repl_repl[Natts_pg_proc];
1473 
1474  /* extract existing proconfig setting */
1475  datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proconfig, &isnull);
1476  a = isnull ? NULL : DatumGetArrayTypeP(datum);
1477 
1478  /* update according to each SET or RESET item, left to right */
1479  a = update_proconfig_value(a, set_items);
1480 
1481  /* update the tuple */
1482  memset(repl_repl, false, sizeof(repl_repl));
1483  repl_repl[Anum_pg_proc_proconfig - 1] = true;
1484 
1485  if (a == NULL)
1486  {
1487  repl_val[Anum_pg_proc_proconfig - 1] = (Datum) 0;
1488  repl_null[Anum_pg_proc_proconfig - 1] = true;
1489  }
1490  else
1491  {
1492  repl_val[Anum_pg_proc_proconfig - 1] = PointerGetDatum(a);
1493  repl_null[Anum_pg_proc_proconfig - 1] = false;
1494  }
1495 
1496  tup = heap_modify_tuple(tup, RelationGetDescr(rel),
1497  repl_val, repl_null, repl_repl);
1498  }
1499  if (parallel_item)
1500  procForm->proparallel = interpret_func_parallel(parallel_item);
1501 
1502  /* Do the update */
1503  CatalogTupleUpdate(rel, &tup->t_self, tup);
1504 
1505  InvokeObjectPostAlterHook(ProcedureRelationId, funcOid, 0);
1506 
1507  table_close(rel, NoLock);
1508  heap_freetuple(tup);
1509 
1510  return address;
1511 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetDescr(relation)
Definition: rel.h:495
Oid GetUserId(void)
Definition: miscinit.c:478
#define PointerGetDatum(X)
Definition: postgres.h:600
double defGetNumeric(DefElem *def)
Definition: define.c:85
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
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:710
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3313
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
static Oid interpret_func_support(DefElem *defel)
Definition: functioncmds.c:659
ItemPointerData t_self
Definition: htup.h:65
ObjectType objtype
Definition: parsenodes.h:2973
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
static char interpret_func_volatility(DefElem *defel)
Definition: functioncmds.c:591
Node * arg
Definition: parsenodes.h:747
char * NameListToString(List *names)
Definition: namespace.c:3101
uintptr_t Datum
Definition: postgres.h:411
static ArrayType * update_proconfig_value(ArrayType *a, List *set_items)
Definition: functioncmds.c:634
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
#define ereport(elevel,...)
Definition: elog.h:157
ObjectWithArgs * func
Definition: parsenodes.h:2974
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:169
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:175
#define intVal(v)
Definition: value.h:52
int errmsg(const char *fmt,...)
Definition: elog.c:909
long changeDependencyFor(Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
Definition: pg_depend.c:388
#define elog(elevel,...)
Definition: elog.h:232
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2177
char * defname
Definition: parsenodes.h:746
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
Definition: pg_list.h:50
static bool compute_common_attribute(ParseState *pstate, bool is_procedure, DefElem *defel, DefElem **volatility_item, DefElem **strict_item, DefElem **security_item, DefElem **leakproof_item, List **set_items, DefElem **cost_item, DefElem **rows_item, DefElem **support_item, DefElem **parallel_item)
Definition: functioncmds.c:482
bool pg_proc_ownercheck(Oid proc_oid, Oid roleid)
Definition: aclchk.c:4901
static char interpret_func_parallel(DefElem *defel)
Definition: functioncmds.c:609
#define DatumGetArrayTypeP(X)
Definition: array.h:254

◆ AlterOperator()

ObjectAddress AlterOperator ( AlterOperatorStmt stmt)

Definition at line 409 of file operatorcmds.c.

References aclcheck_error(), ACLCHECK_NOT_OWNER, DefElem::arg, CatalogTupleUpdate(), defGetQualifiedName(), DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, GetUserId(), heap_modify_tuple(), HeapTupleIsValid, i, InvalidOid, InvokeObjectPostAlterHook, lfirst, LookupOperWithArgs(), makeOperatorDependencies(), NameStr, NIL, NoLock, OBJECT_OPERATOR, ObjectIdGetDatum, OidIsValid, AlterOperatorStmt::opername, OPEROID, AlterOperatorStmt::options, pg_oper_ownercheck(), RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy1, HeapTupleData::t_self, table_close(), table_open(), ValidateJoinEstimator(), ValidateRestrictionEstimator(), and values.

Referenced by ProcessUtilitySlow().

410 {
411  ObjectAddress address;
412  Oid oprId;
413  Relation catalog;
414  HeapTuple tup;
415  Form_pg_operator oprForm;
416  int i;
417  ListCell *pl;
418  Datum values[Natts_pg_operator];
419  bool nulls[Natts_pg_operator];
420  bool replaces[Natts_pg_operator];
421  List *restrictionName = NIL; /* optional restrict. sel. function */
422  bool updateRestriction = false;
423  Oid restrictionOid;
424  List *joinName = NIL; /* optional join sel. function */
425  bool updateJoin = false;
426  Oid joinOid;
427 
428  /* Look up the operator */
429  oprId = LookupOperWithArgs(stmt->opername, false);
430  catalog = table_open(OperatorRelationId, RowExclusiveLock);
432  if (!HeapTupleIsValid(tup))
433  elog(ERROR, "cache lookup failed for operator %u", oprId);
434  oprForm = (Form_pg_operator) GETSTRUCT(tup);
435 
436  /* Process options */
437  foreach(pl, stmt->options)
438  {
439  DefElem *defel = (DefElem *) lfirst(pl);
440  List *param;
441 
442  if (defel->arg == NULL)
443  param = NIL; /* NONE, removes the function */
444  else
445  param = defGetQualifiedName(defel);
446 
447  if (strcmp(defel->defname, "restrict") == 0)
448  {
449  restrictionName = param;
450  updateRestriction = true;
451  }
452  else if (strcmp(defel->defname, "join") == 0)
453  {
454  joinName = param;
455  updateJoin = true;
456  }
457 
458  /*
459  * The rest of the options that CREATE accepts cannot be changed.
460  * Check for them so that we can give a meaningful error message.
461  */
462  else if (strcmp(defel->defname, "leftarg") == 0 ||
463  strcmp(defel->defname, "rightarg") == 0 ||
464  strcmp(defel->defname, "function") == 0 ||
465  strcmp(defel->defname, "procedure") == 0 ||
466  strcmp(defel->defname, "commutator") == 0 ||
467  strcmp(defel->defname, "negator") == 0 ||
468  strcmp(defel->defname, "hashes") == 0 ||
469  strcmp(defel->defname, "merges") == 0)
470  {
471  ereport(ERROR,
472  (errcode(ERRCODE_SYNTAX_ERROR),
473  errmsg("operator attribute \"%s\" cannot be changed",
474  defel->defname)));
475  }
476  else
477  ereport(ERROR,
478  (errcode(ERRCODE_SYNTAX_ERROR),
479  errmsg("operator attribute \"%s\" not recognized",
480  defel->defname)));
481  }
482 
483  /* Check permissions. Must be owner. */
484  if (!pg_oper_ownercheck(oprId, GetUserId()))
486  NameStr(oprForm->oprname));
487 
488  /*
489  * Look up restriction and join estimators if specified
490  */
491  if (restrictionName)
492  restrictionOid = ValidateRestrictionEstimator(restrictionName);
493  else
494  restrictionOid = InvalidOid;
495  if (joinName)
496  joinOid = ValidateJoinEstimator(joinName);
497  else
498  joinOid = InvalidOid;
499 
500  /* Perform additional checks, like OperatorCreate does */
501  if (!(OidIsValid(oprForm->oprleft) && OidIsValid(oprForm->oprright)))
502  {
503  /* If it's not a binary op, these things mustn't be set: */
504  if (OidIsValid(joinOid))
505  ereport(ERROR,
506  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
507  errmsg("only binary operators can have join selectivity")));
508  }
509 
510  if (oprForm->oprresult != BOOLOID)
511  {
512  if (OidIsValid(restrictionOid))
513  ereport(ERROR,
514  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
515  errmsg("only boolean operators can have restriction selectivity")));
516  if (OidIsValid(joinOid))
517  ereport(ERROR,
518  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
519  errmsg("only boolean operators can have join selectivity")));
520  }
521 
522  /* Update the tuple */
523  for (i = 0; i < Natts_pg_operator; ++i)
524  {
525  values[i] = (Datum) 0;
526  replaces[i] = false;
527  nulls[i] = false;
528  }
529  if (updateRestriction)
530  {
531  replaces[Anum_pg_operator_oprrest - 1] = true;
532  values[Anum_pg_operator_oprrest - 1] = restrictionOid;
533  }
534  if (updateJoin)
535  {
536  replaces[Anum_pg_operator_oprjoin - 1] = true;
537  values[Anum_pg_operator_oprjoin - 1] = joinOid;
538  }
539 
540  tup = heap_modify_tuple(tup, RelationGetDescr(catalog),
541  values, nulls, replaces);
542 
543  CatalogTupleUpdate(catalog, &tup->t_self, tup);
544 
545  address = makeOperatorDependencies(tup, true);
546 
547  InvokeObjectPostAlterHook(OperatorRelationId, oprId, 0);
548 
549  table_close(catalog, NoLock);
550 
551  return address;
552 }
Oid LookupOperWithArgs(ObjectWithArgs *oper, bool noError)
Definition: parse_oper.c:145
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetDescr(relation)
Definition: rel.h:495
Oid GetUserId(void)
Definition: miscinit.c:478
ObjectAddress makeOperatorDependencies(HeapTuple tuple, bool isUpdate)
Definition: pg_operator.c:773
static Oid ValidateJoinEstimator(List *joinName)
Definition: operatorcmds.c:308
bool pg_oper_ownercheck(Oid oper_oid, Oid roleid)
Definition: aclchk.c:4875
int errcode(int sqlerrcode)
Definition: elog.c:698
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3313
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
static Oid ValidateRestrictionEstimator(List *restrictionName)
Definition: operatorcmds.c:273
Node * arg
Definition: parsenodes.h:747
ObjectWithArgs * opername
Definition: parsenodes.h:3082
uintptr_t Datum
Definition: postgres.h:411
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:169
List * defGetQualifiedName(DefElem *def)
Definition: define.c:223
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:83
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:175
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
int i
#define NameStr(name)
Definition: c.h:681
char * defname
Definition: parsenodes.h:746
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
Definition: pg_list.h:50

◆ AlterOpFamily()

Oid AlterOpFamily ( AlterOpFamilyStmt stmt)

Definition at line 808 of file opclasscmds.c.

References AlterOpFamilyAdd(), AlterOpFamilyDrop(), AMNAME, AlterOpFamilyStmt::amname, IndexAmRoutine::amoptsprocnum, IndexAmRoutine::amstrategies, IndexAmRoutine::amsupport, CStringGetDatum, ereport, errcode(), errmsg(), ERROR, get_opfamily_oid(), GetIndexAmRoutineByAmId(), GETSTRUCT, HeapTupleIsValid, AlterOpFamilyStmt::isDrop, AlterOpFamilyStmt::items, AlterOpFamilyStmt::opfamilyname, ReleaseSysCache(), SearchSysCache1(), and superuser().

Referenced by ProcessUtilitySlow().

809 {
810  Oid amoid, /* our AM's oid */
811  opfamilyoid; /* oid of opfamily */
812  int maxOpNumber, /* amstrategies value */
813  optsProcNumber, /* amopclassopts value */
814  maxProcNumber; /* amsupport value */
815  HeapTuple tup;
816  Form_pg_am amform;
817  IndexAmRoutine *amroutine;
818 
819  /* Get necessary info about access method */
821  if (!HeapTupleIsValid(tup))
822  ereport(ERROR,
823  (errcode(ERRCODE_UNDEFINED_OBJECT),
824  errmsg("access method \"%s\" does not exist",
825  stmt->amname)));
826 
827  amform = (Form_pg_am) GETSTRUCT(tup);
828  amoid = amform->oid;
829  amroutine = GetIndexAmRoutineByAmId(amoid, false);
830  ReleaseSysCache(tup);
831 
832  maxOpNumber = amroutine->amstrategies;
833  /* if amstrategies is zero, just enforce that op numbers fit in int16 */
834  if (maxOpNumber <= 0)
835  maxOpNumber = SHRT_MAX;
836  maxProcNumber = amroutine->amsupport;
837  optsProcNumber = amroutine->amoptsprocnum;
838 
839  /* XXX Should we make any privilege check against the AM? */
840 
841  /* Look up the opfamily */
842  opfamilyoid = get_opfamily_oid(amoid, stmt->opfamilyname, false);
843 
844  /*
845  * Currently, we require superuser privileges to alter an opfamily.
846  *
847  * XXX re-enable NOT_USED code sections below if you remove this test.
848  */
849  if (!superuser())
850  ereport(ERROR,
851  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
852  errmsg("must be superuser to alter an operator family")));
853 
854  /*
855  * ADD and DROP cases need separate code from here on down.
856  */
857  if (stmt->isDrop)
858  AlterOpFamilyDrop(stmt, amoid, opfamilyoid,
859  maxOpNumber, maxProcNumber, stmt->items);
860  else
861  AlterOpFamilyAdd(stmt, amoid, opfamilyoid,
862  maxOpNumber, maxProcNumber, optsProcNumber,
863  stmt->items);
864 
865  return opfamilyoid;
866 }
uint16 amsupport
Definition: amapi.h:216
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
unsigned int Oid
Definition: postgres_ext.h:31
static void AlterOpFamilyDrop(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid, int maxOpNumber, int maxProcNumber, List *items)
Definition: opclasscmds.c:1021
#define ERROR
Definition: elog.h:46
IndexAmRoutine * GetIndexAmRoutineByAmId(Oid amoid, bool noerror)
Definition: amapi.c:56
#define CStringGetDatum(X)
Definition: postgres.h:622
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
static void AlterOpFamilyAdd(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid, int maxOpNumber, int maxProcNumber, int opclassOptsProcNumber, List *items)
Definition: opclasscmds.c:872
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
Oid get_opfamily_oid(Oid amID, List *opfamilyname, bool missing_ok)
Definition: opclasscmds.c:139
uint16 amstrategies
Definition: amapi.h:214
FormData_pg_am * Form_pg_am
Definition: pg_am.h:48
int errmsg(const char *fmt,...)
Definition: elog.c:909
uint16 amoptsprocnum
Definition: amapi.h:218

◆ AlterStatistics()

ObjectAddress AlterStatistics ( AlterStatsStmt stmt)

Definition at line 589 of file statscmds.c.

References aclcheck_error(), ACLCHECK_NOT_OWNER, Assert, CatalogTupleUpdate(), DeconstructQualifiedName(), AlterStatsStmt::defnames, ereport, errcode(), errmsg(), ERROR, get_statistics_object_oid(), GetUserId(), heap_freetuple(), heap_modify_tuple(), Int32GetDatum, InvalidObjectAddress, InvokeObjectPostAlterHook, AlterStatsStmt::missing_ok, NameListToString(), NOTICE, OBJECT_STATISTIC_EXT, ObjectAddressSet, ObjectIdGetDatum, OidIsValid, pg_statistics_object_ownercheck(), RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), STATEXTOID, AlterStatsStmt::stxstattarget, HeapTupleData::t_self, table_close(), table_open(), and WARNING.

Referenced by ProcessUtilitySlow().

590 {
591  Relation rel;
592  Oid stxoid;
593  HeapTuple oldtup;
594  HeapTuple newtup;
595  Datum repl_val[Natts_pg_statistic_ext];
596  bool repl_null[Natts_pg_statistic_ext];
597  bool repl_repl[Natts_pg_statistic_ext];
598  ObjectAddress address;
599  int newtarget = stmt->stxstattarget;
600 
601  /* Limit statistics target to a sane range */
602  if (newtarget < -1)
603  {
604  ereport(ERROR,
605  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
606  errmsg("statistics target %d is too low",
607  newtarget)));
608  }
609  else if (newtarget > 10000)
610  {
611  newtarget = 10000;
613  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
614  errmsg("lowering statistics target to %d",
615  newtarget)));
616  }
617 
618  /* lookup OID of the statistics object */
619  stxoid = get_statistics_object_oid(stmt->defnames, stmt->missing_ok);
620 
621  /*
622  * If we got here and the OID is not valid, it means the statistics does
623  * not exist, but the command specified IF EXISTS. So report this as a
624  * simple NOTICE and we're done.
625  */
626  if (!OidIsValid(stxoid))
627  {
628  char *schemaname;
629  char *statname;
630 
631  Assert(stmt->missing_ok);
632 
633  DeconstructQualifiedName(stmt->defnames, &schemaname, &statname);
634 
635  if (schemaname)
636  ereport(NOTICE,
637  (errmsg("statistics object \"%s.%s\" does not exist, skipping",
638  schemaname, statname)));
639  else
640  ereport(NOTICE,
641  (errmsg("statistics object \"%s\" does not exist, skipping",
642  statname)));
643 
644  return InvalidObjectAddress;
645  }
646 
647  /* Search pg_statistic_ext */
648  rel = table_open(StatisticExtRelationId, RowExclusiveLock);
649 
650  oldtup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(stxoid));
651 
652  /* Must be owner of the existing statistics object */
655  NameListToString(stmt->defnames));
656 
657  /* Build new tuple. */
658  memset(repl_val, 0, sizeof(repl_val));
659  memset(repl_null, false, sizeof(repl_null));
660  memset(repl_repl, false, sizeof(repl_repl));
661 
662  /* replace the stxstattarget column */
663  repl_repl[Anum_pg_statistic_ext_stxstattarget - 1] = true;
664  repl_val[Anum_pg_statistic_ext_stxstattarget - 1] = Int32GetDatum(newtarget);
665 
666  newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel),
667  repl_val, repl_null, repl_repl);
668 
669  /* Update system catalog. */
670  CatalogTupleUpdate(rel, &newtup->t_self, newtup);
671 
672  InvokeObjectPostAlterHook(StatisticExtRelationId, stxoid, 0);
673 
674  ObjectAddressSet(address, StatisticExtRelationId, stxoid);
675 
676  /*
677  * NOTE: because we only support altering the statistics target, not the
678  * other fields, there is no need to update dependencies.
679  */
680 
681  heap_freetuple(newtup);
682  ReleaseSysCache(oldtup);
683 
685 
686  return address;
687 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define RelationGetDescr(relation)
Definition: rel.h:495
Oid GetUserId(void)
Definition: miscinit.c:478
int errcode(int sqlerrcode)
Definition: elog.c:698
void DeconstructQualifiedName(List *names, char **nspname_p, char **objname_p)
Definition: namespace.c:2808
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3313
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
Oid get_statistics_object_oid(List *names, bool missing_ok)
Definition: namespace.c:2177
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
#define WARNING
Definition: elog.h:40
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
char * NameListToString(List *names)
Definition: namespace.c:3101
uintptr_t Datum
Definition: postgres.h:411
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define ereport(elevel,...)
Definition: elog.h:157
#define NOTICE
Definition: elog.h:37
#define Assert(condition)
Definition: c.h:804
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define Int32GetDatum(X)
Definition: postgres.h:523
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:909
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
bool pg_statistics_object_ownercheck(Oid stat_oid, Oid roleid)
Definition: aclchk.c:5413

◆ AlterTSConfiguration()

ObjectAddress AlterTSConfiguration ( AlterTSConfigurationStmt stmt)

Definition at line 1109 of file tsearchcmds.c.

References aclcheck_error(), ACLCHECK_NOT_OWNER, AlterTSConfigurationStmt::cfgname, AlterTSConfigurationStmt::dicts, DropConfigurationMapping(), ereport, errcode(), errmsg(), ERROR, GETSTRUCT, GetTSConfigTuple(), GetUserId(), HeapTupleIsValid, InvokeObjectPostAlterHook, makeConfigurationDependencies(), MakeConfigurationMapping(), NameListToString(), OBJECT_TSCONFIGURATION, ObjectAddressSet, pg_ts_config_ownercheck(), ReleaseSysCache(), RowExclusiveLock, table_close(), table_open(), and AlterTSConfigurationStmt::tokentype.

Referenced by ProcessUtilitySlow().

1110 {
1111  HeapTuple tup;
1112  Oid cfgId;
1113  Relation relMap;
1114  ObjectAddress address;
1115 
1116  /* Find the configuration */
1117  tup = GetTSConfigTuple(stmt->cfgname);
1118  if (!HeapTupleIsValid(tup))
1119  ereport(ERROR,
1120  (errcode(ERRCODE_UNDEFINED_OBJECT),
1121  errmsg("text search configuration \"%s\" does not exist",
1122  NameListToString(stmt->cfgname))));
1123 
1124  cfgId = ((Form_pg_ts_config) GETSTRUCT(tup))->oid;
1125 
1126  /* must be owner */
1127  if (!pg_ts_config_ownercheck(cfgId, GetUserId()))
1129  NameListToString(stmt->cfgname));
1130 
1131  relMap = table_open(TSConfigMapRelationId, RowExclusiveLock);
1132 
1133  /* Add or drop mappings */
1134  if (stmt->dicts)
1135  MakeConfigurationMapping(stmt, tup, relMap);
1136  else if (stmt->tokentype)
1137  DropConfigurationMapping(stmt, tup, relMap);
1138 
1139  /* Update dependencies */
1140  makeConfigurationDependencies(tup, true, relMap);
1141 
1142  InvokeObjectPostAlterHook(TSConfigRelationId, cfgId, 0);
1143 
1144  ObjectAddressSet(address, TSConfigRelationId, cfgId);
1145 
1146  table_close(relMap, RowExclusiveLock);
1147 
1148  ReleaseSysCache(tup);
1149 
1150  return address;
1151 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
FormData_pg_ts_config * Form_pg_ts_config
Definition: pg_ts_config.h:48
Oid GetUserId(void)
Definition: miscinit.c:478
bool pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid)
Definition: aclchk.c:5133
static ObjectAddress makeConfigurationDependencies(HeapTuple tuple, bool removeOld, Relation mapRel)
Definition: tsearchcmds.c:806
int errcode(int sqlerrcode)
Definition: elog.c:698
unsigned int Oid
Definition: postgres_ext.h:31
static void DropConfigurationMapping(AlterTSConfigurationStmt *stmt, HeapTuple tup, Relation relMap)
Definition: tsearchcmds.c:1376
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3313
#define ERROR
Definition: elog.h:46
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
static HeapTuple GetTSConfigTuple(List *names)
Definition: tsearchcmds.c:781
char * NameListToString(List *names)
Definition: namespace.c:3101
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
int errmsg(const char *fmt,...)
Definition: elog.c:909
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
static void MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, HeapTuple tup, Relation relMap)
Definition: tsearchcmds.c:1212

◆ AlterTSDictionary()

ObjectAddress AlterTSDictionary ( AlterTSDictionaryStmt stmt)

Definition at line 487 of file tsearchcmds.c.

References aclcheck_error(), ACLCHECK_NOT_OWNER, DefElem::arg, CatalogTupleUpdate(), DefElem::defname, deserialize_deflist(), AlterTSDictionaryStmt::dictname, elog, ERROR, foreach_delete_current, get_ts_dict_oid(), GETSTRUCT, GetUserId(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, InvokeObjectPostAlterHook, lappend(), lfirst, NameListToString(), NIL, OBJECT_TSDICTIONARY, ObjectAddressSet, ObjectIdGetDatum, AlterTSDictionaryStmt::options, pg_ts_dict_ownercheck(), PointerGetDatum, RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), serialize_deflist(), SysCacheGetAttr(), HeapTupleData::t_self, table_close(), table_open(), TSDICTOID, and verify_dictoptions().

Referenced by ProcessUtilitySlow().

488 {
489  HeapTuple tup,
490  newtup;
491  Relation rel;
492  Oid dictId;
493  ListCell *pl;
494  List *dictoptions;
495  Datum opt;
496  bool isnull;
497  Datum repl_val[Natts_pg_ts_dict];
498  bool repl_null[Natts_pg_ts_dict];
499  bool repl_repl[Natts_pg_ts_dict];
500  ObjectAddress address;
501 
502  dictId = get_ts_dict_oid(stmt->dictname, false);
503 
504  rel = table_open(TSDictionaryRelationId, RowExclusiveLock);
505 
507 
508  if (!HeapTupleIsValid(tup))
509  elog(ERROR, "cache lookup failed for text search dictionary %u",
510  dictId);
511 
512  /* must be owner */
513  if (!pg_ts_dict_ownercheck(dictId, GetUserId()))
515  NameListToString(stmt->dictname));
516 
517  /* deserialize the existing set of options */
518  opt = SysCacheGetAttr(TSDICTOID, tup,
519  Anum_pg_ts_dict_dictinitoption,
520  &isnull);
521  if (isnull)
522  dictoptions = NIL;
523  else
524  dictoptions = deserialize_deflist(opt);
525 
526  /*
527  * Modify the options list as per specified changes
528  */
529  foreach(pl, stmt->options)
530  {
531  DefElem *defel = (DefElem *) lfirst(pl);
532  ListCell *cell;
533 
534  /*
535  * Remove any matches ...
536  */
537  foreach(cell, dictoptions)
538  {
539  DefElem *oldel = (DefElem *) lfirst(cell);
540 
541  if (strcmp(oldel->defname, defel->defname) == 0)
542  dictoptions = foreach_delete_current(dictoptions, cell);
543  }
544 
545  /*
546  * and add new value if it's got one
547  */
548  if (defel->arg)
549  dictoptions = lappend(dictoptions, defel);
550  }
551 
552  /*
553  * Validate
554  */
555  verify_dictoptions(((Form_pg_ts_dict) GETSTRUCT(tup))->dicttemplate,
556  dictoptions);
557 
558  /*
559  * Looks good, update
560  */
561  memset(repl_val, 0, sizeof(repl_val));
562  memset(repl_null, false, sizeof(repl_null));
563  memset(repl_repl, false, sizeof(repl_repl));
564 
565  if (dictoptions)
566  repl_val[Anum_pg_ts_dict_dictinitoption - 1] =
567  PointerGetDatum(serialize_deflist(dictoptions));
568  else
569  repl_null[Anum_pg_ts_dict_dictinitoption - 1] = true;
570  repl_repl[Anum_pg_ts_dict_dictinitoption - 1] = true;
571 
572  newtup = heap_modify_tuple(tup, RelationGetDescr(rel),
573  repl_val, repl_null, repl_repl);
574 
575  CatalogTupleUpdate(rel, &newtup->t_self, newtup);
576 
577  InvokeObjectPostAlterHook(TSDictionaryRelationId, dictId, 0);
578 
579  ObjectAddressSet(address, TSDictionaryRelationId, dictId);
580 
581  /*
582  * NOTE: because we only support altering the options, not the template,
583  * there is no need to update dependencies. This might have to change if
584  * the options ever reference inside-the-database objects.
585  */
586 
587  heap_freetuple(newtup);
588  ReleaseSysCache(tup);
589 
591 
592  return address;
593 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
bool pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid)
Definition: aclchk.c:5106
#define RelationGetDescr(relation)
Definition: rel.h:495
Oid GetUserId(void)
Definition: miscinit.c:478
#define PointerGetDatum(X)
Definition: postgres.h:600
List * deserialize_deflist(Datum txt)
Definition: tsearchcmds.c:1510
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define foreach_delete_current(lst, cell)
Definition: pg_list.h:369
Oid get_ts_dict_oid(List *names, bool missing_ok)
Definition: namespace.c:2425
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3313
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
FormData_pg_ts_dict * Form_pg_ts_dict
Definition: pg_ts_dict.h:52
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
Node * arg
Definition: parsenodes.h:747
List * lappend(List *list, void *datum)
Definition: list.c:336
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
char * NameListToString(List *names)
Definition: namespace.c:3101
text * serialize_deflist(List *deflist)
Definition: tsearchcmds.c:1454
uintptr_t Datum
Definition: postgres.h:411
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:169
static void verify_dictoptions(Oid tmplId, List *dictoptions)
Definition: tsearchcmds.c:336
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define elog(elevel,...)
Definition: elog.h:232
char * defname
Definition: parsenodes.h:746
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
Definition: pg_list.h:50

◆ AlterUserMapping()

ObjectAddress AlterUserMapping ( AlterUserMappingStmt stmt)

Definition at line 1217 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, InvokeObjectPostAlterHook, 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().

1218 {
1219  Relation rel;
1220  HeapTuple tp;
1221  Datum repl_val[Natts_pg_user_mapping];
1222  bool repl_null[Natts_pg_user_mapping];
1223  bool repl_repl[Natts_pg_user_mapping];
1224  Oid useId;
1225  Oid umId;
1226  ForeignServer *srv;
1227  ObjectAddress address;
1228  RoleSpec *role = (RoleSpec *) stmt->user;
1229 
1230  rel = table_open(UserMappingRelationId, RowExclusiveLock);
1231 
1232  if (role->roletype == ROLESPEC_PUBLIC)
1233  useId = ACL_ID_PUBLIC;
1234  else
1235  useId = get_rolespec_oid(stmt->user, false);
1236 
1237  srv = GetForeignServerByName(stmt->servername, false);
1238 
1239  umId = GetSysCacheOid2(USERMAPPINGUSERSERVER, Anum_pg_user_mapping_oid,
1240  ObjectIdGetDatum(useId),
1241  ObjectIdGetDatum(srv->serverid));
1242  if (!OidIsValid(umId))
1243  ereport(ERROR,
1244  (errcode(ERRCODE_UNDEFINED_OBJECT),
1245  errmsg("user mapping for \"%s\" does not exist for server \"%s\"",
1246  MappingUserName(useId), stmt->servername)));
1247 
1248  user_mapping_ddl_aclcheck(useId, srv->serverid, stmt->servername);
1249 
1251 
1252  if (!HeapTupleIsValid(tp))
1253  elog(ERROR, "cache lookup failed for user mapping %u", umId);
1254 
1255  memset(repl_val, 0, sizeof(repl_val));
1256  memset(repl_null, false, sizeof(repl_null));
1257  memset(repl_repl, false, sizeof(repl_repl));
1258 
1259  if (stmt->options)
1260  {
1261  ForeignDataWrapper *fdw;
1262  Datum datum;
1263  bool isnull;
1264 
1265  /*
1266  * Process the options.
1267  */
1268 
1269  fdw = GetForeignDataWrapper(srv->fdwid);
1270 
1271  datum = SysCacheGetAttr(USERMAPPINGUSERSERVER,
1272  tp,
1273  Anum_pg_user_mapping_umoptions,
1274  &isnull);
1275  if (isnull)
1276  datum = PointerGetDatum(NULL);
1277 
1278  /* Prepare the options array */
1279  datum = transformGenericOptions(UserMappingRelationId,
1280  datum,
1281  stmt->options,
1282  fdw->fdwvalidator);
1283 
1284  if (PointerIsValid(DatumGetPointer(datum)))
1285  repl_val[Anum_pg_user_mapping_umoptions - 1] = datum;
1286  else
1287  repl_null[Anum_pg_user_mapping_umoptions - 1] = true;
1288 
1289  repl_repl[Anum_pg_user_mapping_umoptions - 1] = true;
1290  }
1291 
1292  /* Everything looks good - update the tuple */
1293  tp = heap_modify_tuple(tp, RelationGetDescr(rel),
1294  repl_val, repl_null, repl_repl);
1295 
1296  CatalogTupleUpdate(rel, &tp->t_self, tp);
1297 
1298  InvokeObjectPostAlterHook(UserMappingRelationId,
1299  umId, 0);
1300 
1301  ObjectAddressSet(address, UserMappingRelationId, umId);
1302 
1303  heap_freetuple(tp);
1304 
1306 
1307  return address;
1308 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define RelationGetDescr(relation)
Definition: rel.h:495
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:110
#define PointerGetDatum(X)
Definition: postgres.h:600
int errcode(int sqlerrcode)
Definition: elog.c:698
static void user_mapping_ddl_aclcheck(Oid umuserid, Oid serverid, const char *servername)
Definition: foreigncmds.c:1070
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
ForeignDataWrapper * GetForeignDataWrapper(Oid fdwid)
Definition: foreign.c:35
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
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 InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
uintptr_t Datum
Definition: postgres.h:411
RoleSpecType roletype
Definition: parsenodes.h:339
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5128
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:195
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define DatumGetPointer(X)
Definition: postgres.h:593
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:175
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
#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:698
Oid serverid
Definition: foreign.h:36
#define MappingUserName(userid)
Definition: foreign.h:20

◆ CallStmtResultDesc()

TupleDesc CallStmtResultDesc ( CallStmt stmt)

Definition at line 2353 of file functioncmds.c.

References build_function_result_tupdesc_t(), elog, ERROR, CallStmt::funcexpr, FuncExpr::funcid, HeapTupleIsValid, ObjectIdGetDatum, PROCOID, ReleaseSysCache(), and SearchSysCache1().

Referenced by UtilityTupleDescriptor().

2354 {
2355  FuncExpr *fexpr;
2356  HeapTuple tuple;
2357  TupleDesc tupdesc;
2358 
2359  fexpr = stmt->funcexpr;
2360 
2361  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
2362  if (!HeapTupleIsValid(tuple))
2363  elog(ERROR, "cache lookup failed for procedure %u", fexpr->funcid);
2364 
2365  tupdesc = build_function_result_tupdesc_t(tuple);
2366 
2367  ReleaseSysCache(tuple);
2368 
2369  return tupdesc;
2370 }
FuncExpr * funcexpr
Definition: parsenodes.h:3007
TupleDesc build_function_result_tupdesc_t(HeapTuple procTuple)
Definition: funcapi.c:1604
Oid funcid
Definition: primnodes.h:495
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:232

◆ CheckIndexCompatible()

bool CheckIndexCompatible ( Oid  oldId,
const char *  accessMethodName,
List attributeList,
List exclusionOpNames 
)

Definition at line 164 of file indexcmds.c.

References AccessShareLock, IndexAmRoutine::amcanorder, AMNAME, Assert, CompareOpclassOptions(), ComputeIndexAttrs(), DatumGetPointer, elog, ereport, errcode(), errmsg(), ERROR, get_opclass_input_type(), GetIndexAmRoutine(), GETSTRUCT, heap_attisnull(), HeapTupleIsValid, i, IndexInfo::ii_ExclusionOps, IndexInfo::ii_OpclassOptions, index_close(), INDEX_MAX_KEYS, index_open(), IndexGetRelation(), INDEXRELID, list_length(), makeIndexInfo(), NIL, NoLock, ObjectIdGetDatum, op_input_types(), palloc(), pfree(), PointerGetDatum, RelationData::rd_att, RelationGetExclusionInfo(), RelationGetIndexRawAttOptions(), ReleaseSysCache(), SearchSysCache1(), SysCacheGetAttr(), TupleDescAttr, and oidvector::values.

Referenced by TryReuseIndex().

168 {
169  bool isconstraint;
170  Oid *typeObjectId;
171  Oid *collationObjectId;
172  Oid *classObjectId;
173  Oid accessMethodId;
174  Oid relationId;
175  HeapTuple tuple;
176  Form_pg_index indexForm;
177  Form_pg_am accessMethodForm;
178  IndexAmRoutine *amRoutine;
179  bool amcanorder;
180  int16 *coloptions;
181  IndexInfo *indexInfo;
182  int numberOfAttributes;
183  int old_natts;
184  bool isnull;
185  bool ret = true;
186  oidvector *old_indclass;
187  oidvector *old_indcollation;
188  Relation irel;
189  int i;
190  Datum d;
191 
192  /* Caller should already have the relation locked in some way. */
193  relationId = IndexGetRelation(oldId, false);
194 
195  /*
196  * We can pretend isconstraint = false unconditionally. It only serves to
197  * decide the text of an error message that should never happen for us.
198  */
199  isconstraint = false;
200 
201  numberOfAttributes = list_length(attributeList);
202  Assert(numberOfAttributes > 0);
203  Assert(numberOfAttributes <= INDEX_MAX_KEYS);
204 
205  /* look up the access method */
206  tuple = SearchSysCache1(AMNAME, PointerGetDatum(accessMethodName));
207  if (!HeapTupleIsValid(tuple))
208  ereport(ERROR,
209  (errcode(ERRCODE_UNDEFINED_OBJECT),
210  errmsg("access method \"%s\" does not exist",
211  accessMethodName)));
212  accessMethodForm = (Form_pg_am) GETSTRUCT(tuple);
213  accessMethodId = accessMethodForm->oid;
214  amRoutine = GetIndexAmRoutine(accessMethodForm->amhandler);
215  ReleaseSysCache(tuple);
216 
217  amcanorder = amRoutine->amcanorder;
218 
219  /*
220  * Compute the operator classes, collations, and exclusion operators for
221  * the new index, so we can test whether it's compatible with the existing
222  * one. Note that ComputeIndexAttrs might fail here, but that's OK:
223  * DefineIndex would have called this function with the same arguments
224  * later on, and it would have failed then anyway. Our attributeList
225  * contains only key attributes, thus we're filling ii_NumIndexAttrs and
226  * ii_NumIndexKeyAttrs with same value.
227  */
228  indexInfo = makeIndexInfo(numberOfAttributes, numberOfAttributes,
229  accessMethodId, NIL, NIL, false, false, false);
230  typeObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
231  collationObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
232  classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
233  coloptions = (int16 *) palloc(numberOfAttributes * sizeof(int16));
234  ComputeIndexAttrs(indexInfo,
235  typeObjectId, collationObjectId, classObjectId,
236  coloptions, attributeList,
237  exclusionOpNames, relationId,
238  accessMethodName, accessMethodId,
239  amcanorder, isconstraint);
240 
241 
242  /* Get the soon-obsolete pg_index tuple. */
244  if (!HeapTupleIsValid(tuple))
245  elog(ERROR, "cache lookup failed for index %u", oldId);
246  indexForm = (Form_pg_index) GETSTRUCT(tuple);
247 
248  /*
249  * We don't assess expressions or predicates; assume incompatibility.
250  * Also, if the index is invalid for any reason, treat it as incompatible.
251  */
252  if (!(heap_attisnull(tuple, Anum_pg_index_indpred, NULL) &&
253  heap_attisnull(tuple, Anum_pg_index_indexprs, NULL) &&
254  indexForm->indisvalid))
255  {
256  ReleaseSysCache(tuple);
257  return false;
258  }
259 
260  /* Any change in operator class or collation breaks compatibility. */
261  old_natts = indexForm->indnkeyatts;
262  Assert(old_natts == numberOfAttributes);
263 
264  d = SysCacheGetAttr(INDEXRELID, tuple, Anum_pg_index_indcollation, &isnull);
265  Assert(!isnull);
266  old_indcollation = (oidvector *) DatumGetPointer(d);
267 
268  d = SysCacheGetAttr(INDEXRELID, tuple, Anum_pg_index_indclass, &isnull);
269  Assert(!isnull);
270  old_indclass = (oidvector *) DatumGetPointer(d);
271 
272  ret = (memcmp(old_indclass->values, classObjectId,
273  old_natts * sizeof(Oid)) == 0 &&
274  memcmp(old_indcollation->values, collationObjectId,
275  old_natts * sizeof(Oid)) == 0);
276 
277  ReleaseSysCache(tuple);
278 
279  if (!ret)
280  return false;
281 
282  /* For polymorphic opcintype, column type changes break compatibility. */
283  irel = index_open(oldId, AccessShareLock); /* caller probably has a lock */
284  for (i = 0; i < old_natts; i++)
285  {
286  if (IsPolymorphicType(get_opclass_input_type(classObjectId[i])) &&
287  TupleDescAttr(irel->rd_att, i)->atttypid != typeObjectId[i])
288  {
289  ret = false;
290  break;
291  }
292  }
293 
294  /* Any change in opclass options break compatibility. */
295  if (ret)
296  {
297  Datum *opclassOptions = RelationGetIndexRawAttOptions(irel);
298 
299  ret = CompareOpclassOptions(opclassOptions,
300  indexInfo->ii_OpclassOptions, old_natts);
301 
302  if (opclassOptions)
303  pfree(opclassOptions);
304  }
305 
306  /* Any change in exclusion operator selections breaks compatibility. */
307  if (ret && indexInfo->ii_ExclusionOps != NULL)
308  {
309  Oid *old_operators,
310  *old_procs;
311  uint16 *old_strats;
312 
313  RelationGetExclusionInfo(irel, &old_operators, &old_procs, &old_strats);
314  ret = memcmp(old_operators, indexInfo->ii_ExclusionOps,
315  old_natts * sizeof(Oid)) == 0;
316 
317  /* Require an exact input type match for polymorphic operators. */
318  if (ret)
319  {
320  for (i = 0; i < old_natts && ret; i++)
321  {
322  Oid left,
323  right;
324 
325  op_input_types(indexInfo->ii_ExclusionOps[i], &left, &right);
326  if ((IsPolymorphicType(left) || IsPolymorphicType(right)) &&
327  TupleDescAttr(irel->rd_att, i)->atttypid != typeObjectId[i])
328  {
329  ret = false;
330  break;
331  }
332  }
333  }
334  }
335 
336  index_close(irel, NoLock);
337  return ret;
338 }
signed short int16
Definition: c.h:428
#define NIL
Definition: pg_list.h:65
Definition: c.h:660
Oid IndexGetRelation(Oid indexId, bool missing_ok)
Definition: index.c:3474
void RelationGetExclusionInfo(Relation indexRelation, Oid **operators, Oid **procs, uint16 **strategies)
Definition: relcache.c:5313
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define PointerGetDatum(X)
Definition: postgres.h:600
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:698
static bool CompareOpclassOptions(Datum *opts1, Datum *opts2, int natts)
Definition: indexcmds.c:347
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
unsigned int Oid
Definition: postgres_ext.h:31
unsigned short uint16
Definition: c.h:440
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
IndexAmRoutine * GetIndexAmRoutine(Oid amhandler)
Definition: amapi.c:33
#define NoLock
Definition: lockdefs.h:34
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:668
void op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
Definition: lsyscache.c:1329
IndexInfo * makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions, List *predicates, bool unique, bool isready, bool concurrent)
Definition: makefuncs.c:743
Datum * RelationGetIndexRawAttOptions(Relation indexrel)
Definition: relcache.c:5521
FormData_pg_index * Form_pg_index
Definition: pg_index.h:69
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
uintptr_t Datum
Definition: postgres.h:411
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
TupleDesc rd_att
Definition: rel.h:110
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
#define INDEX_MAX_KEYS
static int list_length(const List *l)
Definition: pg_list.h:149
bool amcanorder
Definition: amapi.h:220
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:158
#define DatumGetPointer(X)
Definition: postgres.h:593
Oid * ii_ExclusionOps
Definition: execnodes.h:165
FormData_pg_am * Form_pg_am
Definition: pg_am.h:48
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
int i
static void ComputeIndexAttrs(IndexInfo *indexInfo, Oid *typeOidP, Oid *collationOidP, Oid *classOidP, int16 *colOptionP, List *attList, List *exclusionOpNames, Oid relId, const char *accessMethodName, Oid accessMethodId, bool amcanorder, bool isconstraint)
Definition: indexcmds.c:1692
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:132
Datum * ii_OpclassOptions
Definition: execnodes.h:171
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1205

◆ ChooseRelationName()

char* ChooseRelationName ( const char *  name1,
const char *  name2,
const char *  label,
Oid  namespaceid,
bool  isconstraint 
)

Definition at line 2294 of file indexcmds.c.

References ConstraintNameExists(), get_relname_relid(), makeObjectName(), NAMEDATALEN, OidIsValid, pfree(), relname, snprintf, and strlcpy().

Referenced by ChooseIndexName(), generateSerialExtraStmts(), and ReindexRelationConcurrently().

2297 {
2298  int pass = 0;
2299  char *relname = NULL;
2300  char modlabel[NAMEDATALEN];
2301 
2302  /* try the unmodified label first */
2303  strlcpy(modlabel, label, sizeof(modlabel));
2304 
2305  for (;;)
2306  {
2307  relname = makeObjectName(name1, name2, modlabel);
2308 
2309  if (!OidIsValid(get_relname_relid(relname, namespaceid)))
2310  {
2311  if (!isconstraint ||
2312  !ConstraintNameExists(relname, namespaceid))
2313  break;
2314  }
2315 
2316  /* found a conflict, so try a new name component */
2317  pfree(relname);
2318  snprintf(modlabel, sizeof(modlabel), "%s%d", label, ++pass);
2319  }
2320 
2321  return relname;
2322 }
bool ConstraintNameExists(const char *conname, Oid namespaceid)
NameData relname
Definition: pg_class.h:38
#define OidIsValid(objectId)
Definition: c.h:710
char * makeObjectName(const char *name1, const char *name2, const char *label)
Definition: indexcmds.c:2208
#define NAMEDATALEN
void pfree(void *pointer)
Definition: mcxt.c:1169
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1856
static char * label
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define snprintf
Definition: port.h:216

◆ CreateAccessMethod()

ObjectAddress CreateAccessMethod ( CreateAmStmt stmt)

Definition at line 43 of file amcmds.c.

References AMNAME, CreateAmStmt::amname, AmOidIndexId, CreateAmStmt::amtype, CatalogTupleInsert(), CharGetDatum, ObjectAddress::classId, CStringGetDatum, DEPENDENCY_NORMAL, DirectFunctionCall1, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errhint(), errmsg(), ERROR, GetNewOidWithIndex(), GetSysCacheOid1, CreateAmStmt::handler_name, heap_form_tuple(), heap_freetuple(), InvokeObjectPostCreateHook, lookup_am_handler_func(), namein(), ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, recordDependencyOn(), recordDependencyOnCurrentExtension(), RelationGetDescr, RowExclusiveLock, superuser(), table_close(), table_open(), and values.

Referenced by ProcessUtilitySlow().

44 {
45  Relation rel;
46  ObjectAddress myself;
47  ObjectAddress referenced;
48  Oid amoid;
49  Oid amhandler;
50  bool nulls[Natts_pg_am];
51  Datum values[Natts_pg_am];
52  HeapTuple tup;
53 
54  rel = table_open(AccessMethodRelationId, RowExclusiveLock);
55 
56  /* Must be super user */
57  if (!superuser())
58  ereport(ERROR,
59  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
60  errmsg("permission denied to create access method \"%s\"",
61  stmt->amname),
62  errhint("Must be superuser to create an access method.")));
63 
64  /* Check if name is used */
65  amoid = GetSysCacheOid1(AMNAME, Anum_pg_am_oid,
66  CStringGetDatum(stmt->amname));
67  if (OidIsValid(amoid))
68  {
69  ereport(ERROR,
71  errmsg("access method \"%s\" already exists",
72  stmt->amname)));
73  }
74 
75  /*
76  * Get the handler function oid, verifying the AM type while at it.
77  */
78  amhandler = lookup_am_handler_func(stmt->handler_name, stmt->amtype);
79 
80  /*
81  * Insert tuple into pg_am.
82  */
83  memset(values, 0, sizeof(values));
84  memset(nulls, false, sizeof(nulls));
85 
86  amoid = GetNewOidWithIndex(rel, AmOidIndexId, Anum_pg_am_oid);
87  values[Anum_pg_am_oid - 1] = ObjectIdGetDatum(amoid);
88  values[Anum_pg_am_amname - 1] =
90  values[Anum_pg_am_amhandler - 1] = ObjectIdGetDatum(amhandler);
91  values[Anum_pg_am_amtype - 1] = CharGetDatum(stmt->amtype);
92 
93  tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
94 
95  CatalogTupleInsert(rel, tup);
96  heap_freetuple(tup);
97 
98  myself.classId = AccessMethodRelationId;
99  myself.objectId = amoid;
100  myself.objectSubId = 0;
101 
102  /* Record dependency on handler function */
103  referenced.classId = ProcedureRelationId;
104  referenced.objectId = amhandler;
105  referenced.objectSubId = 0;
106 
107  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
108 
109  recordDependencyOnCurrentExtension(&myself, false);
110 
111  InvokeObjectPostCreateHook(AccessMethodRelationId, amoid, 0);
112 
114 
115  return myself;
116 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:322
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
int errhint(const char *fmt,...)
Definition: elog.c:1156
static Oid lookup_am_handler_func(List *handler_name, char amtype)
Definition: amcmds.c:234
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
#define RelationGetDescr(relation)
Definition: rel.h:495
#define GetSysCacheOid1(cacheId, oidcol, key1)
Definition: syscache.h:193
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
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:626
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
char * amname
Definition: parsenodes.h:2505
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:622
uintptr_t Datum
Definition: postgres.h:411
List * handler_name
Definition: parsenodes.h:2506
#define ereport(elevel,...)
Definition: elog.h:157
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:180
#define CharGetDatum(X)
Definition: postgres.h:460
#define AmOidIndexId
Definition: pg_am.h:53
static Datum values[MAXATTR]
Definition: bootstrap.c:166
int errmsg(const char *fmt,...)
Definition: elog.c:909
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221

◆ CreateCast()

ObjectAddress CreateCast ( CreateCastStmt stmt)

Definition at line 1518 of file functioncmds.c.

References ACL_USAGE, aclcheck_error_type(), ACLCHECK_OK, CastCreate(), COERCION_ASSIGNMENT, COERCION_EXPLICIT, COERCION_IMPLICIT, CreateCastStmt::context, DEPENDENCY_NORMAL, elog, ereport, errcode(), errmsg(), ERROR, format_type_be(), CreateCastStmt::func, get_element_type(), get_typlenbyvalalign(), get_typtype(), GETSTRUCT, GetUserId(), HeapTupleIsValid, CreateCastStmt::inout, InvalidOid, IsBinaryCoercible(), LookupFuncWithArgs(), OBJECT_FUNCTION, ObjectIdGetDatum, OidIsValid, pg_type_aclcheck(), pg_type_ownercheck(), PROCOID, ReleaseSysCache(), SearchSysCache1(), CreateCastStmt::sourcetype, superuser(), CreateCastStmt::targettype, TypeNameToString(), typenameTypeId(), and WARNING.

Referenced by ProcessUtilitySlow().

1519 {
1520  Oid sourcetypeid;
1521  Oid targettypeid;
1522  char sourcetyptype;
1523  char targettyptype;
1524  Oid funcid;
1525  int nargs;
1526  char castcontext;
1527  char castmethod;
1528  HeapTuple tuple;
1529  AclResult aclresult;
1530  ObjectAddress myself;
1531 
1532  sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
1533  targettypeid = typenameTypeId(NULL, stmt->targettype);
1534  sourcetyptype = get_typtype(sourcetypeid);
1535  targettyptype = get_typtype(targettypeid);
1536 
1537  /* No pseudo-types allowed */
1538  if (sourcetyptype == TYPTYPE_PSEUDO)
1539  ereport(ERROR,
1540  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1541  errmsg("source data type %s is a pseudo-type",
1542  TypeNameToString(stmt->sourcetype))));
1543 
1544  if (targettyptype == TYPTYPE_PSEUDO)
1545  ereport(ERROR,
1546  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1547  errmsg("target data type %s is a pseudo-type",
1548  TypeNameToString(stmt->targettype))));
1549 
1550  /* Permission check */
1551  if (!pg_type_ownercheck(sourcetypeid, GetUserId())
1552  && !pg_type_ownercheck(targettypeid, GetUserId()))
1553  ereport(ERROR,
1554  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1555  errmsg("must be owner of type %s or type %s",
1556  format_type_be(sourcetypeid),
1557  format_type_be(targettypeid))));
1558 
1559  aclresult = pg_type_aclcheck(sourcetypeid, GetUserId(), ACL_USAGE);
1560  if (aclresult != ACLCHECK_OK)
1561  aclcheck_error_type(aclresult, sourcetypeid);
1562 
1563  aclresult = pg_type_aclcheck(targettypeid, GetUserId(), ACL_USAGE);
1564  if (aclresult != ACLCHECK_OK)
1565  aclcheck_error_type(aclresult, targettypeid);
1566 
1567  /* Domains are allowed for historical reasons, but we warn */
1568  if (sourcetyptype == TYPTYPE_DOMAIN)
1569  ereport(WARNING,
1570  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1571  errmsg("cast will be ignored because the source data type is a domain")));
1572 
1573  else if (targettyptype == TYPTYPE_DOMAIN)
1574  ereport(WARNING,
1575  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1576  errmsg("cast will be ignored because the target data type is a domain")));
1577 
1578  /* Determine the cast method */
1579  if (stmt->func != NULL)
1580  castmethod = COERCION_METHOD_FUNCTION;
1581  else if (stmt->inout)
1582  castmethod = COERCION_METHOD_INOUT;
1583  else
1584  castmethod = COERCION_METHOD_BINARY;
1585 
1586  if (castmethod == COERCION_METHOD_FUNCTION)
1587  {
1588  Form_pg_proc procstruct;
1589 
1590  funcid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->func, false);
1591 
1592  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1593  if (!HeapTupleIsValid(tuple))
1594  elog(ERROR, "cache lookup failed for function %u", funcid);
1595 
1596  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1597  nargs = procstruct->pronargs;
1598  if (nargs < 1 || nargs > 3)
1599  ereport(ERROR,
1600  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1601  errmsg("cast function must take one to three arguments")));
1602  if (!IsBinaryCoercible(sourcetypeid, procstruct->proargtypes.values[0]))
1603  ereport(ERROR,
1604  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1605  errmsg("argument of cast function must match or be binary-coercible from source data type")));
1606  if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
1607  ereport(ERROR,
1608  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1609  errmsg("second argument of cast function must be type %s",
1610  "integer")));
1611  if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)
1612  ereport(ERROR,
1613  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1614  errmsg("third argument of cast function must be type %s",
1615  "boolean")));
1616  if (!IsBinaryCoercible(procstruct->prorettype, targettypeid))
1617  ereport(ERROR,
1618  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1619  errmsg("return data type of cast function must match or be binary-coercible to target data type")));
1620 
1621  /*
1622  * Restricting the volatility of a cast function may or may not be a
1623  * good idea in the abstract, but it definitely breaks many old
1624  * user-defined types. Disable this check --- tgl 2/1/03
1625  */
1626 #ifdef NOT_USED
1627  if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1628  ereport(ERROR,
1629  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1630  errmsg("cast function must not be volatile")));
1631 #endif
1632  if (procstruct->prokind != PROKIND_FUNCTION)
1633  ereport(ERROR,
1634  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1635  errmsg("cast function must be a normal function")));
1636  if (procstruct->proretset)
1637  ereport(ERROR,
1638  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1639  errmsg("cast function must not return a set")));
1640 
1641  ReleaseSysCache(tuple);
1642  }
1643  else
1644  {
1645  funcid = InvalidOid;
1646  nargs = 0;
1647  }
1648 
1649  if (castmethod == COERCION_METHOD_BINARY)
1650  {
1651  int16 typ1len;
1652  int16 typ2len;
1653  bool typ1byval;
1654  bool typ2byval;
1655  char typ1align;
1656  char typ2align;
1657 
1658  /*
1659  * Must be superuser to create binary-compatible casts, since
1660  * erroneous casts can easily crash the backend.
1661  */
1662  if (!superuser())
1663  ereport(ERROR,
1664  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1665  errmsg("must be superuser to create a cast WITHOUT FUNCTION")));
1666 
1667  /*
1668  * Also, insist that the types match as to size, alignment, and
1669  * pass-by-value attributes; this provides at least a crude check that
1670  * they have similar representations. A pair of types that fail this
1671  * test should certainly not be equated.
1672  */
1673  get_typlenbyvalalign(sourcetypeid, &typ1len, &typ1byval, &typ1align);
1674  get_typlenbyvalalign(targettypeid, &typ2len, &typ2byval, &typ2align);
1675  if (typ1len != typ2len ||
1676  typ1byval != typ2byval ||
1677  typ1align != typ2align)
1678  ereport(ERROR,
1679  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1680  errmsg("source and target data types are not physically compatible")));
1681 
1682  /*
1683  * We know that composite, enum and array types are never binary-
1684  * compatible with each other. They all have OIDs embedded in them.
1685  *
1686  * Theoretically you could build a user-defined base type that is
1687  * binary-compatible with a composite, enum, or array type. But we
1688  * disallow that too, as in practice such a cast is surely a mistake.
1689  * You can always work around that by writing a cast function.
1690  */
1691  if (sourcetyptype == TYPTYPE_COMPOSITE ||
1692  targettyptype == TYPTYPE_COMPOSITE)
1693  ereport(ERROR,
1694  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1695  errmsg("composite data types are not binary-compatible")));
1696 
1697  if (sourcetyptype == TYPTYPE_ENUM ||
1698  targettyptype == TYPTYPE_ENUM)
1699  ereport(ERROR,
1700  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1701  errmsg("enum data types are not binary-compatible")));
1702 
1703  if (OidIsValid(get_element_type(sourcetypeid)) ||
1704  OidIsValid(get_element_type(targettypeid)))
1705  ereport(ERROR,
1706  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1707  errmsg("array data types are not binary-compatible")));
1708 
1709  /*
1710  * We also disallow creating binary-compatibility casts involving
1711  * domains. Casting from a domain to its base type is already
1712  * allowed, and casting the other way ought to go through domain
1713  * coercion to permit constraint checking. Again, if you're intent on
1714  * having your own semantics for that, create a no-op cast function.
1715  *
1716  * NOTE: if we were to relax this, the above checks for composites
1717  * etc. would have to be modified to look through domains to their
1718  * base types.
1719  */
1720  if (sourcetyptype == TYPTYPE_DOMAIN ||
1721  targettyptype == TYPTYPE_DOMAIN)
1722  ereport(ERROR,
1723  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1724  errmsg("domain data types must not be marked binary-compatible")));
1725  }
1726 
1727  /*
1728  * Allow source and target types to be same only for length coercion
1729  * functions. We assume a multi-arg function does length coercion.
1730  */
1731  if (sourcetypeid == targettypeid && nargs < 2)
1732  ereport(ERROR,
1733  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1734  errmsg("source data type and target data type are the same")));
1735 
1736  /* convert CoercionContext enum to char value for castcontext */
1737  switch (stmt->context)
1738  {
1739  case COERCION_IMPLICIT:
1740  castcontext = COERCION_CODE_IMPLICIT;
1741  break;
1742  case COERCION_ASSIGNMENT:
1743  castcontext = COERCION_CODE_ASSIGNMENT;
1744  break;
1745  /* COERCION_PLPGSQL is intentionally not covered here */
1746  case COERCION_EXPLICIT:
1747  castcontext = COERCION_CODE_EXPLICIT;
1748  break;
1749  default:
1750  elog(ERROR, "unrecognized CoercionContext: %d", stmt->context);
1751  castcontext = 0; /* keep compiler quiet */
1752  break;
1753  }
1754 
1755  myself = CastCreate(sourcetypeid, targettypeid, funcid, castcontext,
1756  castmethod, DEPENDENCY_NORMAL);
1757  return myself;
1758 }
signed short int16
Definition: c.h:428
TypeName * sourcetype
Definition: parsenodes.h:3490
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
Oid GetUserId(void)
Definition: miscinit.c:478
ObjectAddress CastCreate(Oid sourcetypeid, Oid targettypeid, Oid funcid, char castcontext, char castmethod, DependencyType behavior)
Definition: pg_cast.c:43
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2706
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2218
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:476
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
char get_typtype(Oid typid)
Definition: lsyscache.c:2576
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
unsigned int Oid
Definition: postgres_ext.h:31
bool pg_type_ownercheck(Oid type_oid, Oid roleid)
Definition: aclchk.c:4849
#define OidIsValid(objectId)
Definition: c.h:710
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3626
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
CoercionContext context
Definition: parsenodes.h:3493
#define ACL_USAGE
Definition: parsenodes.h:90
bool IsBinaryCoercible(Oid srctype, Oid targettype)
#define WARNING
Definition: elog.h:40
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
AclResult
Definition: acl.h:177
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
ObjectWithArgs * func
Definition: parsenodes.h:3492
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2177
TypeName * targettype
Definition: parsenodes.h:3491
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4811
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:291

◆ CreateForeignDataWrapper()

ObjectAddress CreateForeignDataWrapper ( CreateFdwStmt stmt)

Definition at line 562 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().

563 {
564  Relation rel;
565  Datum values[Natts_pg_foreign_data_wrapper];
566  bool nulls[Natts_pg_foreign_data_wrapper];
567  HeapTuple tuple;
568  Oid fdwId;
569  bool handler_given;
570  bool validator_given;
571  Oid fdwhandler;
572  Oid fdwvalidator;
573  Datum fdwoptions;
574  Oid ownerId;
575  ObjectAddress myself;
576  ObjectAddress referenced;
577 
578  rel = table_open(ForeignDataWrapperRelationId, RowExclusiveLock);
579 
580  /* Must be super user */
581  if (!superuser())
582  ereport(ERROR,
583  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
584  errmsg("permission denied to create foreign-data wrapper \"%s\"",
585  stmt->fdwname),
586  errhint("Must be superuser to create a foreign-data wrapper.")));
587 
588  /* For now the owner cannot be specified on create. Use effective user ID. */
589  ownerId = GetUserId();
590 
591  /*
592  * Check that there is no other foreign-data wrapper by this name.
593  */
594  if (GetForeignDataWrapperByName(stmt->fdwname, true) != NULL)
595  ereport(ERROR,
597  errmsg("foreign-data wrapper \"%s\" already exists",
598  stmt->fdwname)));
599 
600  /*
601  * Insert tuple into pg_foreign_data_wrapper.
602  */
603  memset(values, 0, sizeof(values));
604  memset(nulls, false, sizeof(nulls));
605 
607  Anum_pg_foreign_data_wrapper_oid);
608  values[Anum_pg_foreign_data_wrapper_oid - 1] = ObjectIdGetDatum(fdwId);
609  values[Anum_pg_foreign_data_wrapper_fdwname - 1] =
611  values[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(ownerId);
612 
613  /* Lookup handler and validator functions, if given */
615  &handler_given, &fdwhandler,
616  &validator_given, &fdwvalidator);
617 
618  values[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = ObjectIdGetDatum(fdwhandler);
619  values[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = ObjectIdGetDatum(fdwvalidator);
620 
621  nulls[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
622 
623  fdwoptions = transformGenericOptions(ForeignDataWrapperRelationId,
624  PointerGetDatum(NULL),
625  stmt->options,
626  fdwvalidator);
627 
628  if (PointerIsValid(DatumGetPointer(fdwoptions)))
629  values[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = fdwoptions;
630  else
631  nulls[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = true;
632 
633  tuple = heap_form_tuple(rel->rd_att, values, nulls);
634 
635  CatalogTupleInsert(rel, tuple);
636 
637  heap_freetuple(tuple);
638 
639  /* record dependencies */
640  myself.classId = ForeignDataWrapperRelationId;
641  myself.objectId = fdwId;
642  myself.objectSubId = 0;
643 
644  if (OidIsValid(fdwhandler))
645  {
646  referenced.classId = ProcedureRelationId;
647  referenced.objectId = fdwhandler;
648  referenced.objectSubId = 0;
649  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
650  }
651 
652  if (OidIsValid(fdwvalidator))
653  {
654  referenced.classId = ProcedureRelationId;
655  referenced.objectId = fdwvalidator;
656  referenced.objectSubId = 0;
657  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
658  }
659 
660  recordDependencyOnOwner(ForeignDataWrapperRelationId, fdwId, ownerId);
661 
662  /* dependency on extension */
663  recordDependencyOnCurrentExtension(&myself, false);
664 
665  /* Post creation hook for new foreign data wrapper */
666  InvokeObjectPostCreateHook(ForeignDataWrapperRelationId, fdwId, 0);
667 
669 
670  return myself;
671 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:322
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
int errhint(const char *fmt,...)
Definition: elog.c:1156
static void parse_func_options(List *func_options, bool *handler_given, Oid *fdwhandler, bool *validator_given, Oid *fdwvalidator)
Definition: foreigncmds.c:518
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
Oid GetUserId(void)
Definition: miscinit.c:478
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:110
#define PointerGetDatum(X)
Definition: postgres.h:600
#define ForeignDataWrapperOidIndexId
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
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:626
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:710
List * options
Definition: parsenodes.h:2367
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define RowExclusiveLock
Definition: lockdefs.h:38
char * fdwname
Definition: parsenodes.h:2365
#define CStringGetDatum(X)
Definition: postgres.h:622
uintptr_t Datum
Definition: postgres.h:411
TupleDesc rd_att
Definition: rel.h:110
#define ereport(elevel,...)
Definition: elog.h:157
ForeignDataWrapper * GetForeignDataWrapperByName(const char *fdwname, bool missing_ok)
Definition: foreign.c:94
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:180
#define DatumGetPointer(X)
Definition: postgres.h:593
static Datum values[MAXATTR]
Definition: bootstrap.c:166
int errmsg(const char *fmt,...)
Definition: elog.c:909
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
#define PointerIsValid(pointer)
Definition: c.h:698
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
List * func_options
Definition: parsenodes.h:2366

◆ CreateForeignServer()

ObjectAddress CreateForeignServer ( CreateForeignServerStmt stmt)

Definition at line 842 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().

843 {
844  Relation rel;
845  Datum srvoptions;
846  Datum values[Natts_pg_foreign_server];
847  bool nulls[Natts_pg_foreign_server];
848  HeapTuple tuple;
849  Oid srvId;
850  Oid ownerId;
851  AclResult aclresult;
852  ObjectAddress myself;
853  ObjectAddress referenced;
854  ForeignDataWrapper *fdw;
855 
856  rel = table_open(ForeignServerRelationId, RowExclusiveLock);
857 
858  /* For now the owner cannot be specified on create. Use effective user ID. */
859  ownerId = GetUserId();
860 
861  /*
862  * Check that there is no other foreign server by this name. Do nothing if
863  * IF NOT EXISTS was enforced.
864  */
865  if (GetForeignServerByName(stmt->servername, true) != NULL)
866  {
867  if (stmt->if_not_exists)
868  {
869  ereport(NOTICE,
871  errmsg("server \"%s\" already exists, skipping",
872  stmt->servername)));
874  return InvalidObjectAddress;
875  }
876  else
877  ereport(ERROR,
879  errmsg("server \"%s\" already exists",
880  stmt->servername)));
881  }
882 
883  /*
884  * Check that the FDW exists and that we have USAGE on it. Also get the
885  * actual FDW for option validation etc.
886  */
887  fdw = GetForeignDataWrapperByName(stmt->fdwname, false);
888 
889  aclresult = pg_foreign_data_wrapper_aclcheck(fdw->fdwid, ownerId, ACL_USAGE);
890  if (aclresult != ACLCHECK_OK)
891  aclcheck_error(aclresult, OBJECT_FDW, fdw->fdwname);
892 
893  /*
894  * Insert tuple into pg_foreign_server.
895  */
896  memset(values, 0, sizeof(values));
897  memset(nulls, false, sizeof(nulls));
898 
900  Anum_pg_foreign_server_oid);
901  values[Anum_pg_foreign_server_oid - 1] = ObjectIdGetDatum(srvId);
902  values[Anum_pg_foreign_server_srvname - 1] =
904  values[Anum_pg_foreign_server_srvowner - 1] = ObjectIdGetDatum(ownerId);
905  values[Anum_pg_foreign_server_srvfdw - 1] = ObjectIdGetDatum(fdw->fdwid);
906 
907  /* Add server type if supplied */
908  if (stmt->servertype)
909  values[Anum_pg_foreign_server_srvtype - 1] =
911  else
912  nulls[Anum_pg_foreign_server_srvtype - 1] = true;
913 
914  /* Add server version if supplied */
915  if (stmt->version)
916  values[Anum_pg_foreign_server_srvversion - 1] =
918  else
919  nulls[Anum_pg_foreign_server_srvversion - 1] = true;
920 
921  /* Start with a blank acl */
922  nulls[Anum_pg_foreign_server_srvacl - 1] = true;
923 
924  /* Add server options */
925  srvoptions = transformGenericOptions(ForeignServerRelationId,
926  PointerGetDatum(NULL),
927  stmt->options,
928  fdw->fdwvalidator);
929 
930  if (PointerIsValid(DatumGetPointer(srvoptions)))
931  values[Anum_pg_foreign_server_srvoptions - 1] = srvoptions;
932  else
933  nulls[Anum_pg_foreign_server_srvoptions - 1] = true;
934 
935  tuple = heap_form_tuple(rel->rd_att, values, nulls);
936 
937  CatalogTupleInsert(rel, tuple);
938 
939  heap_freetuple(tuple);
940 
941  /* record dependencies */
942  myself.classId = ForeignServerRelationId;
943  myself.objectId = srvId;
944  myself.objectSubId = 0;
945 
946  referenced.classId = ForeignDataWrapperRelationId;
947  referenced.objectId = fdw->fdwid;
948  referenced.objectSubId = 0;
949  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
950 
951  recordDependencyOnOwner(ForeignServerRelationId, srvId, ownerId);
952 
953  /* dependency on extension */
954  recordDependencyOnCurrentExtension(&myself, false);
955 
956  /* Post creation hook for new foreign server */
957  InvokeObjectPostCreateHook(ForeignServerRelationId, srvId, 0);
958 
960 
961  return myself;
962 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:322
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
Oid GetUserId(void)
Definition: miscinit.c:478
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:600
AclResult pg_foreign_data_wrapper_aclcheck(Oid fdw_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4786
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ForeignServerOidIndexId
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:626
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:3313
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:622
#define ACL_USAGE
Definition: parsenodes.h:90
ForeignServer * GetForeignServerByName(const char *srvname, bool missing_ok)
Definition: foreign.c:180
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:411
TupleDesc rd_att
Definition: rel.h:110
#define ereport(elevel,...)
Definition: elog.h:157
#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:180
#define DatumGetPointer(X)
Definition: postgres.h:593
static Datum values[MAXATTR]
Definition: bootstrap.c:166
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define CStringGetTextDatum(s)
Definition: builtins.h:82
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
#define PointerIsValid(pointer)
Definition: c.h:698
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221

◆ CreateForeignTable()

void CreateForeignTable ( CreateForeignTableStmt stmt,
Oid  relid 
)

Definition at line 1395 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().

1396 {
1397  Relation ftrel;
1398  Datum ftoptions;
1399  Datum values[Natts_pg_foreign_table];
1400  bool nulls[Natts_pg_foreign_table];
1401  HeapTuple tuple;
1402  AclResult aclresult;
1403  ObjectAddress myself;
1404  ObjectAddress referenced;
1405  Oid ownerId;
1406  ForeignDataWrapper *fdw;
1407  ForeignServer *server;
1408 
1409  /*
1410  * Advance command counter to ensure the pg_attribute tuple is visible;
1411  * the tuple might be updated to add constraints in previous step.
1412  */
1414 
1415  ftrel = table_open(ForeignTableRelationId, RowExclusiveLock);
1416 
1417  /*
1418  * For now the owner cannot be specified on create. Use effective user ID.
1419  */
1420  ownerId = GetUserId();
1421 
1422  /*
1423  * Check that the foreign server exists and that we have USAGE on it. Also
1424  * get the actual FDW for option validation etc.
1425  */
1426  server = GetForeignServerByName(stmt->servername, false);
1427  aclresult = pg_foreign_server_aclcheck(server->serverid, ownerId, ACL_USAGE);
1428  if (aclresult != ACLCHECK_OK)
1429  aclcheck_error(aclresult, OBJECT_FOREIGN_SERVER, server->servername);
1430 
1431  fdw = GetForeignDataWrapper(server->fdwid);
1432 
1433  /*
1434  * Insert tuple into pg_foreign_table.
1435  */
1436  memset(values, 0, sizeof(values));
1437  memset(nulls, false, sizeof(nulls));
1438 
1439  values[Anum_pg_foreign_table_ftrelid - 1] = ObjectIdGetDatum(relid);
1440  values[Anum_pg_foreign_table_ftserver - 1] = ObjectIdGetDatum(server->serverid);
1441  /* Add table generic options */
1442  ftoptions = transformGenericOptions(ForeignTableRelationId,
1443  PointerGetDatum(NULL),
1444  stmt->options,
1445  fdw->fdwvalidator);
1446 
1447  if (PointerIsValid(DatumGetPointer(ftoptions)))
1448  values[Anum_pg_foreign_table_ftoptions - 1] = ftoptions;
1449  else
1450  nulls[Anum_pg_foreign_table_ftoptions - 1] = true;
1451 
1452  tuple = heap_form_tuple(ftrel->rd_att, values, nulls);
1453 
1454  CatalogTupleInsert(ftrel, tuple);
1455 
1456  heap_freetuple(tuple);
1457 
1458  /* Add pg_class dependency on the server */
1459  myself.classId = RelationRelationId;
1460  myself.objectId = relid;
1461  myself.objectSubId = 0;
1462 
1463  referenced.classId = ForeignServerRelationId;
1464  referenced.objectId = server->serverid;
1465  referenced.objectSubId = 0;
1466  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1467 
1468  table_close(ftrel, RowExclusiveLock);
1469 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
Oid GetUserId(void)
Definition: miscinit.c:478
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:110
#define PointerGetDatum(X)
Definition: postgres.h:600
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:3313
ForeignDataWrapper * GetForeignDataWrapper(Oid fdwid)
Definition: foreign.c:35
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
AclResult pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4799
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ACL_USAGE
Definition: parsenodes.h:90
ForeignServer * GetForeignServerByName(const char *srvname, bool missing_ok)
Definition: foreign.c:180
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:411
void CommandCounterIncrement(void)
Definition: xact.c:1021
TupleDesc rd_att
Definition: rel.h:110
#define DatumGetPointer(X)
Definition: postgres.h:593
static Datum values[MAXATTR]
Definition: bootstrap.c:166
char * servername
Definition: foreign.h:39
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define PointerIsValid(pointer)
Definition: c.h:698
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
Oid serverid
Definition: foreign.h:36

◆ CreateFunction()

ObjectAddress CreateFunction ( ParseState pstate,
CreateFunctionStmt stmt 
)

Definition at line 1012 of file functioncmds.c.

References ACL_CREATE, ACL_USAGE, aclcheck_error(), ACLCHECK_NO_PRIV, ACLCHECK_OK, Assert, castNode, compute_function_attributes(), compute_return_type(), construct_array(), ereport, errcode(), errhint(), errmsg(), ERROR, extension_file_exists(), format_type_be(), CreateFunctionStmt::funcname, get_base_element_type(), get_namespace_name(), get_transform_oid(), GETSTRUCT, GetUserId(), HeapTupleIsValid, i, interpret_AS_clause(), interpret_function_parameter_list(), InvalidOid, CreateFunctionStmt::is_procedure, LANGNAME, lappend_oid(), lfirst_node, lfirst_oid, list_length(), NameStr, NIL, OBJECT_FUNCTION, OBJECT_LANGUAGE, OBJECT_PROCEDURE, OBJECT_SCHEMA, ObjectIdGetDatum, OidIsValid, CreateFunctionStmt::options, ParseState::p_sourcetext, palloc(), CreateFunctionStmt::parameters, pg_language_aclcheck(), pg_namespace_aclcheck(), PointerGetDatum, ProcedureCreate(), QualifiedNameGetCreationNamespace(), ReleaseSysCache(), CreateFunctionStmt::replace, CreateFunctionStmt::returnType, SearchSysCache1(), CreateFunctionStmt::sql_body, superuser(), and typenameTypeId().

Referenced by ProcessUtilitySlow().

1013 {
1014  char *probin_str;
1015  char *prosrc_str;
1016  Node *prosqlbody;
1017  Oid prorettype;
1018  bool returnsSet;
1019  char *language;
1020  Oid languageOid;
1021  Oid languageValidator;
1022  Node *transformDefElem = NULL;
1023  char *funcname;
1024  Oid namespaceId;
1025  AclResult aclresult;
1026  oidvector *parameterTypes;
1027  List *parameterTypes_list = NIL;
1028  ArrayType *allParameterTypes;
1029  ArrayType *parameterModes;
1030  ArrayType *parameterNames;
1031  List *inParameterNames_list = NIL;
1032  List *parameterDefaults;
1033  Oid variadicArgType;
1034  List *trftypes_list = NIL;
1035  ArrayType *trftypes;
1036  Oid requiredResultType;
1037  bool isWindowFunc,
1038  isStrict,
1039  security,
1040  isLeakProof;
1041  char volatility;
1042  ArrayType *proconfig;
1043  float4 procost;
1044  float4 prorows;
1045  Oid prosupport;
1046  HeapTuple languageTuple;
1047  Form_pg_language languageStruct;
1048  List *as_clause;
1049  char parallel;
1050 
1051  /* Convert list of names to a name and namespace */
1052  namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
1053  &funcname);
1054 
1055  /* Check we have creation rights in target namespace */
1056  aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
1057  if (aclresult != ACLCHECK_OK)
1058  aclcheck_error(aclresult, OBJECT_SCHEMA,
1059  get_namespace_name(namespaceId));
1060 
1061  /* Set default attributes */
1062  as_clause = NIL;
1063  language = NULL;
1064  isWindowFunc = false;
1065  isStrict = false;
1066  security = false;
1067  isLeakProof = false;
1068  volatility = PROVOLATILE_VOLATILE;
1069  proconfig = NULL;
1070  procost = -1; /* indicates not set */
1071  prorows = -1; /* indicates not set */
1072  prosupport = InvalidOid;
1073  parallel = PROPARALLEL_UNSAFE;
1074 
1075  /* Extract non-default attributes from stmt->options list */
1077  stmt->is_procedure,
1078  stmt->options,
1079  &as_clause, &language, &transformDefElem,
1080  &isWindowFunc, &volatility,
1081  &isStrict, &security, &isLeakProof,
1082  &proconfig, &procost, &prorows,
1083  &prosupport, &parallel);
1084 
1085  if (!language)
1086  {
1087  if (stmt->sql_body)
1088  language = "sql";
1089  else
1090  ereport(ERROR,
1091  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1092  errmsg("no language specified")));
1093  }
1094 
1095  /* Look up the language and validate permissions */
1096  languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
1097  if (!HeapTupleIsValid(languageTuple))
1098  ereport(ERROR,
1099  (errcode(ERRCODE_UNDEFINED_OBJECT),
1100  errmsg("language \"%s\" does not exist", language),
1101  (extension_file_exists(language) ?
1102  errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
1103 
1104  languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
1105  languageOid = languageStruct->oid;
1106 
1107  if (languageStruct->lanpltrusted)
1108  {
1109  /* if trusted language, need USAGE privilege */
1110  AclResult aclresult;
1111 
1112  aclresult = pg_language_aclcheck(languageOid, GetUserId(), ACL_USAGE);
1113  if (aclresult != ACLCHECK_OK)
1114  aclcheck_error(aclresult, OBJECT_LANGUAGE,
1115  NameStr(languageStruct->lanname));
1116  }
1117  else
1118  {
1119  /* if untrusted language, must be superuser */
1120  if (!superuser())
1122  NameStr(languageStruct->lanname));
1123  }
1124 
1125  languageValidator = languageStruct->lanvalidator;
1126 
1127  ReleaseSysCache(languageTuple);
1128 
1129  /*
1130  * Only superuser is allowed to create leakproof functions because
1131  * leakproof functions can see tuples which have not yet been filtered out
1132  * by security barrier views or row-level security policies.
1133  */
1134  if (isLeakProof && !superuser())
1135  ereport(ERROR,
1136  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1137  errmsg("only superuser can define a leakproof function")));
1138 
1139  if (transformDefElem)
1140  {
1141  ListCell *lc;
1142 
1143  foreach(lc, castNode(List, transformDefElem))
1144  {
1145  Oid typeid = typenameTypeId(NULL,
1146  lfirst_node(TypeName, lc));
1147  Oid elt = get_base_element_type(typeid);
1148 
1149  typeid = elt ? elt : typeid;
1150 
1151  get_transform_oid(typeid, languageOid, false);
1152  trftypes_list = lappend_oid(trftypes_list, typeid);
1153  }
1154  }
1155 
1156  /*
1157  * Convert remaining parameters of CREATE to form wanted by
1158  * ProcedureCreate.
1159  */
1161  stmt->parameters,
1162  languageOid,
1164  &parameterTypes,
1165  &parameterTypes_list,
1166  &allParameterTypes,
1167  &parameterModes,
1168  &parameterNames,
1169  &inParameterNames_list,
1170  &parameterDefaults,
1171  &variadicArgType,
1172  &requiredResultType);
1173 
1174  if (stmt->is_procedure)
1175  {
1176  Assert(!stmt->returnType);
1177  prorettype = requiredResultType ? requiredResultType : VOIDOID;
1178  returnsSet = false;
1179  }
1180  else if (stmt->returnType)
1181  {
1182  /* explicit RETURNS clause */
1183  compute_return_type(stmt->returnType, languageOid,
1184  &prorettype, &returnsSet);
1185  if (OidIsValid(requiredResultType) && prorettype != requiredResultType)
1186  ereport(ERROR,
1187  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1188  errmsg("function result type must be %s because of OUT parameters",
1189  format_type_be(requiredResultType))));
1190  }
1191  else if (OidIsValid(requiredResultType))
1192  {
1193  /* default RETURNS clause from OUT parameters */
1194  prorettype = requiredResultType;
1195  returnsSet = false;
1196  }
1197  else
1198  {
1199  ereport(ERROR,
1200  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1201  errmsg("function result type must be specified")));
1202  /* Alternative possibility: default to RETURNS VOID */
1203  prorettype = VOIDOID;
1204  returnsSet = false;
1205  }
1206 
1207  if (list_length(trftypes_list) > 0)
1208  {
1209  ListCell *lc;
1210  Datum *arr;
1211  int i;
1212 
1213  arr = palloc(list_length(trftypes_list) * sizeof(Datum));
1214  i = 0;
1215  foreach(lc, trftypes_list)
1216  arr[i++] = ObjectIdGetDatum(lfirst_oid(lc));
1217  trftypes = construct_array(arr, list_length(trftypes_list),
1218  OIDOID, sizeof(Oid), true, TYPALIGN_INT);
1219  }
1220  else
1221  {
1222  /* store SQL NULL instead of empty array */
1223  trftypes = NULL;
1224  }
1225 
1226  interpret_AS_clause(languageOid, language, funcname, as_clause, stmt->sql_body,
1227  parameterTypes_list, inParameterNames_list,
1228  &prosrc_str, &probin_str, &prosqlbody,
1229  pstate->p_sourcetext);
1230 
1231  /*
1232  * Set default values for COST and ROWS depending on other parameters;
1233  * reject ROWS if it's not returnsSet. NB: pg_dump knows these default
1234  * values, keep it in sync if you change them.
1235  */
1236  if (procost < 0)
1237  {
1238  /* SQL and PL-language functions are assumed more expensive */
1239  if (languageOid == INTERNALlanguageId ||
1240  languageOid == ClanguageId)
1241  procost = 1;
1242  else
1243  procost = 100;
1244  }
1245  if (prorows < 0)
1246  {
1247  if (returnsSet)
1248  prorows = 1000;
1249  else
1250  prorows = 0; /* dummy value if not returnsSet */
1251  }
1252  else if (!returnsSet)
1253  ereport(ERROR,
1254  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1255  errmsg("ROWS is not applicable when function does not return a set")));
1256 
1257  /*
1258  * And now that we have all the parameters, and know we're permitted to do
1259  * so, go ahead and create the function.
1260  */
1261  return ProcedureCreate(funcname,
1262  namespaceId,
1263  stmt->replace,
1264  returnsSet,
1265  prorettype,
1266  GetUserId(),
1267  languageOid,
1268  languageValidator,
1269  prosrc_str, /* converted to text later */
1270  probin_str, /* converted to text later */
1271  prosqlbody,
1272  stmt->is_procedure ? PROKIND_PROCEDURE : (isWindowFunc ? PROKIND_WINDOW : PROKIND_FUNCTION),
1273  security,
1274  isLeakProof,
1275  isStrict,
1276  volatility,
1277  parallel,
1278  parameterTypes,
1279  PointerGetDatum(allParameterTypes),
1280  PointerGetDatum(parameterModes),
1281  PointerGetDatum(parameterNames),
1282  parameterDefaults,
1283  PointerGetDatum(trftypes),
1284  PointerGetDatum(proconfig),
1285  prosupport,
1286  procost,
1287  prorows);
1288 }
#define NIL
Definition: pg_list.h:65
Definition: c.h:660
static void interpret_AS_clause(Oid languageOid, const char *languageName, char *funcname, List *as, Node *sql_body_in, List *parameterTypes, List *inParameterNames, char **prosrc_str_p, char **probin_str_p, Node **sql_body_out, const char *queryString)
Definition: functioncmds.c:852
int errhint(const char *fmt,...)
Definition: elog.c:1156
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
Oid GetUserId(void)
Definition: miscinit.c:478
#define castNode(_type_, nodeptr)
Definition: nodes.h:608
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2994
#define PointerGetDatum(X)
Definition: postgres.h:600
static void compute_return_type(TypeName *returnType, Oid languageOid, Oid *prorettype_p, bool *returnsSet_p)
Definition: functioncmds.c:91
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3318
Definition: nodes.h:539
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
#define OidIsValid(objectId)
Definition: c.h:710
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4761
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4735
Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok)
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3313
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define ACL_CREATE
Definition: parsenodes.h:92
#define lfirst_node(type, lc)
Definition: pg_list.h:172
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3316
static void compute_function_attributes(ParseState *pstate, bool is_procedure, List *options, List **as, char **language, Node **transform, bool *windowfunc_p, char *volatility_p, bool *strict_p, bool *security_definer, bool *leakproof_p, ArrayType **proconfig, float4 *procost, float4 *prorows, Oid *prosupport, char *parallel_p)
Definition: functioncmds.c:703
#define ACL_USAGE
Definition: parsenodes.h:90
const char * p_sourcetext
Definition: parse_node.h:181
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
float float4
Definition: c.h:564
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:411
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
void interpret_function_parameter_list(ParseState *pstate, List *parameters, Oid languageOid, ObjectType objtype, oidvector **parameterTypes, List **parameterTypes_list, ArrayType **allParameterTypes, ArrayType **parameterModes, ArrayType **parameterNames, List **inParameterNames_list, List **parameterDefaults, Oid *variadicArgType, Oid *requiredResultType)
Definition: functioncmds.c:187
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
TypeName * returnType
Definition: parsenodes.h:2946
static int list_length(const List *l)
Definition: pg_list.h:149
bool extension_file_exists(const char *extensionName)
Definition: extension.c:2237
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2779
FormData_pg_language * Form_pg_language
Definition: pg_language.h:65
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i
#define NameStr(name)
Definition: c.h:681
ObjectAddress ProcedureCreate(const char *procedureName, Oid procNamespace, bool replace, bool returnsSet, Oid returnType, Oid proowner, Oid languageObjectId, Oid languageValidator, const char *prosrc, const char *probin, Node *prosqlbody, char prokind, bool security_definer, bool isLeakProof, bool isStrict, char volatility, char parallel, oidvector *parameterTypes, Datum allParameterTypes, Datum parameterModes, Datum parameterNames, List *parameterDefaults, Datum trftypes, Datum proconfig, Oid prosupport, float4 procost, float4 prorows)
Definition: pg_proc.c:70
Definition: pg_list.h:50
#define lfirst_oid(lc)
Definition: pg_list.h:171
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:291

◆ CreateStatistics()

ObjectAddress CreateStatistics ( CreateStatsStmt stmt)

Definition at line 64 of file statscmds.c.

References aclcheck_error(), ACLCHECK_NOT_OWNER, allowSystemTableMods, Assert, attname, buildint2vector(), CacheInvalidateRelcache(), CatalogTupleInsert(), CharGetDatum, ChooseExtendedStatisticName(), ChooseExtendedStatisticNameAddition(), compare_int16(), construct_array(), CreateComments(), CStringGetDatum, CStringGetTextDatum, CreateStatsStmt::defnames, DEPENDENCY_AUTO, DEPENDENCY_NORMAL, equal(), ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, StatsElem::expr, CreateStatsStmt::exprs, exprType(), format_type_be(), get_relkind_objtype(), GetNewOidWithIndex(), GETSTRUCT, GetUserId(), heap_form_tuple(), heap_freetuple(), HeapTupleIsValid, i, CreateStatsStmt::if_not_exists, Int32GetDatum, InvalidObjectAddress, InvalidOid, InvokeObjectPostCreateHook, IsA, IsSystemRelation(), lappend(), lengthof, lfirst, list_length(), lookup_type_cache(), TypeCacheEntry::lt_opr, StatsElem::name, NameGetDatum, namestrcpy(), NIL, nodeToString(), NoLock, NOTICE, ObjectAddressSet, ObjectAddressSubSet, ObjectIdGetDatum, pfree(), pg_class_ownercheck(), PointerGetDatum, qsort, QualifiedNameGetCreationNamespace(), RelationData::rd_att, RelationData::rd_rel, recordDependencyOn(), recordDependencyOnOwner(), recordDependencyOnSingleRelExpr(), relation_close(), relation_openrv(), RelationGetNamespace, RelationGetRelationName, RelationGetRelid, CreateStatsStmt::relations, ReleaseSysCache(), RowExclusiveLock, SearchSysCacheAttName(), SearchSysCacheExists2, ShareUpdateExclusiveLock, CreateStatsStmt::stat_types, STATEXTNAMENSP, StatisticExtOidIndexId, STATS_MAX_DIMENSIONS, strVal, CreateStatsStmt::stxcomment, table_open(), generate_unaccent_rules::type, TYPECACHE_LT_OPR, types, and values.

Referenced by ATExecAddStatistics(), and ProcessUtilitySlow().

65 {
66  int16 attnums[STATS_MAX_DIMENSIONS];
67  int nattnums = 0;
68  int numcols;
69  char *namestr;
70  NameData stxname;
71  Oid statoid;
72  Oid namespaceId;
73  Oid stxowner = GetUserId();
74  HeapTuple htup;
75  Datum values[Natts_pg_statistic_ext];
76  bool nulls[Natts_pg_statistic_ext];
77  Datum datavalues[Natts_pg_statistic_ext_data];
78  bool datanulls[Natts_pg_statistic_ext_data];
79  int2vector *stxkeys;
80  List *stxexprs = NIL;
81  Datum exprsDatum;
82  Relation statrel;
83  Relation datarel;
84  Relation rel = NULL;
85  Oid relid;
86  ObjectAddress parentobject,
87  myself;
88  Datum types[4]; /* one for each possible type of statistic */
89  int ntypes;
90  ArrayType *stxkind;
91  bool build_ndistinct;
92  bool build_dependencies;
93  bool build_mcv;
94  bool build_expressions;
95  bool requested_type = false;
96  int i;
97  ListCell *cell;
98  ListCell *cell2;
99 
100  Assert(IsA(stmt, CreateStatsStmt));
101 
102  /*
103  * Examine the FROM clause. Currently, we only allow it to be a single
104  * simple table, but later we'll probably allow multiple tables and JOIN
105  * syntax. The grammar is already prepared for that, so we have to check
106  * here that what we got is what we can support.
107  */
108  if (list_length(stmt->relations) != 1)
109  ereport(ERROR,
110  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
111  errmsg("only a single relation is allowed in CREATE STATISTICS")));
112 
113  foreach(cell, stmt->relations)
114  {
115  Node *rln = (Node *) lfirst(cell);
116 
117  if (!IsA(rln, RangeVar))
118  ereport(ERROR,
119  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
120  errmsg("only a single relation is allowed in CREATE STATISTICS")));
121 
122  /*
123  * CREATE STATISTICS will influence future execution plans but does
124  * not interfere with currently executing plans. So it should be
125  * enough to take only ShareUpdateExclusiveLock on relation,
126  * conflicting with ANALYZE and other DDL that sets statistical
127  * information, but not with normal queries.
128  */
130 
131  /* Restrict to allowed relation types */
132  if (rel->rd_rel->relkind != RELKIND_RELATION &&
133  rel->rd_rel->relkind != RELKIND_MATVIEW &&
134  rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
135  rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
136  ereport(ERROR,
137  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
138  errmsg("relation \"%s\" is not a table, foreign table, or materialized view",
139  RelationGetRelationName(rel))));
140 
141  /* You must own the relation to create stats on it */
142  if (!pg_class_ownercheck(RelationGetRelid(rel), stxowner))
145 
146  /* Creating statistics on system catalogs is not allowed */
148  ereport(ERROR,
149  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
150  errmsg("permission denied: \"%s\" is a system catalog",
151  RelationGetRelationName(rel))));
152  }
153 
154  Assert(rel);
155  relid = RelationGetRelid(rel);
156 
157  /*
158  * If the node has a name, split it up and determine creation namespace.
159  * If not (a possibility not considered by the grammar, but one which can
160  * occur via the "CREATE TABLE ... (LIKE)" command), then we put the
161  * object in the same namespace as the relation, and cons up a name for
162  * it.
163  */
164  if (stmt->defnames)
165  namespaceId = QualifiedNameGetCreationNamespace(stmt->defnames,
166  &namestr);
167  else
168  {
169  namespaceId = RelationGetNamespace(rel);
172  "stat",
173  namespaceId);
174  }
175  namestrcpy(&stxname, namestr);
176 
177  /*
178  * Deal with the possibility that the statistics object already exists.
179  */
181  CStringGetDatum(namestr),
182  ObjectIdGetDatum(namespaceId)))
183  {
184  if (stmt->if_not_exists)
185  {
186  ereport(NOTICE,
188  errmsg("statistics object \"%s\" already exists, skipping",
189  namestr)));
190  relation_close(rel, NoLock);
191  return InvalidObjectAddress;
192  }
193 
194  ereport(ERROR,
196  errmsg("statistics object \"%s\" already exists", namestr)));
197  }
198 
199  /*
200  * Make sure no more than STATS_MAX_DIMENSIONS columns are used. There
201  * might be duplicates and so on, but we'll deal with those later.
202  */
203  numcols = list_length(stmt->exprs);
204  if (numcols > STATS_MAX_DIMENSIONS)
205  ereport(ERROR,
206  (errcode(ERRCODE_TOO_MANY_COLUMNS),
207  errmsg("cannot have more than %d columns in statistics",
209 
210  /*
211  * Convert the expression list to a simple array of attnums, but also keep
212  * a list of more complex expressions. While at it, enforce some
213  * constraints.
214  *
215  * XXX We do only the bare minimum to separate simple attribute and
216  * complex expressions - for example "(a)" will be treated as a complex
217  * expression. No matter how elaborate the check is, there'll always be a
218  * way around it, if the user is determined (consider e.g. "(a+0)"), so
219  * it's not worth protecting against it.
220  */
221  foreach(cell, stmt->exprs)
222  {
223  Node *expr = (Node *) lfirst(cell);
224  StatsElem *selem;
225  HeapTuple atttuple;
226  Form_pg_attribute attForm;
228 
229  /*
230  * We should not get anything else than StatsElem, given the grammar.
231  * But let's keep it as a safety.
232  */
233  if (!IsA(expr, StatsElem))
234  ereport(ERROR,
235  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
236  errmsg("only simple column references and expressions are allowed in CREATE STATISTICS")));
237 
238  selem = (StatsElem *) expr;
239 
240  if (selem->name) /* column reference */
241  {
242  char *attname;
243 
244  attname = selem->name;
245 
246  atttuple = SearchSysCacheAttName(relid, attname);
247  if (!HeapTupleIsValid(atttuple))
248  ereport(ERROR,
249  (errcode(ERRCODE_UNDEFINED_COLUMN),
250  errmsg("column \"%s\" does not exist",
251  attname)));
252  attForm = (Form_pg_attribute) GETSTRUCT(atttuple);
253 
254  /* Disallow use of system attributes in extended stats */
255  if (attForm->attnum <= 0)
256  ereport(ERROR,
257  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
258  errmsg("statistics creation on system columns is not supported")));
259 
260  /* Disallow data types without a less-than operator */
261  type = lookup_type_cache(attForm->atttypid, TYPECACHE_LT_OPR);
262  if (type->lt_opr == InvalidOid)
263  ereport(ERROR,
264  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
265  errmsg("column \"%s\" cannot be used in statistics because its type %s has no default btree operator class",
266  attname, format_type_be(attForm->atttypid))));
267 
268  attnums[nattnums] = attForm->attnum;
269  nattnums++;
270  ReleaseSysCache(atttuple);
271  }
272  else /* expression */
273  {
274  Node *expr = selem->expr;
275  Oid atttype;
276 
277  Assert(expr != NULL);
278 
279  /*
280  * Disallow data types without a less-than operator.
281  *
282  * We ignore this for statistics on a single expression, in which
283  * case we'll build the regular statistics only (and that code can
284  * deal with such data types).
285  */
286  if (list_length(stmt->exprs) > 1)
287  {
288  atttype = exprType(expr);
289  type = lookup_type_cache(atttype, TYPECACHE_LT_OPR);
290  if (type->lt_opr == InvalidOid)
291  ereport(ERROR,
292  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
293  errmsg("expression cannot be used in multivariate statistics because its type %s has no default btree operator class",
294  format_type_be(atttype))));
295  }
296 
297  stxexprs = lappend(stxexprs, expr);
298  }
299  }
300 
301  /*
302  * Parse the statistics kinds.
303  *
304  * First check that if this is the case with a single expression, there
305  * are no statistics kinds specified (we don't allow that for the simple
306  * CREATE STATISTICS form).
307  */
308  if ((list_length(stmt->exprs) == 1) && (list_length(stxexprs) == 1))
309  {
310  /* statistics kinds not specified */
311  if (list_length(stmt->stat_types) > 0)
312  ereport(ERROR,
313  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
314  errmsg("when building statistics on a single expression, statistics kinds may not be specified")));
315  }
316 
317  /* OK, let's check that we recognize the statistics kinds. */
318  build_ndistinct = false;
319  build_dependencies = false;
320  build_mcv = false;
321  foreach(cell, stmt->stat_types)
322  {
323  char *type = strVal((Value *) lfirst(cell));
324 
325  if (strcmp(type, "ndistinct") == 0)
326  {
327  build_ndistinct = true;
328  requested_type = true;
329  }
330  else if (strcmp(type, "dependencies") == 0)
331  {
332  build_dependencies = true;
333  requested_type = true;
334  }
335  else if (strcmp(type, "mcv") == 0)
336  {
337  build_mcv = true;
338  requested_type = true;
339  }
340  else
341  ereport(ERROR,
342  (errcode(ERRCODE_SYNTAX_ERROR),
343  errmsg("unrecognized statistics kind \"%s\"",
344  type)));
345  }
346 
347  /*
348  * If no statistic type was specified, build them all (but only when the
349  * statistics is defined on more than one column/expression).
350  */
351  if ((!requested_type) && (numcols >= 2))
352  {
353  build_ndistinct = true;
354  build_dependencies = true;
355  build_mcv = true;
356  }
357 
358  /*
359  * When there are non-trivial expressions, build the expression stats
360  * automatically. This allows calculating good estimates for stats that
361  * consider per-clause estimates (e.g. functional dependencies).
362  */
363  build_expressions = (list_length(stxexprs) > 0);
364 
365  /*
366  * Check that at least two columns were specified in the statement, or
367  * that we're building statistics on a single expression.
368  */
369  if ((numcols < 2) && (list_length(stxexprs) != 1))
370  ereport(ERROR,
371  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
372  errmsg("extended statistics require at least 2 columns")));
373 
374  /*
375  * Sort the attnums, which makes detecting duplicates somewhat easier, and
376  * it does not hurt (it does not matter for the contents, unlike for
377  * indexes, for example).
378  */
379  qsort(attnums, nattnums, sizeof(int16), compare_int16);
380 
381  /*
382  * Check for duplicates in the list of columns. The attnums are sorted so
383  * just check consecutive elements.
384  */
385  for (i = 1; i < nattnums; i++)
386  {
387  if (attnums[i] == attnums[i - 1])
388  ereport(ERROR,
389  (errcode(ERRCODE_DUPLICATE_COLUMN),
390  errmsg("duplicate column name in statistics definition")));
391  }
392 
393  /*
394  * Check for duplicate expressions. We do two loops, counting the
395  * occurrences of each expression. This is O(N^2) but we only allow small
396  * number of expressions and it's not executed often.
397  *
398  * XXX We don't cross-check attributes and expressions, because it does
399  * not seem worth it. In principle we could check that expressions don't
400  * contain trivial attribute references like "(a)", but the reasoning is
401  * similar to why we don't bother with extracting columns from
402  * expressions. It's either expensive or very easy to defeat for
403  * determined user, and there's no risk if we allow such statistics (the
404  * statistics is useless, but harmless).
405  */
406  foreach(cell, stxexprs)
407  {
408  Node *expr1 = (Node *) lfirst(cell);
409  int cnt = 0;
410 
411  foreach(cell2, stxexprs)
412  {
413  Node *expr2 = (Node *) lfirst(cell2);
414 
415  if (equal(expr1, expr2))
416  cnt += 1;
417  }
418 
419  /* every expression should find at least itself */
420  Assert(cnt >= 1);
421 
422  if (cnt > 1)
423  ereport(ERROR,
424  (errcode(ERRCODE_DUPLICATE_COLUMN),
425  errmsg("duplicate expression in statistics definition")));
426  }
427 
428  /* Form an int2vector representation of the sorted column list */
429  stxkeys = buildint2vector(attnums, nattnums);
430 
431  /* construct the char array of enabled statistic types */
432  ntypes = 0;
433  if (build_ndistinct)
434  types[ntypes++] = CharGetDatum(STATS_EXT_NDISTINCT);
435  if (build_dependencies)
436  types[ntypes++] = CharGetDatum(STATS_EXT_DEPENDENCIES);
437  if (build_mcv)
438  types[ntypes++] = CharGetDatum(STATS_EXT_MCV);
439  if (build_expressions)
440  types[ntypes++] = CharGetDatum(STATS_EXT_EXPRESSIONS);
441  Assert(ntypes > 0 && ntypes <= lengthof(types));
442  stxkind = construct_array(types, ntypes, CHAROID, 1, true, TYPALIGN_CHAR);
443 
444  /* convert the expressions (if any) to a text datum */
445  if (stxexprs != NIL)
446  {
447  char *exprsString;
448 
449  exprsString = nodeToString(stxexprs);
450  exprsDatum = CStringGetTextDatum(exprsString);
451  pfree(exprsString);
452  }
453  else
454  exprsDatum = (Datum) 0;
455 
456  statrel = table_open(StatisticExtRelationId, RowExclusiveLock);
457 
458  /*
459  * Everything seems fine, so let's build the pg_statistic_ext tuple.
460  */
461  memset(values, 0, sizeof(values));
462  memset(nulls, false, sizeof(nulls));
463 
464  statoid = GetNewOidWithIndex(statrel, StatisticExtOidIndexId,
465  Anum_pg_statistic_ext_oid);
466  values[Anum_pg_statistic_ext_oid - 1] = ObjectIdGetDatum(statoid);
467  values[Anum_pg_statistic_ext_stxrelid - 1] = ObjectIdGetDatum(relid);
468  values[Anum_pg_statistic_ext_stxname - 1] = NameGetDatum(&stxname);
469  values[Anum_pg_statistic_ext_stxnamespace - 1] = ObjectIdGetDatum(namespaceId);
470  values[Anum_pg_statistic_ext_stxstattarget - 1] = Int32GetDatum(-1);
471  values[Anum_pg_statistic_ext_stxowner - 1] = ObjectIdGetDatum(stxowner);
472  values[Anum_pg_statistic_ext_stxkeys - 1] = PointerGetDatum(stxkeys);
473  values[Anum_pg_statistic_ext_stxkind - 1] = PointerGetDatum(stxkind);
474 
475  values[Anum_pg_statistic_ext_stxexprs - 1] = exprsDatum;
476  if (exprsDatum == (Datum) 0)
477  nulls[Anum_pg_statistic_ext_stxexprs - 1] = true;
478 
479  /* insert it into pg_statistic_ext */
480  htup = heap_form_tuple(statrel->rd_att, values, nulls);
481  CatalogTupleInsert(statrel, htup);
482  heap_freetuple(htup);
483 
485 
486  /*
487  * Also build the pg_statistic_ext_data tuple, to hold the actual
488  * statistics data.
489  */
490  datarel = table_open(StatisticExtDataRelationId, RowExclusiveLock);
491 
492  memset(datavalues, 0, sizeof(datavalues));
493  memset(datanulls, false, sizeof(datanulls));
494 
495  datavalues[Anum_pg_statistic_ext_data_stxoid - 1] = ObjectIdGetDatum(statoid);
496 
497  /* no statistics built yet */
498  datanulls[Anum_pg_statistic_ext_data_stxdndistinct - 1] = true;
499  datanulls[Anum_pg_statistic_ext_data_stxddependencies - 1] = true;
500  datanulls[Anum_pg_statistic_ext_data_stxdmcv - 1] = true;
501  datanulls[Anum_pg_statistic_ext_data_stxdexpr - 1] = true;
502 
503  /* insert it into pg_statistic_ext_data */
504  htup = heap_form_tuple(datarel->rd_att, datavalues, datanulls);
505  CatalogTupleInsert(datarel, htup);
506  heap_freetuple(htup);
507 
509 
510  InvokeObjectPostCreateHook(StatisticExtRelationId, statoid, 0);
511 
512  /*
513  * Invalidate relcache so that others see the new statistics object.
514  */
516 
517  relation_close(rel, NoLock);
518 
519  /*
520  * Add an AUTO dependency on each column used in the stats, so that the
521  * stats object goes away if any or all of them get dropped.
522  */
523  ObjectAddressSet(myself, StatisticExtRelationId, statoid);
524 
525  /* add dependencies for plain column references */
526  for (i = 0; i < nattnums; i++)
527  {
528  ObjectAddressSubSet(parentobject, RelationRelationId, relid, attnums[i]);
529  recordDependencyOn(&myself, &parentobject, DEPENDENCY_AUTO);
530  }
531 
532  /*
533  * If there are no dependencies on a column, give the statistics an auto
534  * dependency on the whole table. In most cases, this will be redundant,
535  * but it might not be if the statistics expressions contain no Vars
536  * (which might seem strange but possible). This is consistent with what
537  * we do for indexes in index_create.
538  *
539  * XXX We intentionally don't consider the expressions before adding this
540  * dependency, because recordDependencyOnSingleRelExpr may not create any
541  * dependencies for whole-row Vars.
542  */
543  if (!nattnums)
544  {
545  ObjectAddressSet(parentobject, RelationRelationId, relid);
546  recordDependencyOn(&myself, &parentobject, DEPENDENCY_AUTO);
547  }
548 
549  /*
550  * Store dependencies on anything mentioned in statistics expressions,
551  * just like we do for index expressions.
552  */
553  if (stxexprs)
555  (Node *) stxexprs,
556  relid,
558  DEPENDENCY_AUTO, false);
559 
560  /*
561  * Also add dependencies on namespace and owner. These are required
562  * because the stats object might have a different namespace and/or owner
563  * than the underlying table(s).
564  */
565  ObjectAddressSet(parentobject, NamespaceRelationId, namespaceId);
566  recordDependencyOn(&myself, &parentobject, DEPENDENCY_NORMAL);
567 
568  recordDependencyOnOwner(StatisticExtRelationId, statoid, stxowner);
569 
570  /*
571  * XXX probably there should be a recordDependencyOnCurrentExtension call
572  * here too, but we'd have to add support for ALTER EXTENSION ADD/DROP
573  * STATISTICS, which is more work than it seems worth.
574  */
575 
576  /* Add any requested comment */
577  if (stmt->stxcomment != NULL)
578  CreateComments(statoid, StatisticExtRelationId, 0,
579  stmt->stxcomment);
580 
581  /* Return stats object's address */
582  return myself;
583 }
signed short int16
Definition: c.h:428
#define NIL
Definition: pg_list.h:65
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:322
void CreateComments(Oid oid, Oid classoid, int32 subid, const char *comment)
Definition: comment.c:142
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
#define NameGetDatum(X)
Definition: postgres.h:639
static char * ChooseExtendedStatisticName(const char *name1, const char *name2, const char *label, Oid namespaceid)
Definition: statscmds.c:757
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
bool IsSystemRelation(Relation relation)
Definition: catalog.c:73
char * name
Definition: parsenodes.h:2918
struct typedefs * types
Definition: ecpg.c:29
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3113
Oid GetUserId(void)
Definition: miscinit.c:478
void namestrcpy(Name name, const char *str)
Definition: name.c:233
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2994
#define PointerGetDatum(X)
Definition: postgres.h:600
#define StatisticExtOidIndexId
int2vector * buildint2vector(const int16 *int2s, int n)
Definition: int.c:114
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3318
Definition: nodes.h:539
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
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
#define lengthof(array)
Definition: c.h:734
Form_pg_class rd_rel
Definition: rel.h:109
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:3313
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
NameData attname
Definition: pg_attribute.h:41
Node * expr
Definition: parsenodes.h:2919
Definition: c.h:675
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:622
#define RelationGetRelationName(relation)
Definition: rel.h:503
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
static int compare_int16(const void *a, const void *b)
Definition: statscmds.c:51
List * lappend(List *list, void *datum)
Definition: list.c:336
Definition: c.h:649
uintptr_t Datum
Definition: postgres.h:411
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: relation.c:138
TupleDesc rd_att
Definition: rel.h:110
bool allowSystemTableMods
Definition: globals.c:123
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:338
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
#define NOTICE
Definition: elog.h:37
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
Definition: value.h:42
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4823
static char * ChooseExtendedStatisticNameAddition(List *exprs)
Definition: statscmds.c:799
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool reverse_self)
Definition: dependency.c:1621
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
static int list_length(const List *l)
Definition: pg_list.h:149
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition: syscache.h:186
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1268
#define ObjectAddressSubSet(addr, class_id, object_id, object_sub_id)
Definition: objectaddress.h:33
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define CharGetDatum(X)
Definition: postgres.h:460
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1279
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define Int32GetDatum(X)
Definition: postgres.h:523
#define STATS_MAX_DIMENSIONS
Definition: statistics.h:19
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i
ObjectType get_relkind_objtype(char relkind)
#define TYPECACHE_LT_OPR
Definition: typcache.h:137
#define CStringGetTextDatum(s)
Definition: builtins.h:82
char * nodeToString(const void *obj)
Definition: outfuncs.c:4527
#define qsort(a, b, c, d)
Definition: port.h:504
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:469
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
#define RelationGetNamespace(relation)
Definition: rel.h:510

◆ CreateTransform()

ObjectAddress CreateTransform ( CreateTransformStmt stmt)

Definition at line 1792 of file functioncmds.c.

References ACL_EXECUTE, ACL_USAGE, aclcheck_error(), aclcheck_error_type(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, add_exact_object_address(), CatalogTupleInsert(), CatalogTupleUpdate(), check_transform_function(), deleteDependencyRecordsFor(), DEPENDENCY_NORMAL, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, format_type_be(), free_object_addresses(), CreateTransformStmt::fromsql, get_language_oid(), get_typtype(), GetNewOidWithIndex(), GETSTRUCT, GetUserId(), heap_form_tuple(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, InvalidOid, InvokeObjectPostCreateHook, CreateTransformStmt::lang, LookupFuncWithArgs(), MemSet, NameListToString(), new_object_addresses(), OBJECT_FUNCTION, OBJECT_LANGUAGE, ObjectAddressSet, ObjectIdGetDatum, ObjectWithArgs::objname, OidIsValid, pg_language_aclcheck(), pg_proc_aclcheck(), pg_proc_ownercheck(), pg_type_aclcheck(), pg_type_ownercheck(), PROCOID, record_object_address_dependencies(), recordDependencyOnCurrentExtension(), RelationGetDescr, ReleaseSysCache(), CreateTransformStmt::replace, RowExclusiveLock, SearchSysCache1(), SearchSysCache2(), HeapTupleData::t_self, table_close(), table_open(), CreateTransformStmt::tosql, TransformOidIndexId, TRFTYPELANG, CreateTransformStmt::type_name, TypeNameToString(), typenameTypeId(), and values.

Referenced by ProcessUtilitySlow().

1793 {
1794  Oid typeid;
1795  char typtype;
1796  Oid langid;
1797  Oid fromsqlfuncid;
1798  Oid tosqlfuncid;
1799  AclResult aclresult;
1800  Form_pg_proc procstruct;
1801  Datum values[Natts_pg_transform];
1802  bool nulls[Natts_pg_transform];
1803  bool replaces[Natts_pg_transform];
1804  Oid transformid;
1805  HeapTuple tuple;
1806  HeapTuple newtuple;
1807  Relation relation;
1808  ObjectAddress myself,
1809  referenced;
1810  ObjectAddresses *addrs;
1811  bool is_replace;
1812 
1813  /*
1814  * Get the type
1815  */
1816  typeid = typenameTypeId(NULL, stmt->type_name);
1817  typtype = get_typtype(typeid);
1818 
1819  if (typtype == TYPTYPE_PSEUDO)
1820  ereport(ERROR,
1821  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1822  errmsg("data type %s is a pseudo-type",
1823  TypeNameToString(stmt->type_name))));
1824 
1825  if (typtype == TYPTYPE_DOMAIN)
1826  ereport(ERROR,
1827  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1828  errmsg("data type %s is a domain",
1829  TypeNameToString(stmt->type_name))));
1830 
1831  if (!pg_type_ownercheck(typeid, GetUserId()))
1833 
1834  aclresult = pg_type_aclcheck(typeid, GetUserId(), ACL_USAGE);
1835  if (aclresult != ACLCHECK_OK)
1836  aclcheck_error_type(aclresult, typeid);
1837 
1838  /*
1839  * Get the language
1840  */
1841  langid = get_language_oid(stmt->lang, false);
1842 
1843  aclresult = pg_language_aclcheck(langid, GetUserId(), ACL_USAGE);
1844  if (aclresult != ACLCHECK_OK)
1845  aclcheck_error(aclresult, OBJECT_LANGUAGE, stmt->lang);
1846 
1847  /*
1848  * Get the functions
1849  */
1850  if (stmt->fromsql)
1851  {
1852  fromsqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->fromsql, false);
1853 
1854  if (!pg_proc_ownercheck(fromsqlfuncid, GetUserId()))
1856 
1857  aclresult = pg_proc_aclcheck(fromsqlfuncid, GetUserId(), ACL_EXECUTE);
1858  if (aclresult != ACLCHECK_OK)
1860 
1861  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fromsqlfuncid));
1862  if (!HeapTupleIsValid(tuple))
1863  elog(ERROR, "cache lookup failed for function %u", fromsqlfuncid);
1864  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1865  if (procstruct->prorettype != INTERNALOID)
1866  ereport(ERROR,
1867  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1868  errmsg("return data type of FROM SQL function must be %s",
1869  "internal")));
1870  check_transform_function(procstruct);
1871  ReleaseSysCache(tuple);
1872  }
1873  else
1874  fromsqlfuncid = InvalidOid;
1875 
1876  if (stmt->tosql)
1877  {
1878  tosqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->tosql, false);
1879 
1880  if (!pg_proc_ownercheck(tosqlfuncid, GetUserId()))
1882 
1883  aclresult = pg_proc_aclcheck(tosqlfuncid, GetUserId(), ACL_EXECUTE);
1884  if (aclresult != ACLCHECK_OK)
1886 
1887  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(tosqlfuncid));
1888  if (!HeapTupleIsValid(tuple))
1889  elog(ERROR, "cache lookup failed for function %u", tosqlfuncid);
1890  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1891  if (procstruct->prorettype != typeid)
1892  ereport(ERROR,
1893  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1894  errmsg("return data type of TO SQL function must be the transform data type")));
1895  check_transform_function(procstruct);
1896  ReleaseSysCache(tuple);
1897  }
1898  else
1899  tosqlfuncid = InvalidOid;
1900 
1901  /*
1902  * Ready to go
1903  */
1904  values[Anum_pg_transform_trftype - 1] = ObjectIdGetDatum(typeid);
1905  values[Anum_pg_transform_trflang - 1] = ObjectIdGetDatum(langid);
1906  values[Anum_pg_transform_trffromsql - 1] = ObjectIdGetDatum(fromsqlfuncid);
1907  values[Anum_pg_transform_trftosql - 1] = ObjectIdGetDatum(tosqlfuncid);
1908 
1909  MemSet(nulls, false, sizeof(nulls));
1910 
1911  relation = table_open(TransformRelationId, RowExclusiveLock);
1912 
1913  tuple = SearchSysCache2(TRFTYPELANG,
1914  ObjectIdGetDatum(typeid),
1915  ObjectIdGetDatum(langid));
1916  if (HeapTupleIsValid(tuple))
1917  {
1919 
1920  if (!stmt->replace)
1921  ereport(ERROR,
1923  errmsg("transform for type %s language \"%s\" already exists",
1924  format_type_be(typeid),
1925  stmt->lang)));
1926 
1927  MemSet(replaces, false, sizeof(replaces));
1928  replaces[Anum_pg_transform_trffromsql - 1] = true;
1929  replaces[Anum_pg_transform_trftosql - 1] = true;
1930 
1931  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
1932  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
1933 
1934  transformid = form->oid;
1935  ReleaseSysCache(tuple);
1936  is_replace = true;
1937  }
1938  else
1939  {
1940  transformid = GetNewOidWithIndex(relation, TransformOidIndexId,
1941  Anum_pg_transform_oid);
1942  values[Anum_pg_transform_oid - 1] = ObjectIdGetDatum(transformid);
1943  newtuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
1944  CatalogTupleInsert(relation, newtuple);
1945  is_replace = false;
1946  }
1947 
1948  if (is_replace)
1949  deleteDependencyRecordsFor(TransformRelationId, transformid, true);
1950 
1951  addrs = new_object_addresses();
1952 
1953  /* make dependency entries */
1954  ObjectAddressSet(myself, TransformRelationId, transformid);
1955 
1956  /* dependency on language */
1957  ObjectAddressSet(referenced, LanguageRelationId, langid);
1958  add_exact_object_address(&referenced, addrs);
1959 
1960  /* dependency on type */
1961  ObjectAddressSet(referenced, TypeRelationId, typeid);
1962  add_exact_object_address(&referenced, addrs);
1963 
1964  /* dependencies on functions */
1965  if (OidIsValid(fromsqlfuncid))
1966  {
1967  ObjectAddressSet(referenced, ProcedureRelationId, fromsqlfuncid);
1968  add_exact_object_address(&referenced, addrs);
1969  }
1970  if (OidIsValid(tosqlfuncid))
1971  {
1972  ObjectAddressSet(referenced, ProcedureRelationId, tosqlfuncid);
1973  add_exact_object_address(&referenced, addrs);
1974  }
1975 
1977  free_object_addresses(addrs);
1978 
1979  /* dependency on extension */
1980  recordDependencyOnCurrentExtension(&myself, is_replace);
1981 
1982  /* Post creation hook for new transform */
1983  InvokeObjectPostCreateHook(TransformRelationId, transformid, 0);
1984 
1985  heap_freetuple(newtuple);
1986 
1987  table_close(relation, RowExclusiveLock);
1988 
1989  return myself;
1990 }
#define TransformOidIndexId
Definition: pg_transform.h:46
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:322
ObjectWithArgs * tosql
Definition: parsenodes.h:3508
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
static void check_transform_function(Form_pg_proc procstruct)
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
#define RelationGetDescr(relation)
Definition: rel.h:495
Oid GetUserId(void)
Definition: miscinit.c:478
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:476
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2701
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:232
Oid get_language_oid(const char *langname, bool missing_ok)
Definition: proclang.c:228
int errcode(int sqlerrcode)
Definition: elog.c:698
char get_typtype(Oid typid)
Definition: lsyscache.c:2576
#define MemSet(start, val, len)
Definition: c.h:1008
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2492
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2437
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2732
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
bool pg_type_ownercheck(Oid type_oid, Oid roleid)
Definition: aclchk.c:4849
#define OidIsValid(objectId)
Definition: c.h:710
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4735
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3626
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3313
FormData_pg_transform * Form_pg_transform
Definition: pg_transform.h:43
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ACL_USAGE
Definition: parsenodes.h:90
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
char * NameListToString(List *names)
Definition: namespace.c:3101
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:411
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
#define InvalidOid
Definition: postgres_ext.h:36
ObjectWithArgs * fromsql
Definition: parsenodes.h:3507
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:180
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1138
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
TypeName * type_name
Definition: parsenodes.h:3505
static Datum values[MAXATTR]
Definition: bootstrap.c:166
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define ACL_EXECUTE
Definition: parsenodes.h:89
#define elog(elevel,...)
Definition: elog.h:232
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4723
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2177
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4811
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 ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
bool pg_proc_ownercheck(Oid proc_oid, Oid roleid)
Definition: aclchk.c:4901
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:291

◆ CreateUserMapping()

ObjectAddress CreateUserMapping ( CreateUserMappingStmt stmt)

Definition at line 1095 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().

1096 {
1097  Relation rel;
1098  Datum useoptions;
1099  Datum values[Natts_pg_user_mapping];
1100  bool nulls[Natts_pg_user_mapping];
1101  HeapTuple tuple;
1102  Oid useId;
1103  Oid umId;
1104  ObjectAddress myself;
1105  ObjectAddress referenced;
1106  ForeignServer *srv;
1107  ForeignDataWrapper *fdw;
1108  RoleSpec *role = (RoleSpec *) stmt->user;
1109 
1110  rel = table_open(UserMappingRelationId, RowExclusiveLock);
1111 
1112  if (role->roletype == ROLESPEC_PUBLIC)
1113  useId = ACL_ID_PUBLIC;
1114  else
1115  useId = get_rolespec_oid(stmt->user, false);
1116 
1117  /* Check that the server exists. */
1118  srv = GetForeignServerByName(stmt->servername, false);
1119 
1120  user_mapping_ddl_aclcheck(useId, srv->serverid, stmt->servername);
1121 
1122  /*
1123  * Check that the user mapping is unique within server.
1124  */
1125  umId = GetSysCacheOid2(USERMAPPINGUSERSERVER, Anum_pg_user_mapping_oid,
1126  ObjectIdGetDatum(useId),
1127  ObjectIdGetDatum(srv->serverid));
1128 
1129  if (OidIsValid(umId))
1130  {
1131  if (stmt->if_not_exists)
1132  {
1133  ereport(NOTICE,
1135  errmsg("user mapping for \"%s\" already exists for server \"%s\", skipping",
1136  MappingUserName(useId),
1137  stmt->servername)));
1138 
1140  return InvalidObjectAddress;
1141  }
1142  else
1143  ereport(ERROR,
1145  errmsg("user mapping for \"%s\" already exists for server \"%s\"",
1146  MappingUserName(useId),
1147  stmt->servername)));
1148  }
1149 
1150  fdw = GetForeignDataWrapper(srv->fdwid);
1151 
1152  /*
1153  * Insert tuple into pg_user_mapping.
1154  */
1155  memset(values, 0, sizeof(values));
1156  memset(nulls, false, sizeof(nulls));
1157 
1159  Anum_pg_user_mapping_oid);
1160  values[Anum_pg_user_mapping_oid - 1] = ObjectIdGetDatum(umId);
1161  values[Anum_pg_user_mapping_umuser - 1] = ObjectIdGetDatum(useId);
1162  values[Anum_pg_user_mapping_umserver - 1] = ObjectIdGetDatum(srv->serverid);
1163 
1164  /* Add user options */
1165  useoptions = transformGenericOptions(UserMappingRelationId,
1166  PointerGetDatum(NULL),
1167  stmt->options,
1168  fdw->fdwvalidator);
1169 
1170  if (PointerIsValid(DatumGetPointer(useoptions)))
1171  values[Anum_pg_user_mapping_umoptions - 1] = useoptions;
1172  else
1173  nulls[Anum_pg_user_mapping_umoptions - 1] = true;
1174 
1175  tuple = heap_form_tuple(rel->rd_att, values, nulls);
1176 
1177  CatalogTupleInsert(rel, tuple);
1178 
1179  heap_freetuple(tuple);
1180 
1181  /* Add dependency on the server */
1182  myself.classId = UserMappingRelationId;
1183  myself.objectId = umId;
1184  myself.objectSubId = 0;
1185 
1186  referenced.classId = ForeignServerRelationId;
1187  referenced.objectId = srv->serverid;
1188  referenced.objectSubId = 0;
1189  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1190 
1191  if (OidIsValid(useId))
1192  {
1193  /* Record the mapped user dependency */
1194  recordDependencyOnOwner(UserMappingRelationId, umId, useId);
1195  }
1196 
1197  /*
1198  * Perhaps someday there should be a recordDependencyOnCurrentExtension
1199  * call here; but since roles aren't members of extensions, it seems like
1200  * user mappings shouldn't be either. Note that the grammar and pg_dump
1201  * would need to be extended too if we change this.
1202  */
1203 
1204  /* Post creation hook for new user mapping */
1205  InvokeObjectPostCreateHook(UserMappingRelationId, umId, 0);
1206 
1208 
1209  return myself;
1210 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:322
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:110
#define PointerGetDatum(X)
Definition: postgres.h:600
int errcode(int sqlerrcode)
Definition: