PostgreSQL Source Code  git master
operatorcmds.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/table.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "commands/alter.h"
#include "commands/defrem.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
#include "parser/parse_oper.h"
#include "parser/parse_type.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"
Include dependency graph for operatorcmds.c:

Go to the source code of this file.

Functions

static Oid ValidateRestrictionEstimator (List *restrictionName)
 
static Oid ValidateJoinEstimator (List *joinName)
 
ObjectAddress DefineOperator (List *names, List *parameters)
 
void RemoveOperatorById (Oid operOid)
 
ObjectAddress AlterOperator (AlterOperatorStmt *stmt)
 

Function Documentation

◆ AlterOperator()

ObjectAddress AlterOperator ( AlterOperatorStmt stmt)

Definition at line 411 of file operatorcmds.c.

412 {
413  ObjectAddress address;
414  Oid oprId;
415  Relation catalog;
416  HeapTuple tup;
417  Form_pg_operator oprForm;
418  int i;
419  ListCell *pl;
420  Datum values[Natts_pg_operator];
421  bool nulls[Natts_pg_operator];
422  bool replaces[Natts_pg_operator];
423  List *restrictionName = NIL; /* optional restrict. sel. function */
424  bool updateRestriction = false;
425  Oid restrictionOid;
426  List *joinName = NIL; /* optional join sel. function */
427  bool updateJoin = false;
428  Oid joinOid;
429 
430  /* Look up the operator */
431  oprId = LookupOperWithArgs(stmt->opername, false);
432  catalog = table_open(OperatorRelationId, RowExclusiveLock);
434  if (!HeapTupleIsValid(tup))
435  elog(ERROR, "cache lookup failed for operator %u", oprId);
436  oprForm = (Form_pg_operator) GETSTRUCT(tup);
437 
438  /* Process options */
439  foreach(pl, stmt->options)
440  {
441  DefElem *defel = (DefElem *) lfirst(pl);
442  List *param;
443 
444  if (defel->arg == NULL)
445  param = NIL; /* NONE, removes the function */
446  else
447  param = defGetQualifiedName(defel);
448 
449  if (strcmp(defel->defname, "restrict") == 0)
450  {
451  restrictionName = param;
452  updateRestriction = true;
453  }
454  else if (strcmp(defel->defname, "join") == 0)
455  {
456  joinName = param;
457  updateJoin = true;
458  }
459 
460  /*
461  * The rest of the options that CREATE accepts cannot be changed.
462  * Check for them so that we can give a meaningful error message.
463  */
464  else if (strcmp(defel->defname, "leftarg") == 0 ||
465  strcmp(defel->defname, "rightarg") == 0 ||
466  strcmp(defel->defname, "function") == 0 ||
467  strcmp(defel->defname, "procedure") == 0 ||
468  strcmp(defel->defname, "commutator") == 0 ||
469  strcmp(defel->defname, "negator") == 0 ||
470  strcmp(defel->defname, "hashes") == 0 ||
471  strcmp(defel->defname, "merges") == 0)
472  {
473  ereport(ERROR,
474  (errcode(ERRCODE_SYNTAX_ERROR),
475  errmsg("operator attribute \"%s\" cannot be changed",
476  defel->defname)));
477  }
478  else
479  ereport(ERROR,
480  (errcode(ERRCODE_SYNTAX_ERROR),
481  errmsg("operator attribute \"%s\" not recognized",
482  defel->defname)));
483  }
484 
485  /* Check permissions. Must be owner. */
486  if (!object_ownercheck(OperatorRelationId, oprId, GetUserId()))
488  NameStr(oprForm->oprname));
489 
490  /*
491  * Look up restriction and join estimators if specified
492  */
493  if (restrictionName)
494  restrictionOid = ValidateRestrictionEstimator(restrictionName);
495  else
496  restrictionOid = InvalidOid;
497  if (joinName)
498  joinOid = ValidateJoinEstimator(joinName);
499  else
500  joinOid = InvalidOid;
501 
502  /* Perform additional checks, like OperatorCreate does */
503  if (!(OidIsValid(oprForm->oprleft) && OidIsValid(oprForm->oprright)))
504  {
505  /* If it's not a binary op, these things mustn't be set: */
506  if (OidIsValid(joinOid))
507  ereport(ERROR,
508  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
509  errmsg("only binary operators can have join selectivity")));
510  }
511 
512  if (oprForm->oprresult != BOOLOID)
513  {
514  if (OidIsValid(restrictionOid))
515  ereport(ERROR,
516  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
517  errmsg("only boolean operators can have restriction selectivity")));
518  if (OidIsValid(joinOid))
519  ereport(ERROR,
520  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
521  errmsg("only boolean operators can have join selectivity")));
522  }
523 
524  /* Update the tuple */
525  for (i = 0; i < Natts_pg_operator; ++i)
526  {
527  values[i] = (Datum) 0;
528  replaces[i] = false;
529  nulls[i] = false;
530  }
531  if (updateRestriction)
532  {
533  replaces[Anum_pg_operator_oprrest - 1] = true;
534  values[Anum_pg_operator_oprrest - 1] = restrictionOid;
535  }
536  if (updateJoin)
537  {
538  replaces[Anum_pg_operator_oprjoin - 1] = true;
539  values[Anum_pg_operator_oprjoin - 1] = joinOid;
540  }
541 
542  tup = heap_modify_tuple(tup, RelationGetDescr(catalog),
543  values, nulls, replaces);
544 
545  CatalogTupleUpdate(catalog, &tup->t_self, tup);
546 
547  address = makeOperatorDependencies(tup, false, true);
548 
549  InvokeObjectPostAlterHook(OperatorRelationId, oprId, 0);
550 
551  table_close(catalog, NoLock);
552 
553  return address;
554 }
@ ACLCHECK_NOT_OWNER
Definition: acl.h:184
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3477
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4771
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define NameStr(name)
Definition: c.h:682
#define OidIsValid(objectId)
Definition: c.h:711
List * defGetQualifiedName(DefElem *def)
Definition: define.c:253
int errcode(int sqlerrcode)
Definition: elog.c:695
int errmsg(const char *fmt,...)
Definition: elog.c:906
#define ERROR
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:145
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:649
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
int i
Definition: isn.c:73
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
Oid GetUserId(void)
Definition: miscinit.c:497
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
static Oid ValidateJoinEstimator(List *joinName)
Definition: operatorcmds.c:310
static Oid ValidateRestrictionEstimator(List *restrictionName)
Definition: operatorcmds.c:275
Oid LookupOperWithArgs(ObjectWithArgs *oper, bool noError)
Definition: parse_oper.c:145
@ OBJECT_OPERATOR
Definition: parsenodes.h:1885
#define lfirst(lc)
Definition: pg_list.h:170
#define NIL
Definition: pg_list.h:66
ObjectAddress makeOperatorDependencies(HeapTuple tuple, bool makeExtensionDep, bool isUpdate)
Definition: pg_operator.c:777
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:83
uintptr_t Datum
Definition: postgres.h:412
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:600
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationGetDescr(relation)
Definition: rel.h:527
ObjectWithArgs * opername
Definition: parsenodes.h:3197
char * defname
Definition: parsenodes.h:775
Node * arg
Definition: parsenodes.h:776
ItemPointerData t_self
Definition: htup.h:65
Definition: pg_list.h:52
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:179
@ 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

References aclcheck_error(), ACLCHECK_NOT_OWNER, DefElem::arg, CatalogTupleUpdate(), defGetQualifiedName(), DefElem::defname, elog(), ereport, errcode(), errmsg(), ERROR, GETSTRUCT, GetUserId(), heap_modify_tuple(), HeapTupleIsValid, i, InvalidOid, InvokeObjectPostAlterHook, lfirst, LookupOperWithArgs(), makeOperatorDependencies(), NameStr, NIL, NoLock, OBJECT_OPERATOR, object_ownercheck(), ObjectIdGetDatum(), OidIsValid, AlterOperatorStmt::opername, OPEROID, AlterOperatorStmt::options, RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy1, HeapTupleData::t_self, table_close(), table_open(), ValidateJoinEstimator(), ValidateRestrictionEstimator(), and values.

Referenced by ProcessUtilitySlow().

◆ DefineOperator()

ObjectAddress DefineOperator ( List names,
List parameters 
)

Definition at line 67 of file operatorcmds.c.

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)
97  aclcheck_error(aclresult, OBJECT_SCHEMA,
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)
111  ereport(ERROR,
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)
119  ereport(ERROR,
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)
163  ereport(ERROR,
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))
181  ereport(ERROR,
182  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
183  errmsg("operator argument types must be specified")));
184  if (!OidIsValid(typeId2))
185  ereport(ERROR,
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)
232  aclcheck_error(aclresult, OBJECT_FUNCTION,
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 }
AclResult
Definition: acl.h:181
@ ACLCHECK_OK
Definition: acl.h:182
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:4570
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3796
bool defGetBoolean(DefElem *def)
Definition: define.c:108
TypeName * defGetTypeName(DefElem *def)
Definition: define.c:285
int errdetail(const char *fmt,...)
Definition: elog.c:1039
#define WARNING
Definition: elog.h:32
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3331
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1637
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:3038
char * NameListToString(List *names)
Definition: namespace.c:3145
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
Definition: parse_func.c:2146
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:291
#define ACL_USAGE
Definition: parsenodes.h:91
@ OBJECT_SCHEMA
Definition: parsenodes.h:1896
@ OBJECT_FUNCTION
Definition: parsenodes.h:1879
#define ACL_EXECUTE
Definition: parsenodes.h:90
#define ACL_CREATE
Definition: parsenodes.h:92
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:327
bool setof
Definition: parsenodes.h:233

References ACL_CREATE, ACL_EXECUTE, ACL_USAGE, aclcheck_error(), aclcheck_error_type(), ACLCHECK_OK, defGetBoolean(), defGetQualifiedName(), defGetTypeName(), DefElem::defname, ereport, errcode(), errdetail(), errmsg(), ERROR, get_func_rettype(), get_namespace_name(), GetUserId(), InvalidOid, lfirst, LookupFuncName(), NameListToString(), NIL, object_aclcheck(), OBJECT_FUNCTION, OBJECT_SCHEMA, OidIsValid, OperatorCreate(), QualifiedNameGetCreationNamespace(), TypeName::setof, typenameTypeId(), ValidateJoinEstimator(), ValidateRestrictionEstimator(), and WARNING.

Referenced by ProcessUtilitySlow().

◆ RemoveOperatorById()

void RemoveOperatorById ( Oid  operOid)

Definition at line 366 of file operatorcmds.c.

367 {
368  Relation relation;
369  HeapTuple tup;
370  Form_pg_operator op;
371 
372  relation = table_open(OperatorRelationId, RowExclusiveLock);
373 
374  tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
375  if (!HeapTupleIsValid(tup)) /* should not happen */
376  elog(ERROR, "cache lookup failed for operator %u", operOid);
377  op = (Form_pg_operator) GETSTRUCT(tup);
378 
379  /*
380  * Reset links from commutator and negator, if any. In case of a
381  * self-commutator or self-negator, this means we have to re-fetch the
382  * updated tuple. (We could optimize away updates on the tuple we're
383  * about to drop, but it doesn't seem worth convoluting the logic for.)
384  */
385  if (OidIsValid(op->oprcom) || OidIsValid(op->oprnegate))
386  {
387  OperatorUpd(operOid, op->oprcom, op->oprnegate, true);
388  if (operOid == op->oprcom || operOid == op->oprnegate)
389  {
390  ReleaseSysCache(tup);
391  tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
392  if (!HeapTupleIsValid(tup)) /* should not happen */
393  elog(ERROR, "cache lookup failed for operator %u", operOid);
394  }
395  }
396 
397  CatalogTupleDelete(relation, &tup->t_self);
398 
399  ReleaseSysCache(tup);
400 
401  table_close(relation, RowExclusiveLock);
402 }
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
void OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete)
Definition: pg_operator.c:654
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1221
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1173

References CatalogTupleDelete(), elog(), ERROR, GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum(), OidIsValid, OperatorUpd(), OPEROID, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by doDeletion().

◆ ValidateJoinEstimator()

static Oid ValidateJoinEstimator ( List joinName)
static

Definition at line 310 of file operatorcmds.c.

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))
333  ereport(ERROR,
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)
348  ereport(ERROR,
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)
356  aclcheck_error(aclresult, OBJECT_FUNCTION,
357  NameListToString(joinName));
358 
359  return joinOid;
360 }

References ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, ereport, errcode(), errmsg(), ERROR, get_func_rettype(), GetUserId(), LookupFuncName(), NameListToString(), object_aclcheck(), OBJECT_FUNCTION, and OidIsValid.

Referenced by AlterOperator(), and DefineOperator().

◆ ValidateRestrictionEstimator()

static Oid ValidateRestrictionEstimator ( List restrictionName)
static

Definition at line 275 of file operatorcmds.c.

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)
290  ereport(ERROR,
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)
298  aclcheck_error(aclresult, OBJECT_FUNCTION,
299  NameListToString(restrictionName));
300 
301  return restrictionOid;
302 }

References ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, ereport, errcode(), errmsg(), ERROR, get_func_rettype(), GetUserId(), LookupFuncName(), NameListToString(), object_aclcheck(), and OBJECT_FUNCTION.

Referenced by AlterOperator(), and DefineOperator().