PostgreSQL Source Code  git master
pg_operator.h File Reference
#include "catalog/genbki.h"
#include "catalog/objectaddress.h"
#include "catalog/pg_operator_d.h"
#include "nodes/pg_list.h"
Include dependency graph for pg_operator.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef FormData_pg_operatorForm_pg_operator
 

Functions

 CATALOG (pg_operator, 2617, OperatorRelationId)
 
 DECLARE_UNIQUE_INDEX_PKEY (pg_operator_oid_index, 2688, OperatorOidIndexId, pg_operator, btree(oid oid_ops))
 
 DECLARE_UNIQUE_INDEX (pg_operator_oprname_l_r_n_index, 2689, OperatorNameNspIndexId, pg_operator, btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops))
 
 MAKE_SYSCACHE (OPEROID, pg_operator_oid_index, 32)
 
 MAKE_SYSCACHE (OPERNAMENSP, pg_operator_oprname_l_r_n_index, 256)
 
Oid OperatorLookup (List *operatorName, Oid leftObjectId, Oid rightObjectId, bool *defined)
 
ObjectAddress OperatorCreate (const char *operatorName, Oid operatorNamespace, Oid leftTypeId, Oid rightTypeId, Oid procedureId, List *commutatorName, List *negatorName, Oid restrictionId, Oid joinId, bool canMerge, bool canHash)
 
ObjectAddress makeOperatorDependencies (HeapTuple tuple, bool makeExtensionDep, bool isUpdate)
 
void OperatorValidateParams (Oid leftTypeId, Oid rightTypeId, Oid operResultType, bool hasCommutator, bool hasNegator, bool hasRestrictionSelectivity, bool hasJoinSelectivity, bool canMerge, bool canHash)
 
void OperatorUpd (Oid baseId, Oid commId, Oid negId, bool isDelete)
 

Variables

 FormData_pg_operator
 

Typedef Documentation

◆ Form_pg_operator

Definition at line 83 of file pg_operator.h.

Function Documentation

◆ CATALOG()

CATALOG ( pg_operator  ,
2617  ,
OperatorRelationId   
)

Definition at line 31 of file pg_operator.h.

32 {
33  Oid oid; /* oid */
34 
35  /* name of operator */
36  NameData oprname;
37 
38  /* OID of namespace containing this oper */
39  Oid oprnamespace BKI_DEFAULT(pg_catalog) BKI_LOOKUP(pg_namespace);
40 
41  /* operator owner */
42  Oid oprowner BKI_DEFAULT(POSTGRES) BKI_LOOKUP(pg_authid);
43 
44  /* 'l' for prefix or 'b' for infix */
45  char oprkind BKI_DEFAULT(b);
46 
47  /* can be used in merge join? */
48  bool oprcanmerge BKI_DEFAULT(f);
49 
50  /* can be used in hash join? */
51  bool oprcanhash BKI_DEFAULT(f);
52 
53  /* left arg type, or 0 if prefix operator */
54  Oid oprleft BKI_LOOKUP_OPT(pg_type);
55 
56  /* right arg type */
57  Oid oprright BKI_LOOKUP(pg_type);
58 
59  /* result datatype; can be 0 in a "shell" operator */
60  Oid oprresult BKI_LOOKUP_OPT(pg_type);
61 
62  /* OID of commutator oper, or 0 if none */
63  Oid oprcom BKI_DEFAULT(0) BKI_LOOKUP_OPT(pg_operator);
64 
65  /* OID of negator oper, or 0 if none */
66  Oid oprnegate BKI_DEFAULT(0) BKI_LOOKUP_OPT(pg_operator);
67 
68  /* OID of underlying function; can be 0 in a "shell" operator */
69  regproc oprcode BKI_LOOKUP_OPT(pg_proc);
70 
71  /* OID of restriction estimator, or 0 */
72  regproc oprrest BKI_DEFAULT(-) BKI_LOOKUP_OPT(pg_proc);
73 
74  /* OID of join estimator, or 0 */
75  regproc oprjoin BKI_DEFAULT(-) BKI_LOOKUP_OPT(pg_proc);
Oid regproc
Definition: c.h:649
#define BKI_LOOKUP(catalog)
Definition: genbki.h:46
#define BKI_DEFAULT(value)
Definition: genbki.h:35
#define BKI_LOOKUP_OPT(catalog)
Definition: genbki.h:47
int b
Definition: isn.c:70
FormData_pg_operator
Definition: pg_operator.h:76
unsigned int Oid
Definition: postgres_ext.h:31
Definition: c.h:741

References b, BKI_DEFAULT, BKI_LOOKUP, and BKI_LOOKUP_OPT.

◆ DECLARE_UNIQUE_INDEX()

DECLARE_UNIQUE_INDEX ( pg_operator_oprname_l_r_n_index  ,
2689  ,
OperatorNameNspIndexId  ,
pg_operator  ,
btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops)   
)

◆ DECLARE_UNIQUE_INDEX_PKEY()

DECLARE_UNIQUE_INDEX_PKEY ( pg_operator_oid_index  ,
2688  ,
OperatorOidIndexId  ,
pg_operator  ,
btree(oid oid_ops)   
)

◆ MAKE_SYSCACHE() [1/2]

MAKE_SYSCACHE ( OPERNAMENSP  ,
pg_operator_oprname_l_r_n_index  ,
256   
)

◆ MAKE_SYSCACHE() [2/2]

MAKE_SYSCACHE ( OPEROID  ,
pg_operator_oid_index  ,
32   
)

◆ makeOperatorDependencies()

ObjectAddress makeOperatorDependencies ( HeapTuple  tuple,
bool  makeExtensionDep,
bool  isUpdate 
)

Definition at line 853 of file pg_operator.c.

856 {
858  ObjectAddress myself,
859  referenced;
860  ObjectAddresses *addrs;
861 
862  ObjectAddressSet(myself, OperatorRelationId, oper->oid);
863 
864  /*
865  * If we are updating the operator, delete any existing entries, except
866  * for extension membership which should remain the same.
867  */
868  if (isUpdate)
869  {
870  deleteDependencyRecordsFor(myself.classId, myself.objectId, true);
872  }
873 
874  addrs = new_object_addresses();
875 
876  /* Dependency on namespace */
877  if (OidIsValid(oper->oprnamespace))
878  {
879  ObjectAddressSet(referenced, NamespaceRelationId, oper->oprnamespace);
880  add_exact_object_address(&referenced, addrs);
881  }
882 
883  /* Dependency on left type */
884  if (OidIsValid(oper->oprleft))
885  {
886  ObjectAddressSet(referenced, TypeRelationId, oper->oprleft);
887  add_exact_object_address(&referenced, addrs);
888  }
889 
890  /* Dependency on right type */
891  if (OidIsValid(oper->oprright))
892  {
893  ObjectAddressSet(referenced, TypeRelationId, oper->oprright);
894  add_exact_object_address(&referenced, addrs);
895  }
896 
897  /* Dependency on result type */
898  if (OidIsValid(oper->oprresult))
899  {
900  ObjectAddressSet(referenced, TypeRelationId, oper->oprresult);
901  add_exact_object_address(&referenced, addrs);
902  }
903 
904  /*
905  * NOTE: we do not consider the operator to depend on the associated
906  * operators oprcom and oprnegate. We do not want to delete this operator
907  * if those go away, but only reset the link fields; which is not a
908  * function that the dependency logic can handle. (It's taken care of
909  * manually within RemoveOperatorById, instead.)
910  */
911 
912  /* Dependency on implementation function */
913  if (OidIsValid(oper->oprcode))
914  {
915  ObjectAddressSet(referenced, ProcedureRelationId, oper->oprcode);
916  add_exact_object_address(&referenced, addrs);
917  }
918 
919  /* Dependency on restriction selectivity function */
920  if (OidIsValid(oper->oprrest))
921  {
922  ObjectAddressSet(referenced, ProcedureRelationId, oper->oprrest);
923  add_exact_object_address(&referenced, addrs);
924  }
925 
926  /* Dependency on join selectivity function */
927  if (OidIsValid(oper->oprjoin))
928  {
929  ObjectAddressSet(referenced, ProcedureRelationId, oper->oprjoin);
930  add_exact_object_address(&referenced, addrs);
931  }
932 
934  free_object_addresses(addrs);
935 
936  /* Dependency on owner */
937  recordDependencyOnOwner(OperatorRelationId, oper->oid,
938  oper->oprowner);
939 
940  /* Dependency on extension */
941  if (makeExtensionDep)
942  recordDependencyOnCurrentExtension(&myself, isUpdate);
943 
944  return myself;
945 }
#define OidIsValid(objectId)
Definition: c.h:775
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2740
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2485
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2531
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2771
@ DEPENDENCY_NORMAL
Definition: dependency.h:33
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition: parse_oper.c:370
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:300
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:192
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:83
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:997
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:160

References add_exact_object_address(), ObjectAddress::classId, deleteDependencyRecordsFor(), deleteSharedDependencyRecordsFor(), DEPENDENCY_NORMAL, free_object_addresses(), GETSTRUCT, new_object_addresses(), ObjectAddressSet, ObjectAddress::objectId, OidIsValid, oper(), record_object_address_dependencies(), recordDependencyOnCurrentExtension(), and recordDependencyOnOwner().

Referenced by AlterOperator(), OperatorCreate(), and OperatorShellMake().

◆ OperatorCreate()

ObjectAddress OperatorCreate ( const char *  operatorName,
Oid  operatorNamespace,
Oid  leftTypeId,
Oid  rightTypeId,
Oid  procedureId,
List commutatorName,
List negatorName,
Oid  restrictionId,
Oid  joinId,
bool  canMerge,
bool  canHash 
)

Definition at line 321 of file pg_operator.c.

332 {
333  Relation pg_operator_desc;
334  HeapTuple tup;
335  bool isUpdate;
336  bool nulls[Natts_pg_operator];
337  bool replaces[Natts_pg_operator];
338  Datum values[Natts_pg_operator];
339  Oid operatorObjectId;
340  bool operatorAlreadyDefined;
341  Oid operResultType;
342  Oid commutatorId,
343  negatorId;
344  bool selfCommutator = false;
345  NameData oname;
346  int i;
347  ObjectAddress address;
348 
349  /*
350  * Sanity checks
351  */
352  if (!validOperatorName(operatorName))
353  ereport(ERROR,
354  (errcode(ERRCODE_INVALID_NAME),
355  errmsg("\"%s\" is not a valid operator name",
356  operatorName)));
357 
358  operResultType = get_func_rettype(procedureId);
359 
360  OperatorValidateParams(leftTypeId,
361  rightTypeId,
362  operResultType,
363  commutatorName != NIL,
364  negatorName != NIL,
365  OidIsValid(restrictionId),
366  OidIsValid(joinId),
367  canMerge,
368  canHash);
369 
370  operatorObjectId = OperatorGet(operatorName,
371  operatorNamespace,
372  leftTypeId,
373  rightTypeId,
374  &operatorAlreadyDefined);
375 
376  if (operatorAlreadyDefined)
377  ereport(ERROR,
378  (errcode(ERRCODE_DUPLICATE_FUNCTION),
379  errmsg("operator %s already exists",
380  operatorName)));
381 
382  /*
383  * At this point, if operatorObjectId is not InvalidOid then we are
384  * filling in a previously-created shell. Insist that the user own any
385  * such shell.
386  */
387  if (OidIsValid(operatorObjectId) &&
388  !object_ownercheck(OperatorRelationId, operatorObjectId, GetUserId()))
390  operatorName);
391 
392  /*
393  * Set up the other operators. If they do not currently exist, create
394  * shells in order to get ObjectId's.
395  */
396 
397  if (commutatorName)
398  {
399  /* commutator has reversed arg types */
400  commutatorId = get_other_operator(commutatorName,
401  rightTypeId, leftTypeId,
402  operatorName, operatorNamespace,
403  leftTypeId, rightTypeId);
404 
405  /* Permission check: must own other operator */
406  if (OidIsValid(commutatorId) &&
407  !object_ownercheck(OperatorRelationId, commutatorId, GetUserId()))
409  NameListToString(commutatorName));
410 
411  /*
412  * If self-linkage to the new operator is requested, we'll fix it
413  * below. (In case of self-linkage to an existing shell operator, we
414  * need do nothing special.)
415  */
416  if (!OidIsValid(commutatorId))
417  selfCommutator = true;
418  }
419  else
420  commutatorId = InvalidOid;
421 
422  if (negatorName)
423  {
424  /* negator has same arg types */
425  negatorId = get_other_operator(negatorName,
426  leftTypeId, rightTypeId,
427  operatorName, operatorNamespace,
428  leftTypeId, rightTypeId);
429 
430  /* Permission check: must own other operator */
431  if (OidIsValid(negatorId) &&
432  !object_ownercheck(OperatorRelationId, negatorId, GetUserId()))
434  NameListToString(negatorName));
435 
436  /*
437  * Prevent self negation, as it doesn't make sense. It's self
438  * negation if result is InvalidOid (negator would be the same
439  * operator but it doesn't exist yet) or operatorObjectId (we are
440  * replacing a shell that would need to be its own negator).
441  */
442  if (!OidIsValid(negatorId) || negatorId == operatorObjectId)
443  ereport(ERROR,
444  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
445  errmsg("operator cannot be its own negator")));
446  }
447  else
448  negatorId = InvalidOid;
449 
450  /*
451  * set up values in the operator tuple
452  */
453 
454  for (i = 0; i < Natts_pg_operator; ++i)
455  {
456  values[i] = (Datum) NULL;
457  replaces[i] = true;
458  nulls[i] = false;
459  }
460 
461  namestrcpy(&oname, operatorName);
462  values[Anum_pg_operator_oprname - 1] = NameGetDatum(&oname);
463  values[Anum_pg_operator_oprnamespace - 1] = ObjectIdGetDatum(operatorNamespace);
464  values[Anum_pg_operator_oprowner - 1] = ObjectIdGetDatum(GetUserId());
465  values[Anum_pg_operator_oprkind - 1] = CharGetDatum(leftTypeId ? 'b' : 'l');
466  values[Anum_pg_operator_oprcanmerge - 1] = BoolGetDatum(canMerge);
467  values[Anum_pg_operator_oprcanhash - 1] = BoolGetDatum(canHash);
468  values[Anum_pg_operator_oprleft - 1] = ObjectIdGetDatum(leftTypeId);
469  values[Anum_pg_operator_oprright - 1] = ObjectIdGetDatum(rightTypeId);
470  values[Anum_pg_operator_oprresult - 1] = ObjectIdGetDatum(operResultType);
471  values[Anum_pg_operator_oprcom - 1] = ObjectIdGetDatum(commutatorId);
472  values[Anum_pg_operator_oprnegate - 1] = ObjectIdGetDatum(negatorId);
473  values[Anum_pg_operator_oprcode - 1] = ObjectIdGetDatum(procedureId);
474  values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(restrictionId);
475  values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(joinId);
476 
477  pg_operator_desc = table_open(OperatorRelationId, RowExclusiveLock);
478 
479  /*
480  * If we are replacing an operator shell, update; else insert
481  */
482  if (operatorObjectId)
483  {
484  isUpdate = true;
485 
486  tup = SearchSysCacheCopy1(OPEROID,
487  ObjectIdGetDatum(operatorObjectId));
488  if (!HeapTupleIsValid(tup))
489  elog(ERROR, "cache lookup failed for operator %u",
490  operatorObjectId);
491 
492  replaces[Anum_pg_operator_oid - 1] = false;
493  tup = heap_modify_tuple(tup,
494  RelationGetDescr(pg_operator_desc),
495  values,
496  nulls,
497  replaces);
498 
499  CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup);
500  }
501  else
502  {
503  isUpdate = false;
504 
505  operatorObjectId = GetNewOidWithIndex(pg_operator_desc,
506  OperatorOidIndexId,
507  Anum_pg_operator_oid);
508  values[Anum_pg_operator_oid - 1] = ObjectIdGetDatum(operatorObjectId);
509 
510  tup = heap_form_tuple(RelationGetDescr(pg_operator_desc),
511  values, nulls);
512 
513  CatalogTupleInsert(pg_operator_desc, tup);
514  }
515 
516  /* Add dependencies for the entry */
517  address = makeOperatorDependencies(tup, true, isUpdate);
518 
519  /*
520  * If a commutator and/or negator link is provided, update the other
521  * operator(s) to point at this one, if they don't already have a link.
522  * This supports an alternative style of operator definition wherein the
523  * user first defines one operator without giving negator or commutator,
524  * then defines the other operator of the pair with the proper commutator
525  * or negator attribute. That style doesn't require creation of a shell,
526  * and it's the only style that worked right before Postgres version 6.5.
527  * This code also takes care of the situation where the new operator is
528  * its own commutator.
529  */
530  if (selfCommutator)
531  commutatorId = operatorObjectId;
532 
533  if (OidIsValid(commutatorId) || OidIsValid(negatorId))
534  OperatorUpd(operatorObjectId, commutatorId, negatorId, false);
535 
536  /* Post creation hook for new operator */
537  InvokeObjectPostCreateHook(OperatorRelationId, operatorObjectId, 0);
538 
539  table_close(pg_operator_desc, RowExclusiveLock);
540 
541  return address;
542 }
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2688
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4130
static Datum values[MAXATTR]
Definition: bootstrap.c:152
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:391
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#define ereport(elevel,...)
Definition: elog.h:149
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition: heaptuple.c:1209
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1116
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233
int i
Definition: isn.c:73
#define RowExclusiveLock
Definition: lockdefs.h:38
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1655
Oid GetUserId(void)
Definition: miscinit.c:514
void namestrcpy(Name name, const char *str)
Definition: name.c:233
char * NameListToString(const List *names)
Definition: namespace.c:3579
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:173
@ OBJECT_OPERATOR
Definition: parsenodes.h:2288
#define NIL
Definition: pg_list.h:68
static Oid get_other_operator(List *otherOp, Oid otherLeftTypeId, Oid otherRightTypeId, const char *operatorName, Oid operatorNamespace, Oid leftTypeId, Oid rightTypeId)
Definition: pg_operator.c:622
static Oid OperatorGet(const char *operatorName, Oid operatorNamespace, Oid leftObjectId, Oid rightObjectId, bool *defined)
Definition: pg_operator.c:124
static bool validOperatorName(const char *name)
Definition: pg_operator.c:68
void OperatorValidateParams(Oid leftTypeId, Oid rightTypeId, Oid operResultType, bool hasCommutator, bool hasNegator, bool hasRestrictionSelectivity, bool hasJoinSelectivity, bool canMerge, bool canHash)
Definition: pg_operator.c:556
ObjectAddress makeOperatorDependencies(HeapTuple tuple, bool makeExtensionDep, bool isUpdate)
Definition: pg_operator.c:853
void OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete)
Definition: pg_operator.c:684
uintptr_t Datum
Definition: postgres.h:64
static Datum BoolGetDatum(bool X)
Definition: postgres.h:102
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Datum NameGetDatum(const NameData *X)
Definition: postgres.h:373
static Datum CharGetDatum(char X)
Definition: postgres.h:122
#define InvalidOid
Definition: postgres_ext.h:36
#define RelationGetDescr(relation)
Definition: rel.h:531
ItemPointerData t_self
Definition: htup.h:65
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:86
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

References aclcheck_error(), ACLCHECK_NOT_OWNER, BoolGetDatum(), CatalogTupleInsert(), CatalogTupleUpdate(), CharGetDatum(), elog, ereport, errcode(), errmsg(), ERROR, get_func_rettype(), get_other_operator(), GetNewOidWithIndex(), GetUserId(), heap_form_tuple(), heap_modify_tuple(), HeapTupleIsValid, i, InvalidOid, InvokeObjectPostCreateHook, makeOperatorDependencies(), NameGetDatum(), NameListToString(), namestrcpy(), NIL, OBJECT_OPERATOR, object_ownercheck(), ObjectIdGetDatum(), OidIsValid, OperatorGet(), OperatorUpd(), OperatorValidateParams(), RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy1, HeapTupleData::t_self, table_close(), table_open(), validOperatorName(), and values.

Referenced by DefineOperator().

◆ OperatorLookup()

Oid OperatorLookup ( List operatorName,
Oid  leftObjectId,
Oid  rightObjectId,
bool defined 
)

Definition at line 164 of file pg_operator.c.

168 {
169  Oid operatorObjectId;
170  RegProcedure oprcode;
171 
172  operatorObjectId = LookupOperName(NULL, operatorName,
173  leftObjectId, rightObjectId,
174  true, -1);
175  if (!OidIsValid(operatorObjectId))
176  {
177  *defined = false;
178  return InvalidOid;
179  }
180 
181  oprcode = get_opcode(operatorObjectId);
182  *defined = RegProcedureIsValid(oprcode);
183 
184  return operatorObjectId;
185 }
#define RegProcedureIsValid(p)
Definition: c.h:777
regproc RegProcedure
Definition: c.h:650
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1285
Oid LookupOperName(ParseState *pstate, List *opername, Oid oprleft, Oid oprright, bool noError, int location)
Definition: parse_oper.c:99

References get_opcode(), InvalidOid, LookupOperName(), OidIsValid, and RegProcedureIsValid.

Referenced by get_other_operator(), and ValidateOperatorReference().

◆ OperatorUpd()

void OperatorUpd ( Oid  baseId,
Oid  commId,
Oid  negId,
bool  isDelete 
)

Definition at line 684 of file pg_operator.c.

685 {
686  Relation pg_operator_desc;
687  HeapTuple tup;
688 
689  /*
690  * If we're making an operator into its own commutator, then we need a
691  * command-counter increment here, since we've just inserted the tuple
692  * we're about to update. But when we're dropping an operator, we can
693  * skip this because we're at the beginning of the command.
694  */
695  if (!isDelete)
697 
698  /* Open the relation. */
699  pg_operator_desc = table_open(OperatorRelationId, RowExclusiveLock);
700 
701  /* Get a writable copy of the commutator's tuple. */
702  if (OidIsValid(commId))
703  tup = SearchSysCacheCopy1(OPEROID, ObjectIdGetDatum(commId));
704  else
705  tup = NULL;
706 
707  /* Update the commutator's tuple if need be. */
708  if (HeapTupleIsValid(tup))
709  {
711  bool update_commutator = false;
712 
713  /*
714  * We can skip doing anything if the commutator's oprcom field is
715  * already what we want. While that's not expected in the isDelete
716  * case, it's perfectly possible when filling in a shell operator.
717  */
718  if (isDelete && OidIsValid(t->oprcom))
719  {
720  t->oprcom = InvalidOid;
721  update_commutator = true;
722  }
723  else if (!isDelete && t->oprcom != baseId)
724  {
725  /*
726  * If commutator's oprcom field is already set to point to some
727  * third operator, it's an error. Changing its link would be
728  * unsafe, and letting the inconsistency stand would not be good
729  * either. This might be indicative of catalog corruption, so
730  * don't assume t->oprcom is necessarily a valid operator.
731  */
732  if (OidIsValid(t->oprcom))
733  {
734  char *thirdop = get_opname(t->oprcom);
735 
736  if (thirdop != NULL)
737  ereport(ERROR,
738  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
739  errmsg("commutator operator %s is already the commutator of operator %s",
740  NameStr(t->oprname), thirdop)));
741  else
742  ereport(ERROR,
743  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
744  errmsg("commutator operator %s is already the commutator of operator %u",
745  NameStr(t->oprname), t->oprcom)));
746  }
747 
748  t->oprcom = baseId;
749  update_commutator = true;
750  }
751 
752  /* If any columns were found to need modification, update tuple. */
753  if (update_commutator)
754  {
755  CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup);
756 
757  /*
758  * Do CCI to make the updated tuple visible. We must do this in
759  * case the commutator is also the negator. (Which would be a
760  * logic error on the operator definer's part, but that's not a
761  * good reason to fail here.) We would need a CCI anyway in the
762  * deletion case for a self-commutator with no negator.
763  */
765  }
766  }
767 
768  /*
769  * Similarly find and update the negator, if any.
770  */
771  if (OidIsValid(negId))
772  tup = SearchSysCacheCopy1(OPEROID, ObjectIdGetDatum(negId));
773  else
774  tup = NULL;
775 
776  if (HeapTupleIsValid(tup))
777  {
779  bool update_negator = false;
780 
781  /*
782  * We can skip doing anything if the negator's oprnegate field is
783  * already what we want. While that's not expected in the isDelete
784  * case, it's perfectly possible when filling in a shell operator.
785  */
786  if (isDelete && OidIsValid(t->oprnegate))
787  {
788  t->oprnegate = InvalidOid;
789  update_negator = true;
790  }
791  else if (!isDelete && t->oprnegate != baseId)
792  {
793  /*
794  * If negator's oprnegate field is already set to point to some
795  * third operator, it's an error. Changing its link would be
796  * unsafe, and letting the inconsistency stand would not be good
797  * either. This might be indicative of catalog corruption, so
798  * don't assume t->oprnegate is necessarily a valid operator.
799  */
800  if (OidIsValid(t->oprnegate))
801  {
802  char *thirdop = get_opname(t->oprnegate);
803 
804  if (thirdop != NULL)
805  ereport(ERROR,
806  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
807  errmsg("negator operator %s is already the negator of operator %s",
808  NameStr(t->oprname), thirdop)));
809  else
810  ereport(ERROR,
811  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
812  errmsg("negator operator %s is already the negator of operator %u",
813  NameStr(t->oprname), t->oprnegate)));
814  }
815 
816  t->oprnegate = baseId;
817  update_negator = true;
818  }
819 
820  /* If any columns were found to need modification, update tuple. */
821  if (update_negator)
822  {
823  CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup);
824 
825  /*
826  * In the deletion case, do CCI to make the updated tuple visible.
827  * We must do this in case the operator is its own negator. (Which
828  * would be a logic error on the operator definer's part, but
829  * that's not a good reason to fail here.)
830  */
831  if (isDelete)
833  }
834  }
835 
836  /* Close relation and release catalog lock. */
837  table_close(pg_operator_desc, RowExclusiveLock);
838 }
#define NameStr(name)
Definition: c.h:746
char * get_opname(Oid opno)
Definition: lsyscache.c:1310
void CommandCounterIncrement(void)
Definition: xact.c:1097

References CatalogTupleUpdate(), CommandCounterIncrement(), ereport, errcode(), errmsg(), ERROR, get_opname(), GETSTRUCT, HeapTupleIsValid, InvalidOid, NameStr, ObjectIdGetDatum(), OidIsValid, RowExclusiveLock, SearchSysCacheCopy1, HeapTupleData::t_self, table_close(), and table_open().

Referenced by AlterOperator(), OperatorCreate(), and RemoveOperatorById().

◆ OperatorValidateParams()

void OperatorValidateParams ( Oid  leftTypeId,
Oid  rightTypeId,
Oid  operResultType,
bool  hasCommutator,
bool  hasNegator,
bool  hasRestrictionSelectivity,
bool  hasJoinSelectivity,
bool  canMerge,
bool  canHash 
)

Definition at line 556 of file pg_operator.c.

565 {
566  if (!(OidIsValid(leftTypeId) && OidIsValid(rightTypeId)))
567  {
568  /* If it's not a binary op, these things mustn't be set: */
569  if (hasCommutator)
570  ereport(ERROR,
571  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
572  errmsg("only binary operators can have commutators")));
573  if (hasJoinSelectivity)
574  ereport(ERROR,
575  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
576  errmsg("only binary operators can have join selectivity")));
577  if (canMerge)
578  ereport(ERROR,
579  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
580  errmsg("only binary operators can merge join")));
581  if (canHash)
582  ereport(ERROR,
583  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
584  errmsg("only binary operators can hash")));
585  }
586 
587  if (operResultType != BOOLOID)
588  {
589  /* If it's not a boolean op, these things mustn't be set: */
590  if (hasNegator)
591  ereport(ERROR,
592  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
593  errmsg("only boolean operators can have negators")));
594  if (hasRestrictionSelectivity)
595  ereport(ERROR,
596  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
597  errmsg("only boolean operators can have restriction selectivity")));
598  if (hasJoinSelectivity)
599  ereport(ERROR,
600  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
601  errmsg("only boolean operators can have join selectivity")));
602  if (canMerge)
603  ereport(ERROR,
604  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
605  errmsg("only boolean operators can merge join")));
606  if (canHash)
607  ereport(ERROR,
608  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
609  errmsg("only boolean operators can hash")));
610  }
611 }

References ereport, errcode(), errmsg(), ERROR, and OidIsValid.

Referenced by AlterOperator(), and OperatorCreate().

Variable Documentation

◆ FormData_pg_operator

FormData_pg_operator

Definition at line 76 of file pg_operator.h.