PostgreSQL Source Code  git master
defrem.h File Reference
#include "catalog/objectaddress.h"
#include "nodes/params.h"
#include "nodes/parsenodes.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 ReindexIndex (RangeVar *indexRelation, int options, bool concurrent)
 
Oid ReindexTable (RangeVar *relation, int options, bool concurrent)
 
void ReindexMultipleTables (const char *objectName, ReindexObjectType objectKind, int options, bool concurrent)
 
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)
 
void SetFunctionReturnType (Oid funcOid, Oid newRetType)
 
void SetFunctionArgType (Oid funcOid, int argIndex, Oid newArgType)
 
ObjectAddress AlterFunction (ParseState *pstate, AlterFunctionStmt *stmt)
 
ObjectAddress CreateCast (CreateCastStmt *stmt)
 
void DropCastById (Oid castOid)
 
ObjectAddress CreateTransform (CreateTransformStmt *stmt)
 
void DropTransformById (Oid transformOid)
 
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_cast_oid (Oid sourcetypeid, Oid targettypeid, bool missing_ok)
 
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, ArrayType **allParameterTypes, ArrayType **parameterModes, ArrayType **parameterNames, 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)
 
void UpdateStatisticsForTypeChange (Oid statsOid, Oid relationOid, int attnum, Oid oldColumnType, Oid newColumnType)
 
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 RemoveOpClassById (Oid opclassOid)
 
void RemoveOpFamilyById (Oid opfamilyOid)
 
void RemoveAmOpEntryById (Oid entryOid)
 
void RemoveAmProcEntryById (Oid entryOid)
 
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)
 
void RemoveTSParserById (Oid prsId)
 
ObjectAddress DefineTSDictionary (List *names, List *parameters)
 
void RemoveTSDictionaryById (Oid dictId)
 
ObjectAddress AlterTSDictionary (AlterTSDictionaryStmt *stmt)
 
ObjectAddress DefineTSTemplate (List *names, List *parameters)
 
void RemoveTSTemplateById (Oid tmplId)
 
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)
 
void RemoveForeignDataWrapperById (Oid fdwId)
 
ObjectAddress CreateForeignServer (CreateForeignServerStmt *stmt)
 
ObjectAddress AlterForeignServer (AlterForeignServerStmt *stmt)
 
void RemoveForeignServerById (Oid srvId)
 
ObjectAddress CreateUserMapping (CreateUserMappingStmt *stmt)
 
ObjectAddress AlterUserMapping (AlterUserMappingStmt *stmt)
 
Oid RemoveUserMapping (DropUserMappingStmt *stmt)
 
void RemoveUserMappingById (Oid umId)
 
void CreateForeignTable (CreateForeignTableStmt *stmt, Oid relid)
 
void ImportForeignSchema (ImportForeignSchemaStmt *stmt)
 
Datum transformGenericOptions (Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
 
ObjectAddress CreateAccessMethod (CreateAmStmt *stmt)
 
void RemoveAccessMethodById (Oid amOid)
 
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:133
int errhint(const char *fmt,...)
Definition: elog.c:1071
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
static void parse_func_options(List *func_options, bool *handler_given, Oid *fdwhandler, bool *validator_given, Oid *fdwvalidator)
Definition: foreigncmds.c:518
#define RelationGetDescr(relation)
Definition: rel.h:449
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:110
#define PointerGetDatum(X)
Definition: postgres.h:556
int errcode(int sqlerrcode)
Definition: elog.c:608
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:639
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:578
char * fdwname
Definition: parsenodes.h:2263
#define ereport(elevel, rest)
Definition: elog.h:141
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
List * func_options
Definition: parsenodes.h:2264
#define WARNING
Definition: elog.h:40
uintptr_t Datum
Definition: postgres.h:367
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1377
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:240
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_foreign_data_wrapper * Form_pg_foreign_data_wrapper
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define DatumGetPointer(X)
Definition: postgres.h:549
List * options
Definition: parsenodes.h:2265
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
int errmsg(const char *fmt,...)
Definition: elog.c:822
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:627

◆ AlterForeignDataWrapperOwner()

ObjectAddress AlterForeignDataWrapperOwner ( const char *  name,
Oid  newOwnerId 
)

Definition at line 275 of file foreigncmds.c.

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

Referenced by ExecAlterOwnerStmt().

276 {
277  Oid fdwId;
278  HeapTuple tup;
279  Relation rel;
280  ObjectAddress address;
282 
283 
284  rel = table_open(ForeignDataWrapperRelationId, RowExclusiveLock);
285 
287 
288  if (!HeapTupleIsValid(tup))
289  ereport(ERROR,
290  (errcode(ERRCODE_UNDEFINED_OBJECT),
291  errmsg("foreign-data wrapper \"%s\" does not exist", name)));
292 
294  fdwId = form->oid;
295 
296  AlterForeignDataWrapperOwner_internal(rel, tup, newOwnerId);
297 
298  ObjectAddressSet(address, ForeignDataWrapperRelationId, fdwId);
299 
300  heap_freetuple(tup);
301 
303 
304  return address;
305 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
int errcode(int sqlerrcode)
Definition: elog.c:608
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:578
#define ereport(elevel, rest)
Definition: elog.h:141
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_foreign_data_wrapper * Form_pg_foreign_data_wrapper
const char * name
Definition: encode.c:521
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
int errmsg(const char *fmt,...)
Definition: elog.c:822
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:133
int errcode(int sqlerrcode)
Definition: elog.c:608
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:141
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
int errmsg(const char *fmt,...)
Definition: elog.c:822
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 993 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().

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

◆ AlterForeignServerOwner()

ObjectAddress AlterForeignServerOwner ( const char *  name,
Oid  newOwnerId 
)

Definition at line 415 of file foreigncmds.c.

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

Referenced by ExecAlterOwnerStmt().

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

◆ AlterFunction()

ObjectAddress AlterFunction ( ParseState pstate,
AlterFunctionStmt stmt 
)

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

1234 {
1235  HeapTuple tup;
1236  Oid funcOid;
1237  Form_pg_proc procForm;
1238  bool is_procedure;
1239  Relation rel;
1240  ListCell *l;
1241  DefElem *volatility_item = NULL;
1242  DefElem *strict_item = NULL;
1243  DefElem *security_def_item = NULL;
1244  DefElem *leakproof_item = NULL;
1245  List *set_items = NIL;
1246  DefElem *cost_item = NULL;
1247  DefElem *rows_item = NULL;
1248  DefElem *support_item = NULL;
1249  DefElem *parallel_item = NULL;
1250  ObjectAddress address;
1251 
1252  rel = table_open(ProcedureRelationId, RowExclusiveLock);
1253 
1254  funcOid = LookupFuncWithArgs(stmt->objtype, stmt->func, false);
1255 
1256  ObjectAddressSet(address, ProcedureRelationId, funcOid);
1257 
1258  tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1259  if (!HeapTupleIsValid(tup)) /* should not happen */
1260  elog(ERROR, "cache lookup failed for function %u", funcOid);
1261 
1262  procForm = (Form_pg_proc) GETSTRUCT(tup);
1263 
1264  /* Permission check: must own function */
1265  if (!pg_proc_ownercheck(funcOid, GetUserId()))
1267  NameListToString(stmt->func->objname));
1268 
1269  if (procForm->prokind == PROKIND_AGGREGATE)
1270  ereport(ERROR,
1271  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1272  errmsg("\"%s\" is an aggregate function",
1273  NameListToString(stmt->func->objname))));
1274 
1275  is_procedure = (procForm->prokind == PROKIND_PROCEDURE);
1276 
1277  /* Examine requested actions. */
1278  foreach(l, stmt->actions)
1279  {
1280  DefElem *defel = (DefElem *) lfirst(l);
1281 
1282  if (compute_common_attribute(pstate,
1283  is_procedure,
1284  defel,
1285  &volatility_item,
1286  &strict_item,
1287  &security_def_item,
1288  &leakproof_item,
1289  &set_items,
1290  &cost_item,
1291  &rows_item,
1292  &support_item,
1293  &parallel_item) == false)
1294  elog(ERROR, "option \"%s\" not recognized", defel->defname);
1295  }
1296 
1297  if (volatility_item)
1298  procForm->provolatile = interpret_func_volatility(volatility_item);
1299  if (strict_item)
1300  procForm->proisstrict = intVal(strict_item->arg);
1301  if (security_def_item)
1302  procForm->prosecdef = intVal(security_def_item->arg);
1303  if (leakproof_item)
1304  {
1305  procForm->proleakproof = intVal(leakproof_item->arg);
1306  if (procForm->proleakproof && !superuser())
1307  ereport(ERROR,
1308  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1309  errmsg("only superuser can define a leakproof function")));
1310  }
1311  if (cost_item)
1312  {
1313  procForm->procost = defGetNumeric(cost_item);
1314  if (procForm->procost <= 0)
1315  ereport(ERROR,
1316  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1317  errmsg("COST must be positive")));
1318  }
1319  if (rows_item)
1320  {
1321  procForm->prorows = defGetNumeric(rows_item);
1322  if (procForm->prorows <= 0)
1323  ereport(ERROR,
1324  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1325  errmsg("ROWS must be positive")));
1326  if (!procForm->proretset)
1327  ereport(ERROR,
1328  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1329  errmsg("ROWS is not applicable when function does not return a set")));
1330  }
1331  if (support_item)
1332  {
1333  /* interpret_func_support handles the privilege check */
1334  Oid newsupport = interpret_func_support(support_item);
1335 
1336  /* Add or replace dependency on support function */
1337  if (OidIsValid(procForm->prosupport))
1338  changeDependencyFor(ProcedureRelationId, funcOid,
1339  ProcedureRelationId, procForm->prosupport,
1340  newsupport);
1341  else
1342  {
1343  ObjectAddress referenced;
1344 
1345  referenced.classId = ProcedureRelationId;
1346  referenced.objectId = newsupport;
1347  referenced.objectSubId = 0;
1348  recordDependencyOn(&address, &referenced, DEPENDENCY_NORMAL);
1349  }
1350 
1351  procForm->prosupport = newsupport;
1352  }
1353  if (set_items)
1354  {
1355  Datum datum;
1356  bool isnull;
1357  ArrayType *a;
1358  Datum repl_val[Natts_pg_proc];
1359  bool repl_null[Natts_pg_proc];
1360  bool repl_repl[Natts_pg_proc];
1361 
1362  /* extract existing proconfig setting */
1363  datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proconfig, &isnull);
1364  a = isnull ? NULL : DatumGetArrayTypeP(datum);
1365 
1366  /* update according to each SET or RESET item, left to right */
1367  a = update_proconfig_value(a, set_items);
1368 
1369  /* update the tuple */
1370  memset(repl_repl, false, sizeof(repl_repl));
1371  repl_repl[Anum_pg_proc_proconfig - 1] = true;
1372 
1373  if (a == NULL)
1374  {
1375  repl_val[Anum_pg_proc_proconfig - 1] = (Datum) 0;
1376  repl_null[Anum_pg_proc_proconfig - 1] = true;
1377  }
1378  else
1379  {
1380  repl_val[Anum_pg_proc_proconfig - 1] = PointerGetDatum(a);
1381  repl_null[Anum_pg_proc_proconfig - 1] = false;
1382  }
1383 
1384  tup = heap_modify_tuple(tup, RelationGetDescr(rel),
1385  repl_val, repl_null, repl_repl);
1386  }
1387  if (parallel_item)
1388  procForm->proparallel = interpret_func_parallel(parallel_item);
1389 
1390  /* Do the update */
1391  CatalogTupleUpdate(rel, &tup->t_self, tup);
1392 
1393  InvokeObjectPostAlterHook(ProcedureRelationId, funcOid, 0);
1394 
1395  table_close(rel, NoLock);
1396  heap_freetuple(tup);
1397 
1398  return address;
1399 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:449
Oid GetUserId(void)
Definition: miscinit.c:380
#define PointerGetDatum(X)
Definition: postgres.h:556
double defGetNumeric(DefElem *def)
Definition: define.c:85
int errcode(int sqlerrcode)
Definition: elog.c:608
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:639
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
static Oid interpret_func_support(DefElem *defel)
Definition: functioncmds.c:649
ItemPointerData t_self
Definition: htup.h:65
ObjectType objtype
Definition: parsenodes.h:2841
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:141
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
static char interpret_func_volatility(DefElem *defel)
Definition: functioncmds.c:581
Node * arg
Definition: parsenodes.h:731
char * NameListToString(List *names)
Definition: namespace.c:3094
uintptr_t Datum
Definition: postgres.h:367
static ArrayType * update_proconfig_value(ArrayType *a, List *set_items)
Definition: functioncmds.c:624
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1377
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:134
ObjectWithArgs * func
Definition: parsenodes.h:2842
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:190
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
#define intVal(v)
Definition: value.h:52
int errmsg(const char *fmt,...)
Definition: elog.c:822
long changeDependencyFor(Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
Definition: pg_depend.c:297
#define elog(elevel,...)
Definition: elog.h:228
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2161
char * defname
Definition: parsenodes.h:730
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:472
bool pg_proc_ownercheck(Oid proc_oid, Oid roleid)
Definition: aclchk.c:4832
static char interpret_func_parallel(DefElem *defel)
Definition: functioncmds.c:599
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ AlterOperator()

ObjectAddress AlterOperator ( AlterOperatorStmt stmt)

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

385 {
386  ObjectAddress address;
387  Oid oprId;
388  Relation catalog;
389  HeapTuple tup;
390  Form_pg_operator oprForm;
391  int i;
392  ListCell *pl;
393  Datum values[Natts_pg_operator];
394  bool nulls[Natts_pg_operator];
395  bool replaces[Natts_pg_operator];
396  List *restrictionName = NIL; /* optional restrict. sel. function */
397  bool updateRestriction = false;
398  Oid restrictionOid;
399  List *joinName = NIL; /* optional join sel. function */
400  bool updateJoin = false;
401  Oid joinOid;
402 
403  /* Look up the operator */
404  oprId = LookupOperWithArgs(stmt->opername, false);
405  catalog = table_open(OperatorRelationId, RowExclusiveLock);
407  if (!HeapTupleIsValid(tup))
408  elog(ERROR, "cache lookup failed for operator %u", oprId);
409  oprForm = (Form_pg_operator) GETSTRUCT(tup);
410 
411  /* Process options */
412  foreach(pl, stmt->options)
413  {
414  DefElem *defel = (DefElem *) lfirst(pl);
415  List *param;
416 
417  if (defel->arg == NULL)
418  param = NIL; /* NONE, removes the function */
419  else
420  param = defGetQualifiedName(defel);
421 
422  if (strcmp(defel->defname, "restrict") == 0)
423  {
424  restrictionName = param;
425  updateRestriction = true;
426  }
427  else if (strcmp(defel->defname, "join") == 0)
428  {
429  joinName = param;
430  updateJoin = true;
431  }
432 
433  /*
434  * The rest of the options that CREATE accepts cannot be changed.
435  * Check for them so that we can give a meaningful error message.
436  */
437  else if (strcmp(defel->defname, "leftarg") == 0 ||
438  strcmp(defel->defname, "rightarg") == 0 ||
439  strcmp(defel->defname, "function") == 0 ||
440  strcmp(defel->defname, "procedure") == 0 ||
441  strcmp(defel->defname, "commutator") == 0 ||
442  strcmp(defel->defname, "negator") == 0 ||
443  strcmp(defel->defname, "hashes") == 0 ||
444  strcmp(defel->defname, "merges") == 0)
445  {
446  ereport(ERROR,
447  (errcode(ERRCODE_SYNTAX_ERROR),
448  errmsg("operator attribute \"%s\" cannot be changed",
449  defel->defname)));
450  }
451  else
452  ereport(ERROR,
453  (errcode(ERRCODE_SYNTAX_ERROR),
454  errmsg("operator attribute \"%s\" not recognized",
455  defel->defname)));
456  }
457 
458  /* Check permissions. Must be owner. */
459  if (!pg_oper_ownercheck(oprId, GetUserId()))
461  NameStr(oprForm->oprname));
462 
463  /*
464  * Look up restriction and join estimators if specified
465  */
466  if (restrictionName)
467  restrictionOid = ValidateRestrictionEstimator(restrictionName);
468  else
469  restrictionOid = InvalidOid;
470  if (joinName)
471  joinOid = ValidateJoinEstimator(joinName);
472  else
473  joinOid = InvalidOid;
474 
475  /* Perform additional checks, like OperatorCreate does */
476  if (!(OidIsValid(oprForm->oprleft) && OidIsValid(oprForm->oprright)))
477  {
478  /* If it's not a binary op, these things mustn't be set: */
479  if (OidIsValid(joinOid))
480  ereport(ERROR,
481  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
482  errmsg("only binary operators can have join selectivity")));
483  }
484 
485  if (oprForm->oprresult != BOOLOID)
486  {
487  if (OidIsValid(restrictionOid))
488  ereport(ERROR,
489  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
490  errmsg("only boolean operators can have restriction selectivity")));
491  if (OidIsValid(joinOid))
492  ereport(ERROR,
493  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
494  errmsg("only boolean operators can have join selectivity")));
495  }
496 
497  /* Update the tuple */
498  for (i = 0; i < Natts_pg_operator; ++i)
499  {
500  values[i] = (Datum) 0;
501  replaces[i] = false;
502  nulls[i] = false;
503  }
504  if (updateRestriction)
505  {
506  replaces[Anum_pg_operator_oprrest - 1] = true;
507  values[Anum_pg_operator_oprrest - 1] = restrictionOid;
508  }
509  if (updateJoin)
510  {
511  replaces[Anum_pg_operator_oprjoin - 1] = true;
512  values[Anum_pg_operator_oprjoin - 1] = joinOid;
513  }
514 
515  tup = heap_modify_tuple(tup, RelationGetDescr(catalog),
516  values, nulls, replaces);
517 
518  CatalogTupleUpdate(catalog, &tup->t_self, tup);
519 
520  address = makeOperatorDependencies(tup, true);
521 
522  InvokeObjectPostAlterHook(OperatorRelationId, oprId, 0);
523 
524  table_close(catalog, NoLock);
525 
526  return address;
527 }
Oid LookupOperWithArgs(ObjectWithArgs *oper, bool noError)
Definition: parse_oper.c:140
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:449
Oid GetUserId(void)
Definition: miscinit.c:380
ObjectAddress makeOperatorDependencies(HeapTuple tuple, bool isUpdate)
Definition: pg_operator.c:773
static Oid ValidateJoinEstimator(List *joinName)
Definition: operatorcmds.c:295
bool pg_oper_ownercheck(Oid oper_oid, Oid roleid)
Definition: aclchk.c:4806
int errcode(int sqlerrcode)
Definition: elog.c:608
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:639
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:141
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
static Oid ValidateRestrictionEstimator(List *restrictionName)
Definition: operatorcmds.c:260
Node * arg
Definition: parsenodes.h:731
ObjectWithArgs * opername
Definition: parsenodes.h:2950
uintptr_t Datum
Definition: postgres.h:367
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:190
List * defGetQualifiedName(DefElem *def)
Definition: define.c:223
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:84
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
int i
#define NameStr(name)
Definition: c.h:610
char * defname
Definition: parsenodes.h:730
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 775 of file opclasscmds.c.

References AlterOpFamilyAdd(), AlterOpFamilyDrop(), AMNAME, AlterOpFamilyStmt::amname, 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().

776 {
777  Oid amoid, /* our AM's oid */
778  opfamilyoid; /* oid of opfamily */
779  int maxOpNumber, /* amstrategies value */
780  maxProcNumber; /* amsupport value */
781  HeapTuple tup;
782  Form_pg_am amform;
783  IndexAmRoutine *amroutine;
784 
785  /* Get necessary info about access method */
787  if (!HeapTupleIsValid(tup))
788  ereport(ERROR,
789  (errcode(ERRCODE_UNDEFINED_OBJECT),
790  errmsg("access method \"%s\" does not exist",
791  stmt->amname)));
792 
793  amform = (Form_pg_am) GETSTRUCT(tup);
794  amoid = amform->oid;
795  amroutine = GetIndexAmRoutineByAmId(amoid, false);
796  ReleaseSysCache(tup);
797 
798  maxOpNumber = amroutine->amstrategies;
799  /* if amstrategies is zero, just enforce that op numbers fit in int16 */
800  if (maxOpNumber <= 0)
801  maxOpNumber = SHRT_MAX;
802  maxProcNumber = amroutine->amsupport;
803 
804  /* XXX Should we make any privilege check against the AM? */
805 
806  /* Look up the opfamily */
807  opfamilyoid = get_opfamily_oid(amoid, stmt->opfamilyname, false);
808 
809  /*
810  * Currently, we require superuser privileges to alter an opfamily.
811  *
812  * XXX re-enable NOT_USED code sections below if you remove this test.
813  */
814  if (!superuser())
815  ereport(ERROR,
816  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
817  errmsg("must be superuser to alter an operator family")));
818 
819  /*
820  * ADD and DROP cases need separate code from here on down.
821  */
822  if (stmt->isDrop)
823  AlterOpFamilyDrop(stmt, amoid, opfamilyoid,
824  maxOpNumber, maxProcNumber, stmt->items);
825  else
826  AlterOpFamilyAdd(stmt, amoid, opfamilyoid,
827  maxOpNumber, maxProcNumber, stmt->items);
828 
829  return opfamilyoid;
830 }
uint16 amsupport
Definition: amapi.h:173
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
int errcode(int sqlerrcode)
Definition: elog.c:608
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:961
#define ERROR
Definition: elog.h:43
IndexAmRoutine * GetIndexAmRoutineByAmId(Oid amoid, bool noerror)
Definition: amapi.c:56
#define CStringGetDatum(X)
Definition: postgres.h:578
#define ereport(elevel, rest)
Definition: elog.h:141
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static void AlterOpFamilyAdd(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid, int maxOpNumber, int maxProcNumber, List *items)
Definition: opclasscmds.c:836
Oid get_opfamily_oid(Oid amID, List *opfamilyname, bool missing_ok)
Definition: opclasscmds.c:141
uint16 amstrategies
Definition: amapi.h:171
FormData_pg_am * Form_pg_am
Definition: pg_am.h:48
int errmsg(const char *fmt,...)
Definition: elog.c:822

◆ AlterStatistics()

ObjectAddress AlterStatistics ( AlterStatsStmt stmt)

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

426 {
427  Relation rel;
428  Oid stxoid;
429  HeapTuple oldtup;
430  HeapTuple newtup;
431  Datum repl_val[Natts_pg_statistic_ext];
432  bool repl_null[Natts_pg_statistic_ext];
433  bool repl_repl[Natts_pg_statistic_ext];
434  ObjectAddress address;
435  int newtarget = stmt->stxstattarget;
436 
437  /* Limit statistics target to a sane range */
438  if (newtarget < -1)
439  {
440  ereport(ERROR,
441  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
442  errmsg("statistics target %d is too low",
443  newtarget)));
444  }
445  else if (newtarget > 10000)
446  {
447  newtarget = 10000;
449  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
450  errmsg("lowering statistics target to %d",
451  newtarget)));
452  }
453 
454  /* lookup OID of the statistics object */
455  stxoid = get_statistics_object_oid(stmt->defnames, stmt->missing_ok);
456 
457  /*
458  * If we got here and the OID is not valid, it means the statistics
459  * does not exist, but the command specified IF EXISTS. So report
460  * this as a simple NOTICE and we're done.
461  */
462  if (!OidIsValid(stxoid))
463  {
464  char *schemaname;
465  char *statname;
466 
467  Assert(stmt->missing_ok);
468 
469  DeconstructQualifiedName(stmt->defnames, &schemaname, &statname);
470 
471  if (schemaname)
472  ereport(NOTICE,
473  (errmsg("statistics object \"%s.%s\" does not exist, skipping",
474  schemaname, statname)));
475  else
476  ereport(NOTICE,
477  (errmsg("statistics object \"%s\" does not exist, skipping",
478  statname)));
479 
480  return InvalidObjectAddress;
481  }
482 
483  /* Search pg_statistic_ext */
484  rel = table_open(StatisticExtRelationId, RowExclusiveLock);
485 
486  oldtup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(stxoid));
487 
488  /* Must be owner of the existing statistics object */
491  NameListToString(stmt->defnames));
492 
493  /* Build new tuple. */
494  memset(repl_val, 0, sizeof(repl_val));
495  memset(repl_null, false, sizeof(repl_null));
496  memset(repl_repl, false, sizeof(repl_repl));
497 
498  /* replace the stxstattarget column */
499  repl_repl[Anum_pg_statistic_ext_stxstattarget - 1] = true;
500  repl_val[Anum_pg_statistic_ext_stxstattarget - 1] = Int32GetDatum(newtarget);
501 
502  newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel),
503  repl_val, repl_null, repl_repl);
504 
505  /* Update system catalog. */
506  CatalogTupleUpdate(rel, &newtup->t_self, newtup);
507 
508  InvokeObjectPostAlterHook(StatisticExtRelationId, stxoid, 0);
509 
510  ObjectAddressSet(address, StatisticExtRelationId, stxoid);
511 
512  /*
513  * NOTE: because we only support altering the statistics target, not the
514  * other fields, there is no need to update dependencies.
515  */
516 
517  heap_freetuple(newtup);
518  ReleaseSysCache(oldtup);
519 
521 
522  return address;
523 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define RelationGetDescr(relation)
Definition: rel.h:449
Oid GetUserId(void)
Definition: miscinit.c:380
int errcode(int sqlerrcode)
Definition: elog.c:608
void DeconstructQualifiedName(List *names, char **nspname_p, char **objname_p)
Definition: namespace.c:2801
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:639
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
Oid get_statistics_object_oid(List *names, bool missing_ok)
Definition: namespace.c:2170
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:141
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
#define WARNING
Definition: elog.h:40
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
char * NameListToString(List *names)
Definition: namespace.c:3094
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define NOTICE
Definition: elog.h:37
#define Assert(condition)
Definition: c.h:733
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define Int32GetDatum(X)
Definition: postgres.h:479
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:822
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:5344

◆ AlterTSConfiguration()

ObjectAddress AlterTSConfiguration ( AlterTSConfigurationStmt stmt)

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

1180 {
1181  HeapTuple tup;
1182  Oid cfgId;
1183  Relation relMap;
1184  ObjectAddress address;
1185 
1186  /* Find the configuration */
1187  tup = GetTSConfigTuple(stmt->cfgname);
1188  if (!HeapTupleIsValid(tup))
1189  ereport(ERROR,
1190  (errcode(ERRCODE_UNDEFINED_OBJECT),
1191  errmsg("text search configuration \"%s\" does not exist",
1192  NameListToString(stmt->cfgname))));
1193 
1194  cfgId = ((Form_pg_ts_config) GETSTRUCT(tup))->oid;
1195 
1196  /* must be owner */
1197  if (!pg_ts_config_ownercheck(cfgId, GetUserId()))
1199  NameListToString(stmt->cfgname));
1200 
1201  relMap = table_open(TSConfigMapRelationId, RowExclusiveLock);
1202 
1203  /* Add or drop mappings */
1204  if (stmt->dicts)
1205  MakeConfigurationMapping(stmt, tup, relMap);
1206  else if (stmt->tokentype)
1207  DropConfigurationMapping(stmt, tup, relMap);
1208 
1209  /* Update dependencies */
1210  makeConfigurationDependencies(tup, true, relMap);
1211 
1212  InvokeObjectPostAlterHook(TSConfigRelationId, cfgId, 0);
1213 
1214  ObjectAddressSet(address, TSConfigRelationId, cfgId);
1215 
1216  table_close(relMap, RowExclusiveLock);
1217 
1218  ReleaseSysCache(tup);
1219 
1220  return address;
1221 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
FormData_pg_ts_config * Form_pg_ts_config
Definition: pg_ts_config.h:48
Oid GetUserId(void)
Definition: miscinit.c:380
bool pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid)
Definition: aclchk.c:5064
static ObjectAddress makeConfigurationDependencies(HeapTuple tuple, bool removeOld, Relation mapRel)
Definition: tsearchcmds.c:876
int errcode(int sqlerrcode)
Definition: elog.c:608
unsigned int Oid
Definition: postgres_ext.h:31
static void DropConfigurationMapping(AlterTSConfigurationStmt *stmt, HeapTuple tup, Relation relMap)
Definition: tsearchcmds.c:1446
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:141
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
static HeapTuple GetTSConfigTuple(List *names)
Definition: tsearchcmds.c:851
char * NameListToString(List *names)
Definition: namespace.c:3094
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#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:822
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
static void MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, HeapTuple tup, Relation relMap)
Definition: tsearchcmds.c:1282

◆ AlterTSDictionary()

ObjectAddress AlterTSDictionary ( AlterTSDictionaryStmt stmt)

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

533 {
534  HeapTuple tup,
535  newtup;
536  Relation rel;
537  Oid dictId;
538  ListCell *pl;
539  List *dictoptions;
540  Datum opt;
541  bool isnull;
542  Datum repl_val[Natts_pg_ts_dict];
543  bool repl_null[Natts_pg_ts_dict];
544  bool repl_repl[Natts_pg_ts_dict];
545  ObjectAddress address;
546 
547  dictId = get_ts_dict_oid(stmt->dictname, false);
548 
549  rel = table_open(TSDictionaryRelationId, RowExclusiveLock);
550 
552 
553  if (!HeapTupleIsValid(tup))
554  elog(ERROR, "cache lookup failed for text search dictionary %u",
555  dictId);
556 
557  /* must be owner */
558  if (!pg_ts_dict_ownercheck(dictId, GetUserId()))
560  NameListToString(stmt->dictname));
561 
562  /* deserialize the existing set of options */
563  opt = SysCacheGetAttr(TSDICTOID, tup,
564  Anum_pg_ts_dict_dictinitoption,
565  &isnull);
566  if (isnull)
567  dictoptions = NIL;
568  else
569  dictoptions = deserialize_deflist(opt);
570 
571  /*
572  * Modify the options list as per specified changes
573  */
574  foreach(pl, stmt->options)
575  {
576  DefElem *defel = (DefElem *) lfirst(pl);
577  ListCell *cell;
578 
579  /*
580  * Remove any matches ...
581  */
582  foreach(cell, dictoptions)
583  {
584  DefElem *oldel = (DefElem *) lfirst(cell);
585 
586  if (strcmp(oldel->defname, defel->defname) == 0)
587  dictoptions = foreach_delete_current(dictoptions, cell);
588  }
589 
590  /*
591  * and add new value if it's got one
592  */
593  if (defel->arg)
594  dictoptions = lappend(dictoptions, defel);
595  }
596 
597  /*
598  * Validate
599  */
600  verify_dictoptions(((Form_pg_ts_dict) GETSTRUCT(tup))->dicttemplate,
601  dictoptions);
602 
603  /*
604  * Looks good, update
605  */
606  memset(repl_val, 0, sizeof(repl_val));
607  memset(repl_null, false, sizeof(repl_null));
608  memset(repl_repl, false, sizeof(repl_repl));
609 
610  if (dictoptions)
611  repl_val[Anum_pg_ts_dict_dictinitoption - 1] =
612  PointerGetDatum(serialize_deflist(dictoptions));
613  else
614  repl_null[Anum_pg_ts_dict_dictinitoption - 1] = true;
615  repl_repl[Anum_pg_ts_dict_dictinitoption - 1] = true;
616 
617  newtup = heap_modify_tuple(tup, RelationGetDescr(rel),
618  repl_val, repl_null, repl_repl);
619 
620  CatalogTupleUpdate(rel, &newtup->t_self, newtup);
621 
622  InvokeObjectPostAlterHook(TSDictionaryRelationId, dictId, 0);
623 
624  ObjectAddressSet(address, TSDictionaryRelationId, dictId);
625 
626  /*
627  * NOTE: because we only support altering the options, not the template,
628  * there is no need to update dependencies. This might have to change if
629  * the options ever reference inside-the-database objects.
630  */
631 
632  heap_freetuple(newtup);
633  ReleaseSysCache(tup);
634 
636 
637  return address;
638 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
bool pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid)
Definition: aclchk.c:5037
#define RelationGetDescr(relation)
Definition: rel.h:449
Oid GetUserId(void)
Definition: miscinit.c:380
#define PointerGetDatum(X)
Definition: postgres.h:556
List * deserialize_deflist(Datum txt)
Definition: tsearchcmds.c:1572
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:368
Oid get_ts_dict_oid(List *names, bool missing_ok)
Definition: namespace.c:2418
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
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:163
Node * arg
Definition: parsenodes.h:731
List * lappend(List *list, void *datum)
Definition: list.c:322
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
char * NameListToString(List *names)
Definition: namespace.c:3094
text * serialize_deflist(List *deflist)
Definition: tsearchcmds.c:1527
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1377
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:190
static void verify_dictoptions(Oid tmplId, List *dictoptions)
Definition: tsearchcmds.c:357
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define elog(elevel,...)
Definition: elog.h:228
char * defname
Definition: parsenodes.h:730
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 1265 of file foreigncmds.c.

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

Referenced by ProcessUtilitySlow().

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

◆ CallStmtResultDesc()

TupleDesc CallStmtResultDesc ( CallStmt stmt)

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

2466 {
2467  FuncExpr *fexpr;
2468  HeapTuple tuple;
2469  TupleDesc tupdesc;
2470 
2471  fexpr = stmt->funcexpr;
2472 
2473  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
2474  if (!HeapTupleIsValid(tuple))
2475  elog(ERROR, "cache lookup failed for procedure %u", fexpr->funcid);
2476 
2477  tupdesc = build_function_result_tupdesc_t(tuple);
2478 
2479  ReleaseSysCache(tuple);
2480 
2481  return tupdesc;
2482 }
FuncExpr * funcexpr
Definition: parsenodes.h:2875
TupleDesc build_function_result_tupdesc_t(HeapTuple procTuple)
Definition: funcapi.c:1193
Oid funcid
Definition: primnodes.h:455
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:228

◆ CheckIndexCompatible()

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

Definition at line 141 of file indexcmds.c.

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

Referenced by TryReuseIndex().

145 {
146  bool isconstraint;
147  Oid *typeObjectId;
148  Oid *collationObjectId;
149  Oid *classObjectId;
150  Oid accessMethodId;
151  Oid relationId;
152  HeapTuple tuple;
153  Form_pg_index indexForm;
154  Form_pg_am accessMethodForm;
155  IndexAmRoutine *amRoutine;
156  bool amcanorder;
157  int16 *coloptions;
158  IndexInfo *indexInfo;
159  int numberOfAttributes;
160  int old_natts;
161  bool isnull;
162  bool ret = true;
163  oidvector *old_indclass;
164  oidvector *old_indcollation;
165  Relation irel;
166  int i;
167  Datum d;
168 
169  /* Caller should already have the relation locked in some way. */
170  relationId = IndexGetRelation(oldId, false);
171 
172  /*
173  * We can pretend isconstraint = false unconditionally. It only serves to
174  * decide the text of an error message that should never happen for us.
175  */
176  isconstraint = false;
177 
178  numberOfAttributes = list_length(attributeList);
179  Assert(numberOfAttributes > 0);
180  Assert(numberOfAttributes <= INDEX_MAX_KEYS);
181 
182  /* look up the access method */
183  tuple = SearchSysCache1(AMNAME, PointerGetDatum(accessMethodName));
184  if (!HeapTupleIsValid(tuple))
185  ereport(ERROR,
186  (errcode(ERRCODE_UNDEFINED_OBJECT),
187  errmsg("access method \"%s\" does not exist",
188  accessMethodName)));
189  accessMethodForm = (Form_pg_am) GETSTRUCT(tuple);
190  accessMethodId = accessMethodForm->oid;
191  amRoutine = GetIndexAmRoutine(accessMethodForm->amhandler);
192  ReleaseSysCache(tuple);
193 
194  amcanorder = amRoutine->amcanorder;
195 
196  /*
197  * Compute the operator classes, collations, and exclusion operators for
198  * the new index, so we can test whether it's compatible with the existing
199  * one. Note that ComputeIndexAttrs might fail here, but that's OK:
200  * DefineIndex would have called this function with the same arguments
201  * later on, and it would have failed then anyway. Our attributeList
202  * contains only key attributes, thus we're filling ii_NumIndexAttrs and
203  * ii_NumIndexKeyAttrs with same value.
204  */
205  indexInfo = makeIndexInfo(numberOfAttributes, numberOfAttributes,
206  accessMethodId, NIL, NIL, false, false, false);
207  typeObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
208  collationObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
209  classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
210  coloptions = (int16 *) palloc(numberOfAttributes * sizeof(int16));
211  ComputeIndexAttrs(indexInfo,
212  typeObjectId, collationObjectId, classObjectId,
213  coloptions, attributeList,
214  exclusionOpNames, relationId,
215  accessMethodName, accessMethodId,
216  amcanorder, isconstraint);
217 
218 
219  /* Get the soon-obsolete pg_index tuple. */
221  if (!HeapTupleIsValid(tuple))
222  elog(ERROR, "cache lookup failed for index %u", oldId);
223  indexForm = (Form_pg_index) GETSTRUCT(tuple);
224 
225  /*
226  * We don't assess expressions or predicates; assume incompatibility.
227  * Also, if the index is invalid for any reason, treat it as incompatible.
228  */
229  if (!(heap_attisnull(tuple, Anum_pg_index_indpred, NULL) &&
230  heap_attisnull(tuple, Anum_pg_index_indexprs, NULL) &&
231  indexForm->indisvalid))
232  {
233  ReleaseSysCache(tuple);
234  return false;
235  }
236 
237  /* Any change in operator class or collation breaks compatibility. */
238  old_natts = indexForm->indnkeyatts;
239  Assert(old_natts == numberOfAttributes);
240 
241  d = SysCacheGetAttr(INDEXRELID, tuple, Anum_pg_index_indcollation, &isnull);
242  Assert(!isnull);
243  old_indcollation = (oidvector *) DatumGetPointer(d);
244 
245  d = SysCacheGetAttr(INDEXRELID, tuple, Anum_pg_index_indclass, &isnull);
246  Assert(!isnull);
247  old_indclass = (oidvector *) DatumGetPointer(d);
248 
249  ret = (memcmp(old_indclass->values, classObjectId,
250  old_natts * sizeof(Oid)) == 0 &&
251  memcmp(old_indcollation->values, collationObjectId,
252  old_natts * sizeof(Oid)) == 0);
253 
254  ReleaseSysCache(tuple);
255 
256  if (!ret)
257  return false;
258 
259  /* For polymorphic opcintype, column type changes break compatibility. */
260  irel = index_open(oldId, AccessShareLock); /* caller probably has a lock */
261  for (i = 0; i < old_natts; i++)
262  {
263  if (IsPolymorphicType(get_opclass_input_type(classObjectId[i])) &&
264  TupleDescAttr(irel->rd_att, i)->atttypid != typeObjectId[i])
265  {
266  ret = false;
267  break;
268  }
269  }
270 
271  /* Any change in exclusion operator selections breaks compatibility. */
272  if (ret && indexInfo->ii_ExclusionOps != NULL)
273  {
274  Oid *old_operators,
275  *old_procs;
276  uint16 *old_strats;
277 
278  RelationGetExclusionInfo(irel, &old_operators, &old_procs, &old_strats);
279  ret = memcmp(old_operators, indexInfo->ii_ExclusionOps,
280  old_natts * sizeof(Oid)) == 0;
281 
282  /* Require an exact input type match for polymorphic operators. */
283  if (ret)
284  {
285  for (i = 0; i < old_natts && ret; i++)
286  {
287  Oid left,
288  right;
289 
290  op_input_types(indexInfo->ii_ExclusionOps[i], &left, &right);
291  if ((IsPolymorphicType(left) || IsPolymorphicType(right)) &&
292  TupleDescAttr(irel->rd_att, i)->atttypid != typeObjectId[i])
293  {
294  ret = false;
295  break;
296  }
297  }
298  }
299  }
300 
301  index_close(irel, NoLock);
302  return ret;
303 }
signed short int16
Definition: c.h:346
#define NIL
Definition: pg_list.h:65
Definition: c.h:589
Oid IndexGetRelation(Oid indexId, bool missing_ok)
Definition: index.c:3330
void RelationGetExclusionInfo(Relation indexRelation, Oid **operators, Oid **procs, uint16 **strategies)
Definition: relcache.c:4964
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define PointerGetDatum(X)
Definition: postgres.h:556
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:608
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:358
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
IndexAmRoutine * GetIndexAmRoutine(Oid amhandler)
Definition: amapi.c:33
#define NoLock
Definition: lockdefs.h:34
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:597
void op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
Definition: lsyscache.c:1165
IndexInfo * makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions, List *predicates, bool unique, bool isready, bool concurrent)
Definition: makefuncs.c:740
#define ereport(elevel, rest)
Definition: elog.h:141
FormData_pg_index * Form_pg_index
Definition: pg_index.h:66
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1377
TupleDesc rd_att
Definition: rel.h:84
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:733
#define INDEX_MAX_KEYS
static int list_length(const List *l)
Definition: pg_list.h:169
bool amcanorder
Definition: amapi.h:175
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:152
#define DatumGetPointer(X)
Definition: postgres.h:549
Oid * ii_ExclusionOps
Definition: execnodes.h:164
FormData_pg_am * Form_pg_am
Definition: pg_am.h:48
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
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:1518
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:126
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1041

◆ ChooseRelationName()

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

Definition at line 2134 of file indexcmds.c.

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

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

2137 {
2138  int pass = 0;
2139  char *relname = NULL;
2140  char modlabel[NAMEDATALEN];
2141 
2142  /* try the unmodified label first */
2143  StrNCpy(modlabel, label, sizeof(modlabel));
2144 
2145  for (;;)
2146  {
2147  relname = makeObjectName(name1, name2, modlabel);
2148 
2149  if (!OidIsValid(get_relname_relid(relname, namespaceid)))
2150  {
2151  if (!isconstraint ||
2152  !ConstraintNameExists(relname, namespaceid))
2153  break;
2154  }
2155 
2156  /* found a conflict, so try a new name component */
2157  pfree(relname);
2158  snprintf(modlabel, sizeof(modlabel), "%s%d", label, ++pass);
2159  }
2160 
2161  return relname;
2162 }
bool ConstraintNameExists(const char *conname, Oid namespaceid)
NameData relname
Definition: pg_class.h:35
#define OidIsValid(objectId)
Definition: c.h:639
char * makeObjectName(const char *name1, const char *name2, const char *label)
Definition: indexcmds.c:2048
#define NAMEDATALEN
void pfree(void *pointer)
Definition: mcxt.c:1056
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1687
static char * label
Definition: pg_basebackup.c:86
#define StrNCpy(dst, src, len)
Definition: c.h:929
#define snprintf
Definition: port.h:192

◆ CreateAccessMethod()

ObjectAddress CreateAccessMethod ( CreateAmStmt stmt)

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

43 {
44  Relation rel;
45  ObjectAddress myself;
46  ObjectAddress referenced;
47  Oid amoid;
48  Oid amhandler;
49  bool nulls[Natts_pg_am];
50  Datum values[Natts_pg_am];
51  HeapTuple tup;
52 
53  rel = table_open(AccessMethodRelationId, RowExclusiveLock);
54 
55  /* Must be super user */
56  if (!superuser())
57  ereport(ERROR,
58  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
59  errmsg("permission denied to create access method \"%s\"",
60  stmt->amname),
61  errhint("Must be superuser to create an access method.")));
62 
63  /* Check if name is used */
64  amoid = GetSysCacheOid1(AMNAME, Anum_pg_am_oid,
65  CStringGetDatum(stmt->amname));
66  if (OidIsValid(amoid))
67  {
68  ereport(ERROR,
70  errmsg("access method \"%s\" already exists",
71  stmt->amname)));
72  }
73 
74  /*
75  * Get the handler function oid, verifying the AM type while at it.
76  */
77  amhandler = lookup_am_handler_func(stmt->handler_name, stmt->amtype);
78 
79  /*
80  * Insert tuple into pg_am.
81  */
82  memset(values, 0, sizeof(values));
83  memset(nulls, false, sizeof(nulls));
84 
85  amoid = GetNewOidWithIndex(rel, AmOidIndexId, Anum_pg_am_oid);
86  values[Anum_pg_am_oid - 1] = ObjectIdGetDatum(amoid);
87  values[Anum_pg_am_amname - 1] =
89  values[Anum_pg_am_amhandler - 1] = ObjectIdGetDatum(amhandler);
90  values[Anum_pg_am_amtype - 1] = CharGetDatum(stmt->amtype);
91 
92  tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
93 
94  CatalogTupleInsert(rel, tup);
95  heap_freetuple(tup);
96 
97  myself.classId = AccessMethodRelationId;
98  myself.objectId = amoid;
99  myself.objectSubId = 0;
100 
101  /* Record dependency on handler function */
102  referenced.classId = ProcedureRelationId;
103  referenced.objectId = amhandler;
104  referenced.objectSubId = 0;
105 
106  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
107 
108  recordDependencyOnCurrentExtension(&myself, false);
109 
111 
112  return myself;
113 }
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:133
int errhint(const char *fmt,...)
Definition: elog.c:1071
static Oid lookup_am_handler_func(List *handler_name, char amtype)
Definition: amcmds.c:258
#define RelationGetDescr(relation)
Definition: rel.h:449
#define GetSysCacheOid1(cacheId, oidcol, key1)
Definition: syscache.h:192
int errcode(int sqlerrcode)
Definition: elog.c:608
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:617
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:639
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * amname
Definition: parsenodes.h:2395
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:578
#define ereport(elevel, rest)
Definition: elog.h:141
uintptr_t Datum
Definition: postgres.h:367
List * handler_name
Definition: parsenodes.h:2396
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:138
#define CharGetDatum(X)
Definition: postgres.h:416
static Datum values[MAXATTR]
Definition: bootstrap.c:167
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define AmOidIndexId
Definition: indexing.h:74
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:31
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183

◆ CreateCast()

ObjectAddress CreateCast ( CreateCastStmt stmt)

Definition at line 1493 of file functioncmds.c.

References ACL_USAGE, aclcheck_error_type(), ACLCHECK_OK, CastOidIndexId, CASTSOURCETARGET, CatalogTupleInsert(), CharGetDatum, ObjectAddress::classId, COERCION_ASSIGNMENT, COERCION_EXPLICIT, COERCION_IMPLICIT, CreateCastStmt::context, DEPENDENCY_NORMAL, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, format_type_be(), CreateCastStmt::func, get_element_type(), get_typlenbyvalalign(), get_typtype(), GetNewOidWithIndex(), GETSTRUCT, GetUserId(), heap_form_tuple(), heap_freetuple(), HeapTupleIsValid, CreateCastStmt::inout, InvalidOid, InvokeObjectPostCreateHook, IsBinaryCoercible(), LookupFuncWithArgs(), MemSet, OBJECT_FUNCTION, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, pg_type_aclcheck(), pg_type_ownercheck(), PROCOID, recordDependencyOn(), recordDependencyOnCurrentExtension(), RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), SearchSysCache2(), CreateCastStmt::sourcetype, superuser(), table_close(), table_open(), CreateCastStmt::targettype, TypeNameToString(), typenameTypeId(), values, and WARNING.

Referenced by ProcessUtilitySlow().

1494 {
1495  Oid sourcetypeid;
1496  Oid targettypeid;
1497  char sourcetyptype;
1498  char targettyptype;
1499  Oid funcid;
1500  Oid castid;
1501  int nargs;
1502  char castcontext;
1503  char castmethod;
1504  Relation relation;
1505  HeapTuple tuple;
1506  Datum values[Natts_pg_cast];
1507  bool nulls[Natts_pg_cast];
1508  ObjectAddress myself,
1509  referenced;
1510  AclResult aclresult;
1511 
1512  sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
1513  targettypeid = typenameTypeId(NULL, stmt->targettype);
1514  sourcetyptype = get_typtype(sourcetypeid);
1515  targettyptype = get_typtype(targettypeid);
1516 
1517  /* No pseudo-types allowed */
1518  if (sourcetyptype == TYPTYPE_PSEUDO)
1519  ereport(ERROR,
1520  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1521  errmsg("source data type %s is a pseudo-type",
1522  TypeNameToString(stmt->sourcetype))));
1523 
1524  if (targettyptype == TYPTYPE_PSEUDO)
1525  ereport(ERROR,
1526  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1527  errmsg("target data type %s is a pseudo-type",
1528  TypeNameToString(stmt->targettype))));
1529 
1530  /* Permission check */
1531  if (!pg_type_ownercheck(sourcetypeid, GetUserId())
1532  && !pg_type_ownercheck(targettypeid, GetUserId()))
1533  ereport(ERROR,
1534  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1535  errmsg("must be owner of type %s or type %s",
1536  format_type_be(sourcetypeid),
1537  format_type_be(targettypeid))));
1538 
1539  aclresult = pg_type_aclcheck(sourcetypeid, GetUserId(), ACL_USAGE);
1540  if (aclresult != ACLCHECK_OK)
1541  aclcheck_error_type(aclresult, sourcetypeid);
1542 
1543  aclresult = pg_type_aclcheck(targettypeid, GetUserId(), ACL_USAGE);
1544  if (aclresult != ACLCHECK_OK)
1545  aclcheck_error_type(aclresult, targettypeid);
1546 
1547  /* Domains are allowed for historical reasons, but we warn */
1548  if (sourcetyptype == TYPTYPE_DOMAIN)
1549  ereport(WARNING,
1550  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1551  errmsg("cast will be ignored because the source data type is a domain")));
1552 
1553  else if (targettyptype == TYPTYPE_DOMAIN)
1554  ereport(WARNING,
1555  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1556  errmsg("cast will be ignored because the target data type is a domain")));
1557 
1558  /* Determine the cast method */
1559  if (stmt->func != NULL)
1560  castmethod = COERCION_METHOD_FUNCTION;
1561  else if (stmt->inout)
1562  castmethod = COERCION_METHOD_INOUT;
1563  else
1564  castmethod = COERCION_METHOD_BINARY;
1565 
1566  if (castmethod == COERCION_METHOD_FUNCTION)
1567  {
1568  Form_pg_proc procstruct;
1569 
1570  funcid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->func, false);
1571 
1572  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1573  if (!HeapTupleIsValid(tuple))
1574  elog(ERROR, "cache lookup failed for function %u", funcid);
1575 
1576  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1577  nargs = procstruct->pronargs;
1578  if (nargs < 1 || nargs > 3)
1579  ereport(ERROR,
1580  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1581  errmsg("cast function must take one to three arguments")));
1582  if (!IsBinaryCoercible(sourcetypeid, procstruct->proargtypes.values[0]))
1583  ereport(ERROR,
1584  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1585  errmsg("argument of cast function must match or be binary-coercible from source data type")));
1586  if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
1587  ereport(ERROR,
1588  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1589  errmsg("second argument of cast function must be type %s",
1590  "integer")));
1591  if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)
1592  ereport(ERROR,
1593  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1594  errmsg("third argument of cast function must be type %s",
1595  "boolean")));
1596  if (!IsBinaryCoercible(procstruct->prorettype, targettypeid))
1597  ereport(ERROR,
1598  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1599  errmsg("return data type of cast function must match or be binary-coercible to target data type")));
1600 
1601  /*
1602  * Restricting the volatility of a cast function may or may not be a
1603  * good idea in the abstract, but it definitely breaks many old
1604  * user-defined types. Disable this check --- tgl 2/1/03
1605  */
1606 #ifdef NOT_USED
1607  if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1608  ereport(ERROR,
1609  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1610  errmsg("cast function must not be volatile")));
1611 #endif
1612  if (procstruct->prokind != PROKIND_FUNCTION)
1613  ereport(ERROR,
1614  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1615  errmsg("cast function must be a normal function")));
1616  if (procstruct->proretset)
1617  ereport(ERROR,
1618  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1619  errmsg("cast function must not return a set")));
1620 
1621  ReleaseSysCache(tuple);
1622  }
1623  else
1624  {
1625  funcid = InvalidOid;
1626  nargs = 0;
1627  }
1628 
1629  if (castmethod == COERCION_METHOD_BINARY)
1630  {
1631  int16 typ1len;
1632  int16 typ2len;
1633  bool typ1byval;
1634  bool typ2byval;
1635  char typ1align;
1636  char typ2align;
1637 
1638  /*
1639  * Must be superuser to create binary-compatible casts, since
1640  * erroneous casts can easily crash the backend.
1641  */
1642  if (!superuser())
1643  ereport(ERROR,
1644  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1645  errmsg("must be superuser to create a cast WITHOUT FUNCTION")));
1646 
1647  /*
1648  * Also, insist that the types match as to size, alignment, and
1649  * pass-by-value attributes; this provides at least a crude check that
1650  * they have similar representations. A pair of types that fail this
1651  * test should certainly not be equated.
1652  */
1653  get_typlenbyvalalign(sourcetypeid, &typ1len, &typ1byval, &typ1align);
1654  get_typlenbyvalalign(targettypeid, &typ2len, &typ2byval, &typ2align);
1655  if (typ1len != typ2len ||
1656  typ1byval != typ2byval ||
1657  typ1align != typ2align)
1658  ereport(ERROR,
1659  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1660  errmsg("source and target data types are not physically compatible")));
1661 
1662  /*
1663  * We know that composite, enum and array types are never binary-
1664  * compatible with each other. They all have OIDs embedded in them.
1665  *
1666  * Theoretically you could build a user-defined base type that is
1667  * binary-compatible with a composite, enum, or array type. But we
1668  * disallow that too, as in practice such a cast is surely a mistake.
1669  * You can always work around that by writing a cast function.
1670  */
1671  if (sourcetyptype == TYPTYPE_COMPOSITE ||
1672  targettyptype == TYPTYPE_COMPOSITE)
1673  ereport(ERROR,
1674  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1675  errmsg("composite data types are not binary-compatible")));
1676 
1677  if (sourcetyptype == TYPTYPE_ENUM ||
1678  targettyptype == TYPTYPE_ENUM)
1679  ereport(ERROR,
1680  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1681  errmsg("enum data types are not binary-compatible")));
1682 
1683  if (OidIsValid(get_element_type(sourcetypeid)) ||
1684  OidIsValid(get_element_type(targettypeid)))
1685  ereport(ERROR,
1686  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1687  errmsg("array data types are not binary-compatible")));
1688 
1689  /*
1690  * We also disallow creating binary-compatibility casts involving
1691  * domains. Casting from a domain to its base type is already
1692  * allowed, and casting the other way ought to go through domain
1693  * coercion to permit constraint checking. Again, if you're intent on
1694  * having your own semantics for that, create a no-op cast function.
1695  *
1696  * NOTE: if we were to relax this, the above checks for composites
1697  * etc. would have to be modified to look through domains to their
1698  * base types.
1699  */
1700  if (sourcetyptype == TYPTYPE_DOMAIN ||
1701  targettyptype == TYPTYPE_DOMAIN)
1702  ereport(ERROR,
1703  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1704  errmsg("domain data types must not be marked binary-compatible")));
1705  }
1706 
1707  /*
1708  * Allow source and target types to be same only for length coercion
1709  * functions. We assume a multi-arg function does length coercion.
1710  */
1711  if (sourcetypeid == targettypeid && nargs < 2)
1712  ereport(ERROR,
1713  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1714  errmsg("source data type and target data type are the same")));
1715 
1716  /* convert CoercionContext enum to char value for castcontext */
1717  switch (stmt->context)
1718  {
1719  case COERCION_IMPLICIT:
1720  castcontext = COERCION_CODE_IMPLICIT;
1721  break;
1722  case COERCION_ASSIGNMENT:
1723  castcontext = COERCION_CODE_ASSIGNMENT;
1724  break;
1725  case COERCION_EXPLICIT:
1726  castcontext = COERCION_CODE_EXPLICIT;
1727  break;
1728  default:
1729  elog(ERROR, "unrecognized CoercionContext: %d", stmt->context);
1730  castcontext = 0; /* keep compiler quiet */
1731  break;
1732  }
1733 
1734  relation = table_open(CastRelationId, RowExclusiveLock);
1735 
1736  /*
1737  * Check for duplicate. This is just to give a friendly error message,
1738  * the unique index would catch it anyway (so no need to sweat about race
1739  * conditions).
1740  */
1742  ObjectIdGetDatum(sourcetypeid),
1743  ObjectIdGetDatum(targettypeid));
1744  if (HeapTupleIsValid(tuple))
1745  ereport(ERROR,
1747  errmsg("cast from type %s to type %s already exists",
1748  format_type_be(sourcetypeid),
1749  format_type_be(targettypeid))));
1750 
1751  /* ready to go */
1752  castid = GetNewOidWithIndex(relation, CastOidIndexId, Anum_pg_cast_oid);
1753  values[Anum_pg_cast_oid - 1] = ObjectIdGetDatum(castid);
1754  values[Anum_pg_cast_castsource - 1] = ObjectIdGetDatum(sourcetypeid);
1755  values[Anum_pg_cast_casttarget - 1] = ObjectIdGetDatum(targettypeid);
1756  values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid);
1757  values[Anum_pg_cast_castcontext - 1] = CharGetDatum(castcontext);
1758  values[Anum_pg_cast_castmethod - 1] = CharGetDatum(castmethod);
1759 
1760  MemSet(nulls, false, sizeof(nulls));
1761 
1762  tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
1763 
1764  CatalogTupleInsert(relation, tuple);
1765 
1766  /* make dependency entries */
1767  myself.classId = CastRelationId;
1768  myself.objectId = castid;
1769  myself.objectSubId = 0;
1770 
1771  /* dependency on source type */
1772  referenced.classId = TypeRelationId;
1773  referenced.objectId = sourcetypeid;
1774  referenced.objectSubId = 0;
1775  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1776 
1777  /* dependency on target type */
1778  referenced.classId = TypeRelationId;
1779  referenced.objectId = targettypeid;
1780  referenced.objectSubId = 0;
1781  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1782 
1783  /* dependency on function */
1784  if (OidIsValid(funcid))
1785  {
1786  referenced.classId = ProcedureRelationId;
1787  referenced.objectId = funcid;
1788  referenced.objectSubId = 0;
1789  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1790  }
1791 
1792  /* dependency on extension */
1793  recordDependencyOnCurrentExtension(&myself, false);
1794 
1795  /* Post creation hook for new cast */
1796  InvokeObjectPostCreateHook(CastRelationId, castid, 0);
1797 
1798  heap_freetuple(tuple);
1799 
1800  table_close(relation, RowExclusiveLock);
1801 
1802  return myself;
1803 }
signed short int16
Definition: c.h:346
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:322
TypeName * sourcetype
Definition: parsenodes.h:3360
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
#define RelationGetDescr(relation)
Definition: rel.h:449
Oid GetUserId(void)
Definition: miscinit.c:380
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2526
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2049
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:476
int errcode(int sqlerrcode)
Definition: elog.c:608
bool superuser(void)
Definition: superuser.c:46
char get_typtype(Oid typid)
Definition: lsyscache.c:2407
#define MemSet(start, val, len)
Definition: c.h:956
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
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
bool pg_type_ownercheck(Oid type_oid, Oid roleid)
Definition: aclchk.c:4780
#define OidIsValid(objectId)
Definition: c.h:639
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3665
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
CoercionContext context
Definition: parsenodes.h:3363
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CastOidIndexId
Definition: indexing.h:109
#define ACL_USAGE
Definition: parsenodes.h:82
#define ereport(elevel, rest)
Definition: elog.h:141
bool IsBinaryCoercible(Oid srctype, Oid targettype)
#define WARNING
Definition: elog.h:40
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
ObjectWithArgs * func
Definition: parsenodes.h:3362
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:134
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:138
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1127
#define CharGetDatum(X)
Definition: postgres.h:416
static Datum values[MAXATTR]
Definition: bootstrap.c:167
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2161
TypeName * targettype
Definition: parsenodes.h:3361
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4742
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:31
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183
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:133
int errhint(const char *fmt,...)
Definition: elog.c:1071
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:145
Oid GetUserId(void)
Definition: miscinit.c:380
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:110
#define PointerGetDatum(X)
Definition: postgres.h:556
int errcode(int sqlerrcode)
Definition: elog.c:608
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:617
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:164
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:639
List * options
Definition: parsenodes.h:2257
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
char * fdwname
Definition: parsenodes.h:2255
#define CStringGetDatum(X)
Definition: postgres.h:578
#define ereport(elevel, rest)
Definition: elog.h:141
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:84
#define ForeignDataWrapperOidIndexId
Definition: indexing.h:294
ForeignDataWrapper * GetForeignDataWrapperByName(const char *fdwname, bool missing_ok)
Definition: foreign.c:94
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:138
#define DatumGetPointer(X)
Definition: postgres.h:549
static Datum values[MAXATTR]
Definition: bootstrap.c:167
int errmsg(const char *fmt,...)
Definition: elog.c:822
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:31
#define PointerIsValid(pointer)
Definition: c.h:627
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183
List * func_options
Definition: parsenodes.h:2256

◆ CreateForeignServer()

ObjectAddress CreateForeignServer ( CreateForeignServerStmt stmt)

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

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

◆ CreateForeignTable()

void CreateForeignTable ( CreateForeignTableStmt stmt,
Oid  relid 
)

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

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

◆ CreateFunction()

ObjectAddress CreateFunction ( ParseState pstate,
CreateFunctionStmt stmt 
)

Definition at line 920 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, 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, palloc(), CreateFunctionStmt::parameters, pg_language_aclcheck(), pg_namespace_aclcheck(), PLTemplateExists(), PointerGetDatum, ProcedureCreate(), QualifiedNameGetCreationNamespace(), ReleaseSysCache(), CreateFunctionStmt::replace, CreateFunctionStmt::returnType, SearchSysCache1(), superuser(), and typenameTypeId().

Referenced by ProcessUtilitySlow().

921 {
922  char *probin_str;
923  char *prosrc_str;
924  Oid prorettype;
925  bool returnsSet;
926  char *language;
927  Oid languageOid;
928  Oid languageValidator;
929  Node *transformDefElem = NULL;
930  char *funcname;
931  Oid namespaceId;
932  AclResult aclresult;
933  oidvector *parameterTypes;
934  ArrayType *allParameterTypes;
935  ArrayType *parameterModes;
936  ArrayType *parameterNames;
937  List *parameterDefaults;
938  Oid variadicArgType;
939  List *trftypes_list = NIL;
940  ArrayType *trftypes;
941  Oid requiredResultType;
942  bool isWindowFunc,
943  isStrict,
944  security,
945  isLeakProof;
946  char volatility;
947  ArrayType *proconfig;
948  float4 procost;
949  float4 prorows;
950  Oid prosupport;
951  HeapTuple languageTuple;
952  Form_pg_language languageStruct;
953  List *as_clause;
954  char parallel;
955 
956  /* Convert list of names to a name and namespace */
957  namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
958  &funcname);
959 
960  /* Check we have creation rights in target namespace */
961  aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
962  if (aclresult != ACLCHECK_OK)
963  aclcheck_error(aclresult, OBJECT_SCHEMA,
964  get_namespace_name(namespaceId));
965 
966  /* Set default attributes */
967  isWindowFunc = false;
968  isStrict = false;
969  security = false;
970  isLeakProof = false;
971  volatility = PROVOLATILE_VOLATILE;
972  proconfig = NULL;
973  procost = -1; /* indicates not set */
974  prorows = -1; /* indicates not set */
975  prosupport = InvalidOid;
976  parallel = PROPARALLEL_UNSAFE;
977 
978  /* Extract non-default attributes from stmt->options list */
980  stmt->is_procedure,
981  stmt->options,
982  &as_clause, &language, &transformDefElem,
983  &isWindowFunc, &volatility,
984  &isStrict, &security, &isLeakProof,
985  &proconfig, &procost, &prorows,
986  &prosupport, &parallel);
987 
988  /* Look up the language and validate permissions */
989  languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
990  if (!HeapTupleIsValid(languageTuple))
991  ereport(ERROR,
992  (errcode(ERRCODE_UNDEFINED_OBJECT),
993  errmsg("language \"%s\" does not exist", language),
994  (PLTemplateExists(language) ?
995  errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
996 
997  languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
998  languageOid = languageStruct->oid;
999 
1000  if (languageStruct->lanpltrusted)
1001  {
1002  /* if trusted language, need USAGE privilege */
1003  AclResult aclresult;
1004 
1005  aclresult = pg_language_aclcheck(languageOid, GetUserId(), ACL_USAGE);
1006  if (aclresult != ACLCHECK_OK)
1007  aclcheck_error(aclresult, OBJECT_LANGUAGE,
1008  NameStr(languageStruct->lanname));
1009  }
1010  else
1011  {
1012  /* if untrusted language, must be superuser */
1013  if (!superuser())
1015  NameStr(languageStruct->lanname));
1016  }
1017 
1018  languageValidator = languageStruct->lanvalidator;
1019 
1020  ReleaseSysCache(languageTuple);
1021 
1022  /*
1023  * Only superuser is allowed to create leakproof functions because
1024  * leakproof functions can see tuples which have not yet been filtered out
1025  * by security barrier views or row level security policies.
1026  */
1027  if (isLeakProof && !superuser())
1028  ereport(ERROR,
1029  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1030  errmsg("only superuser can define a leakproof function")));
1031 
1032  if (transformDefElem)
1033  {
1034  ListCell *lc;
1035 
1036  foreach(lc, castNode(List, transformDefElem))
1037  {
1038  Oid typeid = typenameTypeId(NULL,
1039  lfirst_node(TypeName, lc));
1040  Oid elt = get_base_element_type(typeid);
1041 
1042  typeid = elt ? elt : typeid;
1043 
1044  get_transform_oid(typeid, languageOid, false);
1045  trftypes_list = lappend_oid(trftypes_list, typeid);
1046  }
1047  }
1048 
1049  /*
1050  * Convert remaining parameters of CREATE to form wanted by
1051  * ProcedureCreate.
1052  */
1054  stmt->parameters,
1055  languageOid,
1057  &parameterTypes,
1058  &allParameterTypes,
1059  &parameterModes,
1060  &parameterNames,
1061  &parameterDefaults,
1062  &variadicArgType,
1063  &requiredResultType);
1064 
1065  if (stmt->is_procedure)
1066  {
1067  Assert(!stmt->returnType);
1068  prorettype = requiredResultType ? requiredResultType : VOIDOID;
1069  returnsSet = false;
1070  }
1071  else if (stmt->returnType)
1072  {
1073  /* explicit RETURNS clause */
1074  compute_return_type(stmt->returnType, languageOid,
1075  &prorettype, &returnsSet);
1076  if (OidIsValid(requiredResultType) && prorettype != requiredResultType)
1077  ereport(ERROR,
1078  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1079  errmsg("function result type must be %s because of OUT parameters",
1080  format_type_be(requiredResultType))));
1081  }
1082  else if (OidIsValid(requiredResultType))
1083  {
1084  /* default RETURNS clause from OUT parameters */
1085  prorettype = requiredResultType;
1086  returnsSet = false;
1087  }
1088  else
1089  {
1090  ereport(ERROR,
1091  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1092  errmsg("function result type must be specified")));
1093  /* Alternative possibility: default to RETURNS VOID */
1094  prorettype = VOIDOID;
1095  returnsSet = false;
1096  }
1097 
1098  if (list_length(trftypes_list) > 0)
1099  {
1100  ListCell *lc;
1101  Datum *arr;
1102  int i;
1103 
1104  arr = palloc(list_length(trftypes_list) * sizeof(Datum));
1105  i = 0;
1106  foreach(lc, trftypes_list)
1107  arr[i++] = ObjectIdGetDatum(lfirst_oid(lc));
1108  trftypes = construct_array(arr, list_length(trftypes_list),
1109  OIDOID, sizeof(Oid), true, 'i');
1110  }
1111  else
1112  {
1113  /* store SQL NULL instead of empty array */
1114  trftypes = NULL;
1115  }
1116 
1117  interpret_AS_clause(languageOid, language, funcname, as_clause,
1118  &prosrc_str, &probin_str);
1119 
1120  /*
1121  * Set default values for COST and ROWS depending on other parameters;
1122  * reject ROWS if it's not returnsSet. NB: pg_dump knows these default
1123  * values, keep it in sync if you change them.
1124  */
1125  if (procost < 0)
1126  {
1127  /* SQL and PL-language functions are assumed more expensive */
1128  if (languageOid == INTERNALlanguageId ||
1129  languageOid == ClanguageId)
1130  procost = 1;
1131  else
1132  procost = 100;
1133  }
1134  if (prorows < 0)
1135  {
1136  if (returnsSet)
1137  prorows = 1000;
1138  else
1139  prorows = 0; /* dummy value if not returnsSet */
1140  }
1141  else if (!returnsSet)
1142  ereport(ERROR,
1143  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1144  errmsg("ROWS is not applicable when function does not return a set")));
1145 
1146  /*
1147  * And now that we have all the parameters, and know we're permitted to do
1148  * so, go ahead and create the function.
1149  */
1150  return ProcedureCreate(funcname,
1151  namespaceId,
1152  stmt->replace,
1153  returnsSet,
1154  prorettype,
1155  GetUserId(),
1156  languageOid,
1157  languageValidator,
1158  prosrc_str, /* converted to text later */
1159  probin_str, /* converted to text later */
1160  stmt->is_procedure ? PROKIND_PROCEDURE : (isWindowFunc ? PROKIND_WINDOW : PROKIND_FUNCTION),
1161  security,
1162  isLeakProof,
1163  isStrict,
1164  volatility,
1165  parallel,
1166  parameterTypes,
1167  PointerGetDatum(allParameterTypes),
1168  PointerGetDatum(parameterModes),
1169  PointerGetDatum(parameterNames),
1170  parameterDefaults,
1171  PointerGetDatum(trftypes),
1172  PointerGetDatum(proconfig),
1173  prosupport,
1174  procost,
1175  prorows);
1176 }
#define NIL
Definition: pg_list.h:65
Definition: c.h:589
int errhint(const char *fmt,...)
Definition: elog.c:1071
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Oid GetUserId(void)
Definition: miscinit.c:380
#define castNode(_type_, nodeptr)
Definition: nodes.h:594
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2987
#define PointerGetDatum(X)
Definition: postgres.h:556
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, 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:68
static void compute_return_type(TypeName *returnType, Oid languageOid, Oid *prorettype_p, bool *returnsSet_p)
Definition: functioncmds.c:87
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3291
Definition: nodes.h:525
int errcode(int sqlerrcode)
Definition: elog.c:608
bool superuser(void)
Definition: superuser.c:46
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
static void interpret_AS_clause(Oid languageOid, const char *languageName, char *funcname, List *as, char **prosrc_str_p, char **probin_str_p)
Definition: functioncmds.c:860
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:358
#define OidIsValid(objectId)
Definition: c.h:639
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4692
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4666
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:3352
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:84
#define lfirst_node(type, lc)
Definition: pg_list.h:193
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
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:693
#define ACL_USAGE
Definition: parsenodes.h:82
#define ereport(elevel, rest)
Definition: elog.h:141
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
float float4
Definition: c.h:491
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
bool PLTemplateExists(const char *languageName)
Definition: proclang.c:525
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:733
TypeName * returnType
Definition: parsenodes.h:2815
void interpret_function_parameter_list(ParseState *pstate, List *parameters, Oid languageOid, ObjectType objtype, oidvector **parameterTypes, ArrayType **allParameterTypes, ArrayType **parameterModes, ArrayType **parameterNames, List **parameterDefaults, Oid *variadicArgType, Oid *requiredResultType)
Definition: functioncmds.c:183
static int list_length(const List *l)
Definition: pg_list.h:169
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2599
FormData_pg_language * Form_pg_language
Definition: pg_language.h:65
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:822
int i
#define NameStr(name)
Definition: c.h:610
Definition: pg_list.h:50
#define lfirst_oid(lc)
Definition: pg_list.h:192
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:291

◆ CreateStatistics()

ObjectAddress CreateStatistics ( CreateStatsStmt stmt)

Definition at line 62 of file statscmds.c.

References aclcheck_error(), ACLCHECK_NOT_OWNER, Assert, attname, buildint2vector(), CacheInvalidateRelcache(), CatalogTupleInsert(), CharGetDatum, ChooseExtendedStatisticName(), ChooseExtendedStatisticNameAddition(), compare_int16(), construct_array(), CreateComments(), CStringGetDatum, CreateStatsStmt::defnames, DEPENDENCY_AUTO, DEPENDENCY_NORMAL, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, CreateStatsStmt::exprs, ColumnRef::fields, format_type_be(), get_relkind_objtype(), GetNewOidWithIndex(), GETSTRUCT, GetUserId(), heap_form_tuple(), heap_freetuple(), HeapTupleIsValid, i, CreateStatsStmt::if_not_exists, Int32GetDatum, InvalidObjectAddress, InvalidOid, IsA, lengthof, lfirst, linitial, list_length(), lookup_type_cache(), TypeCacheEntry::lt_opr, NameGetDatum, namestrcpy(), NoLock, NOTICE, ObjectAddressSet, ObjectAddressSubSet, ObjectIdGetDatum, pg_class_ownercheck(), PointerGetDatum, qsort, QualifiedNameGetCreationNamespace(), RelationData::rd_att, RelationData::rd_rel, recordDependencyOn(), recordDependencyOnOwner(), 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 ProcessUtilitySlow().

63 {
64  int16 attnums[STATS_MAX_DIMENSIONS];
65  int numcols = 0;
66  char *namestr;
67  NameData stxname;
68  Oid statoid;
69  Oid namespaceId;
70  Oid stxowner = GetUserId();
71  HeapTuple htup;
72  Datum values[Natts_pg_statistic_ext];
73  bool nulls[Natts_pg_statistic_ext];
74  Datum datavalues[Natts_pg_statistic_ext_data];
75  bool datanulls[Natts_pg_statistic_ext_data];
76  int2vector *stxkeys;
77  Relation statrel;
78  Relation datarel;
79  Relation rel = NULL;
80  Oid relid;
81  ObjectAddress parentobject,
82  myself;
83  Datum types[3]; /* one for each possible type of statistic */
84  int ntypes;
85  ArrayType *stxkind;
86  bool build_ndistinct;
87  bool build_dependencies;
88  bool build_mcv;
89  bool requested_type = false;
90  int i;
91  ListCell *cell;
92 
93  Assert(IsA(stmt, CreateStatsStmt));
94 
95  /*
96  * Examine the FROM clause. Currently, we only allow it to be a single
97  * simple table, but later we'll probably allow multiple tables and JOIN
98  * syntax. The grammar is already prepared for that, so we have to check
99  * here that what we got is what we can support.
100  */
101  if (list_length(stmt->relations) != 1)
102  ereport(ERROR,
103  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
104  errmsg("only a single relation is allowed in CREATE STATISTICS")));
105 
106  foreach(cell, stmt->relations)
107  {
108  Node *rln = (Node *) lfirst(cell);
109 
110  if (!IsA(rln, RangeVar))
111  ereport(ERROR,
112  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
113  errmsg("only a single relation is allowed in CREATE STATISTICS")));
114 
115  /*
116  * CREATE STATISTICS will influence future execution plans but does
117  * not interfere with currently executing plans. So it should be
118  * enough to take only ShareUpdateExclusiveLock on relation,
119  * conflicting with ANALYZE and other DDL that sets statistical
120  * information, but not with normal queries.
121  */
123 
124  /* Restrict to allowed relation types */
125  if (rel->rd_rel->relkind != RELKIND_RELATION &&
126  rel->rd_rel->relkind != RELKIND_MATVIEW &&
127  rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
128  rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
129  ereport(ERROR,
130  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
131  errmsg("relation \"%s\" is not a table, foreign table, or materialized view",
132  RelationGetRelationName(rel))));
133 
134  /* You must own the relation to create stats on it */
135  if (!pg_class_ownercheck(RelationGetRelid(rel), stxowner))
138  }
139 
140  Assert(rel);
141  relid = RelationGetRelid(rel);
142 
143  /*
144  * If the node has a name, split it up and determine creation namespace.
145  * If not (a possibility not considered by the grammar, but one which can
146  * occur via the "CREATE TABLE ... (LIKE)" command), then we put the
147  * object in the same namespace as the relation, and cons up a name for
148  * it.
149  */
150  if (stmt->defnames)
151  namespaceId = QualifiedNameGetCreationNamespace(stmt->defnames,
152  &namestr);
153  else
154  {
155  namespaceId = RelationGetNamespace(rel);
158  "stat",
159  namespaceId);
160  }
161  namestrcpy(&stxname, namestr);
162 
163  /*
164  * Deal with the possibility that the statistics object already exists.
165  */
167  CStringGetDatum(namestr),
168  ObjectIdGetDatum(namespaceId)))
169  {
170  if (stmt->if_not_exists)
171  {
172  ereport(NOTICE,
174  errmsg("statistics object \"%s\" already exists, skipping",
175  namestr)));
176  relation_close(rel, NoLock);
177  return InvalidObjectAddress;
178  }
179 
180  ereport(ERROR,
182  errmsg("statistics object \"%s\" already exists", namestr)));
183  }
184 
185  /*
186  * Currently, we only allow simple column references in the expression
187  * list. That will change someday, and again the grammar already supports
188  * it so we have to enforce restrictions here. For now, we can convert
189  * the expression list to a simple array of attnums. While at it, enforce
190  * some constraints.
191  */
192  foreach(cell, stmt->exprs)
193  {
194  Node *expr = (Node *) lfirst(cell);
195  ColumnRef *cref;
196  char *attname;
197  HeapTuple atttuple;
198  Form_pg_attribute attForm;
200 
201  if (!IsA(expr, ColumnRef))
202  ereport(ERROR,
203  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
204  errmsg("only simple column references are allowed in CREATE STATISTICS")));
205  cref = (ColumnRef *) expr;
206 
207  if (list_length(cref->fields) != 1)
208  ereport(ERROR,
209  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
210  errmsg("only simple column references are allowed in CREATE STATISTICS")));
211  attname = strVal((Value *) linitial(cref->fields));
212 
213  atttuple = SearchSysCacheAttName(relid, attname);
214  if (!HeapTupleIsValid(atttuple))
215  ereport(ERROR,
216  (errcode(ERRCODE_UNDEFINED_COLUMN),
217  errmsg("column \"%s\" does not exist",
218  attname)));
219  attForm = (Form_pg_attribute) GETSTRUCT(atttuple);
220 
221  /* Disallow use of system attributes in extended stats */
222  if (attForm->attnum <= 0)
223  ereport(ERROR,
224  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
225  errmsg("statistics creation on system columns is not supported")));
226 
227  /* Disallow data types without a less-than operator */
228  type = lookup_type_cache(attForm->atttypid, TYPECACHE_LT_OPR);
229  if (type->lt_opr == InvalidOid)
230  ereport(ERROR,
231  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
232  errmsg("column \"%s\" cannot be used in statistics because its type %s has no default btree operator class",
233  attname, format_type_be(attForm->atttypid))));
234 
235  /* Make sure no more than STATS_MAX_DIMENSIONS columns are used */
236  if (numcols >= STATS_MAX_DIMENSIONS)
237  ereport(ERROR,
238  (errcode(ERRCODE_TOO_MANY_COLUMNS),
239  errmsg("cannot have more than %d columns in statistics",
241 
242  attnums[numcols] = attForm->attnum;
243  numcols++;
244  ReleaseSysCache(atttuple);
245  }
246 
247  /*
248  * Check that at least two columns were specified in the statement. The
249  * upper bound was already checked in the loop above.
250  */
251  if (numcols < 2)
252  ereport(ERROR,
253  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
254  errmsg("extended statistics require at least 2 columns")));
255 
256  /*
257  * Sort the attnums, which makes detecting duplicates somewhat easier, and
258  * it does not hurt (it does not affect the efficiency, unlike for
259  * indexes, for example).
260  */
261  qsort(attnums, numcols, sizeof(int16), compare_int16);
262 
263  /*
264  * Check for duplicates in the list of columns. The attnums are sorted so
265  * just check consecutive elements.
266  */
267  for (i = 1; i < numcols; i++)
268  {
269  if (attnums[i] == attnums[i - 1])
270  ereport(ERROR,
271  (errcode(ERRCODE_DUPLICATE_COLUMN),
272  errmsg("duplicate column name in statistics definition")));
273  }
274 
275  /* Form an int2vector representation of the sorted column list */
276  stxkeys = buildint2vector(attnums, numcols);
277 
278  /*
279  * Parse the statistics kinds.
280  */
281  build_ndistinct = false;
282  build_dependencies = false;
283  build_mcv = false;
284  foreach(cell, stmt->stat_types)
285  {
286  char *type = strVal((Value *) lfirst(cell));
287 
288  if (strcmp(type, "ndistinct") == 0)
289  {
290  build_ndistinct = true;
291  requested_type = true;
292  }
293  else if (strcmp(type, "dependencies") == 0)
294  {
295  build_dependencies = true;
296  requested_type = true;
297  }
298  else if (strcmp(type, "mcv") == 0)
299  {
300  build_mcv = true;
301  requested_type = true;
302  }
303  else
304  ereport(ERROR,
305  (errcode(ERRCODE_SYNTAX_ERROR),
306  errmsg("unrecognized statistics kind \"%s\"",
307  type)));
308  }
309  /* If no statistic type was specified, build them all. */
310  if (!requested_type)
311  {
312  build_ndistinct = true;
313  build_dependencies = true;
314  build_mcv = true;
315  }
316 
317  /* construct the char array of enabled statistic types */
318  ntypes = 0;
319  if (build_ndistinct)
320  types[ntypes++] = CharGetDatum(STATS_EXT_NDISTINCT);
321  if (build_dependencies)
322  types[ntypes++] = CharGetDatum(STATS_EXT_DEPENDENCIES);
323  if (build_mcv)
324  types[ntypes++] = CharGetDatum(STATS_EXT_MCV);
325  Assert(ntypes > 0 && ntypes <= lengthof(types));
326  stxkind = construct_array(types, ntypes, CHAROID, 1, true, 'c');
327 
328  statrel = table_open(StatisticExtRelationId, RowExclusiveLock);
329 
330  /*
331  * Everything seems fine, so let's build the pg_statistic_ext tuple.
332  */
333  memset(values, 0, sizeof(values));
334  memset(nulls, false, sizeof(nulls));
335 
336  statoid = GetNewOidWithIndex(statrel, StatisticExtOidIndexId,
337  Anum_pg_statistic_ext_oid);
338  values[Anum_pg_statistic_ext_oid - 1] = ObjectIdGetDatum(statoid);
339  values[Anum_pg_statistic_ext_stxrelid - 1] = ObjectIdGetDatum(relid);
340  values[Anum_pg_statistic_ext_stxname - 1] = NameGetDatum(&stxname);
341  values[Anum_pg_statistic_ext_stxnamespace - 1] = ObjectIdGetDatum(namespaceId);
342  values[Anum_pg_statistic_ext_stxstattarget - 1] = Int32GetDatum(-1);
343  values[Anum_pg_statistic_ext_stxowner - 1] = ObjectIdGetDatum(stxowner);
344  values[Anum_pg_statistic_ext_stxkeys - 1] = PointerGetDatum(stxkeys);
345  values[Anum_pg_statistic_ext_stxkind - 1] = PointerGetDatum(stxkind);
346 
347  /* insert it into pg_statistic_ext */
348  htup = heap_form_tuple(statrel->rd_att, values, nulls);
349  CatalogTupleInsert(statrel, htup);
350  heap_freetuple(htup);
351 
353 
354  /*
355  * Also build the pg_statistic_ext_data tuple, to hold the actual
356  * statistics data.
357  */
358  datarel = table_open(StatisticExtDataRelationId, RowExclusiveLock);
359 
360  memset(datavalues, 0, sizeof(datavalues));
361  memset(datanulls, false, sizeof(datanulls));
362 
363  datavalues[Anum_pg_statistic_ext_data_stxoid - 1] = ObjectIdGetDatum(statoid);
364 
365  /* no statistics built yet */
366  datanulls[Anum_pg_statistic_ext_data_stxdndistinct - 1] = true;
367  datanulls[Anum_pg_statistic_ext_data_stxddependencies - 1] = true;
368  datanulls[Anum_pg_statistic_ext_data_stxdmcv - 1] = true;
369 
370  /* insert it into pg_statistic_ext_data */
371  htup = heap_form_tuple(datarel->rd_att, datavalues, datanulls);
372  CatalogTupleInsert(datarel, htup);
373  heap_freetuple(htup);
374 
376 
377  /*
378  * Invalidate relcache so that others see the new statistics object.
379  */
381 
382  relation_close(rel, NoLock);
383 
384  /*
385  * Add an AUTO dependency on each column used in the stats, so that the
386  * stats object goes away if any or all of them get dropped.
387  */
388  ObjectAddressSet(myself, StatisticExtRelationId, statoid);
389 
390  for (i = 0; i < numcols; i++)
391  {
392  ObjectAddressSubSet(parentobject, RelationRelationId, relid, attnums[i]);
393  recordDependencyOn(&myself, &parentobject, DEPENDENCY_AUTO);
394  }
395 
396  /*
397  * Also add dependencies on namespace and owner. These are required
398  * because the stats object might have a different namespace and/or owner
399  * than the underlying table(s).
400  */
401  ObjectAddressSet(parentobject, NamespaceRelationId, namespaceId);
402  recordDependencyOn(&myself, &parentobject, DEPENDENCY_NORMAL);
403 
404  recordDependencyOnOwner(StatisticExtRelationId, statoid, stxowner);
405 
406  /*
407  * XXX probably there should be a recordDependencyOnCurrentExtension call
408  * here too, but we'd have to add support for ALTER EXTENSION ADD/DROP
409  * STATISTICS, which is more work than it seems worth.
410  */
411 
412  /* Add any requested comment */
413  if (stmt->stxcomment != NULL)
414  CreateComments(statoid, StatisticExtRelationId, 0,
415  stmt->stxcomment);
416 
417  /* Return stats object's address */
418  return myself;
419 }
signed short int16
Definition: c.h:346
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:576
#define NameGetDatum(X)
Definition: postgres.h:595
static char * ChooseExtendedStatisticName(const char *name1, const char *name2, const char *label, Oid namespaceid)
Definition: statscmds.c:674
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
struct typedefs * types
Definition: ecpg.c:29
Oid GetUserId(void)
Definition: miscinit.c:380
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2987
#define PointerGetDatum(X)
Definition: postgres.h:556
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:3291
Definition: nodes.h:525
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:608
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
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:164
#define lengthof(array)
Definition: c.h:663
Form_pg_class rd_rel
Definition: rel.h:83
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
int namestrcpy(Name name, const char *str)
Definition: name.c:250
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
#define linitial(l)
Definition: pg_list.h:195
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
NameData attname
Definition: pg_attribute.h:40
Definition: c.h:604
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:578
#define RelationGetRelationName(relation)
Definition: rel.h:457
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
static int compare_int16(const void *a, const void *b)
Definition: statscmds.c:49
#define ereport(elevel, rest)
Definition: elog.h:141
Definition: c.h:578
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: relation.c:138
TupleDesc rd_att
Definition: rel.h:84
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
#define InvalidOid
Definition: postgres_ext.h:36
#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:733
#define lfirst(lc)
Definition: pg_list.h:190
Definition: value.h:42
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4754
static char * ChooseExtendedStatisticNameAddition(List *exprs)
Definition: statscmds.c:716
static int list_length(const List *l)
Definition: pg_list.h:169
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition: syscache.h:185
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1257
#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:416
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1270
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define Int32GetDatum(X)
Definition: postgres.h:479
#define STATS_MAX_DIMENSIONS
Definition: statistics.h:19
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:822
int i
ObjectType get_relkind_objtype(char relkind)
#define TYPECACHE_LT_OPR
Definition: typcache.h:129
#define StatisticExtOidIndexId
Definition: indexing.h:234
#define qsort(a, b, c, d)
Definition: port.h:492
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:31
#define RelationGetRelid(relation)
Definition: rel.h:423
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183
List * fields
Definition: parsenodes.h:235
#define RelationGetNamespace(relation)
Definition: rel.h:464

◆ CreateTransform()

ObjectAddress CreateTransform ( CreateTransformStmt stmt)

Definition at line 1886 of file functioncmds.c.

References ACL_EXECUTE, ACL_USAGE, aclcheck_error(), aclcheck_error_type(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, CatalogTupleInsert(), CatalogTupleUpdate(), check_transform_function(), ObjectAddress::classId, deleteDependencyRecordsFor(), DEPENDENCY_NORMAL, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, format_type_be(), 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(), OBJECT_FUNCTION, OBJECT_LANGUAGE, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, ObjectWithArgs::objname, OidIsValid, pg_language_aclcheck(), pg_proc_aclcheck(), pg_proc_ownercheck(), pg_type_aclcheck(), pg_type_ownercheck(), PROCOID, recordDependencyOn(), 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().

1887 {
1888  Oid typeid;
1889  char typtype;
1890  Oid langid;
1891  Oid fromsqlfuncid;
1892  Oid tosqlfuncid;
1893  AclResult aclresult;
1894  Form_pg_proc procstruct;
1895  Datum values[Natts_pg_transform];
1896  bool nulls[Natts_pg_transform];
1897  bool replaces[Natts_pg_transform];
1898  Oid transformid;
1899  HeapTuple tuple;
1900  HeapTuple newtuple;
1901  Relation relation;
1902  ObjectAddress myself,
1903  referenced;
1904  bool is_replace;
1905 
1906  /*
1907  * Get the type
1908  */
1909  typeid = typenameTypeId(NULL, stmt->type_name);
1910  typtype = get_typtype(typeid);
1911 
1912  if (typtype == TYPTYPE_PSEUDO)
1913  ereport(ERROR,
1914  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1915  errmsg("data type %s is a pseudo-type",
1916  TypeNameToString(stmt->type_name))));
1917 
1918  if (typtype == TYPTYPE_DOMAIN)
1919  ereport(ERROR,
1920  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1921  errmsg("data type %s is a domain",
1922  TypeNameToString(stmt->type_name))));
1923 
1924  if (!pg_type_ownercheck(typeid, GetUserId()))
1926 
1927  aclresult = pg_type_aclcheck(typeid, GetUserId(), ACL_USAGE);
1928  if (aclresult != ACLCHECK_OK)
1929  aclcheck_error_type(aclresult, typeid);
1930 
1931  /*
1932  * Get the language
1933  */
1934  langid = get_language_oid(stmt->lang, false);
1935 
1936  aclresult = pg_language_aclcheck(langid, GetUserId(), ACL_USAGE);
1937  if (aclresult != ACLCHECK_OK)
1938  aclcheck_error(aclresult, OBJECT_LANGUAGE, stmt->lang);
1939 
1940  /*
1941  * Get the functions
1942  */
1943  if (stmt->fromsql)
1944  {
1945  fromsqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->fromsql, false);
1946 
1947  if (!pg_proc_ownercheck(fromsqlfuncid, GetUserId()))
1949 
1950  aclresult = pg_proc_aclcheck(fromsqlfuncid, GetUserId(), ACL_EXECUTE);
1951  if (aclresult != ACLCHECK_OK)
1953 
1954  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fromsqlfuncid));
1955  if (!HeapTupleIsValid(tuple))
1956  elog(ERROR, "cache lookup failed for function %u", fromsqlfuncid);
1957  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1958  if (procstruct->prorettype != INTERNALOID)
1959  ereport(ERROR,
1960  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1961  errmsg("return data type of FROM SQL function must be %s",
1962  "internal")));
1963  check_transform_function(procstruct);
1964  ReleaseSysCache(tuple);
1965  }
1966  else
1967  fromsqlfuncid = InvalidOid;
1968 
1969  if (stmt->tosql)
1970  {
1971  tosqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->tosql, false);
1972 
1973  if (!pg_proc_ownercheck(tosqlfuncid, GetUserId()))
1975 
1976  aclresult = pg_proc_aclcheck(tosqlfuncid, GetUserId(), ACL_EXECUTE);
1977  if (aclresult != ACLCHECK_OK)
1979 
1980  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(tosqlfuncid));
1981  if (!HeapTupleIsValid(tuple))
1982  elog(ERROR, "cache lookup failed for function %u", tosqlfuncid);
1983  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1984  if (procstruct->prorettype != typeid)
1985  ereport(ERROR,
1986  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1987  errmsg("return data type of TO SQL function must be the transform data type")));
1988  check_transform_function(procstruct);
1989  ReleaseSysCache(tuple);
1990  }
1991  else
1992  tosqlfuncid = InvalidOid;
1993 
1994  /*
1995  * Ready to go
1996  */
1997  values[Anum_pg_transform_trftype - 1] = ObjectIdGetDatum(typeid);
1998  values[Anum_pg_transform_trflang - 1] = ObjectIdGetDatum(langid);
1999  values[Anum_pg_transform_trffromsql - 1] = ObjectIdGetDatum(fromsqlfuncid);
2000  values[Anum_pg_transform_trftosql - 1] = ObjectIdGetDatum(tosqlfuncid);
2001 
2002  MemSet(nulls, false, sizeof(nulls));
2003 
2004  relation = table_open(TransformRelationId, RowExclusiveLock);
2005 
2006  tuple = SearchSysCache2(TRFTYPELANG,
2007  ObjectIdGetDatum(typeid),
2008  ObjectIdGetDatum(langid));
2009  if (HeapTupleIsValid(tuple))
2010  {
2012 
2013  if (!stmt->replace)
2014  ereport(ERROR,
2016  errmsg("transform for type %s language \"%s\" already exists",
2017  format_type_be(typeid),
2018  stmt->lang)));
2019 
2020  MemSet(replaces, false, sizeof(replaces));
2021  replaces[Anum_pg_transform_trffromsql - 1] = true;
2022  replaces[Anum_pg_transform_trftosql - 1] = true;
2023 
2024  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
2025  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2026 
2027  transformid = form->oid;
2028  ReleaseSysCache(tuple);
2029  is_replace = true;
2030  }
2031  else
2032  {
2033  transformid = GetNewOidWithIndex(relation, TransformOidIndexId,
2034  Anum_pg_transform_oid);
2035  values[Anum_pg_transform_oid - 1] = ObjectIdGetDatum(transformid);
2036  newtuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
2037  CatalogTupleInsert(relation, newtuple);
2038  is_replace = false;
2039  }
2040 
2041  if (is_replace)
2042  deleteDependencyRecordsFor(TransformRelationId, transformid, true);
2043 
2044  /* make dependency entries */
2045  myself.classId = TransformRelationId;
2046  myself.objectId = transformid;
2047  myself.objectSubId = 0;
2048 
2049  /* dependency on language */
2050  referenced.classId = LanguageRelationId;
2051  referenced.objectId = langid;
2052  referenced.objectSubId = 0;
2053  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
2054 
2055  /* dependency on type */
2056  referenced.classId = TypeRelationId;
2057  referenced.objectId = typeid;
2058  referenced.objectSubId = 0;
2059  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
2060 
2061  /* dependencies on functions */
2062  if (OidIsValid(fromsqlfuncid))
2063  {
2064  referenced.classId = ProcedureRelationId;
2065  referenced.objectId = fromsqlfuncid;
2066  referenced.objectSubId = 0;
2067  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
2068  }
2069  if (OidIsValid(tosqlfuncid))
2070  {
2071  referenced.classId = ProcedureRelationId;
2072  referenced.objectId = tosqlfuncid;
2073  referenced.objectSubId = 0;
2074  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
2075  }
2076 
2077  /* dependency on extension */
2078  recordDependencyOnCurrentExtension(&myself, is_replace);
2079 
2080  /* Post creation hook for new transform */
2081  InvokeObjectPostCreateHook(TransformRelationId, transformid, 0);
2082 
2083  heap_freetuple(newtuple);
2084 
2085  table_close(relation, RowExclusiveLock);
2086 
2087  return myself;
2088 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:322
ObjectWithArgs * tosql
Definition: parsenodes.h:3378
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
static void check_transform_function(Form_pg_proc procstruct)
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
#define RelationGetDescr(relation)
Definition: rel.h:449
Oid GetUserId(void)
Definition: miscinit.c:380
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:476
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:190
Oid get_language_oid(const char *langname, bool missing_ok)
Definition: proclang.c:559
int errcode(int sqlerrcode)
Definition: elog.c:608
char get_typtype(Oid typid)
Definition: lsyscache.c:2407
#define MemSet(start, val, len)
Definition: c.h:956
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
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
bool pg_type_ownercheck(Oid type_oid, Oid roleid)
Definition: aclchk.c:4780
#define OidIsValid(objectId)
Definition: c.h:639
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4666
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3665
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
FormData_pg_transform * Form_pg_transform
Definition: pg_transform.h:43
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define TransformOidIndexId
Definition: indexing.h:249
#define ACL_USAGE
Definition: parsenodes.h:82
#define ereport(elevel, rest)
Definition: elog.h:141
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
char * NameListToString(List *names)
Definition: namespace.c:3094
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:134
#define InvalidOid
Definition: postgres_ext.h:36
ObjectWithArgs * fromsql
Definition: parsenodes.h:3377
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:138
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1127
TypeName * type_name
Definition: parsenodes.h:3375
static Datum values[MAXATTR]
Definition: bootstrap.c:167
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define ACL_EXECUTE
Definition: parsenodes.h:81
#define elog(elevel,...)
Definition: elog.h:228
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4654
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2161
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4742
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:31
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183
bool pg_proc_ownercheck(Oid proc_oid, Oid roleid)
Definition: aclchk.c:4832
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:291

◆ CreateUserMapping()

ObjectAddress CreateUserMapping ( CreateUserMappingStmt stmt)

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

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