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, on pg_operator using btree(oid oid_ops))
 
 DECLARE_UNIQUE_INDEX (pg_operator_oprname_l_r_n_index, 2689, OperatorNameNspIndexId, on pg_operator using btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops))
 
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 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:633
#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:725

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  ,
on pg_operator using   btreeoprname 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  ,
on pg_operator using   btreeoid oid_ops 
)

◆ makeOperatorDependencies()

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

Definition at line 777 of file pg_operator.c.

780 {
782  ObjectAddress myself,
783  referenced;
784  ObjectAddresses *addrs;
785 
786  ObjectAddressSet(myself, OperatorRelationId, oper->oid);
787 
788  /*
789  * If we are updating the operator, delete any existing entries, except
790  * for extension membership which should remain the same.
791  */
792  if (isUpdate)
793  {
794  deleteDependencyRecordsFor(myself.classId, myself.objectId, true);
796  }
797 
798  addrs = new_object_addresses();
799 
800  /* Dependency on namespace */
801  if (OidIsValid(oper->oprnamespace))
802  {
803  ObjectAddressSet(referenced, NamespaceRelationId, oper->oprnamespace);
804  add_exact_object_address(&referenced, addrs);
805  }
806 
807  /* Dependency on left type */
808  if (OidIsValid(oper->oprleft))
809  {
810  ObjectAddressSet(referenced, TypeRelationId, oper->oprleft);
811  add_exact_object_address(&referenced, addrs);
812  }
813 
814  /* Dependency on right type */
815  if (OidIsValid(oper->oprright))
816  {
817  ObjectAddressSet(referenced, TypeRelationId, oper->oprright);
818  add_exact_object_address(&referenced, addrs);
819  }
820 
821  /* Dependency on result type */
822  if (OidIsValid(oper->oprresult))
823  {
824  ObjectAddressSet(referenced, TypeRelationId, oper->oprresult);
825  add_exact_object_address(&referenced, addrs);
826  }
827 
828  /*
829  * NOTE: we do not consider the operator to depend on the associated
830  * operators oprcom and oprnegate. We do not want to delete this operator
831  * if those go away, but only reset the link fields; which is not a
832  * function that the dependency logic can handle. (It's taken care of
833  * manually within RemoveOperatorById, instead.)
834  */
835 
836  /* Dependency on implementation function */
837  if (OidIsValid(oper->oprcode))
838  {
839  ObjectAddressSet(referenced, ProcedureRelationId, oper->oprcode);
840  add_exact_object_address(&referenced, addrs);
841  }
842 
843  /* Dependency on restriction selectivity function */
844  if (OidIsValid(oper->oprrest))
845  {
846  ObjectAddressSet(referenced, ProcedureRelationId, oper->oprrest);
847  add_exact_object_address(&referenced, addrs);
848  }
849 
850  /* Dependency on join selectivity function */
851  if (OidIsValid(oper->oprjoin))
852  {
853  ObjectAddressSet(referenced, ProcedureRelationId, oper->oprjoin);
854  add_exact_object_address(&referenced, addrs);
855  }
856 
858  free_object_addresses(addrs);
859 
860  /* Dependency on owner */
861  recordDependencyOnOwner(OperatorRelationId, oper->oid,
862  oper->oprowner);
863 
864  /* Dependency on extension */
865  if (makeExtensionDep)
866  recordDependencyOnCurrentExtension(&myself, isUpdate);
867 
868  return myself;
869 }
#define OidIsValid(objectId)
Definition: c.h:759
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2790
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2532
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2581
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2821
@ 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:382
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:1002
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:165

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 327 of file pg_operator.c.

338 {
339  Relation pg_operator_desc;
340  HeapTuple tup;
341  bool isUpdate;
342  bool nulls[Natts_pg_operator];
343  bool replaces[Natts_pg_operator];
344  Datum values[Natts_pg_operator];
345  Oid operatorObjectId;
346  bool operatorAlreadyDefined;
347  Oid operResultType;
348  Oid commutatorId,
349  negatorId;
350  bool selfCommutator = false;
351  NameData oname;
352  int i;
353  ObjectAddress address;
354 
355  /*
356  * Sanity checks
357  */
358  if (!validOperatorName(operatorName))
359  ereport(ERROR,
360  (errcode(ERRCODE_INVALID_NAME),
361  errmsg("\"%s\" is not a valid operator name",
362  operatorName)));
363 
364  if (!(OidIsValid(leftTypeId) && OidIsValid(rightTypeId)))
365  {
366  /* If it's not a binary op, these things mustn't be set: */
367  if (commutatorName)
368  ereport(ERROR,
369  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
370  errmsg("only binary operators can have commutators")));
371  if (OidIsValid(joinId))
372  ereport(ERROR,
373  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
374  errmsg("only binary operators can have join selectivity")));
375  if (canMerge)
376  ereport(ERROR,
377  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
378  errmsg("only binary operators can merge join")));
379  if (canHash)
380  ereport(ERROR,
381  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
382  errmsg("only binary operators can hash")));
383  }
384 
385  operResultType = get_func_rettype(procedureId);
386 
387  if (operResultType != BOOLOID)
388  {
389  /* If it's not a boolean op, these things mustn't be set: */
390  if (negatorName)
391  ereport(ERROR,
392  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
393  errmsg("only boolean operators can have negators")));
394  if (OidIsValid(restrictionId))
395  ereport(ERROR,
396  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
397  errmsg("only boolean operators can have restriction selectivity")));
398  if (OidIsValid(joinId))
399  ereport(ERROR,
400  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
401  errmsg("only boolean operators can have join selectivity")));
402  if (canMerge)
403  ereport(ERROR,
404  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
405  errmsg("only boolean operators can merge join")));
406  if (canHash)
407  ereport(ERROR,
408  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
409  errmsg("only boolean operators can hash")));
410  }
411 
412  operatorObjectId = OperatorGet(operatorName,
413  operatorNamespace,
414  leftTypeId,
415  rightTypeId,
416  &operatorAlreadyDefined);
417 
418  if (operatorAlreadyDefined)
419  ereport(ERROR,
420  (errcode(ERRCODE_DUPLICATE_FUNCTION),
421  errmsg("operator %s already exists",
422  operatorName)));
423 
424  /*
425  * At this point, if operatorObjectId is not InvalidOid then we are
426  * filling in a previously-created shell. Insist that the user own any
427  * such shell.
428  */
429  if (OidIsValid(operatorObjectId) &&
430  !object_ownercheck(OperatorRelationId, operatorObjectId, GetUserId()))
432  operatorName);
433 
434  /*
435  * Set up the other operators. If they do not currently exist, create
436  * shells in order to get ObjectId's.
437  */
438 
439  if (commutatorName)
440  {
441  /* commutator has reversed arg types */
442  commutatorId = get_other_operator(commutatorName,
443  rightTypeId, leftTypeId,
444  operatorName, operatorNamespace,
445  leftTypeId, rightTypeId,
446  true);
447 
448  /* Permission check: must own other operator */
449  if (OidIsValid(commutatorId) &&
450  !object_ownercheck(OperatorRelationId, commutatorId, GetUserId()))
452  NameListToString(commutatorName));
453 
454  /*
455  * self-linkage to this operator; will fix below. Note that only
456  * self-linkage for commutation makes sense.
457  */
458  if (!OidIsValid(commutatorId))
459  selfCommutator = true;
460  }
461  else
462  commutatorId = InvalidOid;
463 
464  if (negatorName)
465  {
466  /* negator has same arg types */
467  negatorId = get_other_operator(negatorName,
468  leftTypeId, rightTypeId,
469  operatorName, operatorNamespace,
470  leftTypeId, rightTypeId,
471  false);
472 
473  /* Permission check: must own other operator */
474  if (OidIsValid(negatorId) &&
475  !object_ownercheck(OperatorRelationId, negatorId, GetUserId()))
477  NameListToString(negatorName));
478  }
479  else
480  negatorId = InvalidOid;
481 
482  /*
483  * set up values in the operator tuple
484  */
485 
486  for (i = 0; i < Natts_pg_operator; ++i)
487  {
488  values[i] = (Datum) NULL;
489  replaces[i] = true;
490  nulls[i] = false;
491  }
492 
493  namestrcpy(&oname, operatorName);
494  values[Anum_pg_operator_oprname - 1] = NameGetDatum(&oname);
495  values[Anum_pg_operator_oprnamespace - 1] = ObjectIdGetDatum(operatorNamespace);
496  values[Anum_pg_operator_oprowner - 1] = ObjectIdGetDatum(GetUserId());
497  values[Anum_pg_operator_oprkind - 1] = CharGetDatum(leftTypeId ? 'b' : 'l');
498  values[Anum_pg_operator_oprcanmerge - 1] = BoolGetDatum(canMerge);
499  values[Anum_pg_operator_oprcanhash - 1] = BoolGetDatum(canHash);
500  values[Anum_pg_operator_oprleft - 1] = ObjectIdGetDatum(leftTypeId);
501  values[Anum_pg_operator_oprright - 1] = ObjectIdGetDatum(rightTypeId);
502  values[Anum_pg_operator_oprresult - 1] = ObjectIdGetDatum(operResultType);
503  values[Anum_pg_operator_oprcom - 1] = ObjectIdGetDatum(commutatorId);
504  values[Anum_pg_operator_oprnegate - 1] = ObjectIdGetDatum(negatorId);
505  values[Anum_pg_operator_oprcode - 1] = ObjectIdGetDatum(procedureId);
506  values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(restrictionId);
507  values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(joinId);
508 
509  pg_operator_desc = table_open(OperatorRelationId, RowExclusiveLock);
510 
511  /*
512  * If we are replacing an operator shell, update; else insert
513  */
514  if (operatorObjectId)
515  {
516  isUpdate = true;
517 
519  ObjectIdGetDatum(operatorObjectId));
520  if (!HeapTupleIsValid(tup))
521  elog(ERROR, "cache lookup failed for operator %u",
522  operatorObjectId);
523 
524  replaces[Anum_pg_operator_oid - 1] = false;
525  tup = heap_modify_tuple(tup,
526  RelationGetDescr(pg_operator_desc),
527  values,
528  nulls,
529  replaces);
530 
531  CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup);
532  }
533  else
534  {
535  isUpdate = false;
536 
537  operatorObjectId = GetNewOidWithIndex(pg_operator_desc,
538  OperatorOidIndexId,
539  Anum_pg_operator_oid);
540  values[Anum_pg_operator_oid - 1] = ObjectIdGetDatum(operatorObjectId);
541 
542  tup = heap_form_tuple(RelationGetDescr(pg_operator_desc),
543  values, nulls);
544 
545  CatalogTupleInsert(pg_operator_desc, tup);
546  }
547 
548  /* Add dependencies for the entry */
549  address = makeOperatorDependencies(tup, true, isUpdate);
550 
551  /* Post creation hook for new operator */
552  InvokeObjectPostCreateHook(OperatorRelationId, operatorObjectId, 0);
553 
554  table_close(pg_operator_desc, RowExclusiveLock);
555 
556  /*
557  * If a commutator and/or negator link is provided, update the other
558  * operator(s) to point at this one, if they don't already have a link.
559  * This supports an alternative style of operator definition wherein the
560  * user first defines one operator without giving negator or commutator,
561  * then defines the other operator of the pair with the proper commutator
562  * or negator attribute. That style doesn't require creation of a shell,
563  * and it's the only style that worked right before Postgres version 6.5.
564  * This code also takes care of the situation where the new operator is
565  * its own commutator.
566  */
567  if (selfCommutator)
568  commutatorId = operatorObjectId;
569 
570  if (OidIsValid(commutatorId) || OidIsValid(negatorId))
571  OperatorUpd(operatorObjectId, commutatorId, negatorId, false);
572 
573  return address;
574 }
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2673
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:3976
static Datum values[MAXATTR]
Definition: bootstrap.c:156
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:393
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#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:1637
Oid GetUserId(void)
Definition: miscinit.c:510
void namestrcpy(Name name, const char *str)
Definition: name.c:233
char * NameListToString(List *names)
Definition: namespace.c:3145
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:173
@ OBJECT_OPERATOR
Definition: parsenodes.h:2107
static Oid OperatorGet(const char *operatorName, Oid operatorNamespace, Oid leftObjectId, Oid rightObjectId, bool *defined)
Definition: pg_operator.c:130
static bool validOperatorName(const char *name)
Definition: pg_operator.c:74
static Oid get_other_operator(List *otherOp, Oid otherLeftTypeId, Oid otherRightTypeId, const char *operatorName, Oid operatorNamespace, Oid leftTypeId, Oid rightTypeId, bool isCommutator)
Definition: pg_operator.c:585
ObjectAddress makeOperatorDependencies(HeapTuple tuple, bool makeExtensionDep, bool isUpdate)
Definition: pg_operator.c:777
void OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete)
Definition: pg_operator.c:654
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:530
ItemPointerData t_self
Definition: htup.h:65
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:182
@ OPEROID
Definition: syscache.h:72
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(), OBJECT_OPERATOR, object_ownercheck(), ObjectIdGetDatum(), OidIsValid, OperatorGet(), OperatorUpd(), OPEROID, RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy1, HeapTupleData::t_self, table_close(), table_open(), validOperatorName(), and values.

Referenced by DefineOperator().

◆ OperatorUpd()

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

Definition at line 654 of file pg_operator.c.

655 {
656  Relation pg_operator_desc;
657  HeapTuple tup;
658 
659  /*
660  * If we're making an operator into its own commutator, then we need a
661  * command-counter increment here, since we've just inserted the tuple
662  * we're about to update. But when we're dropping an operator, we can
663  * skip this because we're at the beginning of the command.
664  */
665  if (!isDelete)
667 
668  /* Open the relation. */
669  pg_operator_desc = table_open(OperatorRelationId, RowExclusiveLock);
670 
671  /* Get a writable copy of the commutator's tuple. */
672  if (OidIsValid(commId))
674  else
675  tup = NULL;
676 
677  /* Update the commutator's tuple if need be. */
678  if (HeapTupleIsValid(tup))
679  {
681  bool update_commutator = false;
682 
683  /*
684  * Out of due caution, we only change the commutator's oprcom field if
685  * it has the exact value we expected: InvalidOid when creating an
686  * operator, or baseId when dropping one.
687  */
688  if (isDelete && t->oprcom == baseId)
689  {
690  t->oprcom = InvalidOid;
691  update_commutator = true;
692  }
693  else if (!isDelete && !OidIsValid(t->oprcom))
694  {
695  t->oprcom = baseId;
696  update_commutator = true;
697  }
698 
699  /* If any columns were found to need modification, update tuple. */
700  if (update_commutator)
701  {
702  CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup);
703 
704  /*
705  * Do CCI to make the updated tuple visible. We must do this in
706  * case the commutator is also the negator. (Which would be a
707  * logic error on the operator definer's part, but that's not a
708  * good reason to fail here.) We would need a CCI anyway in the
709  * deletion case for a self-commutator with no negator.
710  */
712  }
713  }
714 
715  /*
716  * Similarly find and update the negator, if any.
717  */
718  if (OidIsValid(negId))
720  else
721  tup = NULL;
722 
723  if (HeapTupleIsValid(tup))
724  {
726  bool update_negator = false;
727 
728  /*
729  * Out of due caution, we only change the negator's oprnegate field if
730  * it has the exact value we expected: InvalidOid when creating an
731  * operator, or baseId when dropping one.
732  */
733  if (isDelete && t->oprnegate == baseId)
734  {
735  t->oprnegate = InvalidOid;
736  update_negator = true;
737  }
738  else if (!isDelete && !OidIsValid(t->oprnegate))
739  {
740  t->oprnegate = baseId;
741  update_negator = true;
742  }
743 
744  /* If any columns were found to need modification, update tuple. */
745  if (update_negator)
746  {
747  CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup);
748 
749  /*
750  * In the deletion case, do CCI to make the updated tuple visible.
751  * We must do this in case the operator is its own negator. (Which
752  * would be a logic error on the operator definer's part, but
753  * that's not a good reason to fail here.)
754  */
755  if (isDelete)
757  }
758  }
759 
760  /* Close relation and release catalog lock. */
761  table_close(pg_operator_desc, RowExclusiveLock);
762 }
void CommandCounterIncrement(void)
Definition: xact.c:1078

References CatalogTupleUpdate(), CommandCounterIncrement(), GETSTRUCT, HeapTupleIsValid, InvalidOid, ObjectIdGetDatum(), OidIsValid, OPEROID, RowExclusiveLock, SearchSysCacheCopy1, HeapTupleData::t_self, table_close(), and table_open().

Referenced by OperatorCreate(), and RemoveOperatorById().

Variable Documentation

◆ FormData_pg_operator

FormData_pg_operator

Definition at line 76 of file pg_operator.h.