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