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/hash.h"
#include "access/heapam.h"
#include "access/nbtree.h"
#include "access/htup_details.h"
#include "access/sysattr.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/opfam_internal.h"
#include "catalog/pg_am.h"
#include "catalog/pg_amop.h"
#include "catalog/pg_amproc.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "commands/alter.h"
#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
#include "parser/parse_oper.h"
#include "parser/parse_type.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
Include dependency graph for opclasscmds.c:

Go to the source code of this file.

Functions

static void AlterOpFamilyAdd (AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid, int maxOpNumber, int maxProcNumber, List *items)
 
static void AlterOpFamilyDrop (AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid, int maxOpNumber, int maxProcNumber, List *items)
 
static void processTypesSpec (List *args, Oid *lefttype, Oid *righttype)
 
static void assignOperTypes (OpFamilyMember *member, Oid amoid, Oid typeoid)
 
static void assignProcTypes (OpFamilyMember *member, Oid amoid, Oid typeoid)
 
static void addFamilyMember (List **list, OpFamilyMember *member, bool isProc)
 
static void storeOperators (List *opfamilyname, Oid amoid, Oid opfamilyoid, Oid opclassoid, List *operators, bool isAdd)
 
static void storeProcedures (List *opfamilyname, Oid amoid, Oid opfamilyoid, Oid opclassoid, List *procedures, bool isAdd)
 
static void dropOperators (List *opfamilyname, Oid amoid, Oid opfamilyoid, List *operators)
 
static void dropProcedures (List *opfamilyname, Oid amoid, Oid opfamilyoid, List *procedures)
 
static HeapTuple OpFamilyCacheLookup (Oid amID, List *opfamilyname, bool missing_ok)
 
Oid get_opfamily_oid (Oid amID, List *opfamilyname, bool missing_ok)
 
static HeapTuple OpClassCacheLookup (Oid amID, List *opclassname, bool missing_ok)
 
Oid get_opclass_oid (Oid amID, List *opclassname, bool missing_ok)
 
static ObjectAddress CreateOpFamily (char *amname, char *opfname, Oid namespaceoid, Oid amoid)
 
ObjectAddress DefineOpClass (CreateOpClassStmt *stmt)
 
ObjectAddress DefineOpFamily (CreateOpFamilyStmt *stmt)
 
Oid AlterOpFamily (AlterOpFamilyStmt *stmt)
 
void RemoveOpFamilyById (Oid opfamilyOid)
 
void RemoveOpClassById (Oid opclassOid)
 
void RemoveAmOpEntryById (Oid entryOid)
 
void RemoveAmProcEntryById (Oid entryOid)
 
void IsThereOpClassInNamespace (const char *opcname, Oid opcmethod, Oid opcnamespace)
 
void IsThereOpFamilyInNamespace (const char *opfname, Oid opfmethod, Oid opfnamespace)
 

Function Documentation

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

Definition at line 1232 of file opclasscmds.c.

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

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

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

Definition at line 764 of file opclasscmds.c.

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

Referenced by ProcessUtilitySlow().

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

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

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

950 {
951  List *operators; /* OpFamilyMember list for operators */
952  List *procedures; /* OpFamilyMember list for support procs */
953  ListCell *l;
954 
955  operators = NIL;
956  procedures = NIL;
957 
958  /*
959  * Scan the "items" list to obtain additional info.
960  */
961  foreach(l, items)
962  {
964  Oid lefttype,
965  righttype;
966  OpFamilyMember *member;
967 
968  switch (item->itemtype)
969  {
971  if (item->number <= 0 || item->number > maxOpNumber)
972  ereport(ERROR,
973  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
974  errmsg("invalid operator number %d,"
975  " must be between 1 and %d",
976  item->number, maxOpNumber)));
977  processTypesSpec(item->class_args, &lefttype, &righttype);
978  /* Save the info */
979  member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
980  member->number = item->number;
981  member->lefttype = lefttype;
982  member->righttype = righttype;
983  addFamilyMember(&operators, member, false);
984  break;
986  if (item->number <= 0 || item->number > maxProcNumber)
987  ereport(ERROR,
988  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
989  errmsg("invalid procedure number %d,"
990  " must be between 1 and %d",
991  item->number, maxProcNumber)));
992  processTypesSpec(item->class_args, &lefttype, &righttype);
993  /* Save the info */
994  member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
995  member->number = item->number;
996  member->lefttype = lefttype;
997  member->righttype = righttype;
998  addFamilyMember(&procedures, member, true);
999  break;
1001  /* grammar prevents this from appearing */
1002  default:
1003  elog(ERROR, "unrecognized item type: %d", item->itemtype);
1004  break;
1005  }
1006  }
1007 
1008  /*
1009  * Remove tuples from pg_amop and pg_amproc.
1010  */
1011  dropOperators(stmt->opfamilyname, amoid, opfamilyoid, operators);
1012  dropProcedures(stmt->opfamilyname, amoid, opfamilyoid, procedures);
1013 
1014  /* make information available to event triggers */
1015  EventTriggerCollectAlterOpFam(stmt, opfamilyoid,
1016  operators, procedures);
1017 }
#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:1526
unsigned int Oid
Definition: postgres_ext.h:31
#define OPCLASS_ITEM_OPERATOR
Definition: parsenodes.h:2529
static void dropOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid, List *operators)
Definition: opclasscmds.c:1486
#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:1232
#define ereport(elevel, rest)
Definition: elog.h:122
void EventTriggerCollectAlterOpFam(AlterOpFamilyStmt *stmt, Oid opfamoid, List *operators, List *procedures)
static void processTypesSpec(List *args, Oid *lefttype, Oid *righttype)
Definition: opclasscmds.c:1024
void * palloc0(Size size)
Definition: mcxt.c:877
#define OPCLASS_ITEM_FUNCTION
Definition: parsenodes.h:2530
#define OPCLASS_ITEM_STORAGETYPE
Definition: parsenodes.h:2531
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 1053 of file opclasscmds.c.

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

Referenced by AlterOpFamilyAdd(), and DefineOpClass().

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

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

Referenced by AlterOpFamilyAdd(), and DefineOpClass().

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

243 {
244  Oid opfamilyoid;
245  Relation rel;
246  HeapTuple tup;
248  bool nulls[Natts_pg_opfamily];
249  NameData opfName;
250  ObjectAddress myself,
251  referenced;
252 
254 
255  /*
256  * Make sure there is no existing opfamily of this name (this is just to
257  * give a more friendly error message than "duplicate key").
258  */
260  ObjectIdGetDatum(amoid),
261  CStringGetDatum(opfname),
262  ObjectIdGetDatum(namespaceoid)))
263  ereport(ERROR,
265  errmsg("operator family \"%s\" for access method \"%s\" already exists",
266  opfname, amname)));
267 
268  /*
269  * Okay, let's create the pg_opfamily entry.
270  */
271  memset(values, 0, sizeof(values));
272  memset(nulls, false, sizeof(nulls));
273 
274  values[Anum_pg_opfamily_opfmethod - 1] = ObjectIdGetDatum(amoid);
275  namestrcpy(&opfName, opfname);
276  values[Anum_pg_opfamily_opfname - 1] = NameGetDatum(&opfName);
277  values[Anum_pg_opfamily_opfnamespace - 1] = ObjectIdGetDatum(namespaceoid);
279 
280  tup = heap_form_tuple(rel->rd_att, values, nulls);
281 
282  opfamilyoid = CatalogTupleInsert(rel, tup);
283 
284  heap_freetuple(tup);
285 
286  /*
287  * Create dependencies for the opfamily proper.
288  */
290  myself.objectId = opfamilyoid;
291  myself.objectSubId = 0;
292 
293  /* dependency on access method */
294  referenced.classId = AccessMethodRelationId;
295  referenced.objectId = amoid;
296  referenced.objectSubId = 0;
297  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
298 
299  /* dependency on namespace */
300  referenced.classId = NamespaceRelationId;
301  referenced.objectId = namespaceoid;
302  referenced.objectSubId = 0;
303  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
304 
305  /* dependency on owner */
307 
308  /* dependency on extension */
309  recordDependencyOnCurrentExtension(&myself, false);
310 
311  /* Post creation hook for new operator family */
313 
315 
316  return myself;
317 }
#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:284
#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:695
#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:1373
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:216
#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:186
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
Definition: c.h:487
#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:1290
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:164
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
ObjectAddress DefineOpClass ( CreateOpClassStmt stmt)

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

325 {
326  char *opcname; /* name of opclass we're creating */
327  Oid amoid, /* our AM's oid */
328  typeoid, /* indexable datatype oid */
329  storageoid, /* storage datatype oid, if any */
330  namespaceoid, /* namespace to create opclass in */
331  opfamilyoid, /* oid of containing opfamily */
332  opclassoid; /* oid of opclass we create */
333  int maxOpNumber, /* amstrategies value */
334  maxProcNumber; /* amsupport value */
335  bool amstorage; /* amstorage flag */
336  List *operators; /* OpFamilyMember list for operators */
337  List *procedures; /* OpFamilyMember list for support procs */
338  ListCell *l;
339  Relation rel;
340  HeapTuple tup;
341  IndexAmRoutine *amroutine;
343  bool nulls[Natts_pg_opclass];
344  AclResult aclresult;
345  NameData opcName;
346  ObjectAddress myself,
347  referenced;
348 
349  /* Convert list of names to a name and namespace */
350  namespaceoid = QualifiedNameGetCreationNamespace(stmt->opclassname,
351  &opcname);
352 
353  /* Check we have creation rights in target namespace */
354  aclresult = pg_namespace_aclcheck(namespaceoid, GetUserId(), ACL_CREATE);
355  if (aclresult != ACLCHECK_OK)
357  get_namespace_name(namespaceoid));
358 
359  /* Get necessary info about access method */
361  if (!HeapTupleIsValid(tup))
362  ereport(ERROR,
363  (errcode(ERRCODE_UNDEFINED_OBJECT),
364  errmsg("access method \"%s\" does not exist",
365  stmt->amname)));
366 
367  amoid = HeapTupleGetOid(tup);
368  amroutine = GetIndexAmRoutineByAmId(amoid, false);
369  ReleaseSysCache(tup);
370 
371  maxOpNumber = amroutine->amstrategies;
372  /* if amstrategies is zero, just enforce that op numbers fit in int16 */
373  if (maxOpNumber <= 0)
374  maxOpNumber = SHRT_MAX;
375  maxProcNumber = amroutine->amsupport;
376  amstorage = amroutine->amstorage;
377 
378  /* XXX Should we make any privilege check against the AM? */
379 
380  /*
381  * The question of appropriate permissions for CREATE OPERATOR CLASS is
382  * interesting. Creating an opclass is tantamount to granting public
383  * execute access on the functions involved, since the index machinery
384  * generally does not check access permission before using the functions.
385  * A minimum expectation therefore is that the caller have execute
386  * privilege with grant option. Since we don't have a way to make the
387  * opclass go away if the grant option is revoked, we choose instead to
388  * require ownership of the functions. It's also not entirely clear what
389  * permissions should be required on the datatype, but ownership seems
390  * like a safe choice.
391  *
392  * Currently, we require superuser privileges to create an opclass. This
393  * seems necessary because we have no way to validate that the offered set
394  * of operators and functions are consistent with the AM's expectations.
395  * It would be nice to provide such a check someday, if it can be done
396  * without solving the halting problem :-(
397  *
398  * XXX re-enable NOT_USED code sections below if you remove this test.
399  */
400  if (!superuser())
401  ereport(ERROR,
402  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
403  errmsg("must be superuser to create an operator class")));
404 
405  /* Look up the datatype */
406  typeoid = typenameTypeId(NULL, stmt->datatype);
407 
408 #ifdef NOT_USED
409  /* XXX this is unnecessary given the superuser check above */
410  /* Check we have ownership of the datatype */
411  if (!pg_type_ownercheck(typeoid, GetUserId()))
413 #endif
414 
415  /*
416  * Look up the containing operator family, or create one if FAMILY option
417  * was omitted and there's not a match already.
418  */
419  if (stmt->opfamilyname)
420  {
421  opfamilyoid = get_opfamily_oid(amoid, stmt->opfamilyname, false);
422  }
423  else
424  {
425  /* Lookup existing family of same name and namespace */
427  ObjectIdGetDatum(amoid),
428  PointerGetDatum(opcname),
429  ObjectIdGetDatum(namespaceoid));
430  if (HeapTupleIsValid(tup))
431  {
432  opfamilyoid = HeapTupleGetOid(tup);
433 
434  /*
435  * XXX given the superuser check above, there's no need for an
436  * ownership check here
437  */
438  ReleaseSysCache(tup);
439  }
440  else
441  {
442  ObjectAddress tmpAddr;
443 
444  /*
445  * Create it ... again no need for more permissions ...
446  */
447  tmpAddr = CreateOpFamily(stmt->amname, opcname,
448  namespaceoid, amoid);
449  opfamilyoid = tmpAddr.objectId;
450  }
451  }
452 
453  operators = NIL;
454  procedures = NIL;
455 
456  /* Storage datatype is optional */
457  storageoid = InvalidOid;
458 
459  /*
460  * Scan the "items" list to obtain additional info.
461  */
462  foreach(l, stmt->items)
463  {
465  Oid operOid;
466  Oid funcOid;
467  Oid sortfamilyOid;
468  OpFamilyMember *member;
469 
470  switch (item->itemtype)
471  {
473  if (item->number <= 0 || item->number > maxOpNumber)
474  ereport(ERROR,
475  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
476  errmsg("invalid operator number %d,"
477  " must be between 1 and %d",
478  item->number, maxOpNumber)));
479  if (item->name->objargs != NIL)
480  operOid = LookupOperWithArgs(item->name, false);
481  else
482  {
483  /* Default to binary op on input datatype */
484  operOid = LookupOperName(NULL, item->name->objname,
485  typeoid, typeoid,
486  false, -1);
487  }
488 
489  if (item->order_family)
490  sortfamilyOid = get_opfamily_oid(BTREE_AM_OID,
491  item->order_family,
492  false);
493  else
494  sortfamilyOid = InvalidOid;
495 
496 #ifdef NOT_USED
497  /* XXX this is unnecessary given the superuser check above */
498  /* Caller must own operator and its underlying function */
499  if (!pg_oper_ownercheck(operOid, GetUserId()))
501  get_opname(operOid));
502  funcOid = get_opcode(operOid);
503  if (!pg_proc_ownercheck(funcOid, GetUserId()))
505  get_func_name(funcOid));
506 #endif
507 
508  /* Save the info */
509  member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
510  member->object = operOid;
511  member->number = item->number;
512  member->sortfamily = sortfamilyOid;
513  assignOperTypes(member, amoid, typeoid);
514  addFamilyMember(&operators, member, false);
515  break;
517  if (item->number <= 0 || item->number > maxProcNumber)
518  ereport(ERROR,
519  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
520  errmsg("invalid procedure number %d,"
521  " must be between 1 and %d",
522  item->number, maxProcNumber)));
523  funcOid = LookupFuncWithArgs(item->name, false);
524 #ifdef NOT_USED
525  /* XXX this is unnecessary given the superuser check above */
526  /* Caller must own function */
527  if (!pg_proc_ownercheck(funcOid, GetUserId()))
529  get_func_name(funcOid));
530 #endif
531 
532  /* Save the info */
533  member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
534  member->object = funcOid;
535  member->number = item->number;
536 
537  /* allow overriding of the function's actual arg types */
538  if (item->class_args)
540  &member->lefttype, &member->righttype);
541 
542  assignProcTypes(member, amoid, typeoid);
543  addFamilyMember(&procedures, member, true);
544  break;
546  if (OidIsValid(storageoid))
547  ereport(ERROR,
548  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
549  errmsg("storage type specified more than once")));
550  storageoid = typenameTypeId(NULL, item->storedtype);
551 
552 #ifdef NOT_USED
553  /* XXX this is unnecessary given the superuser check above */
554  /* Check we have ownership of the datatype */
555  if (!pg_type_ownercheck(storageoid, GetUserId()))
557 #endif
558  break;
559  default:
560  elog(ERROR, "unrecognized item type: %d", item->itemtype);
561  break;
562  }
563  }
564 
565  /*
566  * If storagetype is specified, make sure it's legal.
567  */
568  if (OidIsValid(storageoid))
569  {
570  /* Just drop the spec if same as column datatype */
571  if (storageoid == typeoid)
572  storageoid = InvalidOid;
573  else if (!amstorage)
574  ereport(ERROR,
575  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
576  errmsg("storage type cannot be different from data type for access method \"%s\"",
577  stmt->amname)));
578  }
579 
581 
582  /*
583  * Make sure there is no existing opclass of this name (this is just to
584  * give a more friendly error message than "duplicate key").
585  */
587  ObjectIdGetDatum(amoid),
588  CStringGetDatum(opcname),
589  ObjectIdGetDatum(namespaceoid)))
590  ereport(ERROR,
592  errmsg("operator class \"%s\" for access method \"%s\" already exists",
593  opcname, stmt->amname)));
594 
595  /*
596  * If we are creating a default opclass, check there isn't one already.
597  * (Note we do not restrict this test to visible opclasses; this ensures
598  * that typcache.c can find unique solutions to its questions.)
599  */
600  if (stmt->isDefault)
601  {
602  ScanKeyData skey[1];
603  SysScanDesc scan;
604 
605  ScanKeyInit(&skey[0],
607  BTEqualStrategyNumber, F_OIDEQ,
608  ObjectIdGetDatum(amoid));
609 
611  NULL, 1, skey);
612 
613  while (HeapTupleIsValid(tup = systable_getnext(scan)))
614  {
615  Form_pg_opclass opclass = (Form_pg_opclass) GETSTRUCT(tup);
616 
617  if (opclass->opcintype == typeoid && opclass->opcdefault)
618  ereport(ERROR,
620  errmsg("could not make operator class \"%s\" be default for type %s",
621  opcname,
622  TypeNameToString(stmt->datatype)),
623  errdetail("Operator class \"%s\" already is the default.",
624  NameStr(opclass->opcname))));
625  }
626 
627  systable_endscan(scan);
628  }
629 
630  /*
631  * Okay, let's create the pg_opclass entry.
632  */
633  memset(values, 0, sizeof(values));
634  memset(nulls, false, sizeof(nulls));
635 
636  values[Anum_pg_opclass_opcmethod - 1] = ObjectIdGetDatum(amoid);
637  namestrcpy(&opcName, opcname);
638  values[Anum_pg_opclass_opcname - 1] = NameGetDatum(&opcName);
639  values[Anum_pg_opclass_opcnamespace - 1] = ObjectIdGetDatum(namespaceoid);
641  values[Anum_pg_opclass_opcfamily - 1] = ObjectIdGetDatum(opfamilyoid);
642  values[Anum_pg_opclass_opcintype - 1] = ObjectIdGetDatum(typeoid);
644  values[Anum_pg_opclass_opckeytype - 1] = ObjectIdGetDatum(storageoid);
645 
646  tup = heap_form_tuple(rel->rd_att, values, nulls);
647 
648  opclassoid = CatalogTupleInsert(rel, tup);
649 
650  heap_freetuple(tup);
651 
652  /*
653  * Now add tuples to pg_amop and pg_amproc tying in the operators and
654  * functions. Dependencies on them are inserted, too.
655  */
656  storeOperators(stmt->opfamilyname, amoid, opfamilyoid,
657  opclassoid, operators, false);
658  storeProcedures(stmt->opfamilyname, amoid, opfamilyoid,
659  opclassoid, procedures, false);
660 
661  /* let event triggers know what happened */
662  EventTriggerCollectCreateOpClass(stmt, opclassoid, operators, procedures);
663 
664  /*
665  * Create dependencies for the opclass proper. Note: we do not need a
666  * dependency link to the AM, because that exists through the opfamily.
667  */
669  myself.objectId = opclassoid;
670  myself.objectSubId = 0;
671 
672  /* dependency on namespace */
673  referenced.classId = NamespaceRelationId;
674  referenced.objectId = namespaceoid;
675  referenced.objectSubId = 0;
676  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
677 
678  /* dependency on opfamily */
679  referenced.classId = OperatorFamilyRelationId;
680  referenced.objectId = opfamilyoid;
681  referenced.objectSubId = 0;
682  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
683 
684  /* dependency on indexed datatype */
685  referenced.classId = TypeRelationId;
686  referenced.objectId = typeoid;
687  referenced.objectSubId = 0;
688  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
689 
690  /* dependency on storage datatype */
691  if (OidIsValid(storageoid))
692  {
693  referenced.classId = TypeRelationId;
694  referenced.objectId = storageoid;
695  referenced.objectSubId = 0;
696  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
697  }
698 
699  /* dependency on owner */
701 
702  /* dependency on extension */
703  recordDependencyOnCurrentExtension(&myself, false);
704 
705  /* Post creation hook for new operator class */
707 
709 
710  return myself;
711 }
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:1053
#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:284
TypeName * storedtype
Definition: parsenodes.h:2543
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2956
#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:695
#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:1373
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:216
#define OidIsValid(objectId)
Definition: c.h:532
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
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3457
#define OPCLASS_ITEM_OPERATOR
Definition: parsenodes.h:2529
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:186
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
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:1134
#define lfirst_node(type, lc)
Definition: pg_list.h:109
Definition: c.h:487
TypeName * datatype
Definition: parsenodes.h:2524
ObjectWithArgs * name
Definition: parsenodes.h:2537
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
static ObjectAddress CreateOpFamily(char *amname, char *opfname, Oid namespaceoid, Oid amoid)
Definition: opclasscmds.c:242
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:1232
#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:1990
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
static void processTypesSpec(List *args, Oid *lefttype, Oid *righttype)
Definition: opclasscmds.c:1024
void * palloc0(Size size)
Definition: mcxt.c:877
AclResult
Definition: acl.h:178
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
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:2530
#define Natts_pg_opclass
Definition: pg_opclass.h:74
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:139
#define OPCLASS_ITEM_STORAGETYPE
Definition: parsenodes.h:2531
void EventTriggerCollectCreateOpClass(CreateOpClassStmt *stmt, Oid opcoid, List *operators, List *procedures)
Oid get_opfamily_oid(Oid amID, List *opfamilyname, bool missing_ok)
Definition: opclasscmds.c:142
static void storeProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid, Oid opclassoid, List *procedures, bool isAdd)
Definition: opclasscmds.c:1386
uint16 amstrategies
Definition: amapi.h:167
static Datum values[MAXATTR]
Definition: bootstrap.c:164
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:493
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:1119
static void storeOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid, Oid opclassoid, List *operators, bool isAdd)
Definition: opclasscmds.c:1271
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:68
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
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 719 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().

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

Definition at line 1486 of file opclasscmds.c.

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

Referenced by AlterOpFamilyDrop().

1488 {
1489  ListCell *l;
1490 
1491  foreach(l, operators)
1492  {
1493  OpFamilyMember *op = (OpFamilyMember *) lfirst(l);
1494  Oid amopid;
1495  ObjectAddress object;
1496 
1497  amopid = GetSysCacheOid4(AMOPSTRATEGY,
1498  ObjectIdGetDatum(opfamilyoid),
1501  Int16GetDatum(op->number));
1502  if (!OidIsValid(amopid))
1503  ereport(ERROR,
1504  (errcode(ERRCODE_UNDEFINED_OBJECT),
1505  errmsg("operator %d(%s,%s) does not exist in operator family \"%s\"",
1506  op->number,
1507  format_type_be(op->lefttype),
1509  NameListToString(opfamilyname))));
1510 
1511  object.classId = AccessMethodOperatorRelationId;
1512  object.objectId = amopid;
1513  object.objectSubId = 0;
1514 
1515  performDeletion(&object, DROP_RESTRICT, 0);
1516  }
1517 }
#define GetSysCacheOid4(cacheId, key1, key2, key3, key4)
Definition: syscache.h:197
#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:532
#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:3063
#define lfirst(lc)
Definition: pg_list.h:106
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void dropProcedures ( List opfamilyname,
Oid  amoid,
Oid  opfamilyoid,
List procedures 
)
static

Definition at line 1526 of file opclasscmds.c.

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

Referenced by AlterOpFamilyDrop().

1528 {
1529  ListCell *l;
1530 
1531  foreach(l, procedures)
1532  {
1533  OpFamilyMember *op = (OpFamilyMember *) lfirst(l);
1534  Oid amprocid;
1535  ObjectAddress object;
1536 
1537  amprocid = GetSysCacheOid4(AMPROCNUM,
1538  ObjectIdGetDatum(opfamilyoid),
1541  Int16GetDatum(op->number));
1542  if (!OidIsValid(amprocid))
1543  ereport(ERROR,
1544  (errcode(ERRCODE_UNDEFINED_OBJECT),
1545  errmsg("function %d(%s,%s) does not exist in operator family \"%s\"",
1546  op->number,
1547  format_type_be(op->lefttype),
1549  NameListToString(opfamilyname))));
1550 
1551  object.classId = AccessMethodProcedureRelationId;
1552  object.objectId = amprocid;
1553  object.objectSubId = 0;
1554 
1555  performDeletion(&object, DROP_RESTRICT, 0);
1556  }
1557 }
#define GetSysCacheOid4(cacheId, key1, key2, key3, key4)
Definition: syscache.h:197
#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:532
#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:3063
#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 221 of file opclasscmds.c.

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

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

222 {
223  HeapTuple htup;
224  Oid opcID;
225 
226  htup = OpClassCacheLookup(amID, opclassname, missing_ok);
227  if (!HeapTupleIsValid(htup))
228  return InvalidOid;
229  opcID = HeapTupleGetOid(htup);
230  ReleaseSysCache(htup);
231 
232  return opcID;
233 }
static HeapTuple OpClassCacheLookup(Oid amID, List *opclassname, bool missing_ok)
Definition: opclasscmds.c:163
unsigned int Oid
Definition: postgres_ext.h:31
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#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 142 of file opclasscmds.c.

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

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

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

Definition at line 1665 of file opclasscmds.c.

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

Referenced by AlterObjectNamespace_internal(), and AlterObjectRename_internal().

1667 {
1668  /* make sure the new name doesn't exist */
1670  ObjectIdGetDatum(opcmethod),
1671  CStringGetDatum(opcname),
1672  ObjectIdGetDatum(opcnamespace)))
1673  ereport(ERROR,
1675  errmsg("operator class \"%s\" for access method \"%s\" already exists in schema \"%s\"",
1676  opcname,
1677  get_am_name(opcmethod),
1678  get_namespace_name(opcnamespace))));
1679 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:186
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
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:30
void IsThereOpFamilyInNamespace ( const char *  opfname,
Oid  opfmethod,
Oid  opfnamespace 
)

Definition at line 1688 of file opclasscmds.c.

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

Referenced by AlterObjectNamespace_internal(), and AlterObjectRename_internal().

1690 {
1691  /* make sure the new name doesn't exist */
1693  ObjectIdGetDatum(opfmethod),
1694  CStringGetDatum(opfname),
1695  ObjectIdGetDatum(opfnamespace)))
1696  ereport(ERROR,
1698  errmsg("operator family \"%s\" for access method \"%s\" already exists in schema \"%s\"",
1699  opfname,
1700  get_am_name(opfmethod),
1701  get_namespace_name(opfnamespace))));
1702 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:186
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
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:30
static HeapTuple OpClassCacheLookup ( Oid  amID,
List opclassname,
bool  missing_ok 
)
static

Definition at line 163 of file opclasscmds.c.

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

Referenced by get_opclass_oid().

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

Definition at line 84 of file opclasscmds.c.

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

Referenced by get_opfamily_oid().

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

Definition at line 1024 of file opclasscmds.c.

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

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

1025 {
1026  TypeName *typeName;
1027 
1028  Assert(args != NIL);
1029 
1030  typeName = (TypeName *) linitial(args);
1031  *lefttype = typenameTypeId(NULL, typeName);
1032 
1033  if (list_length(args) > 1)
1034  {
1035  typeName = (TypeName *) lsecond(args);
1036  *righttype = typenameTypeId(NULL, typeName);
1037  }
1038  else
1039  *righttype = *lefttype;
1040 
1041  if (list_length(args) > 2)
1042  ereport(ERROR,
1043  (errcode(ERRCODE_SYNTAX_ERROR),
1044  errmsg("one or two argument types must be specified")));
1045 }
#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 Assert(condition)
Definition: c.h:681
static int list_length(const List *l)
Definition: pg_list.h:89
int errmsg(const char *fmt,...)
Definition: elog.c:797
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274
void RemoveAmOpEntryById ( Oid  entryOid)

Definition at line 1601 of file opclasscmds.c.

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

Referenced by doDeletion().

1602 {
1603  Relation rel;
1604  HeapTuple tup;
1605  ScanKeyData skey[1];
1606  SysScanDesc scan;
1607 
1608  ScanKeyInit(&skey[0],
1610  BTEqualStrategyNumber, F_OIDEQ,
1611  ObjectIdGetDatum(entryOid));
1612 
1614 
1616  NULL, 1, skey);
1617 
1618  /* we expect exactly one match */
1619  tup = systable_getnext(scan);
1620  if (!HeapTupleIsValid(tup))
1621  elog(ERROR, "could not find tuple for amop entry %u", entryOid);
1622 
1623  CatalogTupleDelete(rel, &tup->t_self);
1624 
1625  systable_endscan(scan);
1627 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c: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:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define elog
Definition: elog.h:219
#define BTEqualStrategyNumber
Definition: stratnum.h:31
void RemoveAmProcEntryById ( Oid  entryOid)

Definition at line 1630 of file opclasscmds.c.

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

Referenced by doDeletion().

1631 {
1632  Relation rel;
1633  HeapTuple tup;
1634  ScanKeyData skey[1];
1635  SysScanDesc scan;
1636 
1637  ScanKeyInit(&skey[0],
1639  BTEqualStrategyNumber, F_OIDEQ,
1640  ObjectIdGetDatum(entryOid));
1641 
1643 
1645  NULL, 1, skey);
1646 
1647  /* we expect exactly one match */
1648  tup = systable_getnext(scan);
1649  if (!HeapTupleIsValid(tup))
1650  elog(ERROR, "could not find tuple for amproc entry %u", entryOid);
1651 
1652  CatalogTupleDelete(rel, &tup->t_self);
1653 
1654  systable_endscan(scan);
1656 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c: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:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define elog
Definition: elog.h:219
#define AccessMethodProcedureRelationId
Definition: pg_amproc.h:43
#define BTEqualStrategyNumber
Definition: stratnum.h:31
void RemoveOpClassById ( Oid  opclassOid)

Definition at line 1582 of file opclasscmds.c.

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

Referenced by doDeletion().

1583 {
1584  Relation rel;
1585  HeapTuple tup;
1586 
1588 
1589  tup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclassOid));
1590  if (!HeapTupleIsValid(tup)) /* should not happen */
1591  elog(ERROR, "cache lookup failed for opclass %u", opclassOid);
1592 
1593  CatalogTupleDelete(rel, &tup->t_self);
1594 
1595  ReleaseSysCache(tup);
1596 
1598 }
#define OperatorClassRelationId
Definition: pg_opclass.h:49
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
#define 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
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define elog
Definition: elog.h:219
void RemoveOpFamilyById ( Oid  opfamilyOid)

Definition at line 1563 of file opclasscmds.c.

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

Referenced by doDeletion().

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

Definition at line 1271 of file opclasscmds.c.

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

Referenced by AlterOpFamilyAdd(), and DefineOpClass().

1274 {
1275  Relation rel;
1277  bool nulls[Natts_pg_amop];
1278  HeapTuple tup;
1279  Oid entryoid;
1280  ObjectAddress myself,
1281  referenced;
1282  ListCell *l;
1283 
1285 
1286  foreach(l, operators)
1287  {
1288  OpFamilyMember *op = (OpFamilyMember *) lfirst(l);
1289  char oppurpose;
1290 
1291  /*
1292  * If adding to an existing family, check for conflict with an
1293  * existing pg_amop entry (just to give a nicer error message)
1294  */
1295  if (isAdd &&
1297  ObjectIdGetDatum(opfamilyoid),
1300  Int16GetDatum(op->number)))
1301  ereport(ERROR,
1303  errmsg("operator %d(%s,%s) already exists in operator family \"%s\"",
1304  op->number,
1305  format_type_be(op->lefttype),
1307  NameListToString(opfamilyname))));
1308 
1309  oppurpose = OidIsValid(op->sortfamily) ? AMOP_ORDER : AMOP_SEARCH;
1310 
1311  /* Create the pg_amop entry */
1312  memset(values, 0, sizeof(values));
1313  memset(nulls, false, sizeof(nulls));
1314 
1315  values[Anum_pg_amop_amopfamily - 1] = ObjectIdGetDatum(opfamilyoid);
1318  values[Anum_pg_amop_amopstrategy - 1] = Int16GetDatum(op->number);
1319  values[Anum_pg_amop_amoppurpose - 1] = CharGetDatum(oppurpose);
1320  values[Anum_pg_amop_amopopr - 1] = ObjectIdGetDatum(op->object);
1321  values[Anum_pg_amop_amopmethod - 1] = ObjectIdGetDatum(amoid);
1323 
1324  tup = heap_form_tuple(rel->rd_att, values, nulls);
1325 
1326  entryoid = CatalogTupleInsert(rel, tup);
1327 
1328  heap_freetuple(tup);
1329 
1330  /* Make its dependencies */
1332  myself.objectId = entryoid;
1333  myself.objectSubId = 0;
1334 
1335  referenced.classId = OperatorRelationId;
1336  referenced.objectId = op->object;
1337  referenced.objectSubId = 0;
1338 
1339  if (OidIsValid(opclassoid))
1340  {
1341  /* if contained in an opclass, use a NORMAL dep on operator */
1342  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1343 
1344  /* ... and an INTERNAL dep on the opclass */
1345  referenced.classId = OperatorClassRelationId;
1346  referenced.objectId = opclassoid;
1347  referenced.objectSubId = 0;
1348  recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
1349  }
1350  else
1351  {
1352  /* if "loose" in the opfamily, use a AUTO dep on operator */
1353  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1354 
1355  /* ... and an AUTO dep on the opfamily */
1356  referenced.classId = OperatorFamilyRelationId;
1357  referenced.objectId = opfamilyoid;
1358  referenced.objectSubId = 0;
1359  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1360  }
1361 
1362  /* A search operator also needs a dep on the referenced opfamily */
1363  if (OidIsValid(op->sortfamily))
1364  {
1365  referenced.classId = OperatorFamilyRelationId;
1366  referenced.objectId = op->sortfamily;
1367  referenced.objectSubId = 0;
1368  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1369  }
1370  /* Post create hook of this access method operator */
1372  entryoid, 0);
1373  }
1374 
1376 }
#define Anum_pg_amop_amopsortfamily
Definition: pg_amop.h:91
#define OperatorRelationId
Definition: pg_operator.h:32
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
#define Anum_pg_amop_amopmethod
Definition: pg_amop.h:90
#define AMOP_SEARCH
Definition: pg_amop.h:69
#define Int16GetDatum(X)
Definition: postgres.h: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:188
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:695
#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:1373
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:532
#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:3063
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:1290
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:164
#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:30
#define Anum_pg_amop_amopstrategy
Definition: pg_amop.h:87
static void storeProcedures ( List opfamilyname,
Oid  amoid,
Oid  opfamilyoid,
Oid  opclassoid,
List procedures,
bool  isAdd 
)
static

Definition at line 1386 of file opclasscmds.c.

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

Referenced by AlterOpFamilyAdd(), and DefineOpClass().

1389 {
1390  Relation rel;
1392  bool nulls[Natts_pg_amproc];
1393  HeapTuple tup;
1394  Oid entryoid;
1395  ObjectAddress myself,
1396  referenced;
1397  ListCell *l;
1398 
1400 
1401  foreach(l, procedures)
1402  {
1403  OpFamilyMember *proc = (OpFamilyMember *) lfirst(l);
1404 
1405  /*
1406  * If adding to an existing family, check for conflict with an
1407  * existing pg_amproc entry (just to give a nicer error message)
1408  */
1409  if (isAdd &&
1411  ObjectIdGetDatum(opfamilyoid),
1412  ObjectIdGetDatum(proc->lefttype),
1413  ObjectIdGetDatum(proc->righttype),
1414  Int16GetDatum(proc->number)))
1415  ereport(ERROR,
1417  errmsg("function %d(%s,%s) already exists in operator family \"%s\"",
1418  proc->number,
1419  format_type_be(proc->lefttype),
1420  format_type_be(proc->righttype),
1421  NameListToString(opfamilyname))));
1422 
1423  /* Create the pg_amproc entry */
1424  memset(values, 0, sizeof(values));
1425  memset(nulls, false, sizeof(nulls));
1426 
1427  values[Anum_pg_amproc_amprocfamily - 1] = ObjectIdGetDatum(opfamilyoid);
1430  values[Anum_pg_amproc_amprocnum - 1] = Int16GetDatum(proc->number);
1431  values[Anum_pg_amproc_amproc - 1] = ObjectIdGetDatum(proc->object);
1432 
1433  tup = heap_form_tuple(rel->rd_att, values, nulls);
1434 
1435  entryoid = CatalogTupleInsert(rel, tup);
1436 
1437  heap_freetuple(tup);
1438 
1439  /* Make its dependencies */
1441  myself.objectId = entryoid;
1442  myself.objectSubId = 0;
1443 
1444  referenced.classId = ProcedureRelationId;
1445  referenced.objectId = proc->object;
1446  referenced.objectSubId = 0;
1447 
1448  if (OidIsValid(opclassoid))
1449  {
1450  /* if contained in an opclass, use a NORMAL dep on procedure */
1451  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1452 
1453  /* ... and an INTERNAL dep on the opclass */
1454  referenced.classId = OperatorClassRelationId;
1455  referenced.objectId = opclassoid;
1456  referenced.objectSubId = 0;
1457  recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
1458  }
1459  else
1460  {
1461  /* if "loose" in the opfamily, use a AUTO dep on procedure */
1462  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1463 
1464  /* ... and an AUTO dep on the opfamily */
1465  referenced.classId = OperatorFamilyRelationId;
1466  referenced.objectId = opfamilyoid;
1467  referenced.objectSubId = 0;
1468  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1469  }
1470  /* Post create hook of access method procedure */
1472  entryoid, 0);
1473  }
1474 
1476 }
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
#define ProcedureRelationId
Definition: pg_proc.h:33
#define Int16GetDatum(X)
Definition: postgres.h: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:188
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:695
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:532
#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:3063
uintptr_t Datum
Definition: postgres.h:372
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
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:164
#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:30
#define AccessMethodProcedureRelationId
Definition: pg_amproc.h:43