PostgreSQL Source Code git master
operatorcmds.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * operatorcmds.c
4 *
5 * Routines for operator manipulation commands
6 *
7 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
9 *
10 *
11 * IDENTIFICATION
12 * src/backend/commands/operatorcmds.c
13 *
14 * DESCRIPTION
15 * The "DefineFoo" routines take the parse tree and pick out the
16 * appropriate arguments/flags, passing the results to the
17 * corresponding "FooCreate" routines (in src/backend/catalog) that do
18 * the actual catalog-munging. These routines also verify permission
19 * of the user to execute the command.
20 *
21 * NOTES
22 * These things must be defined and committed in the following order:
23 * "create function":
24 * input/output, recv/send functions
25 * "create type":
26 * type
27 * "create operator":
28 * operators
29 *
30 *-------------------------------------------------------------------------
31 */
32#include "postgres.h"
33
34#include "access/htup_details.h"
35#include "access/table.h"
36#include "catalog/indexing.h"
39#include "catalog/pg_operator.h"
40#include "catalog/pg_proc.h"
41#include "catalog/pg_type.h"
42#include "commands/defrem.h"
43#include "miscadmin.h"
44#include "parser/parse_func.h"
45#include "parser/parse_oper.h"
46#include "parser/parse_type.h"
47#include "utils/acl.h"
48#include "utils/lsyscache.h"
49#include "utils/rel.h"
50#include "utils/syscache.h"
51
52static Oid ValidateRestrictionEstimator(List *restrictionName);
53static Oid ValidateJoinEstimator(List *joinName);
55 Oid leftTypeId,
56 Oid rightTypeId);
57
58/*
59 * DefineOperator
60 * this function extracts all the information from the
61 * parameter list generated by the parser and then has
62 * OperatorCreate() do all the actual work.
63 *
64 * 'parameters' is a list of DefElem
65 */
67DefineOperator(List *names, List *parameters)
68{
69 char *oprName;
70 Oid oprNamespace;
71 AclResult aclresult;
72 bool canMerge = false; /* operator merges */
73 bool canHash = false; /* operator hashes */
74 List *functionName = NIL; /* function for operator */
75 TypeName *typeName1 = NULL; /* first type name */
76 TypeName *typeName2 = NULL; /* second type name */
77 Oid typeId1 = InvalidOid; /* types converted to OID */
78 Oid typeId2 = InvalidOid;
79 Oid rettype;
80 List *commutatorName = NIL; /* optional commutator operator name */
81 List *negatorName = NIL; /* optional negator operator name */
82 List *restrictionName = NIL; /* optional restrict. sel. function */
83 List *joinName = NIL; /* optional join sel. function */
84 Oid functionOid; /* functions converted to OID */
85 Oid restrictionOid;
86 Oid joinOid;
87 Oid typeId[2]; /* to hold left and right arg */
88 int nargs;
89 ListCell *pl;
90
91 /* Convert list of names to a name and namespace */
92 oprNamespace = QualifiedNameGetCreationNamespace(names, &oprName);
93
94 /* Check we have creation rights in target namespace */
95 aclresult = object_aclcheck(NamespaceRelationId, oprNamespace, GetUserId(), ACL_CREATE);
96 if (aclresult != ACLCHECK_OK)
98 get_namespace_name(oprNamespace));
99
100 /*
101 * loop over the definition list and extract the information we need.
102 */
103 foreach(pl, parameters)
104 {
105 DefElem *defel = (DefElem *) lfirst(pl);
106
107 if (strcmp(defel->defname, "leftarg") == 0)
108 {
109 typeName1 = defGetTypeName(defel);
110 if (typeName1->setof)
112 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
113 errmsg("SETOF type not allowed for operator argument")));
114 }
115 else if (strcmp(defel->defname, "rightarg") == 0)
116 {
117 typeName2 = defGetTypeName(defel);
118 if (typeName2->setof)
120 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
121 errmsg("SETOF type not allowed for operator argument")));
122 }
123 /* "function" and "procedure" are equivalent here */
124 else if (strcmp(defel->defname, "function") == 0)
125 functionName = defGetQualifiedName(defel);
126 else if (strcmp(defel->defname, "procedure") == 0)
127 functionName = defGetQualifiedName(defel);
128 else if (strcmp(defel->defname, "commutator") == 0)
129 commutatorName = defGetQualifiedName(defel);
130 else if (strcmp(defel->defname, "negator") == 0)
131 negatorName = defGetQualifiedName(defel);
132 else if (strcmp(defel->defname, "restrict") == 0)
133 restrictionName = defGetQualifiedName(defel);
134 else if (strcmp(defel->defname, "join") == 0)
135 joinName = defGetQualifiedName(defel);
136 else if (strcmp(defel->defname, "hashes") == 0)
137 canHash = defGetBoolean(defel);
138 else if (strcmp(defel->defname, "merges") == 0)
139 canMerge = defGetBoolean(defel);
140 /* These obsolete options are taken as meaning canMerge */
141 else if (strcmp(defel->defname, "sort1") == 0)
142 canMerge = true;
143 else if (strcmp(defel->defname, "sort2") == 0)
144 canMerge = true;
145 else if (strcmp(defel->defname, "ltcmp") == 0)
146 canMerge = true;
147 else if (strcmp(defel->defname, "gtcmp") == 0)
148 canMerge = true;
149 else
150 {
151 /* WARNING, not ERROR, for historical backwards-compatibility */
153 (errcode(ERRCODE_SYNTAX_ERROR),
154 errmsg("operator attribute \"%s\" not recognized",
155 defel->defname)));
156 }
157 }
158
159 /*
160 * make sure we have our required definitions
161 */
162 if (functionName == NIL)
164 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
165 errmsg("operator function must be specified")));
166
167 /* Transform type names to type OIDs */
168 if (typeName1)
169 typeId1 = typenameTypeId(NULL, typeName1);
170 if (typeName2)
171 typeId2 = typenameTypeId(NULL, typeName2);
172
173 /*
174 * If only the right argument is missing, the user is likely trying to
175 * create a postfix operator, so give them a hint about why that does not
176 * work. But if both arguments are missing, do not mention postfix
177 * operators, as the user most likely simply neglected to mention the
178 * arguments.
179 */
180 if (!OidIsValid(typeId1) && !OidIsValid(typeId2))
182 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
183 errmsg("operator argument types must be specified")));
184 if (!OidIsValid(typeId2))
186 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
187 errmsg("operator right argument type must be specified"),
188 errdetail("Postfix operators are not supported.")));
189
190 if (typeName1)
191 {
192 aclresult = object_aclcheck(TypeRelationId, typeId1, GetUserId(), ACL_USAGE);
193 if (aclresult != ACLCHECK_OK)
194 aclcheck_error_type(aclresult, typeId1);
195 }
196
197 if (typeName2)
198 {
199 aclresult = object_aclcheck(TypeRelationId, typeId2, GetUserId(), ACL_USAGE);
200 if (aclresult != ACLCHECK_OK)
201 aclcheck_error_type(aclresult, typeId2);
202 }
203
204 /*
205 * Look up the operator's underlying function.
206 */
207 if (!OidIsValid(typeId1))
208 {
209 typeId[0] = typeId2;
210 nargs = 1;
211 }
212 else if (!OidIsValid(typeId2))
213 {
214 typeId[0] = typeId1;
215 nargs = 1;
216 }
217 else
218 {
219 typeId[0] = typeId1;
220 typeId[1] = typeId2;
221 nargs = 2;
222 }
223 functionOid = LookupFuncName(functionName, nargs, typeId, false);
224
225 /*
226 * We require EXECUTE rights for the function. This isn't strictly
227 * necessary, since EXECUTE will be checked at any attempted use of the
228 * operator, but it seems like a good idea anyway.
229 */
230 aclresult = object_aclcheck(ProcedureRelationId, functionOid, GetUserId(), ACL_EXECUTE);
231 if (aclresult != ACLCHECK_OK)
233 NameListToString(functionName));
234
235 rettype = get_func_rettype(functionOid);
236 aclresult = object_aclcheck(TypeRelationId, rettype, GetUserId(), ACL_USAGE);
237 if (aclresult != ACLCHECK_OK)
238 aclcheck_error_type(aclresult, rettype);
239
240 /*
241 * Look up restriction and join estimators if specified
242 */
243 if (restrictionName)
244 restrictionOid = ValidateRestrictionEstimator(restrictionName);
245 else
246 restrictionOid = InvalidOid;
247 if (joinName)
248 joinOid = ValidateJoinEstimator(joinName);
249 else
250 joinOid = InvalidOid;
251
252 /*
253 * now have OperatorCreate do all the work..
254 */
255 return
256 OperatorCreate(oprName, /* operator name */
257 oprNamespace, /* namespace */
258 typeId1, /* left type id */
259 typeId2, /* right type id */
260 functionOid, /* function for operator */
261 commutatorName, /* optional commutator operator name */
262 negatorName, /* optional negator operator name */
263 restrictionOid, /* optional restrict. sel. function */
264 joinOid, /* optional join sel. function name */
265 canMerge, /* operator merges */
266 canHash); /* operator hashes */
267}
268
269/*
270 * Look up a restriction estimator function by name, and verify that it has
271 * the correct signature and we have the permissions to attach it to an
272 * operator.
273 */
274static Oid
276{
277 Oid typeId[4];
278 Oid restrictionOid;
279 AclResult aclresult;
280
281 typeId[0] = INTERNALOID; /* PlannerInfo */
282 typeId[1] = OIDOID; /* operator OID */
283 typeId[2] = INTERNALOID; /* args list */
284 typeId[3] = INT4OID; /* varRelid */
285
286 restrictionOid = LookupFuncName(restrictionName, 4, typeId, false);
287
288 /* estimators must return float8 */
289 if (get_func_rettype(restrictionOid) != FLOAT8OID)
291 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
292 errmsg("restriction estimator function %s must return type %s",
293 NameListToString(restrictionName), "float8")));
294
295 /* Require EXECUTE rights for the estimator */
296 aclresult = object_aclcheck(ProcedureRelationId, restrictionOid, GetUserId(), ACL_EXECUTE);
297 if (aclresult != ACLCHECK_OK)
299 NameListToString(restrictionName));
300
301 return restrictionOid;
302}
303
304/*
305 * Look up a join estimator function by name, and verify that it has the
306 * correct signature and we have the permissions to attach it to an
307 * operator.
308 */
309static Oid
311{
312 Oid typeId[5];
313 Oid joinOid;
314 Oid joinOid2;
315 AclResult aclresult;
316
317 typeId[0] = INTERNALOID; /* PlannerInfo */
318 typeId[1] = OIDOID; /* operator OID */
319 typeId[2] = INTERNALOID; /* args list */
320 typeId[3] = INT2OID; /* jointype */
321 typeId[4] = INTERNALOID; /* SpecialJoinInfo */
322
323 /*
324 * As of Postgres 8.4, the preferred signature for join estimators has 5
325 * arguments, but we still allow the old 4-argument form. Whine about
326 * ambiguity if both forms exist.
327 */
328 joinOid = LookupFuncName(joinName, 5, typeId, true);
329 joinOid2 = LookupFuncName(joinName, 4, typeId, true);
330 if (OidIsValid(joinOid))
331 {
332 if (OidIsValid(joinOid2))
334 (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
335 errmsg("join estimator function %s has multiple matches",
336 NameListToString(joinName))));
337 }
338 else
339 {
340 joinOid = joinOid2;
341 /* If not found, reference the 5-argument signature in error msg */
342 if (!OidIsValid(joinOid))
343 joinOid = LookupFuncName(joinName, 5, typeId, false);
344 }
345
346 /* estimators must return float8 */
347 if (get_func_rettype(joinOid) != FLOAT8OID)
349 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
350 errmsg("join estimator function %s must return type %s",
351 NameListToString(joinName), "float8")));
352
353 /* Require EXECUTE rights for the estimator */
354 aclresult = object_aclcheck(ProcedureRelationId, joinOid, GetUserId(), ACL_EXECUTE);
355 if (aclresult != ACLCHECK_OK)
357 NameListToString(joinName));
358
359 return joinOid;
360}
361
362/*
363 * Look up and return the OID of an operator,
364 * given a possibly-qualified name and left and right type IDs.
365 *
366 * Verifies that the operator is defined (not a shell) and owned by
367 * the current user, so that we have permission to associate it with
368 * the operator being altered. Rejecting shell operators is a policy
369 * choice to help catch mistakes, rather than something essential.
370 */
371static Oid
373 Oid leftTypeId,
374 Oid rightTypeId)
375{
376 Oid oid;
377 bool defined;
378
379 oid = OperatorLookup(name,
380 leftTypeId,
381 rightTypeId,
382 &defined);
383
384 /* These message strings are chosen to match parse_oper.c */
385 if (!OidIsValid(oid))
387 (errcode(ERRCODE_UNDEFINED_FUNCTION),
388 errmsg("operator does not exist: %s",
390 leftTypeId,
391 rightTypeId))));
392
393 if (!defined)
395 (errcode(ERRCODE_UNDEFINED_FUNCTION),
396 errmsg("operator is only a shell: %s",
398 leftTypeId,
399 rightTypeId))));
400
401 if (!object_ownercheck(OperatorRelationId, oid, GetUserId()))
404
405 return oid;
406}
407
408
409/*
410 * Guts of operator deletion.
411 */
412void
414{
415 Relation relation;
416 HeapTuple tup;
418
419 relation = table_open(OperatorRelationId, RowExclusiveLock);
420
421 tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
422 if (!HeapTupleIsValid(tup)) /* should not happen */
423 elog(ERROR, "cache lookup failed for operator %u", operOid);
424 op = (Form_pg_operator) GETSTRUCT(tup);
425
426 /*
427 * Reset links from commutator and negator, if any. In case of a
428 * self-commutator or self-negator, this means we have to re-fetch the
429 * updated tuple. (We could optimize away updates on the tuple we're
430 * about to drop, but it doesn't seem worth convoluting the logic for.)
431 */
432 if (OidIsValid(op->oprcom) || OidIsValid(op->oprnegate))
433 {
434 OperatorUpd(operOid, op->oprcom, op->oprnegate, true);
435 if (operOid == op->oprcom || operOid == op->oprnegate)
436 {
437 ReleaseSysCache(tup);
438 tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
439 if (!HeapTupleIsValid(tup)) /* should not happen */
440 elog(ERROR, "cache lookup failed for operator %u", operOid);
441 }
442 }
443
444 CatalogTupleDelete(relation, &tup->t_self);
445
446 ReleaseSysCache(tup);
447
448 table_close(relation, RowExclusiveLock);
449}
450
451/*
452 * AlterOperator
453 * routine implementing ALTER OPERATOR <operator> SET (option = ...).
454 *
455 * Currently, only RESTRICT and JOIN estimator functions can be changed.
456 * COMMUTATOR, NEGATOR, MERGES, and HASHES attributes can be set if they
457 * have not been set previously. (Changing or removing one of these
458 * attributes could invalidate existing plans, which seems more trouble
459 * than it's worth.)
460 */
463{
464 ObjectAddress address;
465 Oid oprId;
466 Relation catalog;
467 HeapTuple tup;
468 Form_pg_operator oprForm;
469 int i;
470 ListCell *pl;
471 Datum values[Natts_pg_operator];
472 bool nulls[Natts_pg_operator];
473 bool replaces[Natts_pg_operator];
474 List *restrictionName = NIL; /* optional restrict. sel. function */
475 bool updateRestriction = false;
476 Oid restrictionOid;
477 List *joinName = NIL; /* optional join sel. function */
478 bool updateJoin = false;
479 Oid joinOid;
480 List *commutatorName = NIL; /* optional commutator operator name */
481 Oid commutatorOid;
482 List *negatorName = NIL; /* optional negator operator name */
483 Oid negatorOid;
484 bool canMerge = false;
485 bool updateMerges = false;
486 bool canHash = false;
487 bool updateHashes = false;
488
489 /* Look up the operator */
490 oprId = LookupOperWithArgs(stmt->opername, false);
491 catalog = table_open(OperatorRelationId, RowExclusiveLock);
492 tup = SearchSysCacheCopy1(OPEROID, ObjectIdGetDatum(oprId));
493 if (!HeapTupleIsValid(tup))
494 elog(ERROR, "cache lookup failed for operator %u", oprId);
495 oprForm = (Form_pg_operator) GETSTRUCT(tup);
496
497 /* Process options */
498 foreach(pl, stmt->options)
499 {
500 DefElem *defel = (DefElem *) lfirst(pl);
501 List *param;
502
503 if (defel->arg == NULL)
504 param = NIL; /* NONE, removes the function */
505 else
506 param = defGetQualifiedName(defel);
507
508 if (strcmp(defel->defname, "restrict") == 0)
509 {
510 restrictionName = param;
511 updateRestriction = true;
512 }
513 else if (strcmp(defel->defname, "join") == 0)
514 {
515 joinName = param;
516 updateJoin = true;
517 }
518 else if (strcmp(defel->defname, "commutator") == 0)
519 {
520 commutatorName = defGetQualifiedName(defel);
521 }
522 else if (strcmp(defel->defname, "negator") == 0)
523 {
524 negatorName = defGetQualifiedName(defel);
525 }
526 else if (strcmp(defel->defname, "merges") == 0)
527 {
528 canMerge = defGetBoolean(defel);
529 updateMerges = true;
530 }
531 else if (strcmp(defel->defname, "hashes") == 0)
532 {
533 canHash = defGetBoolean(defel);
534 updateHashes = true;
535 }
536
537 /*
538 * The rest of the options that CREATE accepts cannot be changed.
539 * Check for them so that we can give a meaningful error message.
540 */
541 else if (strcmp(defel->defname, "leftarg") == 0 ||
542 strcmp(defel->defname, "rightarg") == 0 ||
543 strcmp(defel->defname, "function") == 0 ||
544 strcmp(defel->defname, "procedure") == 0)
545 {
547 (errcode(ERRCODE_SYNTAX_ERROR),
548 errmsg("operator attribute \"%s\" cannot be changed",
549 defel->defname)));
550 }
551 else
553 (errcode(ERRCODE_SYNTAX_ERROR),
554 errmsg("operator attribute \"%s\" not recognized",
555 defel->defname)));
556 }
557
558 /* Check permissions. Must be owner. */
559 if (!object_ownercheck(OperatorRelationId, oprId, GetUserId()))
561 NameStr(oprForm->oprname));
562
563 /*
564 * Look up OIDs for any parameters specified
565 */
566 if (restrictionName)
567 restrictionOid = ValidateRestrictionEstimator(restrictionName);
568 else
569 restrictionOid = InvalidOid;
570 if (joinName)
571 joinOid = ValidateJoinEstimator(joinName);
572 else
573 joinOid = InvalidOid;
574
575 if (commutatorName)
576 {
577 /* commutator has reversed arg types */
578 commutatorOid = ValidateOperatorReference(commutatorName,
579 oprForm->oprright,
580 oprForm->oprleft);
581
582 /*
583 * We don't need to do anything extra for a self commutator as in
584 * OperatorCreate, since the operator surely exists already.
585 */
586 }
587 else
588 commutatorOid = InvalidOid;
589
590 if (negatorName)
591 {
592 negatorOid = ValidateOperatorReference(negatorName,
593 oprForm->oprleft,
594 oprForm->oprright);
595
596 /* Must reject self-negation */
597 if (negatorOid == oprForm->oid)
599 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
600 errmsg("operator cannot be its own negator")));
601 }
602 else
603 {
604 negatorOid = InvalidOid;
605 }
606
607 /*
608 * Check that we're not changing any attributes that might be depended on
609 * by plans, while allowing no-op updates.
610 */
611 if (OidIsValid(commutatorOid) && OidIsValid(oprForm->oprcom) &&
612 commutatorOid != oprForm->oprcom)
614 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
615 errmsg("operator attribute \"%s\" cannot be changed if it has already been set",
616 "commutator")));
617
618 if (OidIsValid(negatorOid) && OidIsValid(oprForm->oprnegate) &&
619 negatorOid != oprForm->oprnegate)
621 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
622 errmsg("operator attribute \"%s\" cannot be changed if it has already been set",
623 "negator")));
624
625 if (updateMerges && oprForm->oprcanmerge && !canMerge)
627 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
628 errmsg("operator attribute \"%s\" cannot be changed if it has already been set",
629 "merges")));
630
631 if (updateHashes && oprForm->oprcanhash && !canHash)
633 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
634 errmsg("operator attribute \"%s\" cannot be changed if it has already been set",
635 "hashes")));
636
637 /* Perform additional checks, like OperatorCreate does */
638 OperatorValidateParams(oprForm->oprleft,
639 oprForm->oprright,
640 oprForm->oprresult,
641 OidIsValid(commutatorOid),
642 OidIsValid(negatorOid),
643 OidIsValid(restrictionOid),
644 OidIsValid(joinOid),
645 canMerge,
646 canHash);
647
648 /* Update the tuple */
649 for (i = 0; i < Natts_pg_operator; ++i)
650 {
651 values[i] = (Datum) 0;
652 replaces[i] = false;
653 nulls[i] = false;
654 }
655 if (updateRestriction)
656 {
657 replaces[Anum_pg_operator_oprrest - 1] = true;
658 values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(restrictionOid);
659 }
660 if (updateJoin)
661 {
662 replaces[Anum_pg_operator_oprjoin - 1] = true;
663 values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(joinOid);
664 }
665 if (OidIsValid(commutatorOid))
666 {
667 replaces[Anum_pg_operator_oprcom - 1] = true;
668 values[Anum_pg_operator_oprcom - 1] = ObjectIdGetDatum(commutatorOid);
669 }
670 if (OidIsValid(negatorOid))
671 {
672 replaces[Anum_pg_operator_oprnegate - 1] = true;
673 values[Anum_pg_operator_oprnegate - 1] = ObjectIdGetDatum(negatorOid);
674 }
675 if (updateMerges)
676 {
677 replaces[Anum_pg_operator_oprcanmerge - 1] = true;
678 values[Anum_pg_operator_oprcanmerge - 1] = BoolGetDatum(canMerge);
679 }
680 if (updateHashes)
681 {
682 replaces[Anum_pg_operator_oprcanhash - 1] = true;
683 values[Anum_pg_operator_oprcanhash - 1] = BoolGetDatum(canHash);
684 }
685
686 tup = heap_modify_tuple(tup, RelationGetDescr(catalog),
687 values, nulls, replaces);
688
689 CatalogTupleUpdate(catalog, &tup->t_self, tup);
690
691 address = makeOperatorDependencies(tup, false, true);
692
693 if (OidIsValid(commutatorOid) || OidIsValid(negatorOid))
694 OperatorUpd(oprId, commutatorOid, negatorOid, false);
695
696 InvokeObjectPostAlterHook(OperatorRelationId, oprId, 0);
697
698 table_close(catalog, NoLock);
699
700 return address;
701}
AclResult
Definition: acl.h:182
@ ACLCHECK_OK
Definition: acl.h:183
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2622
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3804
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4058
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:2941
static Datum values[MAXATTR]
Definition: bootstrap.c:151
#define NameStr(name)
Definition: c.h:703
#define OidIsValid(objectId)
Definition: c.h:732
TypeName * defGetTypeName(DefElem *def)
Definition: define.c:271
bool defGetBoolean(DefElem *def)
Definition: define.c:94
List * defGetQualifiedName(DefElem *def)
Definition: define.c:239
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define WARNING
Definition: elog.h:36
#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
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
#define stmt
Definition: indent_codes.h:59
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:365
int i
Definition: isn.c:72
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3366
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1655
Oid GetUserId(void)
Definition: miscinit.c:517
char * NameListToString(const List *names)
Definition: namespace.c:3594
Oid QualifiedNameGetCreationNamespace(const List *names, char **objname_p)
Definition: namespace.c:3487
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
ObjectAddress AlterOperator(AlterOperatorStmt *stmt)
Definition: operatorcmds.c:462
void RemoveOperatorById(Oid operOid)
Definition: operatorcmds.c:413
static Oid ValidateJoinEstimator(List *joinName)
Definition: operatorcmds.c:310
static Oid ValidateOperatorReference(List *name, Oid leftTypeId, Oid rightTypeId)
Definition: operatorcmds.c:372
ObjectAddress DefineOperator(List *names, List *parameters)
Definition: operatorcmds.c:67
static Oid ValidateRestrictionEstimator(List *restrictionName)
Definition: operatorcmds.c:275
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
Definition: parse_func.c:2144
const char * op_signature_string(List *op, Oid arg1, Oid arg2)
Definition: parse_oper.c:602
Oid LookupOperWithArgs(ObjectWithArgs *oper, bool noError)
Definition: parse_oper.c:133
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:291
#define ACL_USAGE
Definition: parsenodes.h:84
@ OBJECT_SCHEMA
Definition: parsenodes.h:2348
@ OBJECT_OPERATOR
Definition: parsenodes.h:2337
@ OBJECT_FUNCTION
Definition: parsenodes.h:2331
#define ACL_EXECUTE
Definition: parsenodes.h:83
#define ACL_CREATE
Definition: parsenodes.h:85
#define lfirst(lc)
Definition: pg_list.h:172
#define NIL
Definition: pg_list.h:68
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: pg_operator.c:321
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
Oid OperatorLookup(List *operatorName, Oid leftObjectId, Oid rightObjectId, bool *defined)
Definition: pg_operator.c:164
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
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:83
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
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
#define RelationGetDescr(relation)
Definition: rel.h:531
char * defname
Definition: parsenodes.h:826
Node * arg
Definition: parsenodes.h:827
ItemPointerData t_self
Definition: htup.h:65
Definition: pg_list.h:54
bool setof
Definition: parsenodes.h:281
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221
#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
const char * name