PostgreSQL Source Code  git master
operatorcmds.c File Reference
#include "postgres.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_operator.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/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 384 of file operatorcmds.c.

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

Referenced by ProcessUtilitySlow().

385 {
386  ObjectAddress address;
387  Oid oprId;
388  Relation catalog;
389  HeapTuple tup;
390  Form_pg_operator oprForm;
391  int i;
392  ListCell *pl;
393  Datum values[Natts_pg_operator];
394  bool nulls[Natts_pg_operator];
395  bool replaces[Natts_pg_operator];
396  List *restrictionName = NIL; /* optional restrict. sel. procedure */
397  bool updateRestriction = false;
398  Oid restrictionOid;
399  List *joinName = NIL; /* optional join sel. procedure */
400  bool updateJoin = false;
401  Oid joinOid;
402 
403  /* Look up the operator */
404  oprId = LookupOperWithArgs(stmt->opername, false);
405  catalog = heap_open(OperatorRelationId, RowExclusiveLock);
407  if (tup == NULL)
408  elog(ERROR, "cache lookup failed for operator %u", oprId);
409  oprForm = (Form_pg_operator) GETSTRUCT(tup);
410 
411  /* Process options */
412  foreach(pl, stmt->options)
413  {
414  DefElem *defel = (DefElem *) lfirst(pl);
415  List *param;
416 
417  if (defel->arg == NULL)
418  param = NIL; /* NONE, removes the function */
419  else
420  param = defGetQualifiedName(defel);
421 
422  if (strcmp(defel->defname, "restrict") == 0)
423  {
424  restrictionName = param;
425  updateRestriction = true;
426  }
427  else if (strcmp(defel->defname, "join") == 0)
428  {
429  joinName = param;
430  updateJoin = true;
431  }
432 
433  /*
434  * The rest of the options that CREATE accepts cannot be changed.
435  * Check for them so that we can give a meaningful error message.
436  */
437  else if (strcmp(defel->defname, "leftarg") == 0 ||
438  strcmp(defel->defname, "rightarg") == 0 ||
439  strcmp(defel->defname, "procedure") == 0 ||
440  strcmp(defel->defname, "commutator") == 0 ||
441  strcmp(defel->defname, "negator") == 0 ||
442  strcmp(defel->defname, "hashes") == 0 ||
443  strcmp(defel->defname, "merges") == 0)
444  {
445  ereport(ERROR,
446  (errcode(ERRCODE_SYNTAX_ERROR),
447  errmsg("operator attribute \"%s\" cannot be changed",
448  defel->defname)));
449  }
450  else
451  ereport(ERROR,
452  (errcode(ERRCODE_SYNTAX_ERROR),
453  errmsg("operator attribute \"%s\" not recognized",
454  defel->defname)));
455  }
456 
457  /* Check permissions. Must be owner. */
458  if (!pg_oper_ownercheck(oprId, GetUserId()))
460  NameStr(oprForm->oprname));
461 
462  /*
463  * Look up restriction and join estimators if specified
464  */
465  if (restrictionName)
466  restrictionOid = ValidateRestrictionEstimator(restrictionName);
467  else
468  restrictionOid = InvalidOid;
469  if (joinName)
470  joinOid = ValidateJoinEstimator(joinName);
471  else
472  joinOid = InvalidOid;
473 
474  /* Perform additional checks, like OperatorCreate does */
475  if (!(OidIsValid(oprForm->oprleft) && OidIsValid(oprForm->oprright)))
476  {
477  /* If it's not a binary op, these things mustn't be set: */
478  if (OidIsValid(joinOid))
479  ereport(ERROR,
480  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
481  errmsg("only binary operators can have join selectivity")));
482  }
483 
484  if (oprForm->oprresult != BOOLOID)
485  {
486  if (OidIsValid(restrictionOid))
487  ereport(ERROR,
488  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
489  errmsg("only boolean operators can have restriction selectivity")));
490  if (OidIsValid(joinOid))
491  ereport(ERROR,
492  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
493  errmsg("only boolean operators can have join selectivity")));
494  }
495 
496  /* Update the tuple */
497  for (i = 0; i < Natts_pg_operator; ++i)
498  {
499  values[i] = (Datum) 0;
500  replaces[i] = false;
501  nulls[i] = false;
502  }
503  if (updateRestriction)
504  {
505  replaces[Anum_pg_operator_oprrest - 1] = true;
506  values[Anum_pg_operator_oprrest - 1] = restrictionOid;
507  }
508  if (updateJoin)
509  {
510  replaces[Anum_pg_operator_oprjoin - 1] = true;
511  values[Anum_pg_operator_oprjoin - 1] = joinOid;
512  }
513 
514  tup = heap_modify_tuple(tup, RelationGetDescr(catalog),
515  values, nulls, replaces);
516 
517  CatalogTupleUpdate(catalog, &tup->t_self, tup);
518 
519  address = makeOperatorDependencies(tup, true);
520 
521  InvokeObjectPostAlterHook(OperatorRelationId, oprId, 0);
522 
523  heap_close(catalog, NoLock);
524 
525  return address;
526 }
Oid LookupOperWithArgs(ObjectWithArgs *oper, bool noError)
Definition: parse_oper.c:140
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
#define RelationGetDescr(relation)
Definition: rel.h:433
Oid GetUserId(void)
Definition: miscinit.c:379
ObjectAddress makeOperatorDependencies(HeapTuple tuple, bool isUpdate)
Definition: pg_operator.c:763
static Oid ValidateJoinEstimator(List *joinName)
Definition: operatorcmds.c:295
bool pg_oper_ownercheck(Oid oper_oid, Oid roleid)
Definition: aclchk.c:4803
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3349
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
static Oid ValidateRestrictionEstimator(List *restrictionName)
Definition: operatorcmds.c:260
Node * arg
Definition: parsenodes.h:731
ObjectWithArgs * opername
Definition: parsenodes.h:2902
uintptr_t Datum
Definition: postgres.h:367
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define InvalidOid
Definition: postgres_ext.h:36
#define lfirst(lc)
Definition: pg_list.h:106
List * defGetQualifiedName(DefElem *def)
Definition: define.c:223
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:211
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:82
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define NameStr(name)
Definition: c.h:576
char * defname
Definition: parsenodes.h:730
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1173
Definition: pg_list.h:45

◆ DefineOperator()

ObjectAddress DefineOperator ( List names,
List parameters 
)

Definition at line 67 of file operatorcmds.c.

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

Referenced by ProcessUtilitySlow().

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. procedure */
83  List *joinName = NIL; /* optional join sel. procedure */
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 = pg_namespace_aclcheck(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  else if (strcmp(defel->defname, "procedure") == 0)
124  functionName = defGetQualifiedName(defel);
125  else if (strcmp(defel->defname, "commutator") == 0)
126  commutatorName = defGetQualifiedName(defel);
127  else if (strcmp(defel->defname, "negator") == 0)
128  negatorName = defGetQualifiedName(defel);
129  else if (strcmp(defel->defname, "restrict") == 0)
130  restrictionName = defGetQualifiedName(defel);
131  else if (strcmp(defel->defname, "join") == 0)
132  joinName = defGetQualifiedName(defel);
133  else if (strcmp(defel->defname, "hashes") == 0)
134  canHash = defGetBoolean(defel);
135  else if (strcmp(defel->defname, "merges") == 0)
136  canMerge = defGetBoolean(defel);
137  /* These obsolete options are taken as meaning canMerge */
138  else if (strcmp(defel->defname, "sort1") == 0)
139  canMerge = true;
140  else if (strcmp(defel->defname, "sort2") == 0)
141  canMerge = true;
142  else if (strcmp(defel->defname, "ltcmp") == 0)
143  canMerge = true;
144  else if (strcmp(defel->defname, "gtcmp") == 0)
145  canMerge = true;
146  else
147  {
148  /* WARNING, not ERROR, for historical backwards-compatibility */
150  (errcode(ERRCODE_SYNTAX_ERROR),
151  errmsg("operator attribute \"%s\" not recognized",
152  defel->defname)));
153  }
154  }
155 
156  /*
157  * make sure we have our required definitions
158  */
159  if (functionName == NIL)
160  ereport(ERROR,
161  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
162  errmsg("operator procedure must be specified")));
163 
164  /* Transform type names to type OIDs */
165  if (typeName1)
166  typeId1 = typenameTypeId(NULL, typeName1);
167  if (typeName2)
168  typeId2 = typenameTypeId(NULL, typeName2);
169 
170  if (!OidIsValid(typeId1) && !OidIsValid(typeId2))
171  ereport(ERROR,
172  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
173  errmsg("at least one of leftarg or rightarg must be specified")));
174 
175  if (typeName1)
176  {
177  aclresult = pg_type_aclcheck(typeId1, GetUserId(), ACL_USAGE);
178  if (aclresult != ACLCHECK_OK)
179  aclcheck_error_type(aclresult, typeId1);
180  }
181 
182  if (typeName2)
183  {
184  aclresult = pg_type_aclcheck(typeId2, GetUserId(), ACL_USAGE);
185  if (aclresult != ACLCHECK_OK)
186  aclcheck_error_type(aclresult, typeId2);
187  }
188 
189  /*
190  * Look up the operator's underlying function.
191  */
192  if (!OidIsValid(typeId1))
193  {
194  typeId[0] = typeId2;
195  nargs = 1;
196  }
197  else if (!OidIsValid(typeId2))
198  {
199  typeId[0] = typeId1;
200  nargs = 1;
201  }
202  else
203  {
204  typeId[0] = typeId1;
205  typeId[1] = typeId2;
206  nargs = 2;
207  }
208  functionOid = LookupFuncName(functionName, nargs, typeId, false);
209 
210  /*
211  * We require EXECUTE rights for the function. This isn't strictly
212  * necessary, since EXECUTE will be checked at any attempted use of the
213  * operator, but it seems like a good idea anyway.
214  */
215  aclresult = pg_proc_aclcheck(functionOid, GetUserId(), ACL_EXECUTE);
216  if (aclresult != ACLCHECK_OK)
217  aclcheck_error(aclresult, OBJECT_FUNCTION,
218  NameListToString(functionName));
219 
220  rettype = get_func_rettype(functionOid);
221  aclresult = pg_type_aclcheck(rettype, GetUserId(), ACL_USAGE);
222  if (aclresult != ACLCHECK_OK)
223  aclcheck_error_type(aclresult, rettype);
224 
225  /*
226  * Look up restriction and join estimators if specified
227  */
228  if (restrictionName)
229  restrictionOid = ValidateRestrictionEstimator(restrictionName);
230  else
231  restrictionOid = InvalidOid;
232  if (joinName)
233  joinOid = ValidateJoinEstimator(joinName);
234  else
235  joinOid = InvalidOid;
236 
237  /*
238  * now have OperatorCreate do all the work..
239  */
240  return
241  OperatorCreate(oprName, /* operator name */
242  oprNamespace, /* namespace */
243  typeId1, /* left type id */
244  typeId2, /* right type id */
245  functionOid, /* function for operator */
246  commutatorName, /* optional commutator operator name */
247  negatorName, /* optional negator operator name */
248  restrictionOid, /* optional restrict. sel. procedure */
249  joinOid, /* optional join sel. procedure name */
250  canMerge, /* operator merges */
251  canHash); /* operator hashes */
252 }
#define NIL
Definition: pg_list.h:69
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:323
Oid GetUserId(void)
Definition: miscinit.c:379
static Oid ValidateJoinEstimator(List *joinName)
Definition: operatorcmds.c:295
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2975
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4689
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3662
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1444
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3349
bool defGetBoolean(DefElem *def)
Definition: define.c:111
TypeName * defGetTypeName(DefElem *def)
Definition: define.c:255
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:84
bool setof
Definition: parsenodes.h:212
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3051
#define ACL_USAGE
Definition: parsenodes.h:82
#define ereport(elevel, rest)
Definition: elog.h:122
static Oid ValidateRestrictionEstimator(List *restrictionName)
Definition: operatorcmds.c:260
#define WARNING
Definition: elog.h:40
char * NameListToString(List *names)
Definition: namespace.c:3082
AclResult
Definition: acl.h:178
#define InvalidOid
Definition: postgres_ext.h:36
#define lfirst(lc)
Definition: pg_list.h:106
List * defGetQualifiedName(DefElem *def)
Definition: define.c:223
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
Definition: parse_func.c:2019
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ACL_EXECUTE
Definition: parsenodes.h:81
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4651
char * defname
Definition: parsenodes.h:730
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4739
Definition: pg_list.h:45
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274

◆ RemoveOperatorById()

void RemoveOperatorById ( Oid  operOid)

Definition at line 339 of file operatorcmds.c.

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

Referenced by doDeletion().

340 {
341  Relation relation;
342  HeapTuple tup;
343  Form_pg_operator op;
344 
345  relation = heap_open(OperatorRelationId, RowExclusiveLock);
346 
347  tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
348  if (!HeapTupleIsValid(tup)) /* should not happen */
349  elog(ERROR, "cache lookup failed for operator %u", operOid);
350  op = (Form_pg_operator) GETSTRUCT(tup);
351 
352  /*
353  * Reset links from commutator and negator, if any. In case of a
354  * self-commutator or self-negator, this means we have to re-fetch the
355  * updated tuple. (We could optimize away updates on the tuple we're
356  * about to drop, but it doesn't seem worth convoluting the logic for.)
357  */
358  if (OidIsValid(op->oprcom) || OidIsValid(op->oprnegate))
359  {
360  OperatorUpd(operOid, op->oprcom, op->oprnegate, true);
361  if (operOid == op->oprcom || operOid == op->oprnegate)
362  {
363  ReleaseSysCache(tup);
364  tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
365  if (!HeapTupleIsValid(tup)) /* should not happen */
366  elog(ERROR, "cache lookup failed for operator %u", operOid);
367  }
368  }
369 
370  CatalogTupleDelete(relation, &tup->t_self);
371 
372  ReleaseSysCache(tup);
373 
374  heap_close(relation, RowExclusiveLock);
375 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:256
#define heap_close(r, l)
Definition: heapam.h:97
#define OidIsValid(objectId)
Definition: c.h:605
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
void OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete)
Definition: pg_operator.c:644
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:82
#define elog
Definition: elog.h:219

◆ ValidateJoinEstimator()

static Oid ValidateJoinEstimator ( List joinName)
static

Definition at line 295 of file operatorcmds.c.

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

Referenced by AlterOperator(), and DefineOperator().

296 {
297  Oid typeId[5];
298  Oid joinOid;
299  AclResult aclresult;
300 
301  typeId[0] = INTERNALOID; /* PlannerInfo */
302  typeId[1] = OIDOID; /* operator OID */
303  typeId[2] = INTERNALOID; /* args list */
304  typeId[3] = INT2OID; /* jointype */
305  typeId[4] = INTERNALOID; /* SpecialJoinInfo */
306 
307  /*
308  * As of Postgres 8.4, the preferred signature for join estimators has 5
309  * arguments, but we still allow the old 4-argument form. Try the
310  * preferred form first.
311  */
312  joinOid = LookupFuncName(joinName, 5, typeId, true);
313  if (!OidIsValid(joinOid))
314  joinOid = LookupFuncName(joinName, 4, typeId, true);
315  /* If not found, reference the 5-argument signature in error msg */
316  if (!OidIsValid(joinOid))
317  joinOid = LookupFuncName(joinName, 5, typeId, false);
318 
319  /* estimators must return float8 */
320  if (get_func_rettype(joinOid) != FLOAT8OID)
321  ereport(ERROR,
322  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
323  errmsg("join estimator function %s must return type %s",
324  NameListToString(joinName), "float8")));
325 
326  /* Require EXECUTE rights for the estimator */
327  aclresult = pg_proc_aclcheck(joinOid, GetUserId(), ACL_EXECUTE);
328  if (aclresult != ACLCHECK_OK)
329  aclcheck_error(aclresult, OBJECT_FUNCTION,
330  NameListToString(joinName));
331 
332  return joinOid;
333 }
Oid GetUserId(void)
Definition: miscinit.c:379
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1444
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3349
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
char * NameListToString(List *names)
Definition: namespace.c:3082
AclResult
Definition: acl.h:178
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
Definition: parse_func.c:2019
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ACL_EXECUTE
Definition: parsenodes.h:81
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4651

◆ ValidateRestrictionEstimator()

static Oid ValidateRestrictionEstimator ( List restrictionName)
static

Definition at line 260 of file operatorcmds.c.

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

Referenced by AlterOperator(), and DefineOperator().

261 {
262  Oid typeId[4];
263  Oid restrictionOid;
264  AclResult aclresult;
265 
266  typeId[0] = INTERNALOID; /* PlannerInfo */
267  typeId[1] = OIDOID; /* operator OID */
268  typeId[2] = INTERNALOID; /* args list */
269  typeId[3] = INT4OID; /* varRelid */
270 
271  restrictionOid = LookupFuncName(restrictionName, 4, typeId, false);
272 
273  /* estimators must return float8 */
274  if (get_func_rettype(restrictionOid) != FLOAT8OID)
275  ereport(ERROR,
276  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
277  errmsg("restriction estimator function %s must return type %s",
278  NameListToString(restrictionName), "float8")));
279 
280  /* Require EXECUTE rights for the estimator */
281  aclresult = pg_proc_aclcheck(restrictionOid, GetUserId(), ACL_EXECUTE);
282  if (aclresult != ACLCHECK_OK)
283  aclcheck_error(aclresult, OBJECT_FUNCTION,
284  NameListToString(restrictionName));
285 
286  return restrictionOid;
287 }
Oid GetUserId(void)
Definition: miscinit.c:379
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1444
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3349
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
char * NameListToString(List *names)
Definition: namespace.c:3082
AclResult
Definition: acl.h:178
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
Definition: parse_func.c:2019
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ACL_EXECUTE
Definition: parsenodes.h:81
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4651