Define __EXTENSIONS__ on Solaris, too.
[pgsql.git] / src / backend / catalog / pg_operator.c
blob65b45a424a276b5c17b588cb891204ae013458ec
1 /*-------------------------------------------------------------------------
3 * pg_operator.c
4 * routines to support manipulation of the pg_operator relation
6 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * IDENTIFICATION
11 * src/backend/catalog/pg_operator.c
13 * NOTES
14 * these routines moved here from commands/define.c and somewhat cleaned up.
16 *-------------------------------------------------------------------------
18 #include "postgres.h"
20 #include "access/htup_details.h"
21 #include "access/table.h"
22 #include "access/xact.h"
23 #include "catalog/catalog.h"
24 #include "catalog/dependency.h"
25 #include "catalog/indexing.h"
26 #include "catalog/namespace.h"
27 #include "catalog/objectaccess.h"
28 #include "catalog/pg_namespace.h"
29 #include "catalog/pg_operator.h"
30 #include "catalog/pg_proc.h"
31 #include "catalog/pg_type.h"
32 #include "miscadmin.h"
33 #include "parser/parse_oper.h"
34 #include "utils/acl.h"
35 #include "utils/builtins.h"
36 #include "utils/lsyscache.h"
37 #include "utils/rel.h"
38 #include "utils/syscache.h"
41 static Oid OperatorGet(const char *operatorName,
42 Oid operatorNamespace,
43 Oid leftObjectId,
44 Oid rightObjectId,
45 bool *defined);
47 static Oid OperatorShellMake(const char *operatorName,
48 Oid operatorNamespace,
49 Oid leftTypeId,
50 Oid rightTypeId);
52 static Oid get_other_operator(List *otherOp,
53 Oid otherLeftTypeId, Oid otherRightTypeId,
54 const char *operatorName, Oid operatorNamespace,
55 Oid leftTypeId, Oid rightTypeId);
59 * Check whether a proposed operator name is legal
61 * This had better match the behavior of parser/scan.l!
63 * We need this because the parser is not smart enough to check that
64 * the arguments of CREATE OPERATOR's COMMUTATOR, NEGATOR, etc clauses
65 * are operator names rather than some other lexical entity.
67 static bool
68 validOperatorName(const char *name)
70 size_t len = strlen(name);
72 /* Can't be empty or too long */
73 if (len == 0 || len >= NAMEDATALEN)
74 return false;
76 /* Can't contain any invalid characters */
77 /* Test string here should match op_chars in scan.l */
78 if (strspn(name, "~!@#^&|`?+-*/%<>=") != len)
79 return false;
81 /* Can't contain slash-star or dash-dash (comment starts) */
82 if (strstr(name, "/*") || strstr(name, "--"))
83 return false;
86 * For SQL standard compatibility, '+' and '-' cannot be the last char of
87 * a multi-char operator unless the operator contains chars that are not
88 * in SQL operators. The idea is to lex '=-' as two operators, but not to
89 * forbid operator names like '?-' that could not be sequences of standard
90 * SQL operators.
92 if (len > 1 &&
93 (name[len - 1] == '+' ||
94 name[len - 1] == '-'))
96 int ic;
98 for (ic = len - 2; ic >= 0; ic--)
100 if (strchr("~!@#^&|`?%", name[ic]))
101 break;
103 if (ic < 0)
104 return false; /* nope, not valid */
107 /* != isn't valid either, because parser will convert it to <> */
108 if (strcmp(name, "!=") == 0)
109 return false;
111 return true;
116 * OperatorGet
118 * finds an operator given an exact specification (name, namespace,
119 * left and right type IDs).
121 * *defined is set true if defined (not a shell)
123 static Oid
124 OperatorGet(const char *operatorName,
125 Oid operatorNamespace,
126 Oid leftObjectId,
127 Oid rightObjectId,
128 bool *defined)
130 HeapTuple tup;
131 Oid operatorObjectId;
133 tup = SearchSysCache4(OPERNAMENSP,
134 PointerGetDatum(operatorName),
135 ObjectIdGetDatum(leftObjectId),
136 ObjectIdGetDatum(rightObjectId),
137 ObjectIdGetDatum(operatorNamespace));
138 if (HeapTupleIsValid(tup))
140 Form_pg_operator oprform = (Form_pg_operator) GETSTRUCT(tup);
142 operatorObjectId = oprform->oid;
143 *defined = RegProcedureIsValid(oprform->oprcode);
144 ReleaseSysCache(tup);
146 else
148 operatorObjectId = InvalidOid;
149 *defined = false;
152 return operatorObjectId;
156 * OperatorLookup
158 * looks up an operator given a possibly-qualified name and
159 * left and right type IDs.
161 * *defined is set true if defined (not a shell)
164 OperatorLookup(List *operatorName,
165 Oid leftObjectId,
166 Oid rightObjectId,
167 bool *defined)
169 Oid operatorObjectId;
170 RegProcedure oprcode;
172 operatorObjectId = LookupOperName(NULL, operatorName,
173 leftObjectId, rightObjectId,
174 true, -1);
175 if (!OidIsValid(operatorObjectId))
177 *defined = false;
178 return InvalidOid;
181 oprcode = get_opcode(operatorObjectId);
182 *defined = RegProcedureIsValid(oprcode);
184 return operatorObjectId;
189 * OperatorShellMake
190 * Make a "shell" entry for a not-yet-existing operator.
192 static Oid
193 OperatorShellMake(const char *operatorName,
194 Oid operatorNamespace,
195 Oid leftTypeId,
196 Oid rightTypeId)
198 Relation pg_operator_desc;
199 Oid operatorObjectId;
200 int i;
201 HeapTuple tup;
202 Datum values[Natts_pg_operator];
203 bool nulls[Natts_pg_operator];
204 NameData oname;
205 TupleDesc tupDesc;
208 * validate operator name
210 if (!validOperatorName(operatorName))
211 ereport(ERROR,
212 (errcode(ERRCODE_INVALID_NAME),
213 errmsg("\"%s\" is not a valid operator name",
214 operatorName)));
217 * open pg_operator
219 pg_operator_desc = table_open(OperatorRelationId, RowExclusiveLock);
220 tupDesc = pg_operator_desc->rd_att;
223 * initialize our *nulls and *values arrays
225 for (i = 0; i < Natts_pg_operator; ++i)
227 nulls[i] = false;
228 values[i] = (Datum) NULL; /* redundant, but safe */
232 * initialize values[] with the operator name and input data types. Note
233 * that oprcode is set to InvalidOid, indicating it's a shell.
235 operatorObjectId = GetNewOidWithIndex(pg_operator_desc, OperatorOidIndexId,
236 Anum_pg_operator_oid);
237 values[Anum_pg_operator_oid - 1] = ObjectIdGetDatum(operatorObjectId);
238 namestrcpy(&oname, operatorName);
239 values[Anum_pg_operator_oprname - 1] = NameGetDatum(&oname);
240 values[Anum_pg_operator_oprnamespace - 1] = ObjectIdGetDatum(operatorNamespace);
241 values[Anum_pg_operator_oprowner - 1] = ObjectIdGetDatum(GetUserId());
242 values[Anum_pg_operator_oprkind - 1] = CharGetDatum(leftTypeId ? 'b' : 'l');
243 values[Anum_pg_operator_oprcanmerge - 1] = BoolGetDatum(false);
244 values[Anum_pg_operator_oprcanhash - 1] = BoolGetDatum(false);
245 values[Anum_pg_operator_oprleft - 1] = ObjectIdGetDatum(leftTypeId);
246 values[Anum_pg_operator_oprright - 1] = ObjectIdGetDatum(rightTypeId);
247 values[Anum_pg_operator_oprresult - 1] = ObjectIdGetDatum(InvalidOid);
248 values[Anum_pg_operator_oprcom - 1] = ObjectIdGetDatum(InvalidOid);
249 values[Anum_pg_operator_oprnegate - 1] = ObjectIdGetDatum(InvalidOid);
250 values[Anum_pg_operator_oprcode - 1] = ObjectIdGetDatum(InvalidOid);
251 values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(InvalidOid);
252 values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(InvalidOid);
255 * create a new operator tuple
257 tup = heap_form_tuple(tupDesc, values, nulls);
260 * insert our "shell" operator tuple
262 CatalogTupleInsert(pg_operator_desc, tup);
264 /* Add dependencies for the entry */
265 makeOperatorDependencies(tup, true, false);
267 heap_freetuple(tup);
269 /* Post creation hook for new shell operator */
270 InvokeObjectPostCreateHook(OperatorRelationId, operatorObjectId, 0);
273 * Make sure the tuple is visible for subsequent lookups/updates.
275 CommandCounterIncrement();
278 * close the operator relation and return the oid.
280 table_close(pg_operator_desc, RowExclusiveLock);
282 return operatorObjectId;
286 * OperatorCreate
288 * "X" indicates an optional argument (i.e. one that can be NULL or 0)
289 * operatorName name for new operator
290 * operatorNamespace namespace for new operator
291 * leftTypeId X left type ID
292 * rightTypeId X right type ID
293 * procedureId procedure ID for operator
294 * commutatorName X commutator operator
295 * negatorName X negator operator
296 * restrictionId X restriction selectivity procedure ID
297 * joinId X join selectivity procedure ID
298 * canMerge merge join can be used with this operator
299 * canHash hash join can be used with this operator
301 * The caller should have validated properties and permissions for the
302 * objects passed as OID references. We must handle the commutator and
303 * negator operator references specially, however, since those need not
304 * exist beforehand.
306 * This routine gets complicated because it allows the user to
307 * specify operators that do not exist. For example, if operator
308 * "op" is being defined, the negator operator "negop" and the
309 * commutator "commop" can also be defined without specifying
310 * any information other than their names. Since in order to
311 * add "op" to the PG_OPERATOR catalog, all the Oid's for these
312 * operators must be placed in the fields of "op", a forward
313 * declaration is done on the commutator and negator operators.
314 * This is called creating a shell, and its main effect is to
315 * create a tuple in the PG_OPERATOR catalog with minimal
316 * information about the operator (just its name and types).
317 * Forward declaration is used only for this purpose, it is
318 * not available to the user as it is for type definition.
320 ObjectAddress
321 OperatorCreate(const char *operatorName,
322 Oid operatorNamespace,
323 Oid leftTypeId,
324 Oid rightTypeId,
325 Oid procedureId,
326 List *commutatorName,
327 List *negatorName,
328 Oid restrictionId,
329 Oid joinId,
330 bool canMerge,
331 bool canHash)
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;
350 * Sanity checks
352 if (!validOperatorName(operatorName))
353 ereport(ERROR,
354 (errcode(ERRCODE_INVALID_NAME),
355 errmsg("\"%s\" is not a valid operator name",
356 operatorName)));
358 operResultType = get_func_rettype(procedureId);
360 OperatorValidateParams(leftTypeId,
361 rightTypeId,
362 operResultType,
363 commutatorName != NIL,
364 negatorName != NIL,
365 OidIsValid(restrictionId),
366 OidIsValid(joinId),
367 canMerge,
368 canHash);
370 operatorObjectId = OperatorGet(operatorName,
371 operatorNamespace,
372 leftTypeId,
373 rightTypeId,
374 &operatorAlreadyDefined);
376 if (operatorAlreadyDefined)
377 ereport(ERROR,
378 (errcode(ERRCODE_DUPLICATE_FUNCTION),
379 errmsg("operator %s already exists",
380 operatorName)));
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.
387 if (OidIsValid(operatorObjectId) &&
388 !object_ownercheck(OperatorRelationId, operatorObjectId, GetUserId()))
389 aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_OPERATOR,
390 operatorName);
393 * Set up the other operators. If they do not currently exist, create
394 * shells in order to get ObjectId's.
397 if (commutatorName)
399 /* commutator has reversed arg types */
400 commutatorId = get_other_operator(commutatorName,
401 rightTypeId, leftTypeId,
402 operatorName, operatorNamespace,
403 leftTypeId, rightTypeId);
405 /* Permission check: must own other operator */
406 if (OidIsValid(commutatorId) &&
407 !object_ownercheck(OperatorRelationId, commutatorId, GetUserId()))
408 aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_OPERATOR,
409 NameListToString(commutatorName));
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.)
416 if (!OidIsValid(commutatorId))
417 selfCommutator = true;
419 else
420 commutatorId = InvalidOid;
422 if (negatorName)
424 /* negator has same arg types */
425 negatorId = get_other_operator(negatorName,
426 leftTypeId, rightTypeId,
427 operatorName, operatorNamespace,
428 leftTypeId, rightTypeId);
430 /* Permission check: must own other operator */
431 if (OidIsValid(negatorId) &&
432 !object_ownercheck(OperatorRelationId, negatorId, GetUserId()))
433 aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_OPERATOR,
434 NameListToString(negatorName));
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).
442 if (!OidIsValid(negatorId) || negatorId == operatorObjectId)
443 ereport(ERROR,
444 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
445 errmsg("operator cannot be its own negator")));
447 else
448 negatorId = InvalidOid;
451 * set up values in the operator tuple
454 for (i = 0; i < Natts_pg_operator; ++i)
456 values[i] = (Datum) NULL;
457 replaces[i] = true;
458 nulls[i] = false;
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);
477 pg_operator_desc = table_open(OperatorRelationId, RowExclusiveLock);
480 * If we are replacing an operator shell, update; else insert
482 if (operatorObjectId)
484 isUpdate = true;
486 tup = SearchSysCacheCopy1(OPEROID,
487 ObjectIdGetDatum(operatorObjectId));
488 if (!HeapTupleIsValid(tup))
489 elog(ERROR, "cache lookup failed for operator %u",
490 operatorObjectId);
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);
499 CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup);
501 else
503 isUpdate = false;
505 operatorObjectId = GetNewOidWithIndex(pg_operator_desc,
506 OperatorOidIndexId,
507 Anum_pg_operator_oid);
508 values[Anum_pg_operator_oid - 1] = ObjectIdGetDatum(operatorObjectId);
510 tup = heap_form_tuple(RelationGetDescr(pg_operator_desc),
511 values, nulls);
513 CatalogTupleInsert(pg_operator_desc, tup);
516 /* Add dependencies for the entry */
517 address = makeOperatorDependencies(tup, true, isUpdate);
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.
530 if (selfCommutator)
531 commutatorId = operatorObjectId;
533 if (OidIsValid(commutatorId) || OidIsValid(negatorId))
534 OperatorUpd(operatorObjectId, commutatorId, negatorId, false);
536 /* Post creation hook for new operator */
537 InvokeObjectPostCreateHook(OperatorRelationId, operatorObjectId, 0);
539 table_close(pg_operator_desc, RowExclusiveLock);
541 return address;
545 * OperatorValidateParams
547 * Check that an operator with argument types leftTypeId and rightTypeId,
548 * returning operResultType, can have the attributes that are set to true.
549 * Raise an error for any disallowed attribute.
551 * Note: in ALTER OPERATOR, we only bother to pass "true" for attributes
552 * the command is trying to set, not those that may already be set.
553 * This is OK as long as the attribute checks are independent.
555 void
556 OperatorValidateParams(Oid leftTypeId,
557 Oid rightTypeId,
558 Oid operResultType,
559 bool hasCommutator,
560 bool hasNegator,
561 bool hasRestrictionSelectivity,
562 bool hasJoinSelectivity,
563 bool canMerge,
564 bool canHash)
566 if (!(OidIsValid(leftTypeId) && OidIsValid(rightTypeId)))
568 /* If it's not a binary op, these things mustn't be set: */
569 if (hasCommutator)
570 ereport(ERROR,
571 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
572 errmsg("only binary operators can have commutators")));
573 if (hasJoinSelectivity)
574 ereport(ERROR,
575 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
576 errmsg("only binary operators can have join selectivity")));
577 if (canMerge)
578 ereport(ERROR,
579 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
580 errmsg("only binary operators can merge join")));
581 if (canHash)
582 ereport(ERROR,
583 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
584 errmsg("only binary operators can hash")));
587 if (operResultType != BOOLOID)
589 /* If it's not a boolean op, these things mustn't be set: */
590 if (hasNegator)
591 ereport(ERROR,
592 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
593 errmsg("only boolean operators can have negators")));
594 if (hasRestrictionSelectivity)
595 ereport(ERROR,
596 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
597 errmsg("only boolean operators can have restriction selectivity")));
598 if (hasJoinSelectivity)
599 ereport(ERROR,
600 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
601 errmsg("only boolean operators can have join selectivity")));
602 if (canMerge)
603 ereport(ERROR,
604 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
605 errmsg("only boolean operators can merge join")));
606 if (canHash)
607 ereport(ERROR,
608 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
609 errmsg("only boolean operators can hash")));
614 * Try to lookup another operator (commutator, etc); return its OID
616 * If not found, check to see if it would be the same operator we are trying
617 * to define; if so, return InvalidOid. (Caller must decide whether
618 * that is sensible.) If it is not the same operator, create a shell
619 * operator.
621 static Oid
622 get_other_operator(List *otherOp, Oid otherLeftTypeId, Oid otherRightTypeId,
623 const char *operatorName, Oid operatorNamespace,
624 Oid leftTypeId, Oid rightTypeId)
626 Oid other_oid;
627 bool otherDefined;
628 char *otherName;
629 Oid otherNamespace;
630 AclResult aclresult;
632 other_oid = OperatorLookup(otherOp,
633 otherLeftTypeId,
634 otherRightTypeId,
635 &otherDefined);
637 if (OidIsValid(other_oid))
639 /* other op already in catalogs */
640 return other_oid;
643 otherNamespace = QualifiedNameGetCreationNamespace(otherOp,
644 &otherName);
646 if (strcmp(otherName, operatorName) == 0 &&
647 otherNamespace == operatorNamespace &&
648 otherLeftTypeId == leftTypeId &&
649 otherRightTypeId == rightTypeId)
651 /* self-linkage to new operator; caller must handle this */
652 return InvalidOid;
655 /* not in catalogs, different from operator, so make shell */
657 aclresult = object_aclcheck(NamespaceRelationId, otherNamespace, GetUserId(),
658 ACL_CREATE);
659 if (aclresult != ACLCHECK_OK)
660 aclcheck_error(aclresult, OBJECT_SCHEMA,
661 get_namespace_name(otherNamespace));
663 other_oid = OperatorShellMake(otherName,
664 otherNamespace,
665 otherLeftTypeId,
666 otherRightTypeId);
667 return other_oid;
671 * OperatorUpd
673 * For a given operator, look up its negator and commutator operators.
674 * When isDelete is false, update their negator and commutator fields to
675 * point back to the given operator; when isDelete is true, update those
676 * fields to be InvalidOid.
678 * The !isDelete case solves a problem for users who need to insert two new
679 * operators that are the negator or commutator of each other, while the
680 * isDelete case is needed so as not to leave dangling OID links behind
681 * after dropping an operator.
683 void
684 OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete)
686 Relation pg_operator_desc;
687 HeapTuple tup;
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.
695 if (!isDelete)
696 CommandCounterIncrement();
698 /* Open the relation. */
699 pg_operator_desc = table_open(OperatorRelationId, RowExclusiveLock);
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;
707 /* Update the commutator's tuple if need be. */
708 if (HeapTupleIsValid(tup))
710 Form_pg_operator t = (Form_pg_operator) GETSTRUCT(tup);
711 bool update_commutator = false;
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.
718 if (isDelete && OidIsValid(t->oprcom))
720 t->oprcom = InvalidOid;
721 update_commutator = true;
723 else if (!isDelete && t->oprcom != baseId)
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.
732 if (OidIsValid(t->oprcom))
734 char *thirdop = get_opname(t->oprcom);
736 if (thirdop != NULL)
737 ereport(ERROR,
738 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
739 errmsg("commutator operator %s is already the commutator of operator %s",
740 NameStr(t->oprname), thirdop)));
741 else
742 ereport(ERROR,
743 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
744 errmsg("commutator operator %s is already the commutator of operator %u",
745 NameStr(t->oprname), t->oprcom)));
748 t->oprcom = baseId;
749 update_commutator = true;
752 /* If any columns were found to need modification, update tuple. */
753 if (update_commutator)
755 CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup);
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.
764 CommandCounterIncrement();
769 * Similarly find and update the negator, if any.
771 if (OidIsValid(negId))
772 tup = SearchSysCacheCopy1(OPEROID, ObjectIdGetDatum(negId));
773 else
774 tup = NULL;
776 if (HeapTupleIsValid(tup))
778 Form_pg_operator t = (Form_pg_operator) GETSTRUCT(tup);
779 bool update_negator = false;
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.
786 if (isDelete && OidIsValid(t->oprnegate))
788 t->oprnegate = InvalidOid;
789 update_negator = true;
791 else if (!isDelete && t->oprnegate != baseId)
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.
800 if (OidIsValid(t->oprnegate))
802 char *thirdop = get_opname(t->oprnegate);
804 if (thirdop != NULL)
805 ereport(ERROR,
806 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
807 errmsg("negator operator %s is already the negator of operator %s",
808 NameStr(t->oprname), thirdop)));
809 else
810 ereport(ERROR,
811 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
812 errmsg("negator operator %s is already the negator of operator %u",
813 NameStr(t->oprname), t->oprnegate)));
816 t->oprnegate = baseId;
817 update_negator = true;
820 /* If any columns were found to need modification, update tuple. */
821 if (update_negator)
823 CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup);
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.)
831 if (isDelete)
832 CommandCounterIncrement();
836 /* Close relation and release catalog lock. */
837 table_close(pg_operator_desc, RowExclusiveLock);
841 * Create dependencies for an operator (either a freshly inserted
842 * complete operator, a new shell operator, a just-updated shell,
843 * or an operator that's being modified by ALTER OPERATOR).
845 * makeExtensionDep should be true when making a new operator or
846 * replacing a shell, false for ALTER OPERATOR. Passing false
847 * will prevent any change in the operator's extension membership.
849 * NB: the OidIsValid tests in this routine are necessary, in case
850 * the given operator is a shell.
852 ObjectAddress
853 makeOperatorDependencies(HeapTuple tuple,
854 bool makeExtensionDep,
855 bool isUpdate)
857 Form_pg_operator oper = (Form_pg_operator) GETSTRUCT(tuple);
858 ObjectAddress myself,
859 referenced;
860 ObjectAddresses *addrs;
862 ObjectAddressSet(myself, OperatorRelationId, oper->oid);
865 * If we are updating the operator, delete any existing entries, except
866 * for extension membership which should remain the same.
868 if (isUpdate)
870 deleteDependencyRecordsFor(myself.classId, myself.objectId, true);
871 deleteSharedDependencyRecordsFor(myself.classId, myself.objectId, 0);
874 addrs = new_object_addresses();
876 /* Dependency on namespace */
877 if (OidIsValid(oper->oprnamespace))
879 ObjectAddressSet(referenced, NamespaceRelationId, oper->oprnamespace);
880 add_exact_object_address(&referenced, addrs);
883 /* Dependency on left type */
884 if (OidIsValid(oper->oprleft))
886 ObjectAddressSet(referenced, TypeRelationId, oper->oprleft);
887 add_exact_object_address(&referenced, addrs);
890 /* Dependency on right type */
891 if (OidIsValid(oper->oprright))
893 ObjectAddressSet(referenced, TypeRelationId, oper->oprright);
894 add_exact_object_address(&referenced, addrs);
897 /* Dependency on result type */
898 if (OidIsValid(oper->oprresult))
900 ObjectAddressSet(referenced, TypeRelationId, oper->oprresult);
901 add_exact_object_address(&referenced, addrs);
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.)
912 /* Dependency on implementation function */
913 if (OidIsValid(oper->oprcode))
915 ObjectAddressSet(referenced, ProcedureRelationId, oper->oprcode);
916 add_exact_object_address(&referenced, addrs);
919 /* Dependency on restriction selectivity function */
920 if (OidIsValid(oper->oprrest))
922 ObjectAddressSet(referenced, ProcedureRelationId, oper->oprrest);
923 add_exact_object_address(&referenced, addrs);
926 /* Dependency on join selectivity function */
927 if (OidIsValid(oper->oprjoin))
929 ObjectAddressSet(referenced, ProcedureRelationId, oper->oprjoin);
930 add_exact_object_address(&referenced, addrs);
933 record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
934 free_object_addresses(addrs);
936 /* Dependency on owner */
937 recordDependencyOnOwner(OperatorRelationId, oper->oid,
938 oper->oprowner);
940 /* Dependency on extension */
941 if (makeExtensionDep)
942 recordDependencyOnCurrentExtension(&myself, isUpdate);
944 return myself;