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 1216 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().

1217 {
1218  ListCell *l;
1219 
1220  foreach(l, *list)
1221  {
1222  OpFamilyMember *old = (OpFamilyMember *) lfirst(l);
1223 
1224  if (old->number == member->number &&
1225  old->lefttype == member->lefttype &&
1226  old->righttype == member->righttype)
1227  {
1228  if (isProc)
1229  ereport(ERROR,
1230  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1231  errmsg("procedure number %d for (%s,%s) appears more than once",
1232  member->number,
1233  format_type_be(member->lefttype),
1234  format_type_be(member->righttype))));
1235  else
1236  ereport(ERROR,
1237  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1238  errmsg("operator number %d for (%s,%s) appears more than once",
1239  member->number,
1240  format_type_be(member->lefttype),
1241  format_type_be(member->righttype))));
1242  }
1243  }
1244  *list = lappend(*list, member);
1245 }
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 763 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().

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

References ACL_KIND_OPER, ACL_KIND_PROC, aclcheck_error(), ACLCHECK_NOT_OWNER, addFamilyMember(), assignOperTypes(), assignProcTypes(), BTREE_AM_OID, 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_node, LookupFuncWithArgs(), LookupOperWithArgs(), CreateOpClassItem::name, NIL, OpFamilyMember::number, CreateOpClassItem::number, ObjectWithArgs::objargs, 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().

824 {
825  List *operators; /* OpFamilyMember list for operators */
826  List *procedures; /* OpFamilyMember list for support procs */
827  ListCell *l;
828 
829  operators = NIL;
830  procedures = NIL;
831 
832  /*
833  * Scan the "items" list to obtain additional info.
834  */
835  foreach(l, items)
836  {
838  Oid operOid;
839  Oid funcOid;
840  Oid sortfamilyOid;
841  OpFamilyMember *member;
842 
843  switch (item->itemtype)
844  {
846  if (item->number <= 0 || item->number > maxOpNumber)
847  ereport(ERROR,
848  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
849  errmsg("invalid operator number %d,"
850  " must be between 1 and %d",
851  item->number, maxOpNumber)));
852  if (item->name->objargs != NIL)
853  operOid = LookupOperWithArgs(item->name, false);
854  else
855  {
856  ereport(ERROR,
857  (errcode(ERRCODE_SYNTAX_ERROR),
858  errmsg("operator argument types must be specified in ALTER OPERATOR FAMILY")));
859  operOid = InvalidOid; /* keep compiler quiet */
860  }
861 
862  if (item->order_family)
863  sortfamilyOid = get_opfamily_oid(BTREE_AM_OID,
864  item->order_family,
865  false);
866  else
867  sortfamilyOid = InvalidOid;
868 
869 #ifdef NOT_USED
870  /* XXX this is unnecessary given the superuser check above */
871  /* Caller must own operator and its underlying function */
872  if (!pg_oper_ownercheck(operOid, GetUserId()))
874  get_opname(operOid));
875  funcOid = get_opcode(operOid);
876  if (!pg_proc_ownercheck(funcOid, GetUserId()))
878  get_func_name(funcOid));
879 #endif
880 
881  /* Save the info */
882  member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
883  member->object = operOid;
884  member->number = item->number;
885  member->sortfamily = sortfamilyOid;
886  assignOperTypes(member, amoid, InvalidOid);
887  addFamilyMember(&operators, member, false);
888  break;
890  if (item->number <= 0 || item->number > maxProcNumber)
891  ereport(ERROR,
892  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
893  errmsg("invalid procedure number %d,"
894  " must be between 1 and %d",
895  item->number, maxProcNumber)));
896  funcOid = LookupFuncWithArgs(item->name, false);
897 #ifdef NOT_USED
898  /* XXX this is unnecessary given the superuser check above */
899  /* Caller must own function */
900  if (!pg_proc_ownercheck(funcOid, GetUserId()))
902  get_func_name(funcOid));
903 #endif
904 
905  /* Save the info */
906  member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
907  member->object = funcOid;
908  member->number = item->number;
909 
910  /* allow overriding of the function's actual arg types */
911  if (item->class_args)
913  &member->lefttype, &member->righttype);
914 
915  assignProcTypes(member, amoid, InvalidOid);
916  addFamilyMember(&procedures, member, true);
917  break;
919  ereport(ERROR,
920  (errcode(ERRCODE_SYNTAX_ERROR),
921  errmsg("STORAGE cannot be specified in ALTER OPERATOR FAMILY")));
922  break;
923  default:
924  elog(ERROR, "unrecognized item type: %d", item->itemtype);
925  break;
926  }
927  }
928 
929  /*
930  * Add tuples to pg_amop and pg_amproc tying in the operators and
931  * functions. Dependencies on them are inserted, too.
932  */
933  storeOperators(stmt->opfamilyname, amoid, opfamilyoid,
934  InvalidOid, operators, true);
935  storeProcedures(stmt->opfamilyname, amoid, opfamilyoid,
936  InvalidOid, procedures, true);
937 
938  /* make information available to event triggers */
939  EventTriggerCollectAlterOpFam(stmt, opfamilyoid,
940  operators, procedures);
941 }
Oid LookupOperWithArgs(ObjectWithArgs *oper, bool noError)
Definition: parse_oper.c:140
#define NIL
Definition: pg_list.h:69
static void assignOperTypes(OpFamilyMember *member, Oid amoid, Oid typeoid)
Definition: opclasscmds.c:1052
Oid GetUserId(void)
Definition: miscinit.c:283
#define BTREE_AM_OID
Definition: pg_am.h:70
bool pg_oper_ownercheck(Oid oper_oid, Oid roleid)
Definition: aclchk.c:4598
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OPCLASS_ITEM_OPERATOR
Definition: parsenodes.h:2493
char * get_opname(Oid opno)
Definition: lsyscache.c:1119
#define ERROR
Definition: elog.h:43
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1412
#define lfirst_node(type, lc)
Definition: pg_list.h:109
ObjectWithArgs * name
Definition: parsenodes.h:2501
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
static void addFamilyMember(List **list, OpFamilyMember *member, bool isProc)
Definition: opclasscmds.c:1216
#define ereport(elevel, rest)
Definition: elog.h:122
Oid LookupFuncWithArgs(ObjectWithArgs *func, bool noError)
Definition: parse_func.c:1971
void EventTriggerCollectAlterOpFam(AlterOpFamilyStmt *stmt, Oid opfamoid, List *operators, List *procedures)
static void processTypesSpec(List *args, Oid *lefttype, Oid *righttype)
Definition: opclasscmds.c:1023
void * palloc0(Size size)
Definition: mcxt.c:878
#define InvalidOid
Definition: postgres_ext.h:36
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1094
#define OPCLASS_ITEM_FUNCTION
Definition: parsenodes.h:2494
#define OPCLASS_ITEM_STORAGETYPE
Definition: parsenodes.h:2495
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:1370
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:1118
static void storeOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid, Oid opclassoid, List *operators, bool isAdd)
Definition: opclasscmds.c:1255
Definition: pg_list.h:45
bool pg_proc_ownercheck(Oid proc_oid, Oid roleid)
Definition: aclchk.c:4624
static void AlterOpFamilyDrop ( AlterOpFamilyStmt stmt,
Oid  amoid,
Oid  opfamilyoid,
int  maxOpNumber,
int  maxProcNumber,
List items 
)
static

Definition at line 947 of file opclasscmds.c.

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

Referenced by AlterOpFamily().

949 {
950  List *operators; /* OpFamilyMember list for operators */
951  List *procedures; /* OpFamilyMember list for support procs */
952  ListCell *l;
953 
954  operators = NIL;
955  procedures = NIL;
956 
957  /*
958  * Scan the "items" list to obtain additional info.
959  */
960  foreach(l, items)
961  {
963  Oid lefttype,
964  righttype;
965  OpFamilyMember *member;
966 
967  switch (item->itemtype)
968  {
970  if (item->number <= 0 || item->number > maxOpNumber)
971  ereport(ERROR,
972  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
973  errmsg("invalid operator number %d,"
974  " must be between 1 and %d",
975  item->number, maxOpNumber)));
976  processTypesSpec(item->class_args, &lefttype, &righttype);
977  /* Save the info */
978  member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
979  member->number = item->number;
980  member->lefttype = lefttype;
981  member->righttype = righttype;
982  addFamilyMember(&operators, member, false);
983  break;
985  if (item->number <= 0 || item->number > maxProcNumber)
986  ereport(ERROR,
987  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
988  errmsg("invalid procedure number %d,"
989  " must be between 1 and %d",
990  item->number, maxProcNumber)));
991  processTypesSpec(item->class_args, &lefttype, &righttype);
992  /* Save the info */
993  member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
994  member->number = item->number;
995  member->lefttype = lefttype;
996  member->righttype = righttype;
997  addFamilyMember(&procedures, member, true);
998  break;
1000  /* grammar prevents this from appearing */
1001  default:
1002  elog(ERROR, "unrecognized item type: %d", item->itemtype);
1003  break;
1004  }
1005  }
1006 
1007  /*
1008  * Remove tuples from pg_amop and pg_amproc.
1009  */
1010  dropOperators(stmt->opfamilyname, amoid, opfamilyoid, operators);
1011  dropProcedures(stmt->opfamilyname, amoid, opfamilyoid, procedures);
1012 
1013  /* make information available to event triggers */
1014  EventTriggerCollectAlterOpFam(stmt, opfamilyoid,
1015  operators, procedures);
1016 }
#define NIL
Definition: pg_list.h:69
int errcode(int sqlerrcode)
Definition: elog.c:575
static void dropProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid, List *procedures)
Definition: opclasscmds.c:1510
unsigned int Oid
Definition: postgres_ext.h:31
#define OPCLASS_ITEM_OPERATOR
Definition: parsenodes.h:2493
static void dropOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid, List *operators)
Definition: opclasscmds.c:1470
#define ERROR
Definition: elog.h:43
#define lfirst_node(type, lc)
Definition: pg_list.h:109
static void addFamilyMember(List **list, OpFamilyMember *member, bool isProc)
Definition: opclasscmds.c:1216
#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:1023
void * palloc0(Size size)
Definition: mcxt.c:878
#define OPCLASS_ITEM_FUNCTION
Definition: parsenodes.h:2494
#define OPCLASS_ITEM_STORAGETYPE
Definition: parsenodes.h:2495
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 1052 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().

1053 {
1054  Operator optup;
1055  Form_pg_operator opform;
1056 
1057  /* Fetch the operator definition */
1058  optup = SearchSysCache1(OPEROID, ObjectIdGetDatum(member->object));
1059  if (optup == NULL)
1060  elog(ERROR, "cache lookup failed for operator %u", member->object);
1061  opform = (Form_pg_operator) GETSTRUCT(optup);
1062 
1063  /*
1064  * Opfamily operators must be binary.
1065  */
1066  if (opform->oprkind != 'b')
1067  ereport(ERROR,
1068  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1069  errmsg("index operators must be binary")));
1070 
1071  if (OidIsValid(member->sortfamily))
1072  {
1073  /*
1074  * Ordering op, check index supports that. (We could perhaps also
1075  * check that the operator returns a type supported by the sortfamily,
1076  * but that seems more trouble than it's worth here. If it does not,
1077  * the operator will never be matchable to any ORDER BY clause, but no
1078  * worse consequences can ensue. Also, trying to check that would
1079  * create an ordering hazard during dump/reload: it's possible that
1080  * the family has been created but not yet populated with the required
1081  * operators.)
1082  */
1083  IndexAmRoutine *amroutine = GetIndexAmRoutineByAmId(amoid, false);
1084 
1085  if (!amroutine->amcanorderbyop)
1086  ereport(ERROR,
1087  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1088  errmsg("access method \"%s\" does not support ordering operators",
1089  get_am_name(amoid))));
1090  }
1091  else
1092  {
1093  /*
1094  * Search operators must return boolean.
1095  */
1096  if (opform->oprresult != BOOLOID)
1097  ereport(ERROR,
1098  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1099  errmsg("index search operators must return boolean")));
1100  }
1101 
1102  /*
1103  * If lefttype/righttype isn't specified, use the operator's input types
1104  */
1105  if (!OidIsValid(member->lefttype))
1106  member->lefttype = opform->oprleft;
1107  if (!OidIsValid(member->righttype))
1108  member->righttype = opform->oprright;
1109 
1110  ReleaseSysCache(optup);
1111 }
#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:538
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:1116
#define NULL
Definition: c.h:229
#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 1118 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().

1119 {
1120  HeapTuple proctup;
1121  Form_pg_proc procform;
1122 
1123  /* Fetch the procedure definition */
1124  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(member->object));
1125  if (proctup == NULL)
1126  elog(ERROR, "cache lookup failed for function %u", member->object);
1127  procform = (Form_pg_proc) GETSTRUCT(proctup);
1128 
1129  /*
1130  * btree comparison procs must be 2-arg procs returning int4, while btree
1131  * sortsupport procs must take internal and return void. hash support
1132  * procs must be 1-arg procs returning int4. Otherwise we don't know.
1133  */
1134  if (amoid == BTREE_AM_OID)
1135  {
1136  if (member->number == BTORDER_PROC)
1137  {
1138  if (procform->pronargs != 2)
1139  ereport(ERROR,
1140  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1141  errmsg("btree comparison procedures must have two arguments")));
1142  if (procform->prorettype != INT4OID)
1143  ereport(ERROR,
1144  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1145  errmsg("btree comparison procedures must return integer")));
1146 
1147  /*
1148  * If lefttype/righttype isn't specified, use the proc's input
1149  * types
1150  */
1151  if (!OidIsValid(member->lefttype))
1152  member->lefttype = procform->proargtypes.values[0];
1153  if (!OidIsValid(member->righttype))
1154  member->righttype = procform->proargtypes.values[1];
1155  }
1156  else if (member->number == BTSORTSUPPORT_PROC)
1157  {
1158  if (procform->pronargs != 1 ||
1159  procform->proargtypes.values[0] != INTERNALOID)
1160  ereport(ERROR,
1161  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1162  errmsg("btree sort support procedures must accept type \"internal\"")));
1163  if (procform->prorettype != VOIDOID)
1164  ereport(ERROR,
1165  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1166  errmsg("btree sort support procedures must return void")));
1167 
1168  /*
1169  * Can't infer lefttype/righttype from proc, so use default rule
1170  */
1171  }
1172  }
1173  else if (amoid == HASH_AM_OID)
1174  {
1175  if (procform->pronargs != 1)
1176  ereport(ERROR,
1177  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1178  errmsg("hash procedures must have one argument")));
1179  if (procform->prorettype != INT4OID)
1180  ereport(ERROR,
1181  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1182  errmsg("hash procedures must return integer")));
1183 
1184  /*
1185  * If lefttype/righttype isn't specified, use the proc's input type
1186  */
1187  if (!OidIsValid(member->lefttype))
1188  member->lefttype = procform->proargtypes.values[0];
1189  if (!OidIsValid(member->righttype))
1190  member->righttype = procform->proargtypes.values[0];
1191  }
1192 
1193  /*
1194  * The default in CREATE OPERATOR CLASS is to use the class' opcintype as
1195  * lefttype and righttype. In CREATE or ALTER OPERATOR FAMILY, opcintype
1196  * isn't available, so make the user specify the types.
1197  */
1198  if (!OidIsValid(member->lefttype))
1199  member->lefttype = typeoid;
1200  if (!OidIsValid(member->righttype))
1201  member->righttype = typeoid;
1202 
1203  if (!OidIsValid(member->lefttype) || !OidIsValid(member->righttype))
1204  ereport(ERROR,
1205  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1206  errmsg("associated data types must be specified for index support procedure")));
1207 
1208  ReleaseSysCache(proctup);
1209 }
#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:538
#define HASH_AM_OID
Definition: pg_am.h:73
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
#define VOIDOID
Definition: pg_type.h:690
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
#define INTERNALOID
Definition: pg_type.h:698
#define NULL
Definition: c.h:229
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:601
#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:159
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:513
#define ERROR
Definition: elog.h:43
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:174
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
Definition: c.h:493
#define AccessMethodRelationId
Definition: pg_am.h:32
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:584
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
TupleDesc rd_att
Definition: rel.h:115
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:139
static Datum values[MAXATTR]
Definition: bootstrap.c:163
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:31
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, assignOperTypes(), assignProcTypes(), BoolGetDatum, BTEqualStrategyNumber, BTREE_AM_OID, 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_node, LookupFuncWithArgs(), LookupOperName(), LookupOperWithArgs(), CreateOpClassItem::name, NameGetDatum, NamespaceRelationId, NameStr, namestrcpy(), Natts_pg_opclass, NIL, NULL, OpFamilyMember::number, CreateOpClassItem::number, ObjectWithArgs::objargs, OpFamilyMember::object, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, ObjectWithArgs::objname, 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->name->objargs != NIL)
479  operOid = LookupOperWithArgs(item->name, false);
480  else
481  {
482  /* Default to binary op on input datatype */
483  operOid = LookupOperName(NULL, item->name->objname,
484  typeoid, typeoid,
485  false, -1);
486  }
487 
488  if (item->order_family)
489  sortfamilyOid = get_opfamily_oid(BTREE_AM_OID,
490  item->order_family,
491  false);
492  else
493  sortfamilyOid = InvalidOid;
494 
495 #ifdef NOT_USED
496  /* XXX this is unnecessary given the superuser check above */
497  /* Caller must own operator and its underlying function */
498  if (!pg_oper_ownercheck(operOid, GetUserId()))
500  get_opname(operOid));
501  funcOid = get_opcode(operOid);
502  if (!pg_proc_ownercheck(funcOid, GetUserId()))
504  get_func_name(funcOid));
505 #endif
506 
507  /* Save the info */
508  member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
509  member->object = operOid;
510  member->number = item->number;
511  member->sortfamily = sortfamilyOid;
512  assignOperTypes(member, amoid, typeoid);
513  addFamilyMember(&operators, member, false);
514  break;
516  if (item->number <= 0 || item->number > maxProcNumber)
517  ereport(ERROR,
518  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
519  errmsg("invalid procedure number %d,"
520  " must be between 1 and %d",
521  item->number, maxProcNumber)));
522  funcOid = LookupFuncWithArgs(item->name, false);
523 #ifdef NOT_USED
524  /* XXX this is unnecessary given the superuser check above */
525  /* Caller must own function */
526  if (!pg_proc_ownercheck(funcOid, GetUserId()))
528  get_func_name(funcOid));
529 #endif
530 
531  /* Save the info */
532  member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
533  member->object = funcOid;
534  member->number = item->number;
535 
536  /* allow overriding of the function's actual arg types */
537  if (item->class_args)
539  &member->lefttype, &member->righttype);
540 
541  assignProcTypes(member, amoid, typeoid);
542  addFamilyMember(&procedures, member, true);
543  break;
545  if (OidIsValid(storageoid))
546  ereport(ERROR,
547  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
548  errmsg("storage type specified more than once")));
549  storageoid = typenameTypeId(NULL, item->storedtype);
550 
551 #ifdef NOT_USED
552  /* XXX this is unnecessary given the superuser check above */
553  /* Check we have ownership of the datatype */
554  if (!pg_type_ownercheck(storageoid, GetUserId()))
556 #endif
557  break;
558  default:
559  elog(ERROR, "unrecognized item type: %d", item->itemtype);
560  break;
561  }
562  }
563 
564  /*
565  * If storagetype is specified, make sure it's legal.
566  */
567  if (OidIsValid(storageoid))
568  {
569  /* Just drop the spec if same as column datatype */
570  if (storageoid == typeoid)
571  storageoid = InvalidOid;
572  else if (!amstorage)
573  ereport(ERROR,
574  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
575  errmsg("storage type cannot be different from data type for access method \"%s\"",
576  stmt->amname)));
577  }
578 
580 
581  /*
582  * Make sure there is no existing opclass of this name (this is just to
583  * give a more friendly error message than "duplicate key").
584  */
586  ObjectIdGetDatum(amoid),
587  CStringGetDatum(opcname),
588  ObjectIdGetDatum(namespaceoid)))
589  ereport(ERROR,
591  errmsg("operator class \"%s\" for access method \"%s\" already exists",
592  opcname, stmt->amname)));
593 
594  /*
595  * If we are creating a default opclass, check there isn't one already.
596  * (Note we do not restrict this test to visible opclasses; this ensures
597  * that typcache.c can find unique solutions to its questions.)
598  */
599  if (stmt->isDefault)
600  {
601  ScanKeyData skey[1];
602  SysScanDesc scan;
603 
604  ScanKeyInit(&skey[0],
606  BTEqualStrategyNumber, F_OIDEQ,
607  ObjectIdGetDatum(amoid));
608 
610  NULL, 1, skey);
611 
612  while (HeapTupleIsValid(tup = systable_getnext(scan)))
613  {
614  Form_pg_opclass opclass = (Form_pg_opclass) GETSTRUCT(tup);
615 
616  if (opclass->opcintype == typeoid && opclass->opcdefault)
617  ereport(ERROR,
619  errmsg("could not make operator class \"%s\" be default for type %s",
620  opcname,
621  TypeNameToString(stmt->datatype)),
622  errdetail("Operator class \"%s\" already is the default.",
623  NameStr(opclass->opcname))));
624  }
625 
626  systable_endscan(scan);
627  }
628 
629  /*
630  * Okay, let's create the pg_opclass entry.
631  */
632  memset(values, 0, sizeof(values));
633  memset(nulls, false, sizeof(nulls));
634 
635  values[Anum_pg_opclass_opcmethod - 1] = ObjectIdGetDatum(amoid);
636  namestrcpy(&opcName, opcname);
637  values[Anum_pg_opclass_opcname - 1] = NameGetDatum(&opcName);
638  values[Anum_pg_opclass_opcnamespace - 1] = ObjectIdGetDatum(namespaceoid);
640  values[Anum_pg_opclass_opcfamily - 1] = ObjectIdGetDatum(opfamilyoid);
641  values[Anum_pg_opclass_opcintype - 1] = ObjectIdGetDatum(typeoid);
643  values[Anum_pg_opclass_opckeytype - 1] = ObjectIdGetDatum(storageoid);
644 
645  tup = heap_form_tuple(rel->rd_att, values, nulls);
646 
647  opclassoid = CatalogTupleInsert(rel, tup);
648 
649  heap_freetuple(tup);
650 
651  /*
652  * Now add tuples to pg_amop and pg_amproc tying in the operators and
653  * functions. Dependencies on them are inserted, too.
654  */
655  storeOperators(stmt->opfamilyname, amoid, opfamilyoid,
656  opclassoid, operators, false);
657  storeProcedures(stmt->opfamilyname, amoid, opfamilyoid,
658  opclassoid, procedures, false);
659 
660  /* let event triggers know what happened */
661  EventTriggerCollectCreateOpClass(stmt, opclassoid, operators, procedures);
662 
663  /*
664  * Create dependencies for the opclass proper. Note: we do not need a
665  * dependency link to the AM, because that exists through the opfamily.
666  */
668  myself.objectId = opclassoid;
669  myself.objectSubId = 0;
670 
671  /* dependency on namespace */
672  referenced.classId = NamespaceRelationId;
673  referenced.objectId = namespaceoid;
674  referenced.objectSubId = 0;
675  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
676 
677  /* dependency on opfamily */
678  referenced.classId = OperatorFamilyRelationId;
679  referenced.objectId = opfamilyoid;
680  referenced.objectSubId = 0;
681  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
682 
683  /* dependency on indexed datatype */
684  referenced.classId = TypeRelationId;
685  referenced.objectId = typeoid;
686  referenced.objectSubId = 0;
687  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
688 
689  /* dependency on storage datatype */
690  if (OidIsValid(storageoid))
691  {
692  referenced.classId = TypeRelationId;
693  referenced.objectId = storageoid;
694  referenced.objectSubId = 0;
695  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
696  }
697 
698  /* dependency on owner */
700 
701  /* dependency on extension */
702  recordDependencyOnCurrentExtension(&myself, false);
703 
704  /* Post creation hook for new operator class */
706 
708 
709  return myself;
710 }
Oid LookupOperWithArgs(ObjectWithArgs *oper, bool noError)
Definition: parse_oper.c:140
#define NIL
Definition: pg_list.h:69
#define NamespaceRelationId
Definition: pg_namespace.h:34
#define NameGetDatum(X)
Definition: postgres.h:601
uint16 amsupport
Definition: amapi.h:169
#define Anum_pg_opclass_opcmethod
Definition: pg_opclass.h:75
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
static void assignOperTypes(OpFamilyMember *member, Oid amoid, Oid typeoid)
Definition: opclasscmds.c:1052
#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:2507
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2846
#define PointerGetDatum(X)
Definition: postgres.h:562
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:4598
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:159
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:4572
#define TypeRelationId
Definition: pg_type.h:34
int namestrcpy(Name name, const char *str)
Definition: name.c:217
#define OidIsValid(objectId)
Definition: c.h:538
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4484
#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:328
#define OpclassAmNameNspIndexId
Definition: indexing.h:198
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3457
#define OPCLASS_ITEM_OPERATOR
Definition: parsenodes.h:2493
char * get_opname(Oid opno)
Definition: lsyscache.c:1119
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define Anum_pg_opclass_opcnamespace
Definition: pg_opclass.h:77
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:82
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:174
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:1412
#define lfirst_node(type, lc)
Definition: pg_list.h:109
Definition: c.h:493
TypeName * datatype
Definition: parsenodes.h:2488
ObjectWithArgs * name
Definition: parsenodes.h:2501
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3038
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:3399
#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:1216
#define CStringGetDatum(X)
Definition: postgres.h:584
#define Anum_pg_opclass_opcdefault
Definition: pg_opclass.h:81
#define ereport(elevel, rest)
Definition: elog.h:122
Oid LookupFuncWithArgs(ObjectWithArgs *func, bool noError)
Definition: parse_func.c:1971
static void processTypesSpec(List *args, Oid *lefttype, Oid *righttype)
Definition: opclasscmds.c:1023
void * palloc0(Size size)
Definition: mcxt.c:878
AclResult
Definition: acl.h:170
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
TupleDesc rd_att
Definition: rel.h:115
#define BoolGetDatum(X)
Definition: postgres.h:408
#define InvalidOid
Definition: postgres_ext.h:36
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1094
#define OPCLASS_ITEM_FUNCTION
Definition: parsenodes.h:2494
#define Natts_pg_opclass
Definition: pg_opclass.h:74
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:139
#define OPCLASS_ITEM_STORAGETYPE
Definition: parsenodes.h:2495
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:1370
uint16 amstrategies
Definition: amapi.h:167
static Datum values[MAXATTR]
Definition: bootstrap.c:163
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define SearchSysCache3(cacheId, key1, key2, key3)
Definition: syscache.h:156
#define NameStr(name)
Definition: c.h:499
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:1118
static void storeOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid, Oid opclassoid, List *operators, bool isAdd)
Definition: opclasscmds.c:1255
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:68
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:31
Definition: pg_list.h:45
#define BTEqualStrategyNumber
Definition: stratnum.h:31
bool pg_proc_ownercheck(Oid proc_oid, Oid roleid)
Definition: aclchk.c:4624
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274
ObjectAddress DefineOpFamily ( CreateOpFamilyStmt stmt)

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

719 {
720  char *opfname; /* name of opfamily we're creating */
721  Oid amoid, /* our AM's oid */
722  namespaceoid; /* namespace to create opfamily in */
723  AclResult aclresult;
724 
725  /* Convert list of names to a name and namespace */
726  namespaceoid = QualifiedNameGetCreationNamespace(stmt->opfamilyname,
727  &opfname);
728 
729  /* Check we have creation rights in target namespace */
730  aclresult = pg_namespace_aclcheck(namespaceoid, GetUserId(), ACL_CREATE);
731  if (aclresult != ACLCHECK_OK)
733  get_namespace_name(namespaceoid));
734 
735  /* Get access method OID, throwing an error if it doesn't exist. */
736  amoid = get_index_am_oid(stmt->amname, false);
737 
738  /* XXX Should we make any privilege check against the AM? */
739 
740  /*
741  * Currently, we require superuser privileges to create an opfamily. See
742  * comments in DefineOpClass.
743  */
744  if (!superuser())
745  ereport(ERROR,
746  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
747  errmsg("must be superuser to create an operator family")));
748 
749  /* Insert pg_opfamily catalog entry */
750  return CreateOpFamily(stmt->amname, opfname, namespaceoid, amoid);
751 }
Oid GetUserId(void)
Definition: miscinit.c:283
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2846
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:4484
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:82
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3038
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:3399
#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 1470 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().

1472 {
1473  ListCell *l;
1474 
1475  foreach(l, operators)
1476  {
1477  OpFamilyMember *op = (OpFamilyMember *) lfirst(l);
1478  Oid amopid;
1479  ObjectAddress object;
1480 
1481  amopid = GetSysCacheOid4(AMOPSTRATEGY,
1482  ObjectIdGetDatum(opfamilyoid),
1485  Int16GetDatum(op->number));
1486  if (!OidIsValid(amopid))
1487  ereport(ERROR,
1488  (errcode(ERRCODE_UNDEFINED_OBJECT),
1489  errmsg("operator %d(%s,%s) does not exist in operator family \"%s\"",
1490  op->number,
1491  format_type_be(op->lefttype),
1493  NameListToString(opfamilyname))));
1494 
1495  object.classId = AccessMethodOperatorRelationId;
1496  object.objectId = amopid;
1497  object.objectSubId = 0;
1498 
1499  performDeletion(&object, DROP_RESTRICT, 0);
1500  }
1501 }
#define GetSysCacheOid4(cacheId, key1, key2, key3, key4)
Definition: syscache.h:185
#define Int16GetDatum(X)
Definition: postgres.h:457
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:538
#define AccessMethodOperatorRelationId
Definition: pg_amop.h:54
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:303
#define ereport(elevel, rest)
Definition: elog.h:122
char * NameListToString(List *names)
Definition: namespace.c:2953
#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 1510 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().

1512 {
1513  ListCell *l;
1514 
1515  foreach(l, procedures)
1516  {
1517  OpFamilyMember *op = (OpFamilyMember *) lfirst(l);
1518  Oid amprocid;
1519  ObjectAddress object;
1520 
1521  amprocid = GetSysCacheOid4(AMPROCNUM,
1522  ObjectIdGetDatum(opfamilyoid),
1525  Int16GetDatum(op->number));
1526  if (!OidIsValid(amprocid))
1527  ereport(ERROR,
1528  (errcode(ERRCODE_UNDEFINED_OBJECT),
1529  errmsg("function %d(%s,%s) does not exist in operator family \"%s\"",
1530  op->number,
1531  format_type_be(op->lefttype),
1533  NameListToString(opfamilyname))));
1534 
1535  object.classId = AccessMethodProcedureRelationId;
1536  object.objectId = amprocid;
1537  object.objectSubId = 0;
1538 
1539  performDeletion(&object, DROP_RESTRICT, 0);
1540  }
1541 }
#define GetSysCacheOid4(cacheId, key1, key2, key3, key4)
Definition: syscache.h:185
#define Int16GetDatum(X)
Definition: postgres.h:457
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:538
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:303
#define ereport(elevel, rest)
Definition: elog.h:122
char * NameListToString(List *names)
Definition: namespace.c:2953
#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:1116
#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:1116
#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 1649 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().

1651 {
1652  /* make sure the new name doesn't exist */
1654  ObjectIdGetDatum(opcmethod),
1655  CStringGetDatum(opcname),
1656  ObjectIdGetDatum(opcnamespace)))
1657  ereport(ERROR,
1659  errmsg("operator class \"%s\" for access method \"%s\" already exists in schema \"%s\"",
1660  opcname,
1661  get_am_name(opcmethod),
1662  get_namespace_name(opcnamespace))));
1663 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:174
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3038
char * get_am_name(Oid amOid)
Definition: amcmds.c:202
#define CStringGetDatum(X)
Definition: postgres.h:584
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:31
void IsThereOpFamilyInNamespace ( const char *  opfname,
Oid  opfmethod,
Oid  opfnamespace 
)

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

1674 {
1675  /* make sure the new name doesn't exist */
1677  ObjectIdGetDatum(opfmethod),
1678  CStringGetDatum(opfname),
1679  ObjectIdGetDatum(opfnamespace)))
1680  ereport(ERROR,
1682  errmsg("operator family \"%s\" for access method \"%s\" already exists in schema \"%s\"",
1683  opfname,
1684  get_am_name(opfmethod),
1685  get_namespace_name(opfnamespace))));
1686 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:174
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3038
char * get_am_name(Oid amOid)
Definition: amcmds.c:202
#define CStringGetDatum(X)
Definition: postgres.h:584
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:31
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:2743
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Definition: syscache.h:36
#define PointerGetDatum(X)
Definition: postgres.h:562
int errcode(int sqlerrcode)
Definition: elog.c:575
void DeconstructQualifiedName(List *names, char **nspname_p, char **objname_p)
Definition: namespace.c:2659
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:538
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
char * NameListToString(List *names)
Definition: namespace.c:2953
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
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:156
#define NameStr(name)
Definition: c.h:499
#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:2743
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Definition: syscache.h:36
#define PointerGetDatum(X)
Definition: postgres.h:562
int errcode(int sqlerrcode)
Definition: elog.c:575
void DeconstructQualifiedName(List *names, char **nspname_p, char **objname_p)
Definition: namespace.c:2659
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
Oid OpfamilynameGetOpfid(Oid amid, const char *opfname)
Definition: namespace.c:1842
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
char * NameListToString(List *names)
Definition: namespace.c:2953
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
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:156
#define NameStr(name)
Definition: c.h:499
#define elog
Definition: elog.h:219
static void processTypesSpec ( List args,
Oid lefttype,
Oid righttype 
)
static

Definition at line 1023 of file opclasscmds.c.

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

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

1024 {
1025  TypeName *typeName;
1026 
1027  Assert(args != NIL);
1028 
1029  typeName = (TypeName *) linitial(args);
1030  *lefttype = typenameTypeId(NULL, typeName);
1031 
1032  if (list_length(args) > 1)
1033  {
1034  typeName = (TypeName *) lsecond(args);
1035  *righttype = typenameTypeId(NULL, typeName);
1036  }
1037  else
1038  *righttype = *lefttype;
1039 
1040  if (list_length(args) > 2)
1041  ereport(ERROR,
1042  (errcode(ERRCODE_SYNTAX_ERROR),
1043  errmsg("one or two argument types must be specified")));
1044 }
#define NIL
Definition: pg_list.h:69
int errcode(int sqlerrcode)
Definition: elog.c:575
#define lsecond(l)
Definition: pg_list.h:116
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
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 1585 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().

1586 {
1587  Relation rel;
1588  HeapTuple tup;
1589  ScanKeyData skey[1];
1590  SysScanDesc scan;
1591 
1592  ScanKeyInit(&skey[0],
1594  BTEqualStrategyNumber, F_OIDEQ,
1595  ObjectIdGetDatum(entryOid));
1596 
1598 
1600  NULL, 1, skey);
1601 
1602  /* we expect exactly one match */
1603  tup = systable_getnext(scan);
1604  if (!HeapTupleIsValid(tup))
1605  elog(ERROR, "could not find tuple for amop entry %u", entryOid);
1606 
1607  CatalogTupleDelete(rel, &tup->t_self);
1608 
1609  systable_endscan(scan);
1611 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#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:328
#define AccessMethodOperatorRelationId
Definition: pg_amop.h:54
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:1284
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
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 1614 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().

1615 {
1616  Relation rel;
1617  HeapTuple tup;
1618  ScanKeyData skey[1];
1619  SysScanDesc scan;
1620 
1621  ScanKeyInit(&skey[0],
1623  BTEqualStrategyNumber, F_OIDEQ,
1624  ObjectIdGetDatum(entryOid));
1625 
1627 
1629  NULL, 1, skey);
1630 
1631  /* we expect exactly one match */
1632  tup = systable_getnext(scan);
1633  if (!HeapTupleIsValid(tup))
1634  elog(ERROR, "could not find tuple for amproc entry %u", entryOid);
1635 
1636  CatalogTupleDelete(rel, &tup->t_self);
1637 
1638  systable_endscan(scan);
1640 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#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:328
#define AccessMethodProcedureOidIndexId
Definition: indexing.h:84
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:1284
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
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 1566 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().

1567 {
1568  Relation rel;
1569  HeapTuple tup;
1570 
1572 
1573  tup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclassOid));
1574  if (!HeapTupleIsValid(tup)) /* should not happen */
1575  elog(ERROR, "cache lookup failed for opclass %u", opclassOid);
1576 
1577  CatalogTupleDelete(rel, &tup->t_self);
1578 
1579  ReleaseSysCache(tup);
1580 
1582 }
#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:152
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:1116
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define elog
Definition: elog.h:219
void RemoveOpFamilyById ( Oid  opfamilyOid)

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

1548 {
1549  Relation rel;
1550  HeapTuple tup;
1551 
1553 
1554  tup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfamilyOid));
1555  if (!HeapTupleIsValid(tup)) /* should not happen */
1556  elog(ERROR, "cache lookup failed for opfamily %u", opfamilyOid);
1557 
1558  CatalogTupleDelete(rel, &tup->t_self);
1559 
1560  ReleaseSysCache(tup);
1561 
1563 }
#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:152
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:1116
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#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 1255 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().

1258 {
1259  Relation rel;
1261  bool nulls[Natts_pg_amop];
1262  HeapTuple tup;
1263  Oid entryoid;
1264  ObjectAddress myself,
1265  referenced;
1266  ListCell *l;
1267 
1269 
1270  foreach(l, operators)
1271  {
1272  OpFamilyMember *op = (OpFamilyMember *) lfirst(l);
1273  char oppurpose;
1274 
1275  /*
1276  * If adding to an existing family, check for conflict with an
1277  * existing pg_amop entry (just to give a nicer error message)
1278  */
1279  if (isAdd &&
1281  ObjectIdGetDatum(opfamilyoid),
1284  Int16GetDatum(op->number)))
1285  ereport(ERROR,
1287  errmsg("operator %d(%s,%s) already exists in operator family \"%s\"",
1288  op->number,
1289  format_type_be(op->lefttype),
1291  NameListToString(opfamilyname))));
1292 
1293  oppurpose = OidIsValid(op->sortfamily) ? AMOP_ORDER : AMOP_SEARCH;
1294 
1295  /* Create the pg_amop entry */
1296  memset(values, 0, sizeof(values));
1297  memset(nulls, false, sizeof(nulls));
1298 
1299  values[Anum_pg_amop_amopfamily - 1] = ObjectIdGetDatum(opfamilyoid);
1302  values[Anum_pg_amop_amopstrategy - 1] = Int16GetDatum(op->number);
1303  values[Anum_pg_amop_amoppurpose - 1] = CharGetDatum(oppurpose);
1304  values[Anum_pg_amop_amopopr - 1] = ObjectIdGetDatum(op->object);
1305  values[Anum_pg_amop_amopmethod - 1] = ObjectIdGetDatum(amoid);
1307 
1308  tup = heap_form_tuple(rel->rd_att, values, nulls);
1309 
1310  entryoid = CatalogTupleInsert(rel, tup);
1311 
1312  heap_freetuple(tup);
1313 
1314  /* Make its dependencies */
1316  myself.objectId = entryoid;
1317  myself.objectSubId = 0;
1318 
1319  referenced.classId = OperatorRelationId;
1320  referenced.objectId = op->object;
1321  referenced.objectSubId = 0;
1322 
1323  if (OidIsValid(opclassoid))
1324  {
1325  /* if contained in an opclass, use a NORMAL dep on operator */
1326  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1327 
1328  /* ... and an INTERNAL dep on the opclass */
1329  referenced.classId = OperatorClassRelationId;
1330  referenced.objectId = opclassoid;
1331  referenced.objectSubId = 0;
1332  recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
1333  }
1334  else
1335  {
1336  /* if "loose" in the opfamily, use a AUTO dep on operator */
1337  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1338 
1339  /* ... and an AUTO dep on the opfamily */
1340  referenced.classId = OperatorFamilyRelationId;
1341  referenced.objectId = opfamilyoid;
1342  referenced.objectSubId = 0;
1343  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1344  }
1345 
1346  /* A search operator also needs a dep on the referenced opfamily */
1347  if (OidIsValid(op->sortfamily))
1348  {
1349  referenced.classId = OperatorFamilyRelationId;
1350  referenced.objectId = op->sortfamily;
1351  referenced.objectSubId = 0;
1352  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1353  }
1354  /* Post create hook of this access method operator */
1356  entryoid, 0);
1357  }
1358 
1360 }
#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:457
#define OperatorClassRelationId
Definition: pg_opclass.h:49
#define OperatorFamilyRelationId
Definition: pg_opfamily.h:29
#define SearchSysCacheExists4(cacheId, key1, key2, key3, key4)
Definition: syscache.h:176
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:538
#define AccessMethodOperatorRelationId
Definition: pg_amop.h:54
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:2953
uintptr_t Datum
Definition: postgres.h:372
#define Anum_pg_amop_amoppurpose
Definition: pg_amop.h:88
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
TupleDesc rd_att
Definition: rel.h:115
#define lfirst(lc)
Definition: pg_list.h:106
#define CharGetDatum(X)
Definition: postgres.h:422
static Datum values[MAXATTR]
Definition: bootstrap.c:163
#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:31
#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 1370 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().

1373 {
1374  Relation rel;
1376  bool nulls[Natts_pg_amproc];
1377  HeapTuple tup;
1378  Oid entryoid;
1379  ObjectAddress myself,
1380  referenced;
1381  ListCell *l;
1382 
1384 
1385  foreach(l, procedures)
1386  {
1387  OpFamilyMember *proc = (OpFamilyMember *) lfirst(l);
1388 
1389  /*
1390  * If adding to an existing family, check for conflict with an
1391  * existing pg_amproc entry (just to give a nicer error message)
1392  */
1393  if (isAdd &&
1395  ObjectIdGetDatum(opfamilyoid),
1396  ObjectIdGetDatum(proc->lefttype),
1397  ObjectIdGetDatum(proc->righttype),
1398  Int16GetDatum(proc->number)))
1399  ereport(ERROR,
1401  errmsg("function %d(%s,%s) already exists in operator family \"%s\"",
1402  proc->number,
1403  format_type_be(proc->lefttype),
1404  format_type_be(proc->righttype),
1405  NameListToString(opfamilyname))));
1406 
1407  /* Create the pg_amproc entry */
1408  memset(values, 0, sizeof(values));
1409  memset(nulls, false, sizeof(nulls));
1410 
1411  values[Anum_pg_amproc_amprocfamily - 1] = ObjectIdGetDatum(opfamilyoid);
1414  values[Anum_pg_amproc_amprocnum - 1] = Int16GetDatum(proc->number);
1415  values[Anum_pg_amproc_amproc - 1] = ObjectIdGetDatum(proc->object);
1416 
1417  tup = heap_form_tuple(rel->rd_att, values, nulls);
1418 
1419  entryoid = CatalogTupleInsert(rel, tup);
1420 
1421  heap_freetuple(tup);
1422 
1423  /* Make its dependencies */
1425  myself.objectId = entryoid;
1426  myself.objectSubId = 0;
1427 
1428  referenced.classId = ProcedureRelationId;
1429  referenced.objectId = proc->object;
1430  referenced.objectSubId = 0;
1431 
1432  if (OidIsValid(opclassoid))
1433  {
1434  /* if contained in an opclass, use a NORMAL dep on procedure */
1435  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1436 
1437  /* ... and an INTERNAL dep on the opclass */
1438  referenced.classId = OperatorClassRelationId;
1439  referenced.objectId = opclassoid;
1440  referenced.objectSubId = 0;
1441  recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
1442  }
1443  else
1444  {
1445  /* if "loose" in the opfamily, use a AUTO dep on procedure */
1446  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1447 
1448  /* ... and an AUTO dep on the opfamily */
1449  referenced.classId = OperatorFamilyRelationId;
1450  referenced.objectId = opfamilyoid;
1451  referenced.objectSubId = 0;
1452  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1453  }
1454  /* Post create hook of access method procedure */
1456  entryoid, 0);
1457  }
1458 
1460 }
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
#define ProcedureRelationId
Definition: pg_proc.h:33
#define Int16GetDatum(X)
Definition: postgres.h:457
#define OperatorClassRelationId
Definition: pg_opclass.h:49
#define OperatorFamilyRelationId
Definition: pg_opfamily.h:29
#define SearchSysCacheExists4(cacheId, key1, key2, key3, key4)
Definition: syscache.h:176
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:538
#define Anum_pg_amproc_amproclefttype
Definition: pg_amproc.h:67
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:2953
uintptr_t Datum
Definition: postgres.h:372
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
TupleDesc rd_att
Definition: rel.h:115
#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:163
#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:31
#define AccessMethodProcedureRelationId
Definition: pg_amproc.h:43