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

References BKI_DEFAULT, and BKI_LOOKUP.

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(PGNSP);
40 
41  /* operator owner */
42  Oid oprowner BKI_DEFAULT(PGUID);
43 
44  /* 'l', 'r', or 'b' */
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 'l' oprkind */
54  Oid oprleft BKI_LOOKUP(pg_type);
55 
56  /* right arg type, or 0 if 'r' oprkind */
57  Oid oprright BKI_LOOKUP(pg_type);
58 
59  /* result datatype */
60  Oid oprresult BKI_LOOKUP(pg_type);
61 
62  /* OID of commutator oper, or 0 if none */
63  Oid oprcom BKI_DEFAULT(0) BKI_LOOKUP(pg_operator);
64 
65  /* OID of negator oper, or 0 if none */
66  Oid oprnegate BKI_DEFAULT(0) BKI_LOOKUP(pg_operator);
67 
68  /* OID of underlying function */
69  regproc oprcode BKI_LOOKUP(pg_proc);
70 
71  /* OID of restriction estimator, or 0 */
72  regproc oprrest BKI_DEFAULT(-) BKI_LOOKUP(pg_proc);
73 
74  /* OID of join estimator, or 0 */
75  regproc oprjoin BKI_DEFAULT(-) BKI_LOOKUP(pg_proc);
unsigned int Oid
Definition: postgres_ext.h:31
#define BKI_DEFAULT(value)
Definition: genbki.h:35
FormData_pg_operator
Definition: pg_operator.h:76
Definition: c.h:610
#define BKI_LOOKUP(catalog)
Definition: genbki.h:42
Oid regproc
Definition: c.h:511

◆ makeOperatorDependencies()

ObjectAddress makeOperatorDependencies ( HeapTuple  tuple,
bool  isUpdate 
)

Definition at line 773 of file pg_operator.c.

References ObjectAddress::classId, deleteDependencyRecordsFor(), deleteSharedDependencyRecordsFor(), DEPENDENCY_NORMAL, GETSTRUCT, ObjectAddress::objectId, ObjectAddress::objectSubId, OidIsValid, oper(), recordDependencyOn(), recordDependencyOnCurrentExtension(), and recordDependencyOnOwner().

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

774 {
776  ObjectAddress myself,
777  referenced;
778 
779  myself.classId = OperatorRelationId;
780  myself.objectId = oper->oid;
781  myself.objectSubId = 0;
782 
783  /*
784  * If we are updating the operator, delete any existing entries, except
785  * for extension membership which should remain the same.
786  */
787  if (isUpdate)
788  {
789  deleteDependencyRecordsFor(myself.classId, myself.objectId, true);
791  }
792 
793  /* Dependency on namespace */
794  if (OidIsValid(oper->oprnamespace))
795  {
796  referenced.classId = NamespaceRelationId;
797  referenced.objectId = oper->oprnamespace;
798  referenced.objectSubId = 0;
799  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
800  }
801 
802  /* Dependency on left type */
803  if (OidIsValid(oper->oprleft))
804  {
805  referenced.classId = TypeRelationId;
806  referenced.objectId = oper->oprleft;
807  referenced.objectSubId = 0;
808  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
809  }
810 
811  /* Dependency on right type */
812  if (OidIsValid(oper->oprright))
813  {
814  referenced.classId = TypeRelationId;
815  referenced.objectId = oper->oprright;
816  referenced.objectSubId = 0;
817  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
818  }
819 
820  /* Dependency on result type */
821  if (OidIsValid(oper->oprresult))
822  {
823  referenced.classId = TypeRelationId;
824  referenced.objectId = oper->oprresult;
825  referenced.objectSubId = 0;
826  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
827  }
828 
829  /*
830  * NOTE: we do not consider the operator to depend on the associated
831  * operators oprcom and oprnegate. We would not want to delete this
832  * operator if those go away, but only reset the link fields; which is not
833  * a function that the dependency code can presently handle. (Something
834  * could perhaps be done with objectSubId though.) For now, it's okay to
835  * let those links dangle if a referenced operator is removed.
836  */
837 
838  /* Dependency on implementation function */
839  if (OidIsValid(oper->oprcode))
840  {
841  referenced.classId = ProcedureRelationId;
842  referenced.objectId = oper->oprcode;
843  referenced.objectSubId = 0;
844  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
845  }
846 
847  /* Dependency on restriction selectivity function */
848  if (OidIsValid(oper->oprrest))
849  {
850  referenced.classId = ProcedureRelationId;
851  referenced.objectId = oper->oprrest;
852  referenced.objectSubId = 0;
853  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
854  }
855 
856  /* Dependency on join selectivity function */
857  if (OidIsValid(oper->oprjoin))
858  {
859  referenced.classId = ProcedureRelationId;
860  referenced.objectId = oper->oprjoin;
861  referenced.objectSubId = 0;
862  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
863  }
864 
865  /* Dependency on owner */
866  recordDependencyOnOwner(OperatorRelationId, oper->oid,
867  oper->oprowner);
868 
869  /* Dependency on extension */
870  recordDependencyOnCurrentExtension(&myself, true);
871 
872  return myself;
873 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:190
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:164
#define OidIsValid(objectId)
Definition: c.h:645
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:907
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:138
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:83
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition: parse_oper.c:377

◆ 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.

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, ObjectIdGetDatum, OidIsValid, OperatorGet(), OperatorOidIndexId, OperatorUpd(), OPEROID, pg_oper_ownercheck(), RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy1, HeapTupleData::t_self, table_close(), table_open(), validOperatorName(), and values.

Referenced by DefineOperator().

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  !pg_oper_ownercheck(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  !pg_oper_ownercheck(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  !pg_oper_ownercheck(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 ? (rightTypeId ? 'b' : 'r') : '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,
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, 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 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:322
#define NameGetDatum(X)
Definition: postgres.h:595
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
#define RelationGetDescr(relation)
Definition: rel.h:448
Oid GetUserId(void)
Definition: miscinit.c:380
ObjectAddress makeOperatorDependencies(HeapTuple tuple, bool isUpdate)
Definition: pg_operator.c:773
static Oid OperatorGet(const char *operatorName, Oid operatorNamespace, Oid leftObjectId, Oid rightObjectId, bool *defined)
Definition: pg_operator.c:130
bool pg_oper_ownercheck(Oid oper_oid, Oid roleid)
Definition: aclchk.c:4805
int errcode(int sqlerrcode)
Definition: elog.c:608
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
unsigned int Oid
Definition: postgres_ext.h:31
int namestrcpy(Name name, const char *str)
Definition: name.c:250
#define OidIsValid(objectId)
Definition: c.h:645
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
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1457
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
Definition: c.h:610
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:141
char * NameListToString(List *names)
Definition: namespace.c:3094
#define OperatorOidIndexId
Definition: indexing.h:200
uintptr_t Datum
Definition: postgres.h:367
#define BoolGetDatum(X)
Definition: postgres.h:402
#define InvalidOid
Definition: postgres_ext.h:36
void OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete)
Definition: pg_operator.c:654
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
#define CharGetDatum(X)
Definition: postgres.h:416
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
int i
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183
static bool validOperatorName(const char *name)
Definition: pg_operator.c:74

◆ OperatorUpd()

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

Definition at line 654 of file pg_operator.c.

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

Referenced by OperatorCreate(), and RemoveOperatorById().

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 table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define OidIsValid(objectId)
Definition: c.h:645
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
void CommandCounterIncrement(void)
Definition: xact.c:1005
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:83
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

Variable Documentation

◆ FormData_pg_operator

FormData_pg_operator

Definition at line 76 of file pg_operator.h.