PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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

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 */
40
41 /* operator owner */
43
44 /* 'l' for prefix or 'b' for infix */
45 char oprkind BKI_DEFAULT(b);
46
47 /* can be used in merge join? */
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 */
61
62 /* OID of commutator oper, or 0 if none */
64
65 /* OID of negator oper, or 0 if none */
67
68 /* OID of underlying function; can be 0 in a "shell" operator */
70
71 /* OID of restriction estimator, or 0 */
73
74 /* OID of join estimator, or 0 */
Oid regproc
Definition c.h:663
#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:74
FormData_pg_operator
Definition pg_operator.h:76
unsigned int Oid
static int fb(int x)
Definition c.h:760

References b, BKI_DEFAULT, BKI_LOOKUP, BKI_LOOKUP_OPT, and fb().

◆ 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 
)
extern

Definition at line 853 of file pg_operator.c.

856{
860 ObjectAddresses *addrs;
861
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);
871 deleteSharedDependencyRecordsFor(myself.classId, myself.objectId, 0);
872 }
873
874 addrs = new_object_addresses();
875
876 /* Dependency on namespace */
877 if (OidIsValid(oper->oprnamespace))
878 {
881 }
882
883 /* Dependency on left type */
884 if (OidIsValid(oper->oprleft))
885 {
888 }
889
890 /* Dependency on right type */
891 if (OidIsValid(oper->oprright))
892 {
895 }
896
897 /* Dependency on result type */
898 if (OidIsValid(oper->oprresult))
899 {
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 {
917 }
918
919 /* Dependency on restriction selectivity function */
920 if (OidIsValid(oper->oprrest))
921 {
924 }
925
926 /* Dependency on join selectivity function */
927 if (OidIsValid(oper->oprjoin))
928 {
931 }
932
935
936 /* Dependency on owner */
938 oper->oprowner);
939
940 /* Dependency on extension */
943
944 return myself;
945}
#define OidIsValid(objectId)
Definition c.h:788
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
ObjectAddresses * new_object_addresses(void)
void free_object_addresses(ObjectAddresses *addrs)
@ DEPENDENCY_NORMAL
Definition dependency.h:33
static void * GETSTRUCT(const HeapTupleData *tuple)
#define ObjectAddressSet(addr, class_id, object_id)
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition parse_oper.c:371
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition pg_depend.c:301
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition pg_depend.c:193
FormData_pg_operator * Form_pg_operator
Definition pg_operator.h:83
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)

References add_exact_object_address(), deleteDependencyRecordsFor(), deleteSharedDependencyRecordsFor(), DEPENDENCY_NORMAL, fb(), free_object_addresses(), GETSTRUCT(), new_object_addresses(), ObjectAddressSet, 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 
)
extern

Definition at line 321 of file pg_operator.c.

332{
335 bool isUpdate;
336 bool nulls[Natts_pg_operator];
343 negatorId;
344 bool selfCommutator = false;
346 int i;
347 ObjectAddress address;
348
349 /*
350 * Sanity checks
351 */
355 errmsg("\"%s\" is not a valid operator name",
356 operatorName)));
357
359
364 negatorName != NIL,
367 canMerge,
368 canHash);
369
375
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 */
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 */
404
405 /* Permission check: must own other operator */
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 */
417 selfCommutator = true;
418 }
419 else
421
422 if (negatorName)
423 {
424 /* negator has same arg types */
429
430 /* Permission check: must own other operator */
431 if (OidIsValid(negatorId) &&
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 */
445 errmsg("operator cannot be its own negator")));
446 }
447 else
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) 0;
457 replaces[i] = true;
458 nulls[i] = false;
459 }
460
476
478
479 /*
480 * If we are replacing an operator shell, update; else insert
481 */
483 {
484 isUpdate = true;
485
488 if (!HeapTupleIsValid(tup))
489 elog(ERROR, "cache lookup failed for operator %u",
491
492 replaces[Anum_pg_operator_oid - 1] = false;
495 values,
496 nulls,
497 replaces);
498
500 }
501 else
502 {
503 isUpdate = false;
504
509
511 values, nulls);
512
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)
532
535
536 /* Post creation hook for new operator */
538
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:2654
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition aclchk.c:4090
static Datum values[MAXATTR]
Definition bootstrap.c:155
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition catalog.c:448
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition heaptuple.c:1210
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1117
#define HeapTupleIsValid(tuple)
Definition htup.h:78
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
Definition indexing.c:313
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition indexing.c:233
int i
Definition isn.c:77
#define RowExclusiveLock
Definition lockdefs.h:38
Oid get_func_rettype(Oid funcid)
Definition lsyscache.c:1805
Oid GetUserId(void)
Definition miscinit.c:469
void namestrcpy(Name name, const char *str)
Definition name.c:233
char * NameListToString(const List *names)
Definition namespace.c:3664
#define InvokeObjectPostCreateHook(classId, objectId, subId)
@ OBJECT_OPERATOR
#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)
static Oid OperatorGet(const char *operatorName, Oid operatorNamespace, Oid leftObjectId, Oid rightObjectId, bool *defined)
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)
ObjectAddress makeOperatorDependencies(HeapTuple tuple, bool makeExtensionDep, bool isUpdate)
void OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete)
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:262
static Datum NameGetDatum(const NameData *X)
Definition postgres.h:403
uint64_t Datum
Definition postgres.h:70
static Datum CharGetDatum(char X)
Definition postgres.h:132
#define InvalidOid
#define RelationGetDescr(relation)
Definition rel.h:540
#define SearchSysCacheCopy1(cacheId, key1)
Definition syscache.h:91
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, fb(), 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, table_close(), table_open(), validOperatorName(), and values.

Referenced by DefineOperator().

◆ OperatorLookup()

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

Definition at line 164 of file pg_operator.c.

168{
170 RegProcedure oprcode;
171
174 true, -1);
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:792
regproc RegProcedure
Definition c.h:664
RegProcedure get_opcode(Oid opno)
Definition lsyscache.c:1435
Oid LookupOperName(ParseState *pstate, List *opername, Oid oprleft, Oid oprright, bool noError, int location)
Definition parse_oper.c:100

References fb(), 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 
)
extern

Definition at line 684 of file pg_operator.c.

685{
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. */
700
701 /* Get a writable copy of the commutator's tuple. */
702 if (OidIsValid(commId))
704 else
705 tup = NULL;
706
707 /* Update the commutator's tuple if need be. */
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)
739 errmsg("commutator operator %s is already the commutator of operator %s",
740 NameStr(t->oprname), thirdop)));
741 else
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. */
754 {
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))
773 else
774 tup = NULL;
775
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)
807 errmsg("negator operator %s is already the negator of operator %s",
808 NameStr(t->oprname), thirdop)));
809 else
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 {
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. */
838}
#define NameStr(name)
Definition c.h:765
char * get_opname(Oid opno)
Definition lsyscache.c:1460
void CommandCounterIncrement(void)
Definition xact.c:1101

References CatalogTupleUpdate(), CommandCounterIncrement(), ereport, errcode(), errmsg(), ERROR, fb(), get_opname(), GETSTRUCT(), HeapTupleIsValid, InvalidOid, NameStr, ObjectIdGetDatum(), OidIsValid, RowExclusiveLock, SearchSysCacheCopy1, 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 
)
extern

Definition at line 556 of file pg_operator.c.

565{
567 {
568 /* If it's not a binary op, these things mustn't be set: */
569 if (hasCommutator)
572 errmsg("only binary operators can have commutators")));
576 errmsg("only binary operators can have join selectivity")));
577 if (canMerge)
580 errmsg("only binary operators can merge join")));
581 if (canHash)
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)
593 errmsg("only boolean operators can have negators")));
597 errmsg("only boolean operators can have restriction selectivity")));
601 errmsg("only boolean operators can have join selectivity")));
602 if (canMerge)
605 errmsg("only boolean operators can merge join")));
606 if (canHash)
609 errmsg("only boolean operators can hash")));
610 }
611}

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

Referenced by AlterOperator(), and OperatorCreate().

Variable Documentation

◆ FormData_pg_operator

FormData_pg_operator

Definition at line 76 of file pg_operator.h.