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:606
#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:69
FormData_pg_operator
Definition: pg_operator.h:76
unsigned int Oid
Definition: postgres_ext.h:32
Definition: c.h:698

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
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:732
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2757
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2548
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2502
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2788
@ DEPENDENCY_NORMAL
Definition: dependency.h:33
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
#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: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)
Definition: pg_shdepend.c:1047
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:168

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))
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)
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)
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:2622
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4058
static Datum values[MAXATTR]
Definition: bootstrap.c:151
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:419
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#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: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, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233
int i
Definition: isn.c:72
#define RowExclusiveLock
Definition: lockdefs.h:38
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1682
Oid GetUserId(void)
Definition: miscinit.c:517
void namestrcpy(Name name, const char *str)
Definition: name.c:233
char * NameListToString(const List *names)
Definition: namespace.c:3594
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:173
@ OBJECT_OPERATOR
Definition: parsenodes.h:2337
#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:69
static Datum BoolGetDatum(bool X)
Definition: postgres.h:107
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
static Datum NameGetDatum(const NameData *X)
Definition: postgres.h:378
static Datum CharGetDatum(char X)
Definition: postgres.h:127
#define InvalidOid
Definition: postgres_ext.h:37
#define RelationGetDescr(relation)
Definition: rel.h:538
ItemPointerData t_self
Definition: htup.h:65
#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, 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:734
regproc RegProcedure
Definition: c.h:607
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1312
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)
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
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)
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
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:703
char * get_opname(Oid opno)
Definition: lsyscache.c:1337
void CommandCounterIncrement(void)
Definition: xact.c:1099

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)
571 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
572 errmsg("only binary operators can have commutators")));
573 if (hasJoinSelectivity)
575 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
576 errmsg("only binary operators can have join selectivity")));
577 if (canMerge)
579 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
580 errmsg("only binary operators can merge join")));
581 if (canHash)
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)
592 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
593 errmsg("only boolean operators can have negators")));
594 if (hasRestrictionSelectivity)
596 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
597 errmsg("only boolean operators can have restriction selectivity")));
598 if (hasJoinSelectivity)
600 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
601 errmsg("only boolean operators can have join selectivity")));
602 if (canMerge)
604 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
605 errmsg("only boolean operators can merge join")));
606 if (canHash)
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.