PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
opclasscmds.c File Reference
#include "postgres.h"
#include <limits.h>
#include "access/genam.h"
#include "access/heapam.h"
#include "access/nbtree.h"
#include "access/htup_details.h"
#include "access/sysattr.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/opfam_internal.h"
#include "catalog/pg_am.h"
#include "catalog/pg_amop.h"
#include "catalog/pg_amproc.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "commands/alter.h"
#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
#include "parser/parse_oper.h"
#include "parser/parse_type.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
Include dependency graph for opclasscmds.c:

Go to the source code of this file.

Functions

static void AlterOpFamilyAdd (AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid, int maxOpNumber, int maxProcNumber, List *items)
 
static void AlterOpFamilyDrop (AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid, int maxOpNumber, int maxProcNumber, List *items)
 
static void processTypesSpec (List *args, Oid *lefttype, Oid *righttype)
 
static void assignOperTypes (OpFamilyMember *member, Oid amoid, Oid typeoid)
 
static void assignProcTypes (OpFamilyMember *member, Oid amoid, Oid typeoid)
 
static void addFamilyMember (List **list, OpFamilyMember *member, bool isProc)
 
static void storeOperators (List *opfamilyname, Oid amoid, Oid opfamilyoid, Oid opclassoid, List *operators, bool isAdd)
 
static void storeProcedures (List *opfamilyname, Oid amoid, Oid opfamilyoid, Oid opclassoid, List *procedures, bool isAdd)
 
static void dropOperators (List *opfamilyname, Oid amoid, Oid opfamilyoid, List *operators)
 
static void dropProcedures (List *opfamilyname, Oid amoid, Oid opfamilyoid, List *procedures)
 
static HeapTuple OpFamilyCacheLookup (Oid amID, List *opfamilyname, bool missing_ok)
 
Oid get_opfamily_oid (Oid amID, List *opfamilyname, bool missing_ok)
 
static HeapTuple OpClassCacheLookup (Oid amID, List *opclassname, bool missing_ok)
 
Oid get_opclass_oid (Oid amID, List *opclassname, bool missing_ok)
 
static ObjectAddress CreateOpFamily (char *amname, char *opfname, Oid namespaceoid, Oid amoid)
 
ObjectAddress DefineOpClass (CreateOpClassStmt *stmt)
 
ObjectAddress DefineOpFamily (CreateOpFamilyStmt *stmt)
 
Oid AlterOpFamily (AlterOpFamilyStmt *stmt)
 
void RemoveOpFamilyById (Oid opfamilyOid)
 
void RemoveOpClassById (Oid opclassOid)
 
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)
 

Function Documentation

static void addFamilyMember ( List **  list,
OpFamilyMember member,
bool  isProc 
)
static

Definition at line 1232 of file opclasscmds.c.

References ereport, errcode(), errmsg(), ERROR, format_type_be(), lappend(), OpFamilyMember::lefttype, lfirst, OpFamilyMember::number, and OpFamilyMember::righttype.

Referenced by AlterOpFamilyAdd(), AlterOpFamilyDrop(), and DefineOpClass().

1233 {
1234  ListCell *l;
1235 
1236  foreach(l, *list)
1237  {
1238  OpFamilyMember *old = (OpFamilyMember *) lfirst(l);
1239 
1240  if (old->number == member->number &&
1241  old->lefttype == member->lefttype &&
1242  old->righttype == member->righttype)
1243  {
1244  if (isProc)
1245  ereport(ERROR,
1246  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1247  errmsg("procedure number %d for (%s,%s) appears more than once",
1248  member->number,
1249  format_type_be(member->lefttype),
1250  format_type_be(member->righttype))));
1251  else
1252  ereport(ERROR,
1253  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1254  errmsg("operator number %d for (%s,%s) appears more than once",
1255  member->number,
1256  format_type_be(member->lefttype),
1257  format_type_be(member->righttype))));
1258  }
1259  }
1260  *list = lappend(*list, member);
1261 }
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
List * lappend(List *list, void *datum)
Definition: list.c:128
#define lfirst(lc)
Definition: pg_list.h:106
int errmsg(const char *fmt,...)
Definition: elog.c:797
Oid AlterOpFamily ( AlterOpFamilyStmt stmt)

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

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

Definition at line 830 of file opclasscmds.c.

References ACL_KIND_OPER, ACL_KIND_PROC, aclcheck_error(), ACLCHECK_NOT_OWNER, addFamilyMember(), CreateOpClassItem::args, assignOperTypes(), assignProcTypes(), BTREE_AM_OID, castNode, CreateOpClassItem::class_args, elog, ereport, errcode(), errmsg(), ERROR, EventTriggerCollectAlterOpFam(), get_func_name(), get_opcode(), get_opfamily_oid(), get_opname(), GetUserId(), InvalidOid, CreateOpClassItem::itemtype, OpFamilyMember::lefttype, lfirst, linitial, LookupFuncNameTypeNames(), LookupOperNameTypeNames(), lsecond, CreateOpClassItem::name, NIL, NULL, OpFamilyMember::number, CreateOpClassItem::number, OpFamilyMember::object, OPCLASS_ITEM_FUNCTION, OPCLASS_ITEM_OPERATOR, OPCLASS_ITEM_STORAGETYPE, AlterOpFamilyStmt::opfamilyname, CreateOpClassItem::order_family, palloc0(), pg_oper_ownercheck(), pg_proc_ownercheck(), processTypesSpec(), OpFamilyMember::righttype, OpFamilyMember::sortfamily, storeOperators(), and storeProcedures().

Referenced by AlterOpFamily().

832 {
833  List *operators; /* OpFamilyMember list for operators */
834  List *procedures; /* OpFamilyMember list for support procs */
835  ListCell *l;
836 
837  operators = NIL;
838  procedures = NIL;
839 
840  /*
841  * Scan the "items" list to obtain additional info.
842  */
843  foreach(l, items)
844  {
846  Oid operOid;
847  Oid funcOid;
848  Oid sortfamilyOid;
849  OpFamilyMember *member;
850 
851  switch (item->itemtype)
852  {
854  if (item->number <= 0 || item->number > maxOpNumber)
855  ereport(ERROR,
856  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
857  errmsg("invalid operator number %d,"
858  " must be between 1 and %d",
859  item->number, maxOpNumber)));
860  if (item->args != NIL)
861  {
862  TypeName *typeName1 = (TypeName *) linitial(item->args);
863  TypeName *typeName2 = (TypeName *) lsecond(item->args);
864 
865  operOid = LookupOperNameTypeNames(NULL, item->name,
866  typeName1, typeName2,
867  false, -1);
868  }
869  else
870  {
871  ereport(ERROR,
872  (errcode(ERRCODE_SYNTAX_ERROR),
873  errmsg("operator argument types must be specified in ALTER OPERATOR FAMILY")));
874  operOid = InvalidOid; /* keep compiler quiet */
875  }
876 
877  if (item->order_family)
878  sortfamilyOid = get_opfamily_oid(BTREE_AM_OID,
879  item->order_family,
880  false);
881  else
882  sortfamilyOid = InvalidOid;
883 
884 #ifdef NOT_USED
885  /* XXX this is unnecessary given the superuser check above */
886  /* Caller must own operator and its underlying function */
887  if (!pg_oper_ownercheck(operOid, GetUserId()))
889  get_opname(operOid));
890  funcOid = get_opcode(operOid);
891  if (!pg_proc_ownercheck(funcOid, GetUserId()))
893  get_func_name(funcOid));
894 #endif
895 
896  /* Save the info */
897  member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
898  member->object = operOid;
899  member->number = item->number;
900  member->sortfamily = sortfamilyOid;
901  assignOperTypes(member, amoid, InvalidOid);
902  addFamilyMember(&operators, member, false);
903  break;
905  if (item->number <= 0 || item->number > maxProcNumber)
906  ereport(ERROR,
907  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
908  errmsg("invalid procedure number %d,"
909  " must be between 1 and %d",
910  item->number, maxProcNumber)));
911  funcOid = LookupFuncNameTypeNames(item->name, item->args,
912  false);
913 #ifdef NOT_USED
914  /* XXX this is unnecessary given the superuser check above */
915  /* Caller must own function */
916  if (!pg_proc_ownercheck(funcOid, GetUserId()))
918  get_func_name(funcOid));
919 #endif
920 
921  /* Save the info */
922  member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
923  member->object = funcOid;
924  member->number = item->number;
925 
926  /* allow overriding of the function's actual arg types */
927  if (item->class_args)
929  &member->lefttype, &member->righttype);
930 
931  assignProcTypes(member, amoid, InvalidOid);
932  addFamilyMember(&procedures, member, true);
933  break;
935  ereport(ERROR,
936  (errcode(ERRCODE_SYNTAX_ERROR),
937  errmsg("STORAGE cannot be specified in ALTER OPERATOR FAMILY")));
938  break;
939  default:
940  elog(ERROR, "unrecognized item type: %d", item->itemtype);
941  break;
942  }
943  }
944 
945  /*
946  * Add tuples to pg_amop and pg_amproc tying in the operators and
947  * functions. Dependencies on them are inserted, too.
948  */
949  storeOperators(stmt->opfamilyname, amoid, opfamilyoid,
950  InvalidOid, operators, true);
951  storeProcedures(stmt->opfamilyname, amoid, opfamilyoid,
952  InvalidOid, procedures, true);
953 
954  /* make information available to event triggers */
955  EventTriggerCollectAlterOpFam(stmt, opfamilyoid,
956  operators, procedures);
957 }
Oid LookupOperNameTypeNames(ParseState *pstate, List *opername, TypeName *oprleft, TypeName *oprright, bool noError, int location)
Definition: parse_oper.c:142
#define NIL
Definition: pg_list.h:69
static void assignOperTypes(OpFamilyMember *member, Oid amoid, Oid typeoid)
Definition: opclasscmds.c:1068
Oid GetUserId(void)
Definition: miscinit.c:283
#define castNode(_type_, nodeptr)
Definition: nodes.h:577
#define BTREE_AM_OID
Definition: pg_am.h:70
bool pg_oper_ownercheck(Oid oper_oid, Oid roleid)
Definition: aclchk.c:4573
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define lsecond(l)
Definition: pg_list.h:114
#define OPCLASS_ITEM_OPERATOR
Definition: parsenodes.h:2414
char * get_opname(Oid opno)
Definition: lsyscache.c:1087
#define linitial(l)
Definition: pg_list.h:110
#define ERROR
Definition: elog.h:43
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1380
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3378
static void addFamilyMember(List **list, OpFamilyMember *member, bool isProc)
Definition: opclasscmds.c:1232
Oid LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError)
Definition: parse_func.c:1941
#define ereport(elevel, rest)
Definition: elog.h:122
void EventTriggerCollectAlterOpFam(AlterOpFamilyStmt *stmt, Oid opfamoid, List *operators, List *procedures)
static void processTypesSpec(List *args, Oid *lefttype, Oid *righttype)
Definition: opclasscmds.c:1039
void * palloc0(Size size)
Definition: mcxt.c:920
#define InvalidOid
Definition: postgres_ext.h:36
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1062
#define OPCLASS_ITEM_FUNCTION
Definition: parsenodes.h:2415
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
#define OPCLASS_ITEM_STORAGETYPE
Definition: parsenodes.h:2416
Oid get_opfamily_oid(Oid amID, List *opfamilyname, bool missing_ok)
Definition: opclasscmds.c:141
static void storeProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid, Oid opclassoid, List *procedures, bool isAdd)
Definition: opclasscmds.c:1386
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
static void assignProcTypes(OpFamilyMember *member, Oid amoid, Oid typeoid)
Definition: opclasscmds.c:1134
static void storeOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid, Oid opclassoid, List *operators, bool isAdd)
Definition: opclasscmds.c:1271
Definition: pg_list.h:45
bool pg_proc_ownercheck(Oid proc_oid, Oid roleid)
Definition: aclchk.c:4599
static void AlterOpFamilyDrop ( AlterOpFamilyStmt stmt,
Oid  amoid,
Oid  opfamilyoid,
int  maxOpNumber,
int  maxProcNumber,
List items 
)
static

Definition at line 963 of file opclasscmds.c.

References addFamilyMember(), CreateOpClassItem::args, castNode, dropOperators(), dropProcedures(), elog, ereport, errcode(), errmsg(), ERROR, EventTriggerCollectAlterOpFam(), CreateOpClassItem::itemtype, OpFamilyMember::lefttype, lfirst, NIL, OpFamilyMember::number, CreateOpClassItem::number, OPCLASS_ITEM_FUNCTION, OPCLASS_ITEM_OPERATOR, OPCLASS_ITEM_STORAGETYPE, AlterOpFamilyStmt::opfamilyname, palloc0(), processTypesSpec(), and OpFamilyMember::righttype.

Referenced by AlterOpFamily().

965 {
966  List *operators; /* OpFamilyMember list for operators */
967  List *procedures; /* OpFamilyMember list for support procs */
968  ListCell *l;
969 
970  operators = NIL;
971  procedures = NIL;
972 
973  /*
974  * Scan the "items" list to obtain additional info.
975  */
976  foreach(l, items)
977  {
979  Oid lefttype,
980  righttype;
981  OpFamilyMember *member;
982 
983  switch (item->itemtype)
984  {
986  if (item->number <= 0 || item->number > maxOpNumber)
987  ereport(ERROR,
988  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
989  errmsg("invalid operator number %d,"
990  " must be between 1 and %d",
991  item->number, maxOpNumber)));
992  processTypesSpec(item->args, &lefttype, &righttype);
993  /* Save the info */
994  member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
995  member->number = item->number;
996  member->lefttype = lefttype;
997  member->righttype = righttype;
998  addFamilyMember(&operators, member, false);
999  break;
1000  case OPCLASS_ITEM_FUNCTION:
1001  if (item->number <= 0 || item->number > maxProcNumber)
1002  ereport(ERROR,
1003  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1004  errmsg("invalid procedure number %d,"
1005  " must be between 1 and %d",
1006  item->number, maxProcNumber)));
1007  processTypesSpec(item->args, &lefttype, &righttype);
1008  /* Save the info */
1009  member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
1010  member->number = item->number;
1011  member->lefttype = lefttype;
1012  member->righttype = righttype;
1013  addFamilyMember(&procedures, member, true);
1014  break;
1016  /* grammar prevents this from appearing */
1017  default:
1018  elog(ERROR, "unrecognized item type: %d", item->itemtype);
1019  break;
1020  }
1021  }
1022 
1023  /*
1024  * Remove tuples from pg_amop and pg_amproc.
1025  */
1026  dropOperators(stmt->opfamilyname, amoid, opfamilyoid, operators);
1027  dropProcedures(stmt->opfamilyname, amoid, opfamilyoid, procedures);
1028 
1029  /* make information available to event triggers */
1030  EventTriggerCollectAlterOpFam(stmt, opfamilyoid,
1031  operators, procedures);
1032 }
#define NIL
Definition: pg_list.h:69
#define castNode(_type_, nodeptr)
Definition: nodes.h:577
int errcode(int sqlerrcode)
Definition: elog.c:575
static void dropProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid, List *procedures)
Definition: opclasscmds.c:1526
unsigned int Oid
Definition: postgres_ext.h:31
#define OPCLASS_ITEM_OPERATOR
Definition: parsenodes.h:2414
static void dropOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid, List *operators)
Definition: opclasscmds.c:1486
#define ERROR
Definition: elog.h:43
static void addFamilyMember(List **list, OpFamilyMember *member, bool isProc)
Definition: opclasscmds.c:1232
#define ereport(elevel, rest)
Definition: elog.h:122
void EventTriggerCollectAlterOpFam(AlterOpFamilyStmt *stmt, Oid opfamoid, List *operators, List *procedures)
static void processTypesSpec(List *args, Oid *lefttype, Oid *righttype)
Definition: opclasscmds.c:1039
void * palloc0(Size size)
Definition: mcxt.c:920
#define OPCLASS_ITEM_FUNCTION
Definition: parsenodes.h:2415
#define lfirst(lc)
Definition: pg_list.h:106
#define OPCLASS_ITEM_STORAGETYPE
Definition: parsenodes.h:2416
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
static void assignOperTypes ( OpFamilyMember member,
Oid  amoid,
Oid  typeoid 
)
static

Definition at line 1068 of file opclasscmds.c.

References IndexAmRoutine::amcanorderbyop, BOOLOID, elog, ereport, errcode(), errmsg(), ERROR, get_am_name(), GetIndexAmRoutineByAmId(), GETSTRUCT, OpFamilyMember::lefttype, NULL, OpFamilyMember::object, ObjectIdGetDatum, OidIsValid, OPEROID, ReleaseSysCache(), OpFamilyMember::righttype, SearchSysCache1, and OpFamilyMember::sortfamily.

Referenced by AlterOpFamilyAdd(), and DefineOpClass().

1069 {
1070  Operator optup;
1071  Form_pg_operator opform;
1072 
1073  /* Fetch the operator definition */
1074  optup = SearchSysCache1(OPEROID, ObjectIdGetDatum(member->object));
1075  if (optup == NULL)
1076  elog(ERROR, "cache lookup failed for operator %u", member->object);
1077  opform = (Form_pg_operator) GETSTRUCT(optup);
1078 
1079  /*
1080  * Opfamily operators must be binary.
1081  */
1082  if (opform->oprkind != 'b')
1083  ereport(ERROR,
1084  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1085  errmsg("index operators must be binary")));
1086 
1087  if (OidIsValid(member->sortfamily))
1088  {
1089  /*
1090  * Ordering op, check index supports that. (We could perhaps also
1091  * check that the operator returns a type supported by the sortfamily,
1092  * but that seems more trouble than it's worth here. If it does not,
1093  * the operator will never be matchable to any ORDER BY clause, but no
1094  * worse consequences can ensue. Also, trying to check that would
1095  * create an ordering hazard during dump/reload: it's possible that
1096  * the family has been created but not yet populated with the required
1097  * operators.)
1098  */
1099  IndexAmRoutine *amroutine = GetIndexAmRoutineByAmId(amoid, false);
1100 
1101  if (!amroutine->amcanorderbyop)
1102  ereport(ERROR,
1103  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1104  errmsg("access method \"%s\" does not support ordering operators",
1105  get_am_name(amoid))));
1106  }
1107  else
1108  {
1109  /*
1110  * Search operators must return boolean.
1111  */
1112  if (opform->oprresult != BOOLOID)
1113  ereport(ERROR,
1114  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1115  errmsg("index search operators must return boolean")));
1116  }
1117 
1118  /*
1119  * If lefttype/righttype isn't specified, use the operator's input types
1120  */
1121  if (!OidIsValid(member->lefttype))
1122  member->lefttype = opform->oprleft;
1123  if (!OidIsValid(member->righttype))
1124  member->righttype = opform->oprright;
1125 
1126  ReleaseSysCache(optup);
1127 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
bool amcanorderbyop
Definition: amapi.h:173
int errcode(int sqlerrcode)
Definition: elog.c:575
#define OidIsValid(objectId)
Definition: c.h:533
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
IndexAmRoutine * GetIndexAmRoutineByAmId(Oid amoid, bool noerror)
Definition: amapi.c:56
char * get_am_name(Oid amOid)
Definition: amcmds.c:202
#define ereport(elevel, rest)
Definition: elog.h:122
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
#define NULL
Definition: c.h:226
#define BOOLOID
Definition: pg_type.h:288
FormData_pg_operator* Form_pg_operator
Definition: pg_operator.h:57
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
static void assignProcTypes ( OpFamilyMember member,
Oid  amoid,
Oid  typeoid 
)
static

Definition at line 1134 of file opclasscmds.c.

References BTORDER_PROC, BTREE_AM_OID, BTSORTSUPPORT_PROC, elog, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HASH_AM_OID, INT4OID, INTERNALOID, OpFamilyMember::lefttype, NULL, OpFamilyMember::number, OpFamilyMember::object, ObjectIdGetDatum, OidIsValid, PROCOID, ReleaseSysCache(), OpFamilyMember::righttype, SearchSysCache1, and VOIDOID.

Referenced by AlterOpFamilyAdd(), and DefineOpClass().

1135 {
1136  HeapTuple proctup;
1137  Form_pg_proc procform;
1138 
1139  /* Fetch the procedure definition */
1140  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(member->object));
1141  if (proctup == NULL)
1142  elog(ERROR, "cache lookup failed for function %u", member->object);
1143  procform = (Form_pg_proc) GETSTRUCT(proctup);
1144 
1145  /*
1146  * btree comparison procs must be 2-arg procs returning int4, while btree
1147  * sortsupport procs must take internal and return void. hash support
1148  * procs must be 1-arg procs returning int4. Otherwise we don't know.
1149  */
1150  if (amoid == BTREE_AM_OID)
1151  {
1152  if (member->number == BTORDER_PROC)
1153  {
1154  if (procform->pronargs != 2)
1155  ereport(ERROR,
1156  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1157  errmsg("btree comparison procedures must have two arguments")));
1158  if (procform->prorettype != INT4OID)
1159  ereport(ERROR,
1160  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1161  errmsg("btree comparison procedures must return integer")));
1162 
1163  /*
1164  * If lefttype/righttype isn't specified, use the proc's input
1165  * types
1166  */
1167  if (!OidIsValid(member->lefttype))
1168  member->lefttype = procform->proargtypes.values[0];
1169  if (!OidIsValid(member->righttype))
1170  member->righttype = procform->proargtypes.values[1];
1171  }
1172  else if (member->number == BTSORTSUPPORT_PROC)
1173  {
1174  if (procform->pronargs != 1 ||
1175  procform->proargtypes.values[0] != INTERNALOID)
1176  ereport(ERROR,
1177  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1178  errmsg("btree sort support procedures must accept type \"internal\"")));
1179  if (procform->prorettype != VOIDOID)
1180  ereport(ERROR,
1181  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1182  errmsg("btree sort support procedures must return void")));
1183 
1184  /*
1185  * Can't infer lefttype/righttype from proc, so use default rule
1186  */
1187  }
1188  }
1189  else if (amoid == HASH_AM_OID)
1190  {
1191  if (procform->pronargs != 1)
1192  ereport(ERROR,
1193  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1194  errmsg("hash procedures must have one argument")));
1195  if (procform->prorettype != INT4OID)
1196  ereport(ERROR,
1197  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1198  errmsg("hash procedures must return integer")));
1199 
1200  /*
1201  * If lefttype/righttype isn't specified, use the proc's input type
1202  */
1203  if (!OidIsValid(member->lefttype))
1204  member->lefttype = procform->proargtypes.values[0];
1205  if (!OidIsValid(member->righttype))
1206  member->righttype = procform->proargtypes.values[0];
1207  }
1208 
1209  /*
1210  * The default in CREATE OPERATOR CLASS is to use the class' opcintype as
1211  * lefttype and righttype. In CREATE or ALTER OPERATOR FAMILY, opcintype
1212  * isn't available, so make the user specify the types.
1213  */
1214  if (!OidIsValid(member->lefttype))
1215  member->lefttype = typeoid;
1216  if (!OidIsValid(member->righttype))
1217  member->righttype = typeoid;
1218 
1219  if (!OidIsValid(member->lefttype) || !OidIsValid(member->righttype))
1220  ereport(ERROR,
1221  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1222  errmsg("associated data types must be specified for index support procedure")));
1223 
1224  ReleaseSysCache(proctup);
1225 }
#define BTORDER_PROC
Definition: nbtree.h:229
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define BTSORTSUPPORT_PROC
Definition: nbtree.h:230
#define BTREE_AM_OID
Definition: pg_am.h:70
#define INT4OID
Definition: pg_type.h:316
int errcode(int sqlerrcode)
Definition: elog.c:575
#define OidIsValid(objectId)
Definition: c.h:533
#define HASH_AM_OID
Definition: pg_am.h:73
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
#define VOIDOID
Definition: pg_type.h:678
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
#define INTERNALOID
Definition: pg_type.h:686
#define NULL
Definition: c.h:226
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
static ObjectAddress CreateOpFamily ( char *  amname,
char *  opfname,
Oid  namespaceoid,
Oid  amoid 
)
static

Definition at line 241 of file opclasscmds.c.

References AccessMethodRelationId, Anum_pg_opfamily_opfmethod, Anum_pg_opfamily_opfname, Anum_pg_opfamily_opfnamespace, Anum_pg_opfamily_opfowner, CatalogTupleInsert(), ObjectAddress::classId, CStringGetDatum, DEPENDENCY_AUTO, DEPENDENCY_NORMAL, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, GetUserId(), heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), InvokeObjectPostCreateHook, NameGetDatum, NamespaceRelationId, namestrcpy(), Natts_pg_opfamily, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OperatorFamilyRelationId, OPFAMILYAMNAMENSP, RelationData::rd_att, recordDependencyOn(), recordDependencyOnCurrentExtension(), recordDependencyOnOwner(), RowExclusiveLock, SearchSysCacheExists3, and values.

Referenced by DefineOpClass(), and DefineOpFamily().

242 {
243  Oid opfamilyoid;
244  Relation rel;
245  HeapTuple tup;
247  bool nulls[Natts_pg_opfamily];
248  NameData opfName;
249  ObjectAddress myself,
250  referenced;
251 
253 
254  /*
255  * Make sure there is no existing opfamily of this name (this is just to
256  * give a more friendly error message than "duplicate key").
257  */
259  ObjectIdGetDatum(amoid),
260  CStringGetDatum(opfname),
261  ObjectIdGetDatum(namespaceoid)))
262  ereport(ERROR,
264  errmsg("operator family \"%s\" for access method \"%s\" already exists",
265  opfname, amname)));
266 
267  /*
268  * Okay, let's create the pg_opfamily entry.
269  */
270  memset(values, 0, sizeof(values));
271  memset(nulls, false, sizeof(nulls));
272 
273  values[Anum_pg_opfamily_opfmethod - 1] = ObjectIdGetDatum(amoid);
274  namestrcpy(&opfName, opfname);
275  values[Anum_pg_opfamily_opfname - 1] = NameGetDatum(&opfName);
276  values[Anum_pg_opfamily_opfnamespace - 1] = ObjectIdGetDatum(namespaceoid);
278 
279  tup = heap_form_tuple(rel->rd_att, values, nulls);
280 
281  opfamilyoid = CatalogTupleInsert(rel, tup);
282 
283  heap_freetuple(tup);
284 
285  /*
286  * Create dependencies for the opfamily proper.
287  */
289  myself.objectId = opfamilyoid;
290  myself.objectSubId = 0;
291 
292  /* dependency on access method */
293  referenced.classId = AccessMethodRelationId;
294  referenced.objectId = amoid;
295  referenced.objectSubId = 0;
296  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
297 
298  /* dependency on namespace */
299  referenced.classId = NamespaceRelationId;
300  referenced.objectId = namespaceoid;
301  referenced.objectSubId = 0;
302  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
303 
304  /* dependency on owner */
306 
307  /* dependency on extension */
308  recordDependencyOnCurrentExtension(&myself, false);
309 
310  /* Post creation hook for new operator family */
312 
314 
315  return myself;
316 }
#define NamespaceRelationId
Definition: pg_namespace.h:34
#define NameGetDatum(X)
Definition: postgres.h:603
#define Anum_pg_opfamily_opfmethod
Definition: pg_opfamily.h:51
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
Oid GetUserId(void)
Definition: miscinit.c:283
#define Anum_pg_opfamily_opfowner
Definition: pg_opfamily.h:54
#define Anum_pg_opfamily_opfnamespace
Definition: pg_opfamily.h:53
#define OperatorFamilyRelationId
Definition: pg_opfamily.h:29
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:692
#define heap_close(r, l)
Definition: heapam.h:97
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:158
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
unsigned int Oid
Definition: postgres_ext.h:31
#define Anum_pg_opfamily_opfname
Definition: pg_opfamily.h:52
int namestrcpy(Name name, const char *str)
Definition: name.c:217
#define Natts_pg_opfamily
Definition: pg_opfamily.h:50
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:171
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
Definition: c.h:488
#define AccessMethodRelationId
Definition: pg_am.h:32
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:586
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:374
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
TupleDesc rd_att
Definition: rel.h:114
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:139
static Datum values[MAXATTR]
Definition: bootstrap.c:162
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:34
ObjectAddress DefineOpClass ( CreateOpClassStmt stmt)

Definition at line 323 of file opclasscmds.c.

References ACL_CREATE, ACL_KIND_NAMESPACE, ACL_KIND_OPER, ACL_KIND_PROC, aclcheck_error(), aclcheck_error_type(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, addFamilyMember(), AMNAME, CreateOpClassStmt::amname, IndexAmRoutine::amstorage, IndexAmRoutine::amstrategies, IndexAmRoutine::amsupport, Anum_pg_opclass_opcdefault, Anum_pg_opclass_opcfamily, Anum_pg_opclass_opcintype, Anum_pg_opclass_opckeytype, Anum_pg_opclass_opcmethod, Anum_pg_opclass_opcname, Anum_pg_opclass_opcnamespace, Anum_pg_opclass_opcowner, CreateOpClassItem::args, assignOperTypes(), assignProcTypes(), BoolGetDatum, BTEqualStrategyNumber, BTREE_AM_OID, castNode, CatalogTupleInsert(), CLAAMNAMENSP, CreateOpClassItem::class_args, ObjectAddress::classId, CreateOpFamily(), CStringGetDatum, CreateOpClassStmt::datatype, DEPENDENCY_AUTO, DEPENDENCY_NORMAL, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errdetail(), errmsg(), ERROR, EventTriggerCollectCreateOpClass(), get_func_name(), get_namespace_name(), get_opcode(), get_opfamily_oid(), get_opname(), GetIndexAmRoutineByAmId(), GETSTRUCT, GetUserId(), heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, InvalidOid, InvokeObjectPostCreateHook, CreateOpClassStmt::isDefault, CreateOpClassStmt::items, CreateOpClassItem::itemtype, OpFamilyMember::lefttype, lfirst, linitial, LookupFuncNameTypeNames(), LookupOperName(), LookupOperNameTypeNames(), lsecond, CreateOpClassItem::name, NameGetDatum, NamespaceRelationId, NameStr, namestrcpy(), Natts_pg_opclass, NIL, NULL, OpFamilyMember::number, CreateOpClassItem::number, OpFamilyMember::object, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, OPCLASS_ITEM_FUNCTION, OPCLASS_ITEM_OPERATOR, OPCLASS_ITEM_STORAGETYPE, OpclassAmNameNspIndexId, CreateOpClassStmt::opclassname, OperatorClassRelationId, OperatorFamilyRelationId, OPFAMILYAMNAMENSP, CreateOpClassStmt::opfamilyname, CreateOpClassItem::order_family, palloc0(), pg_namespace_aclcheck(), pg_oper_ownercheck(), pg_proc_ownercheck(), pg_type_ownercheck(), PointerGetDatum, processTypesSpec(), QualifiedNameGetCreationNamespace(), RelationData::rd_att, recordDependencyOn(), recordDependencyOnCurrentExtension(), recordDependencyOnOwner(), ReleaseSysCache(), OpFamilyMember::righttype, RowExclusiveLock, ScanKeyInit(), SearchSysCache1, SearchSysCache3, SearchSysCacheExists3, OpFamilyMember::sortfamily, CreateOpClassItem::storedtype, storeOperators(), storeProcedures(), superuser(), systable_beginscan(), systable_endscan(), systable_getnext(), TypeNameToString(), typenameTypeId(), TypeRelationId, and values.

Referenced by ProcessUtilitySlow().

324 {
325  char *opcname; /* name of opclass we're creating */
326  Oid amoid, /* our AM's oid */
327  typeoid, /* indexable datatype oid */
328  storageoid, /* storage datatype oid, if any */
329  namespaceoid, /* namespace to create opclass in */
330  opfamilyoid, /* oid of containing opfamily */
331  opclassoid; /* oid of opclass we create */
332  int maxOpNumber, /* amstrategies value */
333  maxProcNumber; /* amsupport value */
334  bool amstorage; /* amstorage flag */
335  List *operators; /* OpFamilyMember list for operators */
336  List *procedures; /* OpFamilyMember list for support procs */
337  ListCell *l;
338  Relation rel;
339  HeapTuple tup;
340  IndexAmRoutine *amroutine;
342  bool nulls[Natts_pg_opclass];
343  AclResult aclresult;
344  NameData opcName;
345  ObjectAddress myself,
346  referenced;
347 
348  /* Convert list of names to a name and namespace */
349  namespaceoid = QualifiedNameGetCreationNamespace(stmt->opclassname,
350  &opcname);
351 
352  /* Check we have creation rights in target namespace */
353  aclresult = pg_namespace_aclcheck(namespaceoid, GetUserId(), ACL_CREATE);
354  if (aclresult != ACLCHECK_OK)
356  get_namespace_name(namespaceoid));
357 
358  /* Get necessary info about access method */
360  if (!HeapTupleIsValid(tup))
361  ereport(ERROR,
362  (errcode(ERRCODE_UNDEFINED_OBJECT),
363  errmsg("access method \"%s\" does not exist",
364  stmt->amname)));
365 
366  amoid = HeapTupleGetOid(tup);
367  amroutine = GetIndexAmRoutineByAmId(amoid, false);
368  ReleaseSysCache(tup);
369 
370  maxOpNumber = amroutine->amstrategies;
371  /* if amstrategies is zero, just enforce that op numbers fit in int16 */
372  if (maxOpNumber <= 0)
373  maxOpNumber = SHRT_MAX;
374  maxProcNumber = amroutine->amsupport;
375  amstorage = amroutine->amstorage;
376 
377  /* XXX Should we make any privilege check against the AM? */
378 
379  /*
380  * The question of appropriate permissions for CREATE OPERATOR CLASS is
381  * interesting. Creating an opclass is tantamount to granting public
382  * execute access on the functions involved, since the index machinery
383  * generally does not check access permission before using the functions.
384  * A minimum expectation therefore is that the caller have execute
385  * privilege with grant option. Since we don't have a way to make the
386  * opclass go away if the grant option is revoked, we choose instead to
387  * require ownership of the functions. It's also not entirely clear what
388  * permissions should be required on the datatype, but ownership seems
389  * like a safe choice.
390  *
391  * Currently, we require superuser privileges to create an opclass. This
392  * seems necessary because we have no way to validate that the offered set
393  * of operators and functions are consistent with the AM's expectations.
394  * It would be nice to provide such a check someday, if it can be done
395  * without solving the halting problem :-(
396  *
397  * XXX re-enable NOT_USED code sections below if you remove this test.
398  */
399  if (!superuser())
400  ereport(ERROR,
401  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
402  errmsg("must be superuser to create an operator class")));
403 
404  /* Look up the datatype */
405  typeoid = typenameTypeId(NULL, stmt->datatype);
406 
407 #ifdef NOT_USED
408  /* XXX this is unnecessary given the superuser check above */
409  /* Check we have ownership of the datatype */
410  if (!pg_type_ownercheck(typeoid, GetUserId()))
412 #endif
413 
414  /*
415  * Look up the containing operator family, or create one if FAMILY option
416  * was omitted and there's not a match already.
417  */
418  if (stmt->opfamilyname)
419  {
420  opfamilyoid = get_opfamily_oid(amoid, stmt->opfamilyname, false);
421  }
422  else
423  {
424  /* Lookup existing family of same name and namespace */
426  ObjectIdGetDatum(amoid),
427  PointerGetDatum(opcname),
428  ObjectIdGetDatum(namespaceoid));
429  if (HeapTupleIsValid(tup))
430  {
431  opfamilyoid = HeapTupleGetOid(tup);
432 
433  /*
434  * XXX given the superuser check above, there's no need for an
435  * ownership check here
436  */
437  ReleaseSysCache(tup);
438  }
439  else
440  {
441  ObjectAddress tmpAddr;
442 
443  /*
444  * Create it ... again no need for more permissions ...
445  */
446  tmpAddr = CreateOpFamily(stmt->amname, opcname,
447  namespaceoid, amoid);
448  opfamilyoid = tmpAddr.objectId;
449  }
450  }
451 
452  operators = NIL;
453  procedures = NIL;
454 
455  /* Storage datatype is optional */
456  storageoid = InvalidOid;
457 
458  /*
459  * Scan the "items" list to obtain additional info.
460  */
461  foreach(l, stmt->items)
462  {
464  Oid operOid;
465  Oid funcOid;
466  Oid sortfamilyOid;
467  OpFamilyMember *member;
468 
469  switch (item->itemtype)
470  {
472  if (item->number <= 0 || item->number > maxOpNumber)
473  ereport(ERROR,
474  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
475  errmsg("invalid operator number %d,"
476  " must be between 1 and %d",
477  item->number, maxOpNumber)));
478  if (item->args != NIL)
479  {
480  TypeName *typeName1 = (TypeName *) linitial(item->args);
481  TypeName *typeName2 = (TypeName *) lsecond(item->args);
482 
483  operOid = LookupOperNameTypeNames(NULL, item->name,
484  typeName1, typeName2,
485  false, -1);
486  }
487  else
488  {
489  /* Default to binary op on input datatype */
490  operOid = LookupOperName(NULL, item->name,
491  typeoid, typeoid,
492  false, -1);
493  }
494 
495  if (item->order_family)
496  sortfamilyOid = get_opfamily_oid(BTREE_AM_OID,
497  item->order_family,
498  false);
499  else
500  sortfamilyOid = InvalidOid;
501 
502 #ifdef NOT_USED
503  /* XXX this is unnecessary given the superuser check above */
504  /* Caller must own operator and its underlying function */
505  if (!pg_oper_ownercheck(operOid, GetUserId()))
507  get_opname(operOid));
508  funcOid = get_opcode(operOid);
509  if (!pg_proc_ownercheck(funcOid, GetUserId()))
511  get_func_name(funcOid));
512 #endif
513 
514  /* Save the info */
515  member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
516  member->object = operOid;
517  member->number = item->number;
518  member->sortfamily = sortfamilyOid;
519  assignOperTypes(member, amoid, typeoid);
520  addFamilyMember(&operators, member, false);
521  break;
523  if (item->number <= 0 || item->number > maxProcNumber)
524  ereport(ERROR,
525  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
526  errmsg("invalid procedure number %d,"
527  " must be between 1 and %d",
528  item->number, maxProcNumber)));
529  funcOid = LookupFuncNameTypeNames(item->name, item->args,
530  false);
531 #ifdef NOT_USED
532  /* XXX this is unnecessary given the superuser check above */
533  /* Caller must own function */
534  if (!pg_proc_ownercheck(funcOid, GetUserId()))
536  get_func_name(funcOid));
537 #endif
538 
539  /* Save the info */
540  member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
541  member->object = funcOid;
542  member->number = item->number;
543 
544  /* allow overriding of the function's actual arg types */
545  if (item->class_args)
547  &member->lefttype, &member->righttype);
548 
549  assignProcTypes(member, amoid, typeoid);
550  addFamilyMember(&procedures, member, true);
551  break;
553  if (OidIsValid(storageoid))
554  ereport(ERROR,
555  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
556  errmsg("storage type specified more than once")));
557  storageoid = typenameTypeId(NULL, item->storedtype);
558 
559 #ifdef NOT_USED
560  /* XXX this is unnecessary given the superuser check above */
561  /* Check we have ownership of the datatype */
562  if (!pg_type_ownercheck(storageoid, GetUserId()))
564 #endif
565  break;
566  default:
567  elog(ERROR, "unrecognized item type: %d", item->itemtype);
568  break;
569  }
570  }
571 
572  /*
573  * If storagetype is specified, make sure it's legal.
574  */
575  if (OidIsValid(storageoid))
576  {
577  /* Just drop the spec if same as column datatype */
578  if (storageoid == typeoid)
579  storageoid = InvalidOid;
580  else if (!amstorage)
581  ereport(ERROR,
582  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
583  errmsg("storage type cannot be different from data type for access method \"%s\"",
584  stmt->amname)));
585  }
586 
588 
589  /*
590  * Make sure there is no existing opclass of this name (this is just to
591  * give a more friendly error message than "duplicate key").
592  */
594  ObjectIdGetDatum(amoid),
595  CStringGetDatum(opcname),
596  ObjectIdGetDatum(namespaceoid)))
597  ereport(ERROR,
599  errmsg("operator class \"%s\" for access method \"%s\" already exists",
600  opcname, stmt->amname)));
601 
602  /*
603  * If we are creating a default opclass, check there isn't one already.
604  * (Note we do not restrict this test to visible opclasses; this ensures
605  * that typcache.c can find unique solutions to its questions.)
606  */
607  if (stmt->isDefault)
608  {
609  ScanKeyData skey[1];
610  SysScanDesc scan;
611 
612  ScanKeyInit(&skey[0],
614  BTEqualStrategyNumber, F_OIDEQ,
615  ObjectIdGetDatum(amoid));
616 
618  NULL, 1, skey);
619 
620  while (HeapTupleIsValid(tup = systable_getnext(scan)))
621  {
622  Form_pg_opclass opclass = (Form_pg_opclass) GETSTRUCT(tup);
623 
624  if (opclass->opcintype == typeoid && opclass->opcdefault)
625  ereport(ERROR,
627  errmsg("could not make operator class \"%s\" be default for type %s",
628  opcname,
629  TypeNameToString(stmt->datatype)),
630  errdetail("Operator class \"%s\" already is the default.",
631  NameStr(opclass->opcname))));
632  }
633 
634  systable_endscan(scan);
635  }
636 
637  /*
638  * Okay, let's create the pg_opclass entry.
639  */
640  memset(values, 0, sizeof(values));
641  memset(nulls, false, sizeof(nulls));
642 
643  values[Anum_pg_opclass_opcmethod - 1] = ObjectIdGetDatum(amoid);
644  namestrcpy(&opcName, opcname);
645  values[Anum_pg_opclass_opcname - 1] = NameGetDatum(&opcName);
646  values[Anum_pg_opclass_opcnamespace - 1] = ObjectIdGetDatum(namespaceoid);
648  values[Anum_pg_opclass_opcfamily - 1] = ObjectIdGetDatum(opfamilyoid);
649  values[Anum_pg_opclass_opcintype - 1] = ObjectIdGetDatum(typeoid);
651  values[Anum_pg_opclass_opckeytype - 1] = ObjectIdGetDatum(storageoid);
652 
653  tup = heap_form_tuple(rel->rd_att, values, nulls);
654 
655  opclassoid = CatalogTupleInsert(rel, tup);
656 
657  heap_freetuple(tup);
658 
659  /*
660  * Now add tuples to pg_amop and pg_amproc tying in the operators and
661  * functions. Dependencies on them are inserted, too.
662  */
663  storeOperators(stmt->opfamilyname, amoid, opfamilyoid,
664  opclassoid, operators, false);
665  storeProcedures(stmt->opfamilyname, amoid, opfamilyoid,
666  opclassoid, procedures, false);
667 
668  /* let event triggers know what happened */
669  EventTriggerCollectCreateOpClass(stmt, opclassoid, operators, procedures);
670 
671  /*
672  * Create dependencies for the opclass proper. Note: we do not need a
673  * dependency link to the AM, because that exists through the opfamily.
674  */
676  myself.objectId = opclassoid;
677  myself.objectSubId = 0;
678 
679  /* dependency on namespace */
680  referenced.classId = NamespaceRelationId;
681  referenced.objectId = namespaceoid;
682  referenced.objectSubId = 0;
683  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
684 
685  /* dependency on opfamily */
686  referenced.classId = OperatorFamilyRelationId;
687  referenced.objectId = opfamilyoid;
688  referenced.objectSubId = 0;
689  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
690 
691  /* dependency on indexed datatype */
692  referenced.classId = TypeRelationId;
693  referenced.objectId = typeoid;
694  referenced.objectSubId = 0;
695  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
696 
697  /* dependency on storage datatype */
698  if (OidIsValid(storageoid))
699  {
700  referenced.classId = TypeRelationId;
701  referenced.objectId = storageoid;
702  referenced.objectSubId = 0;
703  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
704  }
705 
706  /* dependency on owner */
708 
709  /* dependency on extension */
710  recordDependencyOnCurrentExtension(&myself, false);
711 
712  /* Post creation hook for new operator class */
714 
716 
717  return myself;
718 }
Oid LookupOperNameTypeNames(ParseState *pstate, List *opername, TypeName *oprleft, TypeName *oprright, bool noError, int location)
Definition: parse_oper.c:142
#define NIL
Definition: pg_list.h:69
#define NamespaceRelationId
Definition: pg_namespace.h:34
#define NameGetDatum(X)
Definition: postgres.h:603
uint16 amsupport
Definition: amapi.h:169
#define Anum_pg_opclass_opcmethod
Definition: pg_opclass.h:75
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
static void assignOperTypes(OpFamilyMember *member, Oid amoid, Oid typeoid)
Definition: opclasscmds.c:1068
#define Anum_pg_opclass_opckeytype
Definition: pg_opclass.h:82
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
Oid GetUserId(void)
Definition: miscinit.c:283
TypeName * storedtype
Definition: parsenodes.h:2429
#define castNode(_type_, nodeptr)
Definition: nodes.h:577
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2790
#define PointerGetDatum(X)
Definition: postgres.h:564
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:459
#define BTREE_AM_OID
Definition: pg_am.h:70
bool amstorage
Definition: amapi.h:187
#define Anum_pg_opclass_opcintype
Definition: pg_opclass.h:80
#define OperatorClassRelationId
Definition: pg_opclass.h:49
#define Anum_pg_opclass_opcowner
Definition: pg_opclass.h:78
#define OperatorFamilyRelationId
Definition: pg_opfamily.h:29
bool pg_oper_ownercheck(Oid oper_oid, Oid roleid)
Definition: aclchk.c:4573
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
Oid LookupOperName(ParseState *pstate, List *opername, Oid oprleft, Oid oprright, bool noError, int location)
Definition: parse_oper.c:102
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
#define heap_close(r, l)
Definition: heapam.h:97
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:158
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
unsigned int Oid
Definition: postgres_ext.h:31
bool pg_type_ownercheck(Oid type_oid, Oid roleid)
Definition: aclchk.c:4547
#define TypeRelationId
Definition: pg_type.h:34
int namestrcpy(Name name, const char *str)
Definition: name.c:217
#define OidIsValid(objectId)
Definition: c.h:533
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4459
#define Anum_pg_opclass_opcfamily
Definition: pg_opclass.h:79
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:322
#define OpclassAmNameNspIndexId
Definition: indexing.h:191
#define lsecond(l)
Definition: pg_list.h:114
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3436
#define OPCLASS_ITEM_OPERATOR
Definition: parsenodes.h:2414
char * get_opname(Oid opno)
Definition: lsyscache.c:1087
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
#define Anum_pg_opclass_opcnamespace
Definition: pg_opclass.h:77
#define linitial(l)
Definition: pg_list.h:110
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:75
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:171
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
IndexAmRoutine * GetIndexAmRoutineByAmId(Oid amoid, bool noerror)
Definition: amapi.c:56
#define Anum_pg_opclass_opcname
Definition: pg_opclass.h:76
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1380
Definition: c.h:488
TypeName * datatype
Definition: parsenodes.h:2409
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
static ObjectAddress CreateOpFamily(char *amname, char *opfname, Oid namespaceoid, Oid amoid)
Definition: opclasscmds.c:241
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3378
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:873
static void addFamilyMember(List **list, OpFamilyMember *member, bool isProc)
Definition: opclasscmds.c:1232
#define CStringGetDatum(X)
Definition: postgres.h:586
#define Anum_pg_opclass_opcdefault
Definition: pg_opclass.h:81
Oid LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError)
Definition: parse_func.c:1941
#define ereport(elevel, rest)
Definition: elog.h:122
static void processTypesSpec(List *args, Oid *lefttype, Oid *righttype)
Definition: opclasscmds.c:1039
void * palloc0(Size size)
Definition: mcxt.c:920
AclResult
Definition: acl.h:170
uintptr_t Datum
Definition: postgres.h:374
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
TupleDesc rd_att
Definition: rel.h:114
#define BoolGetDatum(X)
Definition: postgres.h:410
#define InvalidOid
Definition: postgres_ext.h:36
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1062
#define OPCLASS_ITEM_FUNCTION
Definition: parsenodes.h:2415
#define Natts_pg_opclass
Definition: pg_opclass.h:74
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:139
#define OPCLASS_ITEM_STORAGETYPE
Definition: parsenodes.h:2416
void EventTriggerCollectCreateOpClass(CreateOpClassStmt *stmt, Oid opcoid, List *operators, List *procedures)
Oid get_opfamily_oid(Oid amID, List *opfamilyname, bool missing_ok)
Definition: opclasscmds.c:141
static void storeProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid, Oid opclassoid, List *procedures, bool isAdd)
Definition: opclasscmds.c:1386
uint16 amstrategies
Definition: amapi.h:167
static Datum values[MAXATTR]
Definition: bootstrap.c:162
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define SearchSysCache3(cacheId, key1, key2, key3)
Definition: syscache.h:153
#define NameStr(name)
Definition: c.h:494
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
static void assignProcTypes(OpFamilyMember *member, Oid amoid, Oid typeoid)
Definition: opclasscmds.c:1134
static void storeOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid, Oid opclassoid, List *operators, bool isAdd)
Definition: opclasscmds.c:1271
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:68
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:34
Definition: pg_list.h:45
#define BTEqualStrategyNumber
Definition: stratnum.h:31
bool pg_proc_ownercheck(Oid proc_oid, Oid roleid)
Definition: aclchk.c:4599
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274
ObjectAddress DefineOpFamily ( CreateOpFamilyStmt stmt)

Definition at line 726 of file opclasscmds.c.

References ACL_CREATE, ACL_KIND_NAMESPACE, aclcheck_error(), ACLCHECK_OK, CreateOpFamilyStmt::amname, CreateOpFamily(), ereport, errcode(), errmsg(), ERROR, get_index_am_oid(), get_namespace_name(), GetUserId(), CreateOpFamilyStmt::opfamilyname, pg_namespace_aclcheck(), QualifiedNameGetCreationNamespace(), and superuser().

Referenced by ProcessUtilitySlow().

727 {
728  char *opfname; /* name of opfamily we're creating */
729  Oid amoid, /* our AM's oid */
730  namespaceoid; /* namespace to create opfamily in */
731  AclResult aclresult;
732 
733  /* Convert list of names to a name and namespace */
734  namespaceoid = QualifiedNameGetCreationNamespace(stmt->opfamilyname,
735  &opfname);
736 
737  /* Check we have creation rights in target namespace */
738  aclresult = pg_namespace_aclcheck(namespaceoid, GetUserId(), ACL_CREATE);
739  if (aclresult != ACLCHECK_OK)
741  get_namespace_name(namespaceoid));
742 
743  /* Get access method OID, throwing an error if it doesn't exist. */
744  amoid = get_index_am_oid(stmt->amname, false);
745 
746  /* XXX Should we make any privilege check against the AM? */
747 
748  /*
749  * Currently, we require superuser privileges to create an opfamily. See
750  * comments in DefineOpClass.
751  */
752  if (!superuser())
753  ereport(ERROR,
754  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
755  errmsg("must be superuser to create an operator family")));
756 
757  /* Insert pg_opfamily catalog entry */
758  return CreateOpFamily(stmt->amname, opfname, namespaceoid, amoid);
759 }
Oid GetUserId(void)
Definition: miscinit.c:283
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2790
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
unsigned int Oid
Definition: postgres_ext.h:31
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4459
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:75
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
Oid get_index_am_oid(const char *amname, bool missing_ok)
Definition: amcmds.c:183
static ObjectAddress CreateOpFamily(char *amname, char *opfname, Oid namespaceoid, Oid amoid)
Definition: opclasscmds.c:241
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3378
#define ereport(elevel, rest)
Definition: elog.h:122
AclResult
Definition: acl.h:170
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void dropOperators ( List opfamilyname,
Oid  amoid,
Oid  opfamilyoid,
List operators 
)
static

Definition at line 1486 of file opclasscmds.c.

References AccessMethodOperatorRelationId, AMOPSTRATEGY, DROP_RESTRICT, ereport, errcode(), errmsg(), ERROR, format_type_be(), GetSysCacheOid4, Int16GetDatum, OpFamilyMember::lefttype, lfirst, NameListToString(), OpFamilyMember::number, ObjectIdGetDatum, OidIsValid, performDeletion(), and OpFamilyMember::righttype.

Referenced by AlterOpFamilyDrop().

1488 {
1489  ListCell *l;
1490 
1491  foreach(l, operators)
1492  {
1493  OpFamilyMember *op = (OpFamilyMember *) lfirst(l);
1494  Oid amopid;
1495  ObjectAddress object;
1496 
1497  amopid = GetSysCacheOid4(AMOPSTRATEGY,
1498  ObjectIdGetDatum(opfamilyoid),
1501  Int16GetDatum(op->number));
1502  if (!OidIsValid(amopid))
1503  ereport(ERROR,
1504  (errcode(ERRCODE_UNDEFINED_OBJECT),
1505  errmsg("operator %d(%s,%s) does not exist in operator family \"%s\"",
1506  op->number,
1507  format_type_be(op->lefttype),
1509  NameListToString(opfamilyname))));
1510 
1511  object.classId = AccessMethodOperatorRelationId;
1512  object.objectId = amopid;
1513  object.objectSubId = 0;
1514 
1515  performDeletion(&object, DROP_RESTRICT, 0);
1516  }
1517 }
#define GetSysCacheOid4(cacheId, key1, key2, key3, key4)
Definition: syscache.h:182
#define Int16GetDatum(X)
Definition: postgres.h:459
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
#define AccessMethodOperatorRelationId
Definition: pg_amop.h:54
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:301
#define ereport(elevel, rest)
Definition: elog.h:122
char * NameListToString(List *names)
Definition: namespace.c:2897
#define lfirst(lc)
Definition: pg_list.h:106
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void dropProcedures ( List opfamilyname,
Oid  amoid,
Oid  opfamilyoid,
List procedures 
)
static

Definition at line 1526 of file opclasscmds.c.

References AccessMethodProcedureRelationId, AMPROCNUM, DROP_RESTRICT, ereport, errcode(), errmsg(), ERROR, format_type_be(), GetSysCacheOid4, Int16GetDatum, OpFamilyMember::lefttype, lfirst, NameListToString(), OpFamilyMember::number, ObjectIdGetDatum, OidIsValid, performDeletion(), and OpFamilyMember::righttype.

Referenced by AlterOpFamilyDrop().

1528 {
1529  ListCell *l;
1530 
1531  foreach(l, procedures)
1532  {
1533  OpFamilyMember *op = (OpFamilyMember *) lfirst(l);
1534  Oid amprocid;
1535  ObjectAddress object;
1536 
1537  amprocid = GetSysCacheOid4(AMPROCNUM,
1538  ObjectIdGetDatum(opfamilyoid),
1541  Int16GetDatum(op->number));
1542  if (!OidIsValid(amprocid))
1543  ereport(ERROR,
1544  (errcode(ERRCODE_UNDEFINED_OBJECT),
1545  errmsg("function %d(%s,%s) does not exist in operator family \"%s\"",
1546  op->number,
1547  format_type_be(op->lefttype),
1549  NameListToString(opfamilyname))));
1550 
1551  object.classId = AccessMethodProcedureRelationId;
1552  object.objectId = amprocid;
1553  object.objectSubId = 0;
1554 
1555  performDeletion(&object, DROP_RESTRICT, 0);
1556  }
1557 }
#define GetSysCacheOid4(cacheId, key1, key2, key3, key4)
Definition: syscache.h:182
#define Int16GetDatum(X)
Definition: postgres.h:459
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:301
#define ereport(elevel, rest)
Definition: elog.h:122
char * NameListToString(List *names)
Definition: namespace.c:2897
#define lfirst(lc)
Definition: pg_list.h:106
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define AccessMethodProcedureRelationId
Definition: pg_amproc.h:43
Oid get_opclass_oid ( Oid  amID,
List opclassname,
bool  missing_ok 
)

Definition at line 220 of file opclasscmds.c.

References HeapTupleGetOid, HeapTupleIsValid, InvalidOid, OpClassCacheLookup(), and ReleaseSysCache().

Referenced by findRangeSubOpclass(), get_object_address_opcf(), and resolve_unique_index_expr().

221 {
222  HeapTuple htup;
223  Oid opcID;
224 
225  htup = OpClassCacheLookup(amID, opclassname, missing_ok);
226  if (!HeapTupleIsValid(htup))
227  return InvalidOid;
228  opcID = HeapTupleGetOid(htup);
229  ReleaseSysCache(htup);
230 
231  return opcID;
232 }
static HeapTuple OpClassCacheLookup(Oid amID, List *opclassname, bool missing_ok)
Definition: opclasscmds.c:162
unsigned int Oid
Definition: postgres_ext.h:31
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
Oid get_opfamily_oid ( Oid  amID,
List opfamilyname,
bool  missing_ok 
)

Definition at line 141 of file opclasscmds.c.

References HeapTupleGetOid, HeapTupleIsValid, InvalidOid, OpFamilyCacheLookup(), and ReleaseSysCache().

Referenced by AlterOpFamily(), AlterOpFamilyAdd(), DefineOpClass(), and get_object_address_opcf().

142 {
143  HeapTuple htup;
144  Oid opfID;
145 
146  htup = OpFamilyCacheLookup(amID, opfamilyname, missing_ok);
147  if (!HeapTupleIsValid(htup))
148  return InvalidOid;
149  opfID = HeapTupleGetOid(htup);
150  ReleaseSysCache(htup);
151 
152  return opfID;
153 }
static HeapTuple OpFamilyCacheLookup(Oid amID, List *opfamilyname, bool missing_ok)
Definition: opclasscmds.c:83
unsigned int Oid
Definition: postgres_ext.h:31
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
void IsThereOpClassInNamespace ( const char *  opcname,
Oid  opcmethod,
Oid  opcnamespace 
)

Definition at line 1665 of file opclasscmds.c.

References CLAAMNAMENSP, CStringGetDatum, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, get_am_name(), get_namespace_name(), ObjectIdGetDatum, and SearchSysCacheExists3.

Referenced by AlterObjectNamespace_internal(), and AlterObjectRename_internal().

1667 {
1668  /* make sure the new name doesn't exist */
1670  ObjectIdGetDatum(opcmethod),
1671  CStringGetDatum(opcname),
1672  ObjectIdGetDatum(opcnamespace)))
1673  ereport(ERROR,
1675  errmsg("operator class \"%s\" for access method \"%s\" already exists in schema \"%s\"",
1676  opcname,
1677  get_am_name(opcmethod),
1678  get_namespace_name(opcnamespace))));
1679 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:171
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
char * get_am_name(Oid amOid)
Definition: amcmds.c:202
#define CStringGetDatum(X)
Definition: postgres.h:586
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:34
void IsThereOpFamilyInNamespace ( const char *  opfname,
Oid  opfmethod,
Oid  opfnamespace 
)

Definition at line 1688 of file opclasscmds.c.

References CStringGetDatum, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, get_am_name(), get_namespace_name(), ObjectIdGetDatum, OPFAMILYAMNAMENSP, and SearchSysCacheExists3.

Referenced by AlterObjectNamespace_internal(), and AlterObjectRename_internal().

1690 {
1691  /* make sure the new name doesn't exist */
1693  ObjectIdGetDatum(opfmethod),
1694  CStringGetDatum(opfname),
1695  ObjectIdGetDatum(opfnamespace)))
1696  ereport(ERROR,
1698  errmsg("operator family \"%s\" for access method \"%s\" already exists in schema \"%s\"",
1699  opfname,
1700  get_am_name(opfmethod),
1701  get_namespace_name(opfnamespace))));
1702 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:171
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
char * get_am_name(Oid amOid)
Definition: amcmds.c:202
#define CStringGetDatum(X)
Definition: postgres.h:586
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:34
static HeapTuple OpClassCacheLookup ( Oid  amID,
List opclassname,
bool  missing_ok 
)
static

Definition at line 162 of file opclasscmds.c.

References AMOID, CLAAMNAMENSP, CLAOID, DeconstructQualifiedName(), elog, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, LookupExplicitNamespace(), NameListToString(), NameStr, NULL, ObjectIdGetDatum, OidIsValid, OpclassnameGetOpcid(), PointerGetDatum, SearchSysCache1, and SearchSysCache3.

Referenced by get_opclass_oid().

163 {
164  char *schemaname;
165  char *opcname;
166  HeapTuple htup;
167 
168  /* deconstruct the name list */
169  DeconstructQualifiedName(opclassname, &schemaname, &opcname);
170 
171  if (schemaname)
172  {
173  /* Look in specific schema only */
174  Oid namespaceId;
175 
176  namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
177  if (!OidIsValid(namespaceId))
178  htup = NULL;
179  else
181  ObjectIdGetDatum(amID),
182  PointerGetDatum(opcname),
183  ObjectIdGetDatum(namespaceId));
184  }
185  else
186  {
187  /* Unqualified opclass name, so search the search path */
188  Oid opcID = OpclassnameGetOpcid(amID, opcname);
189 
190  if (!OidIsValid(opcID))
191  htup = NULL;
192  else
193  htup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opcID));
194  }
195 
196  if (!HeapTupleIsValid(htup) && !missing_ok)
197  {
198  HeapTuple amtup;
199 
200  amtup = SearchSysCache1(AMOID, ObjectIdGetDatum(amID));
201  if (!HeapTupleIsValid(amtup))
202  elog(ERROR, "cache lookup failed for access method %u", amID);
203  ereport(ERROR,
204  (errcode(ERRCODE_UNDEFINED_OBJECT),
205  errmsg("operator class \"%s\" does not exist for access method \"%s\"",
206  NameListToString(opclassname),
207  NameStr(((Form_pg_am) GETSTRUCT(amtup))->amname))));
208  }
209 
210  return htup;
211 }
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:2687
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Definition: syscache.h:36
#define PointerGetDatum(X)
Definition: postgres.h:564
int errcode(int sqlerrcode)
Definition: elog.c:575
void DeconstructQualifiedName(List *names, char **nspname_p, char **objname_p)
Definition: namespace.c:2603
unsigned int Oid
Definition: postgres_ext.h:31
Oid OpclassnameGetOpcid(Oid amid, const char *opcname)
Definition: namespace.c:1759
#define OidIsValid(objectId)
Definition: c.h:533
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
char * NameListToString(List *names)
Definition: namespace.c:2897
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
FormData_pg_am * Form_pg_am
Definition: pg_am.h:46
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define SearchSysCache3(cacheId, key1, key2, key3)
Definition: syscache.h:153
#define NameStr(name)
Definition: c.h:494
#define elog
Definition: elog.h:219
static HeapTuple OpFamilyCacheLookup ( Oid  amID,
List opfamilyname,
bool  missing_ok 
)
static

Definition at line 83 of file opclasscmds.c.

References AMOID, DeconstructQualifiedName(), elog, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, LookupExplicitNamespace(), NameListToString(), NameStr, NULL, ObjectIdGetDatum, OidIsValid, OPFAMILYAMNAMENSP, OpfamilynameGetOpfid(), OPFAMILYOID, PointerGetDatum, SearchSysCache1, and SearchSysCache3.

Referenced by get_opfamily_oid().

84 {
85  char *schemaname;
86  char *opfname;
87  HeapTuple htup;
88 
89  /* deconstruct the name list */
90  DeconstructQualifiedName(opfamilyname, &schemaname, &opfname);
91 
92  if (schemaname)
93  {
94  /* Look in specific schema only */
95  Oid namespaceId;
96 
97  namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
98  if (!OidIsValid(namespaceId))
99  htup = NULL;
100  else
102  ObjectIdGetDatum(amID),
103  PointerGetDatum(opfname),
104  ObjectIdGetDatum(namespaceId));
105  }
106  else
107  {
108  /* Unqualified opfamily name, so search the search path */
109  Oid opfID = OpfamilynameGetOpfid(amID, opfname);
110 
111  if (!OidIsValid(opfID))
112  htup = NULL;
113  else
115  }
116 
117  if (!HeapTupleIsValid(htup) && !missing_ok)
118  {
119  HeapTuple amtup;
120 
121  amtup = SearchSysCache1(AMOID, ObjectIdGetDatum(amID));
122  if (!HeapTupleIsValid(amtup))
123  elog(ERROR, "cache lookup failed for access method %u", amID);
124  ereport(ERROR,
125  (errcode(ERRCODE_UNDEFINED_OBJECT),
126  errmsg("operator family \"%s\" does not exist for access method \"%s\"",
127  NameListToString(opfamilyname),
128  NameStr(((Form_pg_am) GETSTRUCT(amtup))->amname))));
129  }
130 
131  return htup;
132 }
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:2687
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Definition: syscache.h:36
#define PointerGetDatum(X)
Definition: postgres.h:564
int errcode(int sqlerrcode)
Definition: elog.c:575
void DeconstructQualifiedName(List *names, char **nspname_p, char **objname_p)
Definition: namespace.c:2603
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
Oid OpfamilynameGetOpfid(Oid amid, const char *opfname)
Definition: namespace.c:1842
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
char * NameListToString(List *names)
Definition: namespace.c:2897
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
FormData_pg_am * Form_pg_am
Definition: pg_am.h:46
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define SearchSysCache3(cacheId, key1, key2, key3)
Definition: syscache.h:153
#define NameStr(name)
Definition: c.h:494
#define elog
Definition: elog.h:219
static void processTypesSpec ( List args,
Oid lefttype,
Oid righttype 
)
static

Definition at line 1039 of file opclasscmds.c.

References Assert, ereport, errcode(), errmsg(), ERROR, linitial, list_length(), lsecond, NIL, NULL, and typenameTypeId().

Referenced by AlterOpFamilyAdd(), AlterOpFamilyDrop(), and DefineOpClass().

1040 {
1041  TypeName *typeName;
1042 
1043  Assert(args != NIL);
1044 
1045  typeName = (TypeName *) linitial(args);
1046  *lefttype = typenameTypeId(NULL, typeName);
1047 
1048  if (list_length(args) > 1)
1049  {
1050  typeName = (TypeName *) lsecond(args);
1051  *righttype = typenameTypeId(NULL, typeName);
1052  }
1053  else
1054  *righttype = *lefttype;
1055 
1056  if (list_length(args) > 2)
1057  ereport(ERROR,
1058  (errcode(ERRCODE_SYNTAX_ERROR),
1059  errmsg("one or two argument types must be specified")));
1060 }
#define NIL
Definition: pg_list.h:69
int errcode(int sqlerrcode)
Definition: elog.c:575
#define lsecond(l)
Definition: pg_list.h:114
#define linitial(l)
Definition: pg_list.h:110
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
static int list_length(const List *l)
Definition: pg_list.h:89
int errmsg(const char *fmt,...)
Definition: elog.c:797
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274
void RemoveAmOpEntryById ( Oid  entryOid)

Definition at line 1601 of file opclasscmds.c.

References AccessMethodOperatorOidIndexId, AccessMethodOperatorRelationId, BTEqualStrategyNumber, CatalogTupleDelete(), elog, ERROR, heap_close, heap_open(), HeapTupleIsValid, NULL, ObjectIdAttributeNumber, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.

Referenced by doDeletion().

1602 {
1603  Relation rel;
1604  HeapTuple tup;
1605  ScanKeyData skey[1];
1606  SysScanDesc scan;
1607 
1608  ScanKeyInit(&skey[0],
1610  BTEqualStrategyNumber, F_OIDEQ,
1611  ObjectIdGetDatum(entryOid));
1612 
1614 
1616  NULL, 1, skey);
1617 
1618  /* we expect exactly one match */
1619  tup = systable_getnext(scan);
1620  if (!HeapTupleIsValid(tup))
1621  elog(ERROR, "could not find tuple for amop entry %u", entryOid);
1622 
1623  CatalogTupleDelete(rel, &tup->t_self);
1624 
1625  systable_endscan(scan);
1627 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define AccessMethodOperatorOidIndexId
Definition: indexing.h:79
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:322
#define AccessMethodOperatorRelationId
Definition: pg_amop.h:54
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define elog
Definition: elog.h:219
#define BTEqualStrategyNumber
Definition: stratnum.h:31
void RemoveAmProcEntryById ( Oid  entryOid)

Definition at line 1630 of file opclasscmds.c.

References AccessMethodProcedureOidIndexId, AccessMethodProcedureRelationId, BTEqualStrategyNumber, CatalogTupleDelete(), elog, ERROR, heap_close, heap_open(), HeapTupleIsValid, NULL, ObjectIdAttributeNumber, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.

Referenced by doDeletion().

1631 {
1632  Relation rel;
1633  HeapTuple tup;
1634  ScanKeyData skey[1];
1635  SysScanDesc scan;
1636 
1637  ScanKeyInit(&skey[0],
1639  BTEqualStrategyNumber, F_OIDEQ,
1640  ObjectIdGetDatum(entryOid));
1641 
1643 
1645  NULL, 1, skey);
1646 
1647  /* we expect exactly one match */
1648  tup = systable_getnext(scan);
1649  if (!HeapTupleIsValid(tup))
1650  elog(ERROR, "could not find tuple for amproc entry %u", entryOid);
1651 
1652  CatalogTupleDelete(rel, &tup->t_self);
1653 
1654  systable_endscan(scan);
1656 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:322
#define AccessMethodProcedureOidIndexId
Definition: indexing.h:84
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define elog
Definition: elog.h:219
#define AccessMethodProcedureRelationId
Definition: pg_amproc.h:43
#define BTEqualStrategyNumber
Definition: stratnum.h:31
void RemoveOpClassById ( Oid  opclassOid)

Definition at line 1582 of file opclasscmds.c.

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

Referenced by doDeletion().

1583 {
1584  Relation rel;
1585  HeapTuple tup;
1586 
1588 
1589  tup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclassOid));
1590  if (!HeapTupleIsValid(tup)) /* should not happen */
1591  elog(ERROR, "cache lookup failed for opclass %u", opclassOid);
1592 
1593  CatalogTupleDelete(rel, &tup->t_self);
1594 
1595  ReleaseSysCache(tup);
1596 
1598 }
#define OperatorClassRelationId
Definition: pg_opclass.h:49
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define elog
Definition: elog.h:219
void RemoveOpFamilyById ( Oid  opfamilyOid)

Definition at line 1563 of file opclasscmds.c.

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

Referenced by doDeletion().

1564 {
1565  Relation rel;
1566  HeapTuple tup;
1567 
1569 
1570  tup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfamilyOid));
1571  if (!HeapTupleIsValid(tup)) /* should not happen */
1572  elog(ERROR, "cache lookup failed for opfamily %u", opfamilyOid);
1573 
1574  CatalogTupleDelete(rel, &tup->t_self);
1575 
1576  ReleaseSysCache(tup);
1577 
1579 }
#define OperatorFamilyRelationId
Definition: pg_opfamily.h:29
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define elog
Definition: elog.h:219
static void storeOperators ( List opfamilyname,
Oid  amoid,
Oid  opfamilyoid,
Oid  opclassoid,
List operators,
bool  isAdd 
)
static

Definition at line 1271 of file opclasscmds.c.

References AccessMethodOperatorRelationId, AMOP_ORDER, AMOP_SEARCH, AMOPSTRATEGY, Anum_pg_amop_amopfamily, Anum_pg_amop_amoplefttype, Anum_pg_amop_amopmethod, Anum_pg_amop_amopopr, Anum_pg_amop_amoppurpose, Anum_pg_amop_amoprighttype, Anum_pg_amop_amopsortfamily, Anum_pg_amop_amopstrategy, CatalogTupleInsert(), CharGetDatum, ObjectAddress::classId, DEPENDENCY_AUTO, DEPENDENCY_INTERNAL, DEPENDENCY_NORMAL, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, format_type_be(), heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), Int16GetDatum, InvokeObjectPostCreateHook, OpFamilyMember::lefttype, lfirst, NameListToString(), Natts_pg_amop, OpFamilyMember::number, OpFamilyMember::object, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, OperatorClassRelationId, OperatorFamilyRelationId, OperatorRelationId, RelationData::rd_att, recordDependencyOn(), OpFamilyMember::righttype, RowExclusiveLock, SearchSysCacheExists4, OpFamilyMember::sortfamily, and values.

Referenced by AlterOpFamilyAdd(), and DefineOpClass().

1274 {
1275  Relation rel;
1277  bool nulls[Natts_pg_amop];
1278  HeapTuple tup;
1279  Oid entryoid;
1280  ObjectAddress myself,
1281  referenced;
1282  ListCell *l;
1283 
1285 
1286  foreach(l, operators)
1287  {
1288  OpFamilyMember *op = (OpFamilyMember *) lfirst(l);
1289  char oppurpose;
1290 
1291  /*
1292  * If adding to an existing family, check for conflict with an
1293  * existing pg_amop entry (just to give a nicer error message)
1294  */
1295  if (isAdd &&
1297  ObjectIdGetDatum(opfamilyoid),
1300  Int16GetDatum(op->number)))
1301  ereport(ERROR,
1303  errmsg("operator %d(%s,%s) already exists in operator family \"%s\"",
1304  op->number,
1305  format_type_be(op->lefttype),
1307  NameListToString(opfamilyname))));
1308 
1309  oppurpose = OidIsValid(op->sortfamily) ? AMOP_ORDER : AMOP_SEARCH;
1310 
1311  /* Create the pg_amop entry */
1312  memset(values, 0, sizeof(values));
1313  memset(nulls, false, sizeof(nulls));
1314 
1315  values[Anum_pg_amop_amopfamily - 1] = ObjectIdGetDatum(opfamilyoid);
1318  values[Anum_pg_amop_amopstrategy - 1] = Int16GetDatum(op->number);
1319  values[Anum_pg_amop_amoppurpose - 1] = CharGetDatum(oppurpose);
1320  values[Anum_pg_amop_amopopr - 1] = ObjectIdGetDatum(op->object);
1321  values[Anum_pg_amop_amopmethod - 1] = ObjectIdGetDatum(amoid);
1323 
1324  tup = heap_form_tuple(rel->rd_att, values, nulls);
1325 
1326  entryoid = CatalogTupleInsert(rel, tup);
1327 
1328  heap_freetuple(tup);
1329 
1330  /* Make its dependencies */
1332  myself.objectId = entryoid;
1333  myself.objectSubId = 0;
1334 
1335  referenced.classId = OperatorRelationId;
1336  referenced.objectId = op->object;
1337  referenced.objectSubId = 0;
1338 
1339  if (OidIsValid(opclassoid))
1340  {
1341  /* if contained in an opclass, use a NORMAL dep on operator */
1342  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1343 
1344  /* ... and an INTERNAL dep on the opclass */
1345  referenced.classId = OperatorClassRelationId;
1346  referenced.objectId = opclassoid;
1347  referenced.objectSubId = 0;
1348  recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
1349  }
1350  else
1351  {
1352  /* if "loose" in the opfamily, use a AUTO dep on operator */
1353  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1354 
1355  /* ... and an AUTO dep on the opfamily */
1356  referenced.classId = OperatorFamilyRelationId;
1357  referenced.objectId = opfamilyoid;
1358  referenced.objectSubId = 0;
1359  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1360  }
1361 
1362  /* A search operator also needs a dep on the referenced opfamily */
1363  if (OidIsValid(op->sortfamily))
1364  {
1365  referenced.classId = OperatorFamilyRelationId;
1366  referenced.objectId = op->sortfamily;
1367  referenced.objectSubId = 0;
1368  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1369  }
1370  /* Post create hook of this access method operator */
1372  entryoid, 0);
1373  }
1374 
1376 }
#define Anum_pg_amop_amopsortfamily
Definition: pg_amop.h:91
#define OperatorRelationId
Definition: pg_operator.h:32
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
#define Anum_pg_amop_amopmethod
Definition: pg_amop.h:90
#define AMOP_SEARCH
Definition: pg_amop.h:69
#define Int16GetDatum(X)
Definition: postgres.h:459
#define OperatorClassRelationId
Definition: pg_opclass.h:49
#define OperatorFamilyRelationId
Definition: pg_opfamily.h:29
#define SearchSysCacheExists4(cacheId, key1, key2, key3, key4)
Definition: syscache.h:173
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
#define Natts_pg_amop
Definition: pg_amop.h:83
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:692
#define Anum_pg_amop_amoprighttype
Definition: pg_amop.h:86
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
#define AccessMethodOperatorRelationId
Definition: pg_amop.h:54
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
#define Anum_pg_amop_amoplefttype
Definition: pg_amop.h:85
char * NameListToString(List *names)
Definition: namespace.c:2897
uintptr_t Datum
Definition: postgres.h:374
#define Anum_pg_amop_amoppurpose
Definition: pg_amop.h:88
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
TupleDesc rd_att
Definition: rel.h:114
#define lfirst(lc)
Definition: pg_list.h:106
#define CharGetDatum(X)
Definition: postgres.h:424
static Datum values[MAXATTR]
Definition: bootstrap.c:162
#define Anum_pg_amop_amopopr
Definition: pg_amop.h:89
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define Anum_pg_amop_amopfamily
Definition: pg_amop.h:84
#define AMOP_ORDER
Definition: pg_amop.h:70
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:34
#define Anum_pg_amop_amopstrategy
Definition: pg_amop.h:87
static void storeProcedures ( List opfamilyname,
Oid  amoid,
Oid  opfamilyoid,
Oid  opclassoid,
List procedures,
bool  isAdd 
)
static

Definition at line 1386 of file opclasscmds.c.

References AccessMethodProcedureRelationId, AMPROCNUM, Anum_pg_amproc_amproc, Anum_pg_amproc_amprocfamily, Anum_pg_amproc_amproclefttype, Anum_pg_amproc_amprocnum, Anum_pg_amproc_amprocrighttype, CatalogTupleInsert(), ObjectAddress::classId, DEPENDENCY_AUTO, DEPENDENCY_INTERNAL, DEPENDENCY_NORMAL, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, format_type_be(), heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), Int16GetDatum, InvokeObjectPostCreateHook, OpFamilyMember::lefttype, lfirst, NameListToString(), Natts_pg_amproc, OpFamilyMember::number, OpFamilyMember::object, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, OperatorClassRelationId, OperatorFamilyRelationId, ProcedureRelationId, RelationData::rd_att, recordDependencyOn(), OpFamilyMember::righttype, RowExclusiveLock, SearchSysCacheExists4, and values.

Referenced by AlterOpFamilyAdd(), and DefineOpClass().

1389 {
1390  Relation rel;
1392  bool nulls[Natts_pg_amproc];
1393  HeapTuple tup;
1394  Oid entryoid;
1395  ObjectAddress myself,
1396  referenced;
1397  ListCell *l;
1398 
1400 
1401  foreach(l, procedures)
1402  {
1403  OpFamilyMember *proc = (OpFamilyMember *) lfirst(l);
1404 
1405  /*
1406  * If adding to an existing family, check for conflict with an
1407  * existing pg_amproc entry (just to give a nicer error message)
1408  */
1409  if (isAdd &&
1411  ObjectIdGetDatum(opfamilyoid),
1412  ObjectIdGetDatum(proc->lefttype),
1413  ObjectIdGetDatum(proc->righttype),
1414  Int16GetDatum(proc->number)))
1415  ereport(ERROR,
1417  errmsg("function %d(%s,%s) already exists in operator family \"%s\"",
1418  proc->number,
1419  format_type_be(proc->lefttype),
1420  format_type_be(proc->righttype),
1421  NameListToString(opfamilyname))));
1422 
1423  /* Create the pg_amproc entry */
1424  memset(values, 0, sizeof(values));
1425  memset(nulls, false, sizeof(nulls));
1426 
1427  values[Anum_pg_amproc_amprocfamily - 1] = ObjectIdGetDatum(opfamilyoid);
1430  values[Anum_pg_amproc_amprocnum - 1] = Int16GetDatum(proc->number);
1431  values[Anum_pg_amproc_amproc - 1] = ObjectIdGetDatum(proc->object);
1432 
1433  tup = heap_form_tuple(rel->rd_att, values, nulls);
1434 
1435  entryoid = CatalogTupleInsert(rel, tup);
1436 
1437  heap_freetuple(tup);
1438 
1439  /* Make its dependencies */
1441  myself.objectId = entryoid;
1442  myself.objectSubId = 0;
1443 
1444  referenced.classId = ProcedureRelationId;
1445  referenced.objectId = proc->object;
1446  referenced.objectSubId = 0;
1447 
1448  if (OidIsValid(opclassoid))
1449  {
1450  /* if contained in an opclass, use a NORMAL dep on procedure */
1451  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1452 
1453  /* ... and an INTERNAL dep on the opclass */
1454  referenced.classId = OperatorClassRelationId;
1455  referenced.objectId = opclassoid;
1456  referenced.objectSubId = 0;
1457  recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
1458  }
1459  else
1460  {
1461  /* if "loose" in the opfamily, use a AUTO dep on procedure */
1462  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1463 
1464  /* ... and an AUTO dep on the opfamily */
1465  referenced.classId = OperatorFamilyRelationId;
1466  referenced.objectId = opfamilyoid;
1467  referenced.objectSubId = 0;
1468  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1469  }
1470  /* Post create hook of access method procedure */
1472  entryoid, 0);
1473  }
1474 
1476 }
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
#define ProcedureRelationId
Definition: pg_proc.h:33
#define Int16GetDatum(X)
Definition: postgres.h:459
#define OperatorClassRelationId
Definition: pg_opclass.h:49
#define OperatorFamilyRelationId
Definition: pg_opfamily.h:29
#define SearchSysCacheExists4(cacheId, key1, key2, key3, key4)
Definition: syscache.h:173
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
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:692
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
#define Anum_pg_amproc_amproclefttype
Definition: pg_amproc.h:67
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
#define Anum_pg_amproc_amprocfamily
Definition: pg_amproc.h:66
#define RowExclusiveLock
Definition: lockdefs.h:38
#define Anum_pg_amproc_amprocnum
Definition: pg_amproc.h:69
#define ereport(elevel, rest)
Definition: elog.h:122
#define Anum_pg_amproc_amprocrighttype
Definition: pg_amproc.h:68
char * NameListToString(List *names)
Definition: namespace.c:2897
uintptr_t Datum
Definition: postgres.h:374
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
TupleDesc rd_att
Definition: rel.h:114
#define lfirst(lc)
Definition: pg_list.h:106
#define Anum_pg_amproc_amproc
Definition: pg_amproc.h:70
static Datum values[MAXATTR]
Definition: bootstrap.c:162
#define Natts_pg_amproc
Definition: pg_amproc.h:65
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:34
#define AccessMethodProcedureRelationId
Definition: pg_amproc.h:43