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)
 
Oid ReindexTable (RangeVar *relation, int options)
 
void ReindexMultipleTables (const char *objectName, ReindexObjectType objectKind, int options)
 
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 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)
 
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)
 
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)
 
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_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 673 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_close, heap_freetuple(), heap_modify_tuple(), heap_open(), HeapTupleGetOid, 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, transformGenericOptions(), and WARNING.

Referenced by ProcessUtilitySlow().

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

◆ AlterForeignDataWrapperOwner()

ObjectAddress AlterForeignDataWrapperOwner ( const char *  name,
Oid  newOwnerId 
)

Definition at line 277 of file foreigncmds.c.

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

Referenced by ExecAlterOwnerStmt().

278 {
279  Oid fdwId;
280  HeapTuple tup;
281  Relation rel;
282  ObjectAddress address;
283 
284  rel = heap_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 
293  fdwId = HeapTupleGetOid(tup);
294 
295  AlterForeignDataWrapperOwner_internal(rel, tup, newOwnerId);
296 
297  ObjectAddressSet(address, ForeignDataWrapperRelationId, fdwId);
298 
299  heap_freetuple(tup);
300 
302 
303  return address;
304 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
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:563
#define ereport(elevel, rest)
Definition: elog.h:122
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
const char * name
Definition: encode.c:521
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void AlterForeignDataWrapperOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
Definition: foreigncmds.c:207
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:707

◆ AlterForeignDataWrapperOwner_oid()

void AlterForeignDataWrapperOwner_oid ( Oid  fwdId,
Oid  newOwnerId 
)

Definition at line 312 of file foreigncmds.c.

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

Referenced by shdepReassignOwned().

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

◆ AlterForeignServer()

ObjectAddress AlterForeignServer ( AlterForeignServerStmt stmt)

Definition at line 985 of file foreigncmds.c.

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

Referenced by ProcessUtilitySlow().

986 {
987  Relation rel;
988  HeapTuple tp;
989  Datum repl_val[Natts_pg_foreign_server];
990  bool repl_null[Natts_pg_foreign_server];
991  bool repl_repl[Natts_pg_foreign_server];
992  Oid srvId;
993  Form_pg_foreign_server srvForm;
994  ObjectAddress address;
995 
996  rel = heap_open(ForeignServerRelationId, RowExclusiveLock);
997 
999  CStringGetDatum(stmt->servername));
1000 
1001  if (!HeapTupleIsValid(tp))
1002  ereport(ERROR,
1003  (errcode(ERRCODE_UNDEFINED_OBJECT),
1004  errmsg("server \"%s\" does not exist", stmt->servername)));
1005 
1006  srvId = HeapTupleGetOid(tp);
1007  srvForm = (Form_pg_foreign_server) GETSTRUCT(tp);
1008 
1009  /*
1010  * Only owner or a superuser can ALTER a SERVER.
1011  */
1012  if (!pg_foreign_server_ownercheck(srvId, GetUserId()))
1014  stmt->servername);
1015 
1016  memset(repl_val, 0, sizeof(repl_val));
1017  memset(repl_null, false, sizeof(repl_null));
1018  memset(repl_repl, false, sizeof(repl_repl));
1019 
1020  if (stmt->has_version)
1021  {
1022  /*
1023  * Change the server VERSION string.
1024  */
1025  if (stmt->version)
1026  repl_val[Anum_pg_foreign_server_srvversion - 1] =
1028  else
1029  repl_null[Anum_pg_foreign_server_srvversion - 1] = true;
1030 
1031  repl_repl[Anum_pg_foreign_server_srvversion - 1] = true;
1032  }
1033 
1034  if (stmt->options)
1035  {
1036  ForeignDataWrapper *fdw = GetForeignDataWrapper(srvForm->srvfdw);
1037  Datum datum;
1038  bool isnull;
1039 
1040  /* Extract the current srvoptions */
1042  tp,
1043  Anum_pg_foreign_server_srvoptions,
1044  &isnull);
1045  if (isnull)
1046  datum = PointerGetDatum(NULL);
1047 
1048  /* Prepare the options array */
1049  datum = transformGenericOptions(ForeignServerRelationId,
1050  datum,
1051  stmt->options,
1052  fdw->fdwvalidator);
1053 
1054  if (PointerIsValid(DatumGetPointer(datum)))
1055  repl_val[Anum_pg_foreign_server_srvoptions - 1] = datum;
1056  else
1057  repl_null[Anum_pg_foreign_server_srvoptions - 1] = true;
1058 
1059  repl_repl[Anum_pg_foreign_server_srvoptions - 1] = true;
1060  }
1061 
1062  /* Everything looks good - update the tuple */
1063  tp = heap_modify_tuple(tp, RelationGetDescr(rel),
1064  repl_val, repl_null, repl_repl);
1065 
1066  CatalogTupleUpdate(rel, &tp->t_self, tp);
1067 
1068  InvokeObjectPostAlterHook(ForeignServerRelationId, srvId, 0);
1069 
1070  ObjectAddressSet(address, ForeignServerRelationId, srvId);
1071 
1072  heap_freetuple(tp);
1073 
1075 
1076  return address;
1077 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
#define RelationGetDescr(relation)
Definition: rel.h:433
Oid GetUserId(void)
Definition: miscinit.c:379
Datum transformGenericOptions(Oid catalogId, Datum oldOptions, List *options, Oid fdwvalidator)
Definition: foreigncmds.c:109
#define PointerGetDatum(X)
Definition: postgres.h:541
bool pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid)
Definition: aclchk.c:5115
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
unsigned int Oid
Definition: postgres_ext.h:31
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3349
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:563
#define ereport(elevel, rest)
Definition: elog.h:122
#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:1368
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
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:211
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define DatumGetPointer(X)
Definition: postgres.h:534
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define CStringGetTextDatum(s)
Definition: builtins.h:95
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:707
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1173
#define PointerIsValid(pointer)
Definition: c.h:593

◆ AlterForeignServerOwner()

ObjectAddress AlterForeignServerOwner ( const char *  name,
Oid  newOwnerId 
)

Definition at line 414 of file foreigncmds.c.

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

Referenced by ExecAlterOwnerStmt().

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

◆ AlterForeignServerOwner_oid()

void AlterForeignServerOwner_oid ( Oid  ,
Oid  newOwnerId 
)

Definition at line 447 of file foreigncmds.c.

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

Referenced by shdepReassignOwned().

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

◆ AlterFunction()

ObjectAddress AlterFunction ( ParseState pstate,
AlterFunctionStmt stmt 
)

Definition at line 1174 of file functioncmds.c.

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

Referenced by ProcessUtilitySlow().

1175 {
1176  HeapTuple tup;
1177  Oid funcOid;
1178  Form_pg_proc procForm;
1179  bool is_procedure;
1180  Relation rel;
1181  ListCell *l;
1182  DefElem *volatility_item = NULL;
1183  DefElem *strict_item = NULL;
1184  DefElem *security_def_item = NULL;
1185  DefElem *leakproof_item = NULL;
1186  List *set_items = NIL;
1187  DefElem *cost_item = NULL;
1188  DefElem *rows_item = NULL;
1189  DefElem *parallel_item = NULL;
1190  ObjectAddress address;
1191 
1192  rel = heap_open(ProcedureRelationId, RowExclusiveLock);
1193 
1194  funcOid = LookupFuncWithArgs(stmt->objtype, stmt->func, false);
1195 
1196  tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1197  if (!HeapTupleIsValid(tup)) /* should not happen */
1198  elog(ERROR, "cache lookup failed for function %u", funcOid);
1199 
1200  procForm = (Form_pg_proc) GETSTRUCT(tup);
1201 
1202  /* Permission check: must own function */
1203  if (!pg_proc_ownercheck(funcOid, GetUserId()))
1205  NameListToString(stmt->func->objname));
1206 
1207  if (procForm->prokind == PROKIND_AGGREGATE)
1208  ereport(ERROR,
1209  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1210  errmsg("\"%s\" is an aggregate function",
1211  NameListToString(stmt->func->objname))));
1212 
1213  is_procedure = (procForm->prokind == PROKIND_PROCEDURE);
1214 
1215  /* Examine requested actions. */
1216  foreach(l, stmt->actions)
1217  {
1218  DefElem *defel = (DefElem *) lfirst(l);
1219 
1220  if (compute_common_attribute(pstate,
1221  is_procedure,
1222  defel,
1223  &volatility_item,
1224  &strict_item,
1225  &security_def_item,
1226  &leakproof_item,
1227  &set_items,
1228  &cost_item,
1229  &rows_item,
1230  &parallel_item) == false)
1231  elog(ERROR, "option \"%s\" not recognized", defel->defname);
1232  }
1233 
1234  if (volatility_item)
1235  procForm->provolatile = interpret_func_volatility(volatility_item);
1236  if (strict_item)
1237  procForm->proisstrict = intVal(strict_item->arg);
1238  if (security_def_item)
1239  procForm->prosecdef = intVal(security_def_item->arg);
1240  if (leakproof_item)
1241  {
1242  procForm->proleakproof = intVal(leakproof_item->arg);
1243  if (procForm->proleakproof && !superuser())
1244  ereport(ERROR,
1245  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1246  errmsg("only superuser can define a leakproof function")));
1247  }
1248  if (cost_item)
1249  {
1250  procForm->procost = defGetNumeric(cost_item);
1251  if (procForm->procost <= 0)
1252  ereport(ERROR,
1253  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1254  errmsg("COST must be positive")));
1255  }
1256  if (rows_item)
1257  {
1258  procForm->prorows = defGetNumeric(rows_item);
1259  if (procForm->prorows <= 0)
1260  ereport(ERROR,
1261  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1262  errmsg("ROWS must be positive")));
1263  if (!procForm->proretset)
1264  ereport(ERROR,
1265  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1266  errmsg("ROWS is not applicable when function does not return a set")));
1267  }
1268  if (set_items)
1269  {
1270  Datum datum;
1271  bool isnull;
1272  ArrayType *a;
1273  Datum repl_val[Natts_pg_proc];
1274  bool repl_null[Natts_pg_proc];
1275  bool repl_repl[Natts_pg_proc];
1276 
1277  /* extract existing proconfig setting */
1278  datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proconfig, &isnull);
1279  a = isnull ? NULL : DatumGetArrayTypeP(datum);
1280 
1281  /* update according to each SET or RESET item, left to right */
1282  a = update_proconfig_value(a, set_items);
1283 
1284  /* update the tuple */
1285  memset(repl_repl, false, sizeof(repl_repl));
1286  repl_repl[Anum_pg_proc_proconfig - 1] = true;
1287 
1288  if (a == NULL)
1289  {
1290  repl_val[Anum_pg_proc_proconfig - 1] = (Datum) 0;
1291  repl_null[Anum_pg_proc_proconfig - 1] = true;
1292  }
1293  else
1294  {
1295  repl_val[Anum_pg_proc_proconfig - 1] = PointerGetDatum(a);
1296  repl_null[Anum_pg_proc_proconfig - 1] = false;
1297  }
1298 
1299  tup = heap_modify_tuple(tup, RelationGetDescr(rel),
1300  repl_val, repl_null, repl_repl);
1301  }
1302  if (parallel_item)
1303  procForm->proparallel = interpret_func_parallel(parallel_item);
1304 
1305  /* Do the update */
1306  CatalogTupleUpdate(rel, &tup->t_self, tup);
1307 
1308  InvokeObjectPostAlterHook(ProcedureRelationId, funcOid, 0);
1309 
1310  ObjectAddressSet(address, ProcedureRelationId, funcOid);
1311 
1312  heap_close(rel, NoLock);
1313  heap_freetuple(tup);
1314 
1315  return address;
1316 }
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
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 **parallel_item)
Definition: functioncmds.c:471
#define RelationGetDescr(relation)
Definition: rel.h:433
Oid GetUserId(void)
Definition: miscinit.c:379
#define PointerGetDatum(X)
Definition: postgres.h:541
double defGetNumeric(DefElem *def)
Definition: define.c:85
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
unsigned int Oid
Definition: postgres_ext.h:31
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3349
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
ObjectType objtype
Definition: parsenodes.h:2793
#define NoLock
Definition: lockdefs.h:34
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool noError)
Definition: parse_func.c:2086
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
static char interpret_func_volatility(DefElem *defel)
Definition: functioncmds.c:570
Node * arg
Definition: parsenodes.h:731
char * NameListToString(List *names)
Definition: namespace.c:3082
uintptr_t Datum
Definition: postgres.h:367
static ArrayType * update_proconfig_value(ArrayType *a, List *set_items)
Definition: functioncmds.c:613
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:132
ObjectWithArgs * func
Definition: parsenodes.h:2794
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:106
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:211
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
#define intVal(v)
Definition: value.h:52
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * defname
Definition: parsenodes.h:730
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1173
Definition: pg_list.h:45
bool pg_proc_ownercheck(Oid proc_oid, Oid roleid)
Definition: aclchk.c:4829
static char interpret_func_parallel(DefElem *defel)
Definition: functioncmds.c:588
#define DatumGetArrayTypeP(X)
Definition: array.h:246

◆ 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_close, heap_modify_tuple(), heap_open(), 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, 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. procedure */
397  bool updateRestriction = false;
398  Oid restrictionOid;
399  List *joinName = NIL; /* optional join sel. procedure */
400  bool updateJoin = false;
401  Oid joinOid;
402 
403  /* Look up the operator */
404  oprId = LookupOperWithArgs(stmt->opername, false);
405  catalog = heap_open(OperatorRelationId, RowExclusiveLock);
407  if (tup == NULL)
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, "procedure") == 0 ||
440  strcmp(defel->defname, "commutator") == 0 ||
441  strcmp(defel->defname, "negator") == 0 ||
442  strcmp(defel->defname, "hashes") == 0 ||
443  strcmp(defel->defname, "merges") == 0)
444  {
445  ereport(ERROR,
446  (errcode(ERRCODE_SYNTAX_ERROR),
447  errmsg("operator attribute \"%s\" cannot be changed",
448  defel->defname)));
449  }
450  else
451  ereport(ERROR,
452  (errcode(ERRCODE_SYNTAX_ERROR),
453  errmsg("operator attribute \"%s\" not recognized",
454  defel->defname)));
455  }
456 
457  /* Check permissions. Must be owner. */
458  if (!pg_oper_ownercheck(oprId, GetUserId()))
460  NameStr(oprForm->oprname));
461 
462  /*
463  * Look up restriction and join estimators if specified
464  */
465  if (restrictionName)
466  restrictionOid = ValidateRestrictionEstimator(restrictionName);
467  else
468  restrictionOid = InvalidOid;
469  if (joinName)
470  joinOid = ValidateJoinEstimator(joinName);
471  else
472  joinOid = InvalidOid;
473 
474  /* Perform additional checks, like OperatorCreate does */
475  if (!(OidIsValid(oprForm->oprleft) && OidIsValid(oprForm->oprright)))
476  {
477  /* If it's not a binary op, these things mustn't be set: */
478  if (OidIsValid(joinOid))
479  ereport(ERROR,
480  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
481  errmsg("only binary operators can have join selectivity")));
482  }
483 
484  if (oprForm->oprresult != BOOLOID)
485  {
486  if (OidIsValid(restrictionOid))
487  ereport(ERROR,
488  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
489  errmsg("only boolean operators can have restriction selectivity")));
490  if (OidIsValid(joinOid))
491  ereport(ERROR,
492  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
493  errmsg("only boolean operators can have join selectivity")));
494  }
495 
496  /* Update the tuple */
497  for (i = 0; i < Natts_pg_operator; ++i)
498  {
499  values[i] = (Datum) 0;
500  replaces[i] = false;
501  nulls[i] = false;
502  }
503  if (updateRestriction)
504  {
505  replaces[Anum_pg_operator_oprrest - 1] = true;
506  values[Anum_pg_operator_oprrest - 1] = restrictionOid;
507  }
508  if (updateJoin)
509  {
510  replaces[Anum_pg_operator_oprjoin - 1] = true;
511  values[Anum_pg_operator_oprjoin - 1] = joinOid;
512  }
513 
514  tup = heap_modify_tuple(tup, RelationGetDescr(catalog),
515  values, nulls, replaces);
516 
517  CatalogTupleUpdate(catalog, &tup->t_self, tup);
518 
519  address = makeOperatorDependencies(tup, true);
520 
521  InvokeObjectPostAlterHook(OperatorRelationId, oprId, 0);
522 
523  heap_close(catalog, NoLock);
524 
525  return address;
526 }
Oid LookupOperWithArgs(ObjectWithArgs *oper, bool noError)
Definition: parse_oper.c:140
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
#define RelationGetDescr(relation)
Definition: rel.h:433
Oid GetUserId(void)
Definition: miscinit.c:379
ObjectAddress makeOperatorDependencies(HeapTuple tuple, bool isUpdate)
Definition: pg_operator.c:763
static Oid ValidateJoinEstimator(List *joinName)
Definition: operatorcmds.c:295
bool pg_oper_ownercheck(Oid oper_oid, Oid roleid)
Definition: aclchk.c:4803
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3349
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#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:122
#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:2902
uintptr_t Datum
Definition: postgres.h:367
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define InvalidOid
Definition: postgres_ext.h:36
#define lfirst(lc)
Definition: pg_list.h:106
List * defGetQualifiedName(DefElem *def)
Definition: define.c:223
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:211
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:82
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define NameStr(name)
Definition: c.h:576
char * defname
Definition: parsenodes.h:730
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1173
Definition: pg_list.h:45

◆ AlterOpFamily()

Oid AlterOpFamily ( AlterOpFamilyStmt stmt)

Definition at line 764 of file opclasscmds.c.

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

Referenced by ProcessUtilitySlow().

765 {
766  Oid amoid, /* our AM's oid */
767  opfamilyoid; /* oid of opfamily */
768  int maxOpNumber, /* amstrategies value */
769  maxProcNumber; /* amsupport value */
770  HeapTuple tup;
771  IndexAmRoutine *amroutine;
772 
773  /* Get necessary info about access method */
775  if (!HeapTupleIsValid(tup))
776  ereport(ERROR,
777  (errcode(ERRCODE_UNDEFINED_OBJECT),
778  errmsg("access method \"%s\" does not exist",
779  stmt->amname)));
780 
781  amoid = HeapTupleGetOid(tup);
782  amroutine = GetIndexAmRoutineByAmId(amoid, false);
783  ReleaseSysCache(tup);
784 
785  maxOpNumber = amroutine->amstrategies;
786  /* if amstrategies is zero, just enforce that op numbers fit in int16 */
787  if (maxOpNumber <= 0)
788  maxOpNumber = SHRT_MAX;
789  maxProcNumber = amroutine->amsupport;
790 
791  /* XXX Should we make any privilege check against the AM? */
792 
793  /* Look up the opfamily */
794  opfamilyoid = get_opfamily_oid(amoid, stmt->opfamilyname, false);
795 
796  /*
797  * Currently, we require superuser privileges to alter an opfamily.
798  *
799  * XXX re-enable NOT_USED code sections below if you remove this test.
800  */
801  if (!superuser())
802  ereport(ERROR,
803  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
804  errmsg("must be superuser to alter an operator family")));
805 
806  /*
807  * ADD and DROP cases need separate code from here on down.
808  */
809  if (stmt->isDrop)
810  AlterOpFamilyDrop(stmt, amoid, opfamilyoid,
811  maxOpNumber, maxProcNumber, stmt->items);
812  else
813  AlterOpFamilyAdd(stmt, amoid, opfamilyoid,
814  maxOpNumber, maxProcNumber, stmt->items);
815 
816  return opfamilyoid;
817 }
uint16 amsupport
Definition: amapi.h:170
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
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:948
#define ERROR
Definition: elog.h:43
IndexAmRoutine * GetIndexAmRoutineByAmId(Oid amoid, bool noerror)
Definition: amapi.c:56
#define CStringGetDatum(X)
Definition: postgres.h:563
#define ereport(elevel, rest)
Definition: elog.h:122
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#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:823
Oid get_opfamily_oid(Oid amID, List *opfamilyname, bool missing_ok)
Definition: opclasscmds.c:142
uint16 amstrategies
Definition: amapi.h:168
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:707

◆ AlterTSConfiguration()

ObjectAddress AlterTSConfiguration ( AlterTSConfigurationStmt stmt)

Definition at line 1173 of file tsearchcmds.c.

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

Referenced by ProcessUtilitySlow().

1174 {
1175  HeapTuple tup;
1176  Oid cfgId;
1177  Relation relMap;
1178  ObjectAddress address;
1179 
1180  /* Find the configuration */
1181  tup = GetTSConfigTuple(stmt->cfgname);
1182  if (!HeapTupleIsValid(tup))
1183  ereport(ERROR,
1184  (errcode(ERRCODE_UNDEFINED_OBJECT),
1185  errmsg("text search configuration \"%s\" does not exist",
1186  NameListToString(stmt->cfgname))));
1187 
1188  cfgId = HeapTupleGetOid(tup);
1189 
1190  /* must be owner */
1193  NameListToString(stmt->cfgname));
1194 
1195  relMap = heap_open(TSConfigMapRelationId, RowExclusiveLock);
1196 
1197  /* Add or drop mappings */
1198  if (stmt->dicts)
1199  MakeConfigurationMapping(stmt, tup, relMap);
1200  else if (stmt->tokentype)
1201  DropConfigurationMapping(stmt, tup, relMap);
1202 
1203  /* Update dependencies */
1204  makeConfigurationDependencies(tup, true, relMap);
1205 
1206  InvokeObjectPostAlterHook(TSConfigRelationId,
1207  HeapTupleGetOid(tup), 0);
1208 
1209  ObjectAddressSet(address, TSConfigRelationId, cfgId);
1210 
1211  heap_close(relMap, RowExclusiveLock);
1212 
1213  ReleaseSysCache(tup);
1214 
1215  return address;
1216 }
Oid GetUserId(void)
Definition: miscinit.c:379
bool pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid)
Definition: aclchk.c:5061
static ObjectAddress makeConfigurationDependencies(HeapTuple tuple, bool removeOld, Relation mapRel)
Definition: tsearchcmds.c:873
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
static void DropConfigurationMapping(AlterTSConfigurationStmt *stmt, HeapTuple tup, Relation relMap)
Definition: tsearchcmds.c:1438
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3349
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
static HeapTuple GetTSConfigTuple(List *names)
Definition: tsearchcmds.c:848
char * NameListToString(List *names)
Definition: namespace.c:3082
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#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:797
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:707
static void MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, HeapTuple tup, Relation relMap)
Definition: tsearchcmds.c:1277

◆ AlterTSDictionary()

ObjectAddress AlterTSDictionary ( AlterTSDictionaryStmt stmt)

Definition at line 525 of file tsearchcmds.c.

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

Referenced by ProcessUtilitySlow().

526 {
527  HeapTuple tup,
528  newtup;
529  Relation rel;
530  Oid dictId;
531  ListCell *pl;
532  List *dictoptions;
533  Datum opt;
534  bool isnull;
535  Datum repl_val[Natts_pg_ts_dict];
536  bool repl_null[Natts_pg_ts_dict];
537  bool repl_repl[Natts_pg_ts_dict];
538  ObjectAddress address;
539 
540  dictId = get_ts_dict_oid(stmt->dictname, false);
541 
542  rel = heap_open(TSDictionaryRelationId, RowExclusiveLock);
543 
545 
546  if (!HeapTupleIsValid(tup))
547  elog(ERROR, "cache lookup failed for text search dictionary %u",
548  dictId);
549 
550  /* must be owner */
551  if (!pg_ts_dict_ownercheck(dictId, GetUserId()))
553  NameListToString(stmt->dictname));
554 
555  /* deserialize the existing set of options */
556  opt = SysCacheGetAttr(TSDICTOID, tup,
557  Anum_pg_ts_dict_dictinitoption,
558  &isnull);
559  if (isnull)
560  dictoptions = NIL;
561  else
562  dictoptions = deserialize_deflist(opt);
563 
564  /*
565  * Modify the options list as per specified changes
566  */
567  foreach(pl, stmt->options)
568  {
569  DefElem *defel = (DefElem *) lfirst(pl);
570  ListCell *cell;
571  ListCell *prev;
572  ListCell *next;
573 
574  /*
575  * Remove any matches ...
576  */
577  prev = NULL;
578  for (cell = list_head(dictoptions); cell; cell = next)
579  {
580  DefElem *oldel = (DefElem *) lfirst(cell);
581 
582  next = lnext(cell);
583  if (strcmp(oldel->defname, defel->defname) == 0)
584  dictoptions = list_delete_cell(dictoptions, cell, prev);
585  else
586  prev = cell;
587  }
588 
589  /*
590  * and add new value if it's got one
591  */
592  if (defel->arg)
593  dictoptions = lappend(dictoptions, defel);
594  }
595 
596  /*
597  * Validate
598  */
599  verify_dictoptions(((Form_pg_ts_dict) GETSTRUCT(tup))->dicttemplate,
600  dictoptions);
601 
602  /*
603  * Looks good, update
604  */
605  memset(repl_val, 0, sizeof(repl_val));
606  memset(repl_null, false, sizeof(repl_null));
607  memset(repl_repl, false, sizeof(repl_repl));
608 
609  if (dictoptions)
610  repl_val[Anum_pg_ts_dict_dictinitoption - 1] =
611  PointerGetDatum(serialize_deflist(dictoptions));
612  else
613  repl_null[Anum_pg_ts_dict_dictinitoption - 1] = true;
614  repl_repl[Anum_pg_ts_dict_dictinitoption - 1] = true;
615 
616  newtup = heap_modify_tuple(tup, RelationGetDescr(rel),
617  repl_val, repl_null, repl_repl);
618 
619  CatalogTupleUpdate(rel, &newtup->t_self, newtup);
620 
621  InvokeObjectPostAlterHook(TSDictionaryRelationId, dictId, 0);
622 
623  ObjectAddressSet(address, TSDictionaryRelationId, dictId);
624 
625  /*
626  * NOTE: because we only support altering the options, not the template,
627  * there is no need to update dependencies. This might have to change if
628  * the options ever reference inside-the-database objects.
629  */
630 
631  heap_freetuple(newtup);
632  ReleaseSysCache(tup);
633 
635 
636  return address;
637 }
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
static int32 next
Definition: blutils.c:211
bool pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid)
Definition: aclchk.c:5034
#define RelationGetDescr(relation)
Definition: rel.h:433
Oid GetUserId(void)
Definition: miscinit.c:379
#define PointerGetDatum(X)
Definition: postgres.h:541
List * deserialize_deflist(Datum txt)
Definition: tsearchcmds.c:1561
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
unsigned int Oid
Definition: postgres_ext.h:31
Oid get_ts_dict_oid(List *names, bool missing_ok)
Definition: namespace.c:2405
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3349
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#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:41
#define RowExclusiveLock
Definition: lockdefs.h:38
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
Node * arg
Definition: parsenodes.h:731
List * lappend(List *list, void *datum)
Definition: list.c:128
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
char * NameListToString(List *names)
Definition: namespace.c:3082
List * list_delete_cell(List *list, ListCell *cell, ListCell *prev)
Definition: list.c:528
text * serialize_deflist(List *deflist)
Definition: tsearchcmds.c:1516
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:106
static void verify_dictoptions(Oid tmplId, List *dictoptions)
Definition: tsearchcmds.c:354
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:211
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
char * defname
Definition: parsenodes.h:730
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1173
Definition: pg_list.h:45

◆ AlterUserMapping()

ObjectAddress AlterUserMapping ( AlterUserMappingStmt stmt)

Definition at line 1250 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_close, heap_freetuple(), heap_modify_tuple(), heap_open(), HeapTupleIsValid, MappingUserName, ObjectAddressSet, ObjectIdGetDatum, OidIsValid, AlterUserMappingStmt::options, PointerGetDatum, PointerIsValid, RelationGetDescr, ROLESPEC_PUBLIC, RoleSpec::roletype, RowExclusiveLock, SearchSysCacheCopy1, ForeignServer::serverid, AlterUserMappingStmt::servername, SysCacheGetAttr(), HeapTupleData::t_self, transformGenericOptions(), AlterUserMappingStmt::user, user_mapping_ddl_aclcheck(), and USERMAPPINGOID.

Referenced by ProcessUtilitySlow().

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

◆ CheckIndexCompatible()

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

Definition at line 126 of file indexcmds.c.

References AccessShareLock, IndexAmRoutine::amcanorder, AMNAME, Assert, ComputeIndexAttrs(), CurrentMemoryContext, DatumGetPointer, elog, ereport, errcode(), errmsg(), ERROR, get_opclass_input_type(), GetIndexAmRoutine(), GETSTRUCT, heap_attisnull(), HeapTupleGetOid, HeapTupleIsValid, i, IndexInfo::ii_Am, IndexInfo::ii_AmCache, IndexInfo::ii_Context, IndexInfo::ii_ExclusionOps, IndexInfo::ii_ExclusionProcs, IndexInfo::ii_ExclusionStrats, IndexInfo::ii_Expressions, IndexInfo::ii_ExpressionsState, IndexInfo::ii_NumIndexAttrs, IndexInfo::ii_NumIndexKeyAttrs, IndexInfo::ii_PredicateState, index_close(), INDEX_MAX_KEYS, index_open(), IndexGetRelation(), IndexIsValid, INDEXRELID, list_length(), makeNode, NIL, NoLock, ObjectIdGetDatum, op_input_types(), palloc(), PointerGetDatum, RelationData::rd_att, RelationGetExclusionInfo(), ReleaseSysCache(), SearchSysCache1(), SysCacheGetAttr(), TupleDescAttr, and oidvector::values.

Referenced by TryReuseIndex().

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

◆ ChooseRelationName()

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

Definition at line 1988 of file indexcmds.c.

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

Referenced by ChooseIndexName(), and generateSerialExtraStmts().

1990 {
1991  int pass = 0;
1992  char *relname = NULL;
1993  char modlabel[NAMEDATALEN];
1994 
1995  /* try the unmodified label first */
1996  StrNCpy(modlabel, label, sizeof(modlabel));
1997 
1998  for (;;)
1999  {
2000  relname = makeObjectName(name1, name2, modlabel);
2001 
2002  if (!OidIsValid(get_relname_relid(relname, namespaceid)))
2003  break;
2004 
2005  /* found a conflict, so try a new name component */
2006  pfree(relname);
2007  snprintf(modlabel, sizeof(modlabel), "%s%d", label, ++pass);
2008  }
2009 
2010  return relname;
2011 }
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define OidIsValid(objectId)
Definition: c.h:605
char * makeObjectName(const char *name1, const char *name2, const char *label)
Definition: indexcmds.c:1908
#define NAMEDATALEN
void pfree(void *pointer)
Definition: mcxt.c:1031
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1687
static char * label
Definition: pg_basebackup.c:84
#define StrNCpy(dst, src, len)
Definition: c.h:881

◆ CreateAccessMethod()

ObjectAddress CreateAccessMethod ( CreateAmStmt stmt)

Definition at line 41 of file amcmds.c.

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

Referenced by ProcessUtilitySlow().

42 {
43  Relation rel;
44  ObjectAddress myself;
45  ObjectAddress referenced;
46  Oid amoid;
47  Oid amhandler;
48  bool nulls[Natts_pg_am];
49  Datum values[Natts_pg_am];
50  HeapTuple tup;
51 
52  rel = heap_open(AccessMethodRelationId, RowExclusiveLock);
53 
54  /* Must be super user */
55  if (!superuser())
56  ereport(ERROR,
57  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
58  errmsg("permission denied to create access method \"%s\"",
59  stmt->amname),
60  errhint("Must be superuser to create an access method.")));
61 
62  /* Check if name is used */
64  if (OidIsValid(amoid))
65  {
66  ereport(ERROR,
68  errmsg("access method \"%s\" already exists",
69  stmt->amname)));
70  }
71 
72  /*
73  * Get the handler function oid, verifying the AM type while at it.
74  */
75  amhandler = lookup_index_am_handler_func(stmt->handler_name, stmt->amtype);
76 
77  /*
78  * Insert tuple into pg_am.
79  */
80  memset(values, 0, sizeof(values));
81  memset(nulls, false, sizeof(nulls));
82 
83  values[Anum_pg_am_amname - 1] =
85  values[Anum_pg_am_amhandler - 1] = ObjectIdGetDatum(amhandler);
86  values[Anum_pg_am_amtype - 1] = CharGetDatum(stmt->amtype);
87 
88  tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
89 
90  amoid = CatalogTupleInsert(rel, tup);
91  heap_freetuple(tup);
92 
93  myself.classId = AccessMethodRelationId;
94  myself.objectId = amoid;
95  myself.objectSubId = 0;
96 
97  /* Record dependency on handler function */
98  referenced.classId = ProcedureRelationId;
99  referenced.objectId = amhandler;
100  referenced.objectSubId = 0;
101 
102  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
103 
104  recordDependencyOnCurrentExtension(&myself, false);
105 
107 
108  return myself;
109 }
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:46
int errhint(const char *fmt,...)
Definition: elog.c:987
#define RelationGetDescr(relation)
Definition: rel.h:433
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1074
#define heap_close(r, l)
Definition: heapam.h:97
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
#define GetSysCacheOid1(cacheId, key1)
Definition: syscache.h:191
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:163
char * amname
Definition: parsenodes.h:2356
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:563
static Oid lookup_index_am_handler_func(List *handler_name, char amtype)
Definition: amcmds.c:242
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:367
List * handler_name
Definition: parsenodes.h:2357
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:139
#define CharGetDatum(X)
Definition: postgres.h:401
static Datum values[MAXATTR]
Definition: bootstrap.c:164
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32

◆ CreateCast()

ObjectAddress CreateCast ( CreateCastStmt stmt)

Definition at line 1410 of file functioncmds.c.

References ACL_USAGE, aclcheck_error_type(), ACLCHECK_OK, 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(), GETSTRUCT, GetUserId(), heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), 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(), CreateCastStmt::targettype, TypeNameToString(), typenameTypeId(), values, and WARNING.

Referenced by ProcessUtilitySlow().

1411 {
1412  Oid sourcetypeid;
1413  Oid targettypeid;
1414  char sourcetyptype;
1415  char targettyptype;
1416  Oid funcid;
1417  Oid castid;
1418  int nargs;
1419  char castcontext;
1420  char castmethod;
1421  Relation relation;
1422  HeapTuple tuple;
1423  Datum values[Natts_pg_cast];
1424  bool nulls[Natts_pg_cast];
1425  ObjectAddress myself,
1426  referenced;
1427  AclResult aclresult;
1428 
1429  sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
1430  targettypeid = typenameTypeId(NULL, stmt->targettype);
1431  sourcetyptype = get_typtype(sourcetypeid);
1432  targettyptype = get_typtype(targettypeid);
1433 
1434  /* No pseudo-types allowed */
1435  if (sourcetyptype == TYPTYPE_PSEUDO)
1436  ereport(ERROR,
1437  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1438  errmsg("source data type %s is a pseudo-type",
1439  TypeNameToString(stmt->sourcetype))));
1440 
1441  if (targettyptype == TYPTYPE_PSEUDO)
1442  ereport(ERROR,
1443  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1444  errmsg("target data type %s is a pseudo-type",
1445  TypeNameToString(stmt->targettype))));
1446 
1447  /* Permission check */
1448  if (!pg_type_ownercheck(sourcetypeid, GetUserId())
1449  && !pg_type_ownercheck(targettypeid, GetUserId()))
1450  ereport(ERROR,
1451  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1452  errmsg("must be owner of type %s or type %s",
1453  format_type_be(sourcetypeid),
1454  format_type_be(targettypeid))));
1455 
1456  aclresult = pg_type_aclcheck(sourcetypeid, GetUserId(), ACL_USAGE);
1457  if (aclresult != ACLCHECK_OK)
1458  aclcheck_error_type(aclresult, sourcetypeid);
1459 
1460  aclresult = pg_type_aclcheck(targettypeid, GetUserId(), ACL_USAGE);
1461  if (aclresult != ACLCHECK_OK)
1462  aclcheck_error_type(aclresult, targettypeid);
1463 
1464  /* Domains are allowed for historical reasons, but we warn */
1465  if (sourcetyptype == TYPTYPE_DOMAIN)
1466  ereport(WARNING,
1467  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1468  errmsg("cast will be ignored because the source data type is a domain")));
1469 
1470  else if (targettyptype == TYPTYPE_DOMAIN)
1471  ereport(WARNING,
1472  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1473  errmsg("cast will be ignored because the target data type is a domain")));
1474 
1475  /* Determine the cast method */
1476  if (stmt->func != NULL)
1477  castmethod = COERCION_METHOD_FUNCTION;
1478  else if (stmt->inout)
1479  castmethod = COERCION_METHOD_INOUT;
1480  else
1481  castmethod = COERCION_METHOD_BINARY;
1482 
1483  if (castmethod == COERCION_METHOD_FUNCTION)
1484  {
1485  Form_pg_proc procstruct;
1486 
1487  funcid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->func, false);
1488 
1489  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1490  if (!HeapTupleIsValid(tuple))
1491  elog(ERROR, "cache lookup failed for function %u", funcid);
1492 
1493  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1494  nargs = procstruct->pronargs;
1495  if (nargs < 1 || nargs > 3)
1496  ereport(ERROR,
1497  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1498  errmsg("cast function must take one to three arguments")));
1499  if (!IsBinaryCoercible(sourcetypeid, procstruct->proargtypes.values[0]))
1500  ereport(ERROR,
1501  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1502  errmsg("argument of cast function must match or be binary-coercible from source data type")));
1503  if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
1504  ereport(ERROR,
1505  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1506  errmsg("second argument of cast function must be type %s",
1507  "integer")));
1508  if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)
1509  ereport(ERROR,
1510  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1511  errmsg("third argument of cast function must be type %s",
1512  "boolean")));
1513  if (!IsBinaryCoercible(procstruct->prorettype, targettypeid))
1514  ereport(ERROR,
1515  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1516  errmsg("return data type of cast function must match or be binary-coercible to target data type")));
1517 
1518  /*
1519  * Restricting the volatility of a cast function may or may not be a
1520  * good idea in the abstract, but it definitely breaks many old
1521  * user-defined types. Disable this check --- tgl 2/1/03
1522  */
1523 #ifdef NOT_USED
1524  if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1525  ereport(ERROR,
1526  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1527  errmsg("cast function must not be volatile")));
1528 #endif
1529  if (procstruct->prokind != PROKIND_FUNCTION)
1530  ereport(ERROR,
1531  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1532  errmsg("cast function must be a normal function")));
1533  if (procstruct->proretset)
1534  ereport(ERROR,
1535  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1536  errmsg("cast function must not return a set")));
1537 
1538  ReleaseSysCache(tuple);
1539  }
1540  else
1541  {
1542  funcid = InvalidOid;
1543  nargs = 0;
1544  }
1545 
1546  if (castmethod == COERCION_METHOD_BINARY)
1547  {
1548  int16 typ1len;
1549  int16 typ2len;
1550  bool typ1byval;
1551  bool typ2byval;
1552  char typ1align;
1553  char typ2align;
1554 
1555  /*
1556  * Must be superuser to create binary-compatible casts, since
1557  * erroneous casts can easily crash the backend.
1558  */
1559  if (!superuser())
1560  ereport(ERROR,
1561  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1562  errmsg("must be superuser to create a cast WITHOUT FUNCTION")));
1563 
1564  /*
1565  * Also, insist that the types match as to size, alignment, and
1566  * pass-by-value attributes; this provides at least a crude check that
1567  * they have similar representations. A pair of types that fail this
1568  * test should certainly not be equated.
1569  */
1570  get_typlenbyvalalign(sourcetypeid, &typ1len, &typ1byval, &typ1align);
1571  get_typlenbyvalalign(targettypeid, &typ2len, &typ2byval, &typ2align);
1572  if (typ1len != typ2len ||
1573  typ1byval != typ2byval ||
1574  typ1align != typ2align)
1575  ereport(ERROR,
1576  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1577  errmsg("source and target data types are not physically compatible")));
1578 
1579  /*
1580  * We know that composite, enum and array types are never binary-
1581  * compatible with each other. They all have OIDs embedded in them.
1582  *
1583  * Theoretically you could build a user-defined base type that is
1584  * binary-compatible with a composite, enum, or array type. But we
1585  * disallow that too, as in practice such a cast is surely a mistake.
1586  * You can always work around that by writing a cast function.
1587  */
1588  if (sourcetyptype == TYPTYPE_COMPOSITE ||
1589  targettyptype == TYPTYPE_COMPOSITE)
1590  ereport(ERROR,
1591  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1592  errmsg("composite data types are not binary-compatible")));
1593 
1594  if (sourcetyptype == TYPTYPE_ENUM ||
1595  targettyptype == TYPTYPE_ENUM)
1596  ereport(ERROR,
1597  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1598  errmsg("enum data types are not binary-compatible")));
1599 
1600  if (OidIsValid(get_element_type(sourcetypeid)) ||
1601  OidIsValid(get_element_type(targettypeid)))
1602  ereport(ERROR,
1603  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1604  errmsg("array data types are not binary-compatible")));
1605 
1606  /*
1607  * We also disallow creating binary-compatibility casts involving
1608  * domains. Casting from a domain to its base type is already
1609  * allowed, and casting the other way ought to go through domain
1610  * coercion to permit constraint checking. Again, if you're intent on
1611  * having your own semantics for that, create a no-op cast function.
1612  *
1613  * NOTE: if we were to relax this, the above checks for composites
1614  * etc. would have to be modified to look through domains to their
1615  * base types.
1616  */
1617  if (sourcetyptype == TYPTYPE_DOMAIN ||
1618  targettyptype == TYPTYPE_DOMAIN)
1619  ereport(ERROR,
1620  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1621  errmsg("domain data types must not be marked binary-compatible")));
1622  }
1623 
1624  /*
1625  * Allow source and target types to be same only for length coercion
1626  * functions. We assume a multi-arg function does length coercion.
1627  */
1628  if (sourcetypeid == targettypeid && nargs < 2)
1629  ereport(ERROR,
1630  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1631  errmsg("source data type and target data type are the same")));
1632 
1633  /* convert CoercionContext enum to char value for castcontext */
1634  switch (stmt->context)
1635  {
1636  case COERCION_IMPLICIT:
1637  castcontext = COERCION_CODE_IMPLICIT;
1638  break;
1639  case COERCION_ASSIGNMENT:
1640  castcontext = COERCION_CODE_ASSIGNMENT;
1641  break;
1642  case COERCION_EXPLICIT:
1643  castcontext = COERCION_CODE_EXPLICIT;
1644  break;
1645  default:
1646  elog(ERROR, "unrecognized CoercionContext: %d", stmt->context);
1647  castcontext = 0; /* keep compiler quiet */
1648  break;
1649  }
1650 
1651  relation = heap_open(CastRelationId, RowExclusiveLock);
1652 
1653  /*
1654  * Check for duplicate. This is just to give a friendly error message,
1655  * the unique index would catch it anyway (so no need to sweat about race
1656  * conditions).
1657  */
1659  ObjectIdGetDatum(sourcetypeid),
1660  ObjectIdGetDatum(targettypeid));
1661  if (HeapTupleIsValid(tuple))
1662  ereport(ERROR,
1664  errmsg("cast from type %s to type %s already exists",
1665  format_type_be(sourcetypeid),
1666  format_type_be(targettypeid))));
1667 
1668  /* ready to go */
1669  values[Anum_pg_cast_castsource - 1] = ObjectIdGetDatum(sourcetypeid);
1670  values[Anum_pg_cast_casttarget - 1] = ObjectIdGetDatum(targettypeid);
1671  values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid);
1672  values[Anum_pg_cast_castcontext - 1] = CharGetDatum(castcontext);
1673  values[Anum_pg_cast_castmethod - 1] = CharGetDatum(castmethod);
1674 
1675  MemSet(nulls, false, sizeof(nulls));
1676 
1677  tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
1678 
1679  castid = CatalogTupleInsert(relation, tuple);
1680 
1681  /* make dependency entries */
1682  myself.classId = CastRelationId;
1683  myself.objectId = castid;
1684  myself.objectSubId = 0;
1685 
1686  /* dependency on source type */
1687  referenced.classId = TypeRelationId;
1688  referenced.objectId = sourcetypeid;
1689  referenced.objectSubId = 0;
1690  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1691 
1692  /* dependency on target type */
1693  referenced.classId = TypeRelationId;
1694  referenced.objectId = targettypeid;
1695  referenced.objectSubId = 0;
1696  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1697 
1698  /* dependency on function */
1699  if (OidIsValid(funcid))
1700  {
1701  referenced.classId = ProcedureRelationId;
1702  referenced.objectId = funcid;
1703  referenced.objectSubId = 0;
1704  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1705  }
1706 
1707  /* dependency on extension */
1708  recordDependencyOnCurrentExtension(&myself, false);
1709 
1710  /* Post creation hook for new cast */
1711  InvokeObjectPostCreateHook(CastRelationId, castid, 0);
1712 
1713  heap_freetuple(tuple);
1714 
1715  heap_close(relation, RowExclusiveLock);
1716 
1717  return myself;
1718 }
signed short int16
Definition: c.h:312
TypeName * sourcetype
Definition: parsenodes.h:3314
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
#define RelationGetDescr(relation)
Definition: rel.h:433
Oid GetUserId(void)
Definition: miscinit.c:379
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2502
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2025
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:459
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
char get_typtype(Oid typid)
Definition: lsyscache.c:2383
#define MemSet(start, val, len)
Definition: c.h:908
char * format_type_be(Oid type_oid)
Definition: format_type.c:328
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1074
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
unsigned int Oid
Definition: postgres_ext.h:31
bool pg_type_ownercheck(Oid type_oid, Oid roleid)
Definition: aclchk.c:4777
#define OidIsValid(objectId)
Definition: c.h:605
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3662
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:163
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool noError)
Definition: parse_func.c:2086
CoercionContext context
Definition: parsenodes.h:3317
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ACL_USAGE
Definition: parsenodes.h:82
#define ereport(elevel, rest)
Definition: elog.h:122
bool IsBinaryCoercible(Oid srctype, Oid targettype)
#define WARNING
Definition: elog.h:40
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
AclResult
Definition: acl.h:178
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
ObjectWithArgs * func
Definition: parsenodes.h:3316
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:132
#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:139
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1123
#define CharGetDatum(X)
Definition: postgres.h:401
static Datum values[MAXATTR]
Definition: bootstrap.c:164
int errmsg(const char *fmt,...)
Definition: elog.c:797
TypeName * targettype
Definition: parsenodes.h:3315
#define elog
Definition: elog.h:219
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4739
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274

◆ CreateForeignDataWrapper()

ObjectAddress CreateForeignDataWrapper ( CreateFdwStmt stmt)

Definition at line 560 of file foreigncmds.c.

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

Referenced by ProcessUtilitySlow().

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

◆ CreateForeignServer()

ObjectAddress CreateForeignServer ( CreateForeignServerStmt stmt)

Definition at line 861 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, GetForeignDataWrapperByName(), GetForeignServerByName(), GetUserId(), heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), 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, transformGenericOptions(), values, and CreateForeignServerStmt::version.

Referenced by ProcessUtilitySlow().

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

◆ CreateForeignTable()

void CreateForeignTable ( CreateForeignTableStmt stmt,
Oid  relid 
)

Definition at line 1446 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_close, heap_form_tuple(), heap_freetuple(), heap_open(), 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, transformGenericOptions(), and values.

Referenced by ProcessUtilitySlow().

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

◆ CreateFunction()

ObjectAddress CreateFunction ( ParseState pstate,
CreateFunctionStmt stmt 
)

Definition at line 865 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(), HeapTupleGetOid, HeapTupleIsValid, i, interpret_AS_clause(), interpret_function_parameter_list(), 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().

866 {
867  char *probin_str;
868  char *prosrc_str;
869  Oid prorettype;
870  bool returnsSet;
871  char *language;
872  Oid languageOid;
873  Oid languageValidator;
874  Node *transformDefElem = NULL;
875  char *funcname;
876  Oid namespaceId;
877  AclResult aclresult;
878  oidvector *parameterTypes;
879  ArrayType *allParameterTypes;
880  ArrayType *parameterModes;
881  ArrayType *parameterNames;
882  List *parameterDefaults;
883  Oid variadicArgType;
884  List *trftypes_list = NIL;
885  ArrayType *trftypes;
886  Oid requiredResultType;
887  bool isWindowFunc,
888  isStrict,
889  security,
890  isLeakProof;
891  char volatility;
892  ArrayType *proconfig;
893  float4 procost;
894  float4 prorows;
895  HeapTuple languageTuple;
896  Form_pg_language languageStruct;
897  List *as_clause;
898  char parallel;
899 
900  /* Convert list of names to a name and namespace */
901  namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
902  &funcname);
903 
904  /* Check we have creation rights in target namespace */
905  aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
906  if (aclresult != ACLCHECK_OK)
907  aclcheck_error(aclresult, OBJECT_SCHEMA,
908  get_namespace_name(namespaceId));
909 
910  /* Set default attributes */
911  isWindowFunc = false;
912  isStrict = false;
913  security = false;
914  isLeakProof = false;
915  volatility = PROVOLATILE_VOLATILE;
916  proconfig = NULL;
917  procost = -1; /* indicates not set */
918  prorows = -1; /* indicates not set */
919  parallel = PROPARALLEL_UNSAFE;
920 
921  /* Extract non-default attributes from stmt->options list */
923  stmt->is_procedure,
924  stmt->options,
925  &as_clause, &language, &transformDefElem,
926  &isWindowFunc, &volatility,
927  &isStrict, &security, &isLeakProof,
928  &proconfig, &procost, &prorows, &parallel);
929 
930  /* Look up the language and validate permissions */
931  languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
932  if (!HeapTupleIsValid(languageTuple))
933  ereport(ERROR,
934  (errcode(ERRCODE_UNDEFINED_OBJECT),
935  errmsg("language \"%s\" does not exist", language),
936  (PLTemplateExists(language) ?
937  errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
938 
939  languageOid = HeapTupleGetOid(languageTuple);
940  languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
941 
942  if (languageStruct->lanpltrusted)
943  {
944  /* if trusted language, need USAGE privilege */
945  AclResult aclresult;
946 
947  aclresult = pg_language_aclcheck(languageOid, GetUserId(), ACL_USAGE);
948  if (aclresult != ACLCHECK_OK)
949  aclcheck_error(aclresult, OBJECT_LANGUAGE,
950  NameStr(languageStruct->lanname));
951  }
952  else
953  {
954  /* if untrusted language, must be superuser */
955  if (!superuser())
957  NameStr(languageStruct->lanname));
958  }
959 
960  languageValidator = languageStruct->lanvalidator;
961 
962  ReleaseSysCache(languageTuple);
963 
964  /*
965  * Only superuser is allowed to create leakproof functions because
966  * leakproof functions can see tuples which have not yet been filtered out
967  * by security barrier views or row level security policies.
968  */
969  if (isLeakProof && !superuser())
970  ereport(ERROR,
971  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
972  errmsg("only superuser can define a leakproof function")));
973 
974  if (transformDefElem)
975  {
976  ListCell *lc;
977 
978  foreach(lc, castNode(List, transformDefElem))
979  {
980  Oid typeid = typenameTypeId(NULL,
981  lfirst_node(TypeName, lc));
982  Oid elt = get_base_element_type(typeid);
983 
984  typeid = elt ? elt : typeid;
985 
986  get_transform_oid(typeid, languageOid, false);
987  trftypes_list = lappend_oid(trftypes_list, typeid);
988  }
989  }
990 
991  /*
992  * Convert remaining parameters of CREATE to form wanted by
993  * ProcedureCreate.
994  */
996  stmt->parameters,
997  languageOid,
999  &parameterTypes,
1000  &allParameterTypes,
1001  &parameterModes,
1002  &parameterNames,
1003  &parameterDefaults,
1004  &variadicArgType,
1005  &requiredResultType);
1006 
1007  if (stmt->is_procedure)
1008  {
1009  Assert(!stmt->returnType);
1010  prorettype = requiredResultType ? requiredResultType : VOIDOID;
1011  returnsSet = false;
1012  }
1013  else if (stmt->returnType)
1014  {
1015  /* explicit RETURNS clause */
1016  compute_return_type(stmt->returnType, languageOid,
1017  &prorettype, &returnsSet);
1018  if (OidIsValid(requiredResultType) && prorettype != requiredResultType)
1019  ereport(ERROR,
1020  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1021  errmsg("function result type must be %s because of OUT parameters",
1022  format_type_be(requiredResultType))));
1023  }
1024  else if (OidIsValid(requiredResultType))
1025  {
1026  /* default RETURNS clause from OUT parameters */
1027  prorettype = requiredResultType;
1028  returnsSet = false;
1029  }
1030  else
1031  {
1032  ereport(ERROR,
1033  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1034  errmsg("function result type must be specified")));
1035  /* Alternative possibility: default to RETURNS VOID */
1036  prorettype = VOIDOID;
1037  returnsSet = false;
1038  }
1039 
1040  if (list_length(trftypes_list) > 0)
1041  {
1042  ListCell *lc;
1043  Datum *arr;
1044  int i;
1045 
1046  arr = palloc(list_length(trftypes_list) * sizeof(Datum));
1047  i = 0;
1048  foreach(lc, trftypes_list)
1049  arr[i++] = ObjectIdGetDatum(lfirst_oid(lc));
1050  trftypes = construct_array(arr, list_length(trftypes_list),
1051  OIDOID, sizeof(Oid), true, 'i');
1052  }
1053  else
1054  {
1055  /* store SQL NULL instead of empty array */
1056  trftypes = NULL;
1057  }
1058 
1059  interpret_AS_clause(languageOid, language, funcname, as_clause,
1060  &prosrc_str, &probin_str);
1061 
1062  /*
1063  * Set default values for COST and ROWS depending on other parameters;
1064  * reject ROWS if it's not returnsSet. NB: pg_dump knows these default
1065  * values, keep it in sync if you change them.
1066  */
1067  if (procost < 0)
1068  {
1069  /* SQL and PL-language functions are assumed more expensive */
1070  if (languageOid == INTERNALlanguageId ||
1071  languageOid == ClanguageId)
1072  procost = 1;
1073  else
1074  procost = 100;
1075  }
1076  if (prorows < 0)
1077  {
1078  if (returnsSet)
1079  prorows = 1000;
1080  else
1081  prorows = 0; /* dummy value if not returnsSet */
1082  }
1083  else if (!returnsSet)
1084  ereport(ERROR,
1085  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1086  errmsg("ROWS is not applicable when function does not return a set")));
1087 
1088  /*
1089  * And now that we have all the parameters, and know we're permitted to do
1090  * so, go ahead and create the function.
1091  */
1092  return ProcedureCreate(funcname,
1093  namespaceId,
1094  stmt->replace,
1095  returnsSet,
1096  prorettype,
1097  GetUserId(),
1098  languageOid,
1099  languageValidator,
1100  prosrc_str, /* converted to text later */
1101  probin_str, /* converted to text later */
1102  stmt->is_procedure ? PROKIND_PROCEDURE : (isWindowFunc ? PROKIND_WINDOW : PROKIND_FUNCTION),
1103  security,
1104  isLeakProof,
1105  isStrict,
1106  volatility,
1107  parallel,
1108  parameterTypes,
1109  PointerGetDatum(allParameterTypes),
1110  PointerGetDatum(parameterModes),
1111  PointerGetDatum(parameterNames),
1112  parameterDefaults,
1113  PointerGetDatum(trftypes),
1114  PointerGetDatum(proconfig),
1115  procost,
1116  prorows);
1117 }
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, float4 procost, float4 prorows)
Definition: pg_proc.c:66
#define NIL
Definition: pg_list.h:69
Definition: c.h:555
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
Oid GetUserId(void)
Definition: miscinit.c:379
#define castNode(_type_, nodeptr)
Definition: nodes.h:585
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, char *parallel_p)
Definition: functioncmds.c:643
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2975
#define PointerGetDatum(X)
Definition: postgres.h:541
static void compute_return_type(TypeName *returnType, Oid languageOid, Oid *prorettype_p, bool *returnsSet_p)
Definition: functioncmds.c:86
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3279
Definition: nodes.h:516
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
char * format_type_be(Oid type_oid)
Definition: format_type.c:328
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:805
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define OidIsValid(objectId)
Definition: c.h:605
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4689
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4663
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:3349
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:84
#define lfirst_node(type, lc)
Definition: pg_list.h:109
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3051
#define ACL_USAGE
Definition: parsenodes.h:82
#define ereport(elevel, rest)
Definition: elog.h:122
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
float float4
Definition: c.h:457
AclResult
Definition: acl.h:178
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
bool PLTemplateExists(const char *languageName)
Definition: proclang.c:515
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:699
TypeName * returnType
Definition: parsenodes.h:2767
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:182
static int list_length(const List *l)
Definition: pg_list.h:89
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2575
FormData_pg_language * Form_pg_language
Definition: pg_language.h:63
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define NameStr(name)
Definition: c.h:576
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:707
Definition: pg_list.h:45
#define lfirst_oid(lc)
Definition: pg_list.h:108
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274

◆ CreateStatistics()

ObjectAddress CreateStatistics ( CreateStatsStmt stmt)

Definition at line 55 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(), GETSTRUCT, GetUserId(), heap_form_tuple(), heap_freetuple(), heap_open(), HeapTupleIsValid, i, CreateStatsStmt::if_not_exists, 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, STATS_MAX_DIMENSIONS, strVal, CreateStatsStmt::stxcomment, generate_unaccent_rules::type, TYPECACHE_LT_OPR, types, and values.

Referenced by ProcessUtilitySlow().

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

◆ CreateTransform()

ObjectAddress CreateTransform ( CreateTransformStmt stmt)

Definition at line 1801 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(), GETSTRUCT, GetUserId(), heap_close, heap_form_tuple(), heap_freetuple(), heap_modify_tuple(), heap_open(), HeapTupleGetOid, 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, CreateTransformStmt::tosql, TRFTYPELANG, CreateTransformStmt::type_name, TypeNameToString(), typenameTypeId(), and values.

Referenced by ProcessUtilitySlow().

1802 {
1803  Oid typeid;
1804  char typtype;
1805  Oid langid;
1806  Oid fromsqlfuncid;
1807  Oid tosqlfuncid;
1808  AclResult aclresult;
1809  Form_pg_proc procstruct;
1810  Datum values[Natts_pg_transform];
1811  bool nulls[Natts_pg_transform];
1812  bool replaces[Natts_pg_transform];
1813  Oid transformid;
1814  HeapTuple tuple;
1815  HeapTuple newtuple;
1816  Relation relation;
1817  ObjectAddress myself,
1818  referenced;
1819  bool is_replace;
1820 
1821  /*
1822  * Get the type
1823  */
1824  typeid = typenameTypeId(NULL, stmt->type_name);
1825  typtype = get_typtype(typeid);
1826 
1827  if (typtype == TYPTYPE_PSEUDO)
1828  ereport(ERROR,
1829  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1830  errmsg("data type %s is a pseudo-type",
1831  TypeNameToString(stmt->type_name))));
1832 
1833  if (typtype == TYPTYPE_DOMAIN)
1834  ereport(ERROR,
1835  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1836  errmsg("data type %s is a domain",
1837  TypeNameToString(stmt->type_name))));
1838 
1839  if (!pg_type_ownercheck(typeid, GetUserId()))
1841 
1842  aclresult = pg_type_aclcheck(typeid, GetUserId(), ACL_USAGE);
1843  if (aclresult != ACLCHECK_OK)
1844  aclcheck_error_type(aclresult, typeid);
1845 
1846  /*
1847  * Get the language
1848  */
1849  langid = get_language_oid(stmt->lang, false);
1850 
1851  aclresult = pg_language_aclcheck(langid, GetUserId(), ACL_USAGE);
1852  if (aclresult != ACLCHECK_OK)
1853  aclcheck_error(aclresult, OBJECT_LANGUAGE, stmt->lang);
1854 
1855  /*
1856  * Get the functions
1857  */
1858  if (stmt->fromsql)
1859  {
1860  fromsqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->fromsql, false);
1861 
1862  if (!pg_proc_ownercheck(fromsqlfuncid, GetUserId()))
1864 
1865  aclresult = pg_proc_aclcheck(fromsqlfuncid, GetUserId(), ACL_EXECUTE);
1866  if (aclresult != ACLCHECK_OK)
1868 
1869  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fromsqlfuncid));
1870  if (!HeapTupleIsValid(tuple))
1871  elog(ERROR, "cache lookup failed for function %u", fromsqlfuncid);
1872  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1873  if (procstruct->prorettype != INTERNALOID)
1874  ereport(ERROR,
1875  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1876  errmsg("return data type of FROM SQL function must be %s",
1877  "internal")));
1878  check_transform_function(procstruct);
1879  ReleaseSysCache(tuple);
1880  }
1881  else
1882  fromsqlfuncid = InvalidOid;
1883 
1884  if (stmt->tosql)
1885  {
1886  tosqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->tosql, false);
1887 
1888  if (!pg_proc_ownercheck(tosqlfuncid, GetUserId()))
1890 
1891  aclresult = pg_proc_aclcheck(tosqlfuncid, GetUserId(), ACL_EXECUTE);
1892  if (aclresult != ACLCHECK_OK)
1894 
1895  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(tosqlfuncid));
1896  if (!HeapTupleIsValid(tuple))
1897  elog(ERROR, "cache lookup failed for function %u", tosqlfuncid);
1898  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1899  if (procstruct->prorettype != typeid)
1900  ereport(ERROR,
1901  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1902  errmsg("return data type of TO SQL function must be the transform data type")));
1903  check_transform_function(procstruct);
1904  ReleaseSysCache(tuple);
1905  }
1906  else
1907  tosqlfuncid = InvalidOid;
1908 
1909  /*
1910  * Ready to go
1911  */
1912  values[Anum_pg_transform_trftype - 1] = ObjectIdGetDatum(typeid);
1913  values[Anum_pg_transform_trflang - 1] = ObjectIdGetDatum(langid);
1914  values[Anum_pg_transform_trffromsql - 1] = ObjectIdGetDatum(fromsqlfuncid);
1915  values[Anum_pg_transform_trftosql - 1] = ObjectIdGetDatum(tosqlfuncid);
1916 
1917  MemSet(nulls, false, sizeof(nulls));
1918 
1919  relation = heap_open(TransformRelationId, RowExclusiveLock);
1920 
1921  tuple = SearchSysCache2(TRFTYPELANG,
1922  ObjectIdGetDatum(typeid),
1923  ObjectIdGetDatum(langid));
1924  if (HeapTupleIsValid(tuple))
1925  {
1926  if (!stmt->replace)
1927  ereport(ERROR,
1929  errmsg("transform for type %s language \"%s\" already exists",
1930  format_type_be(typeid),
1931  stmt->lang)));
1932 
1933  MemSet(replaces, false, sizeof(replaces));
1934  replaces[Anum_pg_transform_trffromsql - 1] = true;
1935  replaces[Anum_pg_transform_trftosql - 1] = true;
1936 
1937  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
1938  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
1939 
1940  transformid = HeapTupleGetOid(tuple);
1941  ReleaseSysCache(tuple);
1942  is_replace = true;
1943  }
1944  else
1945  {
1946  newtuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
1947  transformid = CatalogTupleInsert(relation, newtuple);
1948  is_replace = false;
1949  }
1950 
1951  if (is_replace)
1952  deleteDependencyRecordsFor(TransformRelationId, transformid, true);
1953 
1954  /* make dependency entries */
1955  myself.classId = TransformRelationId;
1956  myself.objectId = transformid;
1957  myself.objectSubId = 0;
1958 
1959  /* dependency on language */
1960  referenced.classId = LanguageRelationId;
1961  referenced.objectId = langid;
1962  referenced.objectSubId = 0;
1963  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1964 
1965  /* dependency on type */
1966  referenced.classId = TypeRelationId;
1967  referenced.objectId = typeid;
1968  referenced.objectSubId = 0;
1969  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1970 
1971  /* dependencies on functions */
1972  if (OidIsValid(fromsqlfuncid))
1973  {
1974  referenced.classId = ProcedureRelationId;
1975  referenced.objectId = fromsqlfuncid;
1976  referenced.objectSubId = 0;
1977  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1978  }
1979  if (OidIsValid(tosqlfuncid))
1980  {
1981  referenced.classId = ProcedureRelationId;
1982  referenced.objectId = tosqlfuncid;
1983  referenced.objectSubId = 0;
1984  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1985  }
1986 
1987  /* dependency on extension */
1988  recordDependencyOnCurrentExtension(&myself, is_replace);
1989 
1990  /* Post creation hook for new transform */
1991  InvokeObjectPostCreateHook(TransformRelationId, transformid, 0);
1992 
1993  heap_freetuple(newtuple);
1994 
1995  heap_close(relation, RowExclusiveLock);
1996 
1997  return myself;
1998 }
ObjectWithArgs * tosql
Definition: parsenodes.h:3332
static void check_transform_function(Form_pg_proc procstruct)
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
#define RelationGetDescr(relation)
Definition: rel.h:433
Oid GetUserId(void)
Definition: miscinit.c:379
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:459
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:191
Oid get_language_oid(const char *langname, bool missing_ok)
Definition: proclang.c:549
int errcode(int sqlerrcode)
Definition: elog.c:575
char get_typtype(Oid typid)
Definition: lsyscache.c:2383
#define MemSet(start, val, len)
Definition: c.h:908
char * format_type_be(Oid type_oid)
Definition: format_type.c:328
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1074
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
unsigned int Oid
Definition: postgres_ext.h:31
bool pg_type_ownercheck(Oid type_oid, Oid roleid)
Definition: aclchk.c:4777
#define OidIsValid(objectId)
Definition: c.h:605
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4663
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3662
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3349
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:163
ItemPointerData t_self
Definition: htup.h:65
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool noError)
Definition: parse_func.c:2086
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ACL_USAGE
Definition: parsenodes.h:82
#define ereport(elevel, rest)
Definition: elog.h:122
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
char * NameListToString(List *names)
Definition: namespace.c:3082
AclResult
Definition: acl.h:178
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:132
#define InvalidOid
Definition: postgres_ext.h:36
ObjectWithArgs * fromsql
Definition: parsenodes.h:3331
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:139
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:211
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1123
TypeName * type_name
Definition: parsenodes.h:3329
static Datum values[MAXATTR]
Definition: bootstrap.c:164
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ACL_EXECUTE
Definition: parsenodes.h:81
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4651
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:707
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4739
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1173
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
bool pg_proc_ownercheck(Oid proc_oid, Oid roleid)
Definition: aclchk.c:4829
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274

◆ CreateUserMapping()

ObjectAddress CreateUserMapping ( CreateUserMappingStmt stmt)

Definition at line 1135 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(), GetSysCacheOid2, heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), CreateUserMappingStmt::if_not_exists, InvalidObjectAddress, InvokeObjectPostCreateHook, MappingUserName, NOTICE, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, CreateUserMappingStmt::options, PointerGetDatum, PointerIsValid, RelationData::rd_att, recordDependencyOn(), recordDependencyOnCurrentExtension(), recordDependencyOnOwner(), ROLESPEC_PUBLIC, RoleSpec::roletype, RowExclusiveLock, ForeignServer::serverid, CreateUserMappingStmt::servername, transformGenericOptions(), CreateUserMappingStmt::user, user_mapping_ddl_aclcheck(), and values.

Referenced by ProcessUtilitySlow().

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

◆ defGetBoolean()

bool defGetBoolean ( DefElem def)

Definition at line 111 of file define.c.

References DefElem::arg, defGetString(), DefElem::defname, ereport, errcode(), errmsg(), ERROR, intVal, nodeTag, pg_strcasecmp(), and T_Integer.

Referenced by AlterDatabase(), apply_server_options(), apply_table_options(), createdb(), CreateExtension(), DefineAggregate(), DefineOperator(), DefineType(), dintdict_init(), dsimple_init(), dsynonym_init(), dxsyn_init(), ExplainQuery(), file_fdw_validator(), get_file_fdw_attribute_options(), GetCommandLogLevel(), interpretOidsOption(), parse_subscription_options(), parseCreateReplSlotOptions(), postgres_fdw_validator(), postgresImportForeignSchema(), postgresIsForeignRelUpdatable(), and ProcessCopyOptions().

112 {
113  /*
114  * If no parameter given, assume "true" is meant.
115  */
116  if (def->arg == NULL)
117  return true;
118 
119  /*
120  * Allow 0, 1, "true", "false", "on", "off"
121  */
122  switch (nodeTag(def->arg))
123  {
124  case T_Integer:
125  switch (intVal(def->arg))
126  {
127  case 0:
128  return false;
129  case 1:
130  return true;
131  default:
132  /* otherwise, error out below */
133  break;
134  }
135  break;
136  default:
137  {
138  char *sval = defGetString(def);
139 
140  /*
141  * The set of strings accepted here should match up with the
142  * grammar's opt_boolean production.
143  */
144  if (pg_strcasecmp(sval, "true") == 0)
145  return true;
146  if (pg_strcasecmp(sval, "false") == 0)
147  return false;
148  if (pg_strcasecmp(sval, "on") == 0)
149  return true;
150  if (pg_strcasecmp(sval, "off") == 0)
151  return false;
152  }
153  break;
154  }
155  ereport(ERROR,
156  (errcode(ERRCODE_SYNTAX_ERROR),
157  errmsg("%s requires a Boolean value",
158  def->defname)));
159  return false; /* keep compiler quiet */
160 }
int errcode(int sqlerrcode)
Definition: elog.c:575
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define ERROR
Definition: elog.h:43
char * defGetString(DefElem *def)
Definition: define.c:49
#define ereport(elevel, rest)
Definition: elog.h:122
Node * arg
Definition: parsenodes.h:731
#define nodeTag(nodeptr)
Definition: nodes.h:521
#define intVal(v)
Definition: value.h:52
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * defname
Definition: parsenodes.h:730

◆ defGetInt32()

int32 defGetInt32 ( DefElem def)

Definition at line 166 of file define.c.

References DefElem::arg, DefElem::defname, ereport, errcode(), errmsg(), ERROR, intVal, nodeTag, and T_Integer.

Referenced by AlterDatabase(), ATExecSetIdentity(), createdb(), and DefineAggregate().

167 {
168  if (def->arg == NULL)
169  ereport(ERROR,
170  (errcode(ERRCODE_SYNTAX_ERROR),
171  errmsg("%s requires an integer value",
172  def->defname)));
173  switch (nodeTag(def->arg))
174  {
175  case T_Integer:
176  return (int32) intVal(def->arg);
177  default:
178  ereport(ERROR,
179  (errcode(ERRCODE_SYNTAX_ERROR),
180  errmsg("%s requires an integer value",
181  def->defname)));
182  }
183  return 0; /* keep compiler quiet */
184 }
int errcode(int sqlerrcode)
Definition: elog.c:575
signed int int32
Definition: c.h:313
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
Node * arg
Definition: parsenodes.h:731
#define nodeTag(nodeptr)
Definition: nodes.h:521
#define intVal(v)
Definition: value.h:52
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * defname
Definition: parsenodes.h:730

◆ defGetInt64()

int64 defGetInt64 ( DefElem def)

Definition at line 190 of file define.c.

References DefElem::arg, CStringGetDatum, DatumGetInt64, DefElem::defname, DirectFunctionCall1, ereport, errcode(), errmsg(), ERROR, int8in(), intVal, nodeTag, strVal, T_Float, and T_Integer.

Referenced by init_params().

191 {
192  if (def->arg == NULL)
193  ereport(ERROR,
194  (errcode(ERRCODE_SYNTAX_ERROR),
195  errmsg("%s requires a numeric value",
196  def->defname)));
197  switch (nodeTag(def->arg))
198  {
199  case T_Integer:
200  return (int64) intVal(def->arg);
201  case T_Float:
202 
203  /*
204  * Values too large for int4 will be represented as Float
205  * constants by the lexer. Accept these if they are valid int8
206  * strings.
207  */
209  CStringGetDatum(strVal(def->arg))));
210  default:
211  ereport(ERROR,
212  (errcode(ERRCODE_SYNTAX_ERROR),
213  errmsg("%s requires a numeric value",
214  def->defname)));
215  }
216  return 0; /* keep compiler quiet */
217 }
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
#define ERROR
Definition: elog.h:43
#define DatumGetInt64(X)
Definition: postgres.h:592
#define CStringGetDatum(X)
Definition: postgres.h:563
#define ereport(elevel, rest)
Definition: elog.h:122
Node * arg
Definition: parsenodes.h:731
Datum int8in(PG_FUNCTION_ARGS)
Definition: int8.c:133
#define nodeTag(nodeptr)
Definition: nodes.h:521
Definition: nodes.h:287
#define intVal(v)
Definition: value.h:52
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * defname
Definition: parsenodes.h:730

◆ defGetNumeric()

double defGetNumeric ( DefElem def)

Definition at line 85 of file define.c.

References DefElem::arg, DefElem::defname, ereport, errcode(), errmsg(), ERROR, floatVal, intVal, nodeTag, T_Float, and T_Integer.

Referenced by AlterFunction(), and compute_function_attributes().

86 {
87  if (def->arg == NULL)
88  ereport(ERROR,
89  (errcode(ERRCODE_SYNTAX_ERROR),
90  errmsg("%s requires a numeric value",
91  def->defname)));
92  switch (nodeTag(def->arg))
93  {
94  case T_Integer:
95  return (double) intVal(def->arg);
96  case T_Float:
97  return floatVal(def->arg);
98  default:
99  ereport(ERROR,
100  (errcode(ERRCODE_SYNTAX_ERROR),
101  errmsg("%s requires a numeric value",
102  def->defname)));
103  }
104  return 0; /* keep compiler quiet */
105 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
#define floatVal(v)
Definition: value.h:53
#define ereport(elevel, rest)
Definition: elog.h:122
Node * arg
Definition: parsenodes.h:731
#define nodeTag(nodeptr)
Definition: nodes.h:521
Definition: nodes.h:287
#define intVal(v)
Definition: value.h:52
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * defname
Definition: parsenodes.h:730

◆ defGetQualifiedName()

List* defGetQualifiedName ( DefElem def)

Definition at line 223 of file define.c.

References DefElem::arg, DefElem::defname, ereport, errcode(), errmsg(), ERROR, list_make1, NIL, nodeTag, T_List, T_String, and T_TypeName.

Referenced by AlterOperator(), DefineAggregate(), DefineCollation(), DefineOperator(), DefineRange(), DefineTSConfiguration(), DefineTSDictionary(), DefineType(), get_ts_parser_func(), get_ts_template_func(), and init_params().

224 {
225  if (def->arg == NULL)
226  ereport(ERROR,
227  (errcode(ERRCODE_SYNTAX_ERROR),
228  errmsg("%s requires a parameter",
229  def->defname)));
230  switch (nodeTag(def->arg))
231  {
232  case T_TypeName:
233  return ((TypeName *) def->arg)->names;
234  case T_List:
235  return (List *) def->arg;
236  case T_String:
237  /* Allow quoted name for backwards compatibility */
238  return list_make1(def->arg);
239  default:
240  ereport(ERROR,
241  (errcode(ERRCODE_SYNTAX_ERROR),
242  errmsg("argument of %s must be a name",
243  def->defname)));
244  }
245  return NIL; /* keep compiler quiet */
246 }
#define NIL
Definition: pg_list.h:69
int errcode(int sqlerrcode)
Definition: elog.c:575
#define list_make1(x1)
Definition: pg_list.h:139
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
Definition: nodes.h:295
Node * arg
Definition: parsenodes.h:731
#define nodeTag(nodeptr)
Definition: nodes.h:521
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * defname
Definition: parsenodes.h:730
Definition: pg_list.h:45

◆ defGetString()