PostgreSQL Source Code  git master
functioncmds.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/table.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_cast.h"
#include "catalog/pg_language.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_transform.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "commands/extension.h"
#include "commands/proclang.h"
#include "executor/executor.h"
#include "executor/functions.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/optimizer.h"
#include "parser/analyze.h"
#include "parser/parse_coerce.h"
#include "parser/parse_collate.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h"
#include "parser/parse_type.h"
#include "pgstat.h"
#include "tcop/pquery.h"
#include "tcop/utility.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
Include dependency graph for functioncmds.c:

Go to the source code of this file.

Functions

static void compute_return_type (TypeName *returnType, Oid languageOid, Oid *prorettype_p, bool *returnsSet_p)
 
void interpret_function_parameter_list (ParseState *pstate, List *parameters, Oid languageOid, ObjectType objtype, oidvector **parameterTypes, List **parameterTypes_list, ArrayType **allParameterTypes, ArrayType **parameterModes, ArrayType **parameterNames, List **inParameterNames_list, List **parameterDefaults, Oid *variadicArgType, Oid *requiredResultType)
 
static bool compute_common_attribute (ParseState *pstate, bool is_procedure, DefElem *defel, DefElem **volatility_item, DefElem **strict_item, DefElem **security_item, DefElem **leakproof_item, List **set_items, DefElem **cost_item, DefElem **rows_item, DefElem **support_item, DefElem **parallel_item)
 
static char interpret_func_volatility (DefElem *defel)
 
static char interpret_func_parallel (DefElem *defel)
 
static ArrayTypeupdate_proconfig_value (ArrayType *a, List *set_items)
 
static Oid interpret_func_support (DefElem *defel)
 
static void compute_function_attributes (ParseState *pstate, bool is_procedure, List *options, List **as, char **language, Node **transform, bool *windowfunc_p, char *volatility_p, bool *strict_p, bool *security_definer, bool *leakproof_p, ArrayType **proconfig, float4 *procost, float4 *prorows, Oid *prosupport, char *parallel_p)
 
static void interpret_AS_clause (Oid languageOid, const char *languageName, char *funcname, List *as, Node *sql_body_in, List *parameterTypes, List *inParameterNames, char **prosrc_str_p, char **probin_str_p, Node **sql_body_out, const char *queryString)
 
ObjectAddress CreateFunction (ParseState *pstate, CreateFunctionStmt *stmt)
 
void RemoveFunctionById (Oid funcOid)
 
ObjectAddress AlterFunction (ParseState *pstate, AlterFunctionStmt *stmt)
 
ObjectAddress CreateCast (CreateCastStmt *stmt)
 
static void check_transform_function (Form_pg_proc procstruct)
 
ObjectAddress CreateTransform (CreateTransformStmt *stmt)
 
Oid get_transform_oid (Oid type_id, Oid lang_id, bool missing_ok)
 
void IsThereFunctionInNamespace (const char *proname, int pronargs, oidvector *proargtypes, Oid nspOid)
 
void ExecuteDoStmt (ParseState *pstate, DoStmt *stmt, bool atomic)
 
void ExecuteCallStmt (CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest)
 
TupleDesc CallStmtResultDesc (CallStmt *stmt)
 

Function Documentation

◆ AlterFunction()

ObjectAddress AlterFunction ( ParseState pstate,
AlterFunctionStmt stmt 
)

Definition at line 1343 of file functioncmds.c.

1344 {
1345  HeapTuple tup;
1346  Oid funcOid;
1347  Form_pg_proc procForm;
1348  bool is_procedure;
1349  Relation rel;
1350  ListCell *l;
1351  DefElem *volatility_item = NULL;
1352  DefElem *strict_item = NULL;
1353  DefElem *security_def_item = NULL;
1354  DefElem *leakproof_item = NULL;
1355  List *set_items = NIL;
1356  DefElem *cost_item = NULL;
1357  DefElem *rows_item = NULL;
1358  DefElem *support_item = NULL;
1359  DefElem *parallel_item = NULL;
1360  ObjectAddress address;
1361 
1362  rel = table_open(ProcedureRelationId, RowExclusiveLock);
1363 
1364  funcOid = LookupFuncWithArgs(stmt->objtype, stmt->func, false);
1365 
1366  ObjectAddressSet(address, ProcedureRelationId, funcOid);
1367 
1368  tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1369  if (!HeapTupleIsValid(tup)) /* should not happen */
1370  elog(ERROR, "cache lookup failed for function %u", funcOid);
1371 
1372  procForm = (Form_pg_proc) GETSTRUCT(tup);
1373 
1374  /* Permission check: must own function */
1375  if (!object_ownercheck(ProcedureRelationId, funcOid, GetUserId()))
1377  NameListToString(stmt->func->objname));
1378 
1379  if (procForm->prokind == PROKIND_AGGREGATE)
1380  ereport(ERROR,
1381  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1382  errmsg("\"%s\" is an aggregate function",
1383  NameListToString(stmt->func->objname))));
1384 
1385  is_procedure = (procForm->prokind == PROKIND_PROCEDURE);
1386 
1387  /* Examine requested actions. */
1388  foreach(l, stmt->actions)
1389  {
1390  DefElem *defel = (DefElem *) lfirst(l);
1391 
1392  if (compute_common_attribute(pstate,
1393  is_procedure,
1394  defel,
1395  &volatility_item,
1396  &strict_item,
1397  &security_def_item,
1398  &leakproof_item,
1399  &set_items,
1400  &cost_item,
1401  &rows_item,
1402  &support_item,
1403  &parallel_item) == false)
1404  elog(ERROR, "option \"%s\" not recognized", defel->defname);
1405  }
1406 
1407  if (volatility_item)
1408  procForm->provolatile = interpret_func_volatility(volatility_item);
1409  if (strict_item)
1410  procForm->proisstrict = boolVal(strict_item->arg);
1411  if (security_def_item)
1412  procForm->prosecdef = boolVal(security_def_item->arg);
1413  if (leakproof_item)
1414  {
1415  procForm->proleakproof = boolVal(leakproof_item->arg);
1416  if (procForm->proleakproof && !superuser())
1417  ereport(ERROR,
1418  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1419  errmsg("only superuser can define a leakproof function")));
1420  }
1421  if (cost_item)
1422  {
1423  procForm->procost = defGetNumeric(cost_item);
1424  if (procForm->procost <= 0)
1425  ereport(ERROR,
1426  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1427  errmsg("COST must be positive")));
1428  }
1429  if (rows_item)
1430  {
1431  procForm->prorows = defGetNumeric(rows_item);
1432  if (procForm->prorows <= 0)
1433  ereport(ERROR,
1434  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1435  errmsg("ROWS must be positive")));
1436  if (!procForm->proretset)
1437  ereport(ERROR,
1438  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1439  errmsg("ROWS is not applicable when function does not return a set")));
1440  }
1441  if (support_item)
1442  {
1443  /* interpret_func_support handles the privilege check */
1444  Oid newsupport = interpret_func_support(support_item);
1445 
1446  /* Add or replace dependency on support function */
1447  if (OidIsValid(procForm->prosupport))
1448  {
1449  if (changeDependencyFor(ProcedureRelationId, funcOid,
1450  ProcedureRelationId, procForm->prosupport,
1451  newsupport) != 1)
1452  elog(ERROR, "could not change support dependency for function %s",
1453  get_func_name(funcOid));
1454  }
1455  else
1456  {
1457  ObjectAddress referenced;
1458 
1459  referenced.classId = ProcedureRelationId;
1460  referenced.objectId = newsupport;
1461  referenced.objectSubId = 0;
1462  recordDependencyOn(&address, &referenced, DEPENDENCY_NORMAL);
1463  }
1464 
1465  procForm->prosupport = newsupport;
1466  }
1467  if (parallel_item)
1468  procForm->proparallel = interpret_func_parallel(parallel_item);
1469  if (set_items)
1470  {
1471  Datum datum;
1472  bool isnull;
1473  ArrayType *a;
1474  Datum repl_val[Natts_pg_proc];
1475  bool repl_null[Natts_pg_proc];
1476  bool repl_repl[Natts_pg_proc];
1477 
1478  /* extract existing proconfig setting */
1479  datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proconfig, &isnull);
1480  a = isnull ? NULL : DatumGetArrayTypeP(datum);
1481 
1482  /* update according to each SET or RESET item, left to right */
1483  a = update_proconfig_value(a, set_items);
1484 
1485  /* update the tuple */
1486  memset(repl_repl, false, sizeof(repl_repl));
1487  repl_repl[Anum_pg_proc_proconfig - 1] = true;
1488 
1489  if (a == NULL)
1490  {
1491  repl_val[Anum_pg_proc_proconfig - 1] = (Datum) 0;
1492  repl_null[Anum_pg_proc_proconfig - 1] = true;
1493  }
1494  else
1495  {
1496  repl_val[Anum_pg_proc_proconfig - 1] = PointerGetDatum(a);
1497  repl_null[Anum_pg_proc_proconfig - 1] = false;
1498  }
1499 
1500  tup = heap_modify_tuple(tup, RelationGetDescr(rel),
1501  repl_val, repl_null, repl_repl);
1502  }
1503  /* DO NOT put more touches of procForm below here; it's now dangling. */
1504 
1505  /* Do the update */
1506  CatalogTupleUpdate(rel, &tup->t_self, tup);
1507 
1508  InvokeObjectPostAlterHook(ProcedureRelationId, funcOid, 0);
1509 
1510  table_close(rel, NoLock);
1511  heap_freetuple(tup);
1512 
1513  return address;
1514 }
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2700
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4142
#define DatumGetArrayTypeP(X)
Definition: array.h:261
#define OidIsValid(objectId)
Definition: c.h:775
double defGetNumeric(DefElem *def)
Definition: define.c:81
@ DEPENDENCY_NORMAL
Definition: dependency.h:33
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#define ereport(elevel,...)
Definition: elog.h:149
static ArrayType * update_proconfig_value(ArrayType *a, List *set_items)
Definition: functioncmds.c:645
static Oid interpret_func_support(DefElem *defel)
Definition: functioncmds.c:670
static bool compute_common_attribute(ParseState *pstate, bool is_procedure, DefElem *defel, DefElem **volatility_item, DefElem **strict_item, DefElem **security_item, DefElem **leakproof_item, List **set_items, DefElem **cost_item, DefElem **rows_item, DefElem **support_item, DefElem **parallel_item)
Definition: functioncmds.c:500
static char interpret_func_volatility(DefElem *defel)
Definition: functioncmds.c:602
static char interpret_func_parallel(DefElem *defel)
Definition: functioncmds.c:620
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition: heaptuple.c:1209
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1434
#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
int a
Definition: isn.c:69
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1608
Oid GetUserId(void)
Definition: miscinit.c:514
char * NameListToString(const List *names)
Definition: namespace.c:3579
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2206
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:46
long changeDependencyFor(Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
Definition: pg_depend.c:458
#define lfirst(lc)
Definition: pg_list.h:172
#define NIL
Definition: pg_list.h:68
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationGetDescr(relation)
Definition: rel.h:531
char * defname
Definition: parsenodes.h:815
Node * arg
Definition: parsenodes.h:816
ItemPointerData t_self
Definition: htup.h:65
Definition: pg_list.h:54
bool superuser(void)
Definition: superuser.c:46
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:479
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:86
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
#define boolVal(v)
Definition: value.h:81

References a, aclcheck_error(), ACLCHECK_NOT_OWNER, DefElem::arg, boolVal, CatalogTupleUpdate(), changeDependencyFor(), ObjectAddress::classId, compute_common_attribute(), DatumGetArrayTypeP, defGetNumeric(), DefElem::defname, DEPENDENCY_NORMAL, elog, ereport, errcode(), errmsg(), ERROR, get_func_name(), GETSTRUCT, GetUserId(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, interpret_func_parallel(), interpret_func_support(), interpret_func_volatility(), InvokeObjectPostAlterHook, lfirst, LookupFuncWithArgs(), NameListToString(), NIL, NoLock, object_ownercheck(), ObjectAddressSet, ObjectAddress::objectId, ObjectIdGetDatum(), ObjectAddress::objectSubId, OidIsValid, PointerGetDatum(), recordDependencyOn(), RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy1, stmt, superuser(), SysCacheGetAttr(), HeapTupleData::t_self, table_close(), table_open(), and update_proconfig_value().

Referenced by ProcessUtilitySlow().

◆ CallStmtResultDesc()

TupleDesc CallStmtResultDesc ( CallStmt stmt)

Definition at line 2352 of file functioncmds.c.

2353 {
2354  FuncExpr *fexpr;
2355  HeapTuple tuple;
2356  TupleDesc tupdesc;
2357 
2358  fexpr = stmt->funcexpr;
2359 
2360  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
2361  if (!HeapTupleIsValid(tuple))
2362  elog(ERROR, "cache lookup failed for procedure %u", fexpr->funcid);
2363 
2364  tupdesc = build_function_result_tupdesc_t(tuple);
2365 
2366  ReleaseSysCache(tuple);
2367 
2368  /*
2369  * The result of build_function_result_tupdesc_t has the right column
2370  * names, but it just has the declared output argument types, which is the
2371  * wrong thing in polymorphic cases. Get the correct types by examining
2372  * stmt->outargs. We intentionally keep the atttypmod as -1 and the
2373  * attcollation as the type's default, since that's always the appropriate
2374  * thing for function outputs; there's no point in considering any
2375  * additional info available from outargs. Note that tupdesc is null if
2376  * there are no outargs.
2377  */
2378  if (tupdesc)
2379  {
2380  Assert(tupdesc->natts == list_length(stmt->outargs));
2381  for (int i = 0; i < tupdesc->natts; i++)
2382  {
2383  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
2384  Node *outarg = (Node *) list_nth(stmt->outargs, i);
2385 
2386  TupleDescInitEntry(tupdesc,
2387  i + 1,
2388  NameStr(att->attname),
2389  exprType(outarg),
2390  -1,
2391  0);
2392  }
2393  }
2394 
2395  return tupdesc;
2396 }
#define NameStr(name)
Definition: c.h:746
#define Assert(condition)
Definition: c.h:858
TupleDesc build_function_result_tupdesc_t(HeapTuple procTuple)
Definition: funcapi.c:1705
int i
Definition: isn.c:73
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
static int list_length(const List *l)
Definition: pg_list.h:152
static void * list_nth(const List *list, int n)
Definition: pg_list.h:299
Oid funcid
Definition: primnodes.h:750
Definition: nodes.h:129
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:266
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:218
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:651
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92

References Assert, build_function_result_tupdesc_t(), elog, ERROR, exprType(), FuncExpr::funcid, HeapTupleIsValid, i, list_length(), list_nth(), NameStr, TupleDescData::natts, ObjectIdGetDatum(), ReleaseSysCache(), SearchSysCache1(), stmt, TupleDescAttr, and TupleDescInitEntry().

Referenced by UtilityTupleDescriptor().

◆ check_transform_function()

static void check_transform_function ( Form_pg_proc  procstruct)
static

Definition at line 1771 of file functioncmds.c.

1772 {
1773  if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1774  ereport(ERROR,
1775  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1776  errmsg("transform function must not be volatile")));
1777  if (procstruct->prokind != PROKIND_FUNCTION)
1778  ereport(ERROR,
1779  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1780  errmsg("transform function must be a normal function")));
1781  if (procstruct->proretset)
1782  ereport(ERROR,
1783  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1784  errmsg("transform function must not return a set")));
1785  if (procstruct->pronargs != 1)
1786  ereport(ERROR,
1787  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1788  errmsg("transform function must take one argument")));
1789  if (procstruct->proargtypes.values[0] != INTERNALOID)
1790  ereport(ERROR,
1791  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1792  errmsg("first argument of transform function must be type %s",
1793  "internal")));
1794 }

References ereport, errcode(), errmsg(), and ERROR.

Referenced by CreateTransform().

◆ compute_common_attribute()

static bool compute_common_attribute ( ParseState pstate,
bool  is_procedure,
DefElem defel,
DefElem **  volatility_item,
DefElem **  strict_item,
DefElem **  security_item,
DefElem **  leakproof_item,
List **  set_items,
DefElem **  cost_item,
DefElem **  rows_item,
DefElem **  support_item,
DefElem **  parallel_item 
)
static

Definition at line 500 of file functioncmds.c.

512 {
513  if (strcmp(defel->defname, "volatility") == 0)
514  {
515  if (is_procedure)
516  goto procedure_error;
517  if (*volatility_item)
518  errorConflictingDefElem(defel, pstate);
519 
520  *volatility_item = defel;
521  }
522  else if (strcmp(defel->defname, "strict") == 0)
523  {
524  if (is_procedure)
525  goto procedure_error;
526  if (*strict_item)
527  errorConflictingDefElem(defel, pstate);
528 
529  *strict_item = defel;
530  }
531  else if (strcmp(defel->defname, "security") == 0)
532  {
533  if (*security_item)
534  errorConflictingDefElem(defel, pstate);
535 
536  *security_item = defel;
537  }
538  else if (strcmp(defel->defname, "leakproof") == 0)
539  {
540  if (is_procedure)
541  goto procedure_error;
542  if (*leakproof_item)
543  errorConflictingDefElem(defel, pstate);
544 
545  *leakproof_item = defel;
546  }
547  else if (strcmp(defel->defname, "set") == 0)
548  {
549  *set_items = lappend(*set_items, defel->arg);
550  }
551  else if (strcmp(defel->defname, "cost") == 0)
552  {
553  if (is_procedure)
554  goto procedure_error;
555  if (*cost_item)
556  errorConflictingDefElem(defel, pstate);
557 
558  *cost_item = defel;
559  }
560  else if (strcmp(defel->defname, "rows") == 0)
561  {
562  if (is_procedure)
563  goto procedure_error;
564  if (*rows_item)
565  errorConflictingDefElem(defel, pstate);
566 
567  *rows_item = defel;
568  }
569  else if (strcmp(defel->defname, "support") == 0)
570  {
571  if (is_procedure)
572  goto procedure_error;
573  if (*support_item)
574  errorConflictingDefElem(defel, pstate);
575 
576  *support_item = defel;
577  }
578  else if (strcmp(defel->defname, "parallel") == 0)
579  {
580  if (is_procedure)
581  goto procedure_error;
582  if (*parallel_item)
583  errorConflictingDefElem(defel, pstate);
584 
585  *parallel_item = defel;
586  }
587  else
588  return false;
589 
590  /* Recognized an option */
591  return true;
592 
593 procedure_error:
594  ereport(ERROR,
595  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
596  errmsg("invalid attribute in procedure definition"),
597  parser_errposition(pstate, defel->location)));
598  return false;
599 }
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:384
List * lappend(List *list, void *datum)
Definition: list.c:339
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:106
ParseLoc location
Definition: parsenodes.h:819

References DefElem::arg, DefElem::defname, ereport, errcode(), errmsg(), ERROR, errorConflictingDefElem(), lappend(), DefElem::location, and parser_errposition().

Referenced by AlterFunction(), and compute_function_attributes().

◆ compute_function_attributes()

static void compute_function_attributes ( ParseState pstate,
bool  is_procedure,
List options,
List **  as,
char **  language,
Node **  transform,
bool windowfunc_p,
char *  volatility_p,
bool strict_p,
bool security_definer,
bool leakproof_p,
ArrayType **  proconfig,
float4 procost,
float4 prorows,
Oid prosupport,
char *  parallel_p 
)
static

Definition at line 714 of file functioncmds.c.

730 {
731  ListCell *option;
732  DefElem *as_item = NULL;
733  DefElem *language_item = NULL;
734  DefElem *transform_item = NULL;
735  DefElem *windowfunc_item = NULL;
736  DefElem *volatility_item = NULL;
737  DefElem *strict_item = NULL;
738  DefElem *security_item = NULL;
739  DefElem *leakproof_item = NULL;
740  List *set_items = NIL;
741  DefElem *cost_item = NULL;
742  DefElem *rows_item = NULL;
743  DefElem *support_item = NULL;
744  DefElem *parallel_item = NULL;
745 
746  foreach(option, options)
747  {
748  DefElem *defel = (DefElem *) lfirst(option);
749 
750  if (strcmp(defel->defname, "as") == 0)
751  {
752  if (as_item)
753  errorConflictingDefElem(defel, pstate);
754  as_item = defel;
755  }
756  else if (strcmp(defel->defname, "language") == 0)
757  {
758  if (language_item)
759  errorConflictingDefElem(defel, pstate);
760  language_item = defel;
761  }
762  else if (strcmp(defel->defname, "transform") == 0)
763  {
764  if (transform_item)
765  errorConflictingDefElem(defel, pstate);
766  transform_item = defel;
767  }
768  else if (strcmp(defel->defname, "window") == 0)
769  {
770  if (windowfunc_item)
771  errorConflictingDefElem(defel, pstate);
772  if (is_procedure)
773  ereport(ERROR,
774  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
775  errmsg("invalid attribute in procedure definition"),
776  parser_errposition(pstate, defel->location)));
777  windowfunc_item = defel;
778  }
779  else if (compute_common_attribute(pstate,
780  is_procedure,
781  defel,
782  &volatility_item,
783  &strict_item,
784  &security_item,
785  &leakproof_item,
786  &set_items,
787  &cost_item,
788  &rows_item,
789  &support_item,
790  &parallel_item))
791  {
792  /* recognized common option */
793  continue;
794  }
795  else
796  elog(ERROR, "option \"%s\" not recognized",
797  defel->defname);
798  }
799 
800  if (as_item)
801  *as = (List *) as_item->arg;
802  if (language_item)
803  *language = strVal(language_item->arg);
804  if (transform_item)
805  *transform = transform_item->arg;
806  if (windowfunc_item)
807  *windowfunc_p = boolVal(windowfunc_item->arg);
808  if (volatility_item)
809  *volatility_p = interpret_func_volatility(volatility_item);
810  if (strict_item)
811  *strict_p = boolVal(strict_item->arg);
812  if (security_item)
813  *security_definer = boolVal(security_item->arg);
814  if (leakproof_item)
815  *leakproof_p = boolVal(leakproof_item->arg);
816  if (set_items)
817  *proconfig = update_proconfig_value(NULL, set_items);
818  if (cost_item)
819  {
820  *procost = defGetNumeric(cost_item);
821  if (*procost <= 0)
822  ereport(ERROR,
823  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
824  errmsg("COST must be positive")));
825  }
826  if (rows_item)
827  {
828  *prorows = defGetNumeric(rows_item);
829  if (*prorows <= 0)
830  ereport(ERROR,
831  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
832  errmsg("ROWS must be positive")));
833  }
834  if (support_item)
835  *prosupport = interpret_func_support(support_item);
836  if (parallel_item)
837  *parallel_p = interpret_func_parallel(parallel_item);
838 }
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
#define strVal(v)
Definition: value.h:82

References DefElem::arg, boolVal, compute_common_attribute(), defGetNumeric(), DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, errorConflictingDefElem(), if(), interpret_func_parallel(), interpret_func_support(), interpret_func_volatility(), lfirst, DefElem::location, NIL, parser_errposition(), strVal, and update_proconfig_value().

Referenced by CreateFunction().

◆ compute_return_type()

static void compute_return_type ( TypeName returnType,
Oid  languageOid,
Oid prorettype_p,
bool returnsSet_p 
)
static

Definition at line 88 of file functioncmds.c.

90 {
91  Oid rettype;
92  Type typtup;
93  AclResult aclresult;
94 
95  typtup = LookupTypeName(NULL, returnType, NULL, false);
96 
97  if (typtup)
98  {
99  if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
100  {
101  if (languageOid == SQLlanguageId)
102  ereport(ERROR,
103  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
104  errmsg("SQL function cannot return shell type %s",
105  TypeNameToString(returnType))));
106  else
107  ereport(NOTICE,
108  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
109  errmsg("return type %s is only a shell",
110  TypeNameToString(returnType))));
111  }
112  rettype = typeTypeId(typtup);
113  ReleaseSysCache(typtup);
114  }
115  else
116  {
117  char *typnam = TypeNameToString(returnType);
118  Oid namespaceId;
119  char *typname;
120  ObjectAddress address;
121 
122  /*
123  * Only C-coded functions can be I/O functions. We enforce this
124  * restriction here mainly to prevent littering the catalogs with
125  * shell types due to simple typos in user-defined function
126  * definitions.
127  */
128  if (languageOid != INTERNALlanguageId &&
129  languageOid != ClanguageId)
130  ereport(ERROR,
131  (errcode(ERRCODE_UNDEFINED_OBJECT),
132  errmsg("type \"%s\" does not exist", typnam)));
133 
134  /* Reject if there's typmod decoration, too */
135  if (returnType->typmods != NIL)
136  ereport(ERROR,
137  (errcode(ERRCODE_SYNTAX_ERROR),
138  errmsg("type modifier cannot be specified for shell type \"%s\"",
139  typnam)));
140 
141  /* Otherwise, go ahead and make a shell type */
142  ereport(NOTICE,
143  (errcode(ERRCODE_UNDEFINED_OBJECT),
144  errmsg("type \"%s\" is not yet defined", typnam),
145  errdetail("Creating a shell type definition.")));
146  namespaceId = QualifiedNameGetCreationNamespace(returnType->names,
147  &typname);
148  aclresult = object_aclcheck(NamespaceRelationId, namespaceId, GetUserId(),
149  ACL_CREATE);
150  if (aclresult != ACLCHECK_OK)
151  aclcheck_error(aclresult, OBJECT_SCHEMA,
152  get_namespace_name(namespaceId));
153  address = TypeShellMake(typname, namespaceId, GetUserId());
154  rettype = address.objectId;
155  Assert(OidIsValid(rettype));
156  }
157 
158  aclresult = object_aclcheck(TypeRelationId, rettype, GetUserId(), ACL_USAGE);
159  if (aclresult != ACLCHECK_OK)
160  aclcheck_error_type(aclresult, rettype);
161 
162  *prorettype_p = rettype;
163  *returnsSet_p = returnType->setof;
164 }
AclResult
Definition: acl.h:182
@ ACLCHECK_OK
Definition: acl.h:183
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3888
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3019
int errdetail(const char *fmt,...)
Definition: elog.c:1203
#define NOTICE
Definition: elog.h:35
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3366
Oid QualifiedNameGetCreationNamespace(const List *names, char **objname_p)
Definition: namespace.c:3472
Type LookupTypeName(ParseState *pstate, const TypeName *typeName, int32 *typmod_p, bool missing_ok)
Definition: parse_type.c:38
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:478
Oid typeTypeId(Type tp)
Definition: parse_type.c:590
#define ACL_USAGE
Definition: parsenodes.h:84
@ OBJECT_SCHEMA
Definition: parsenodes.h:2297
#define ACL_CREATE
Definition: parsenodes.h:85
ObjectAddress TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
Definition: pg_type.c:57
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
NameData typname
Definition: pg_type.h:41
bool setof
Definition: parsenodes.h:270
List * names
Definition: parsenodes.h:268
List * typmods
Definition: parsenodes.h:272

References ACL_CREATE, ACL_USAGE, aclcheck_error(), aclcheck_error_type(), ACLCHECK_OK, Assert, ereport, errcode(), errdetail(), errmsg(), ERROR, get_namespace_name(), GETSTRUCT, GetUserId(), LookupTypeName(), TypeName::names, NIL, NOTICE, object_aclcheck(), OBJECT_SCHEMA, ObjectAddress::objectId, OidIsValid, QualifiedNameGetCreationNamespace(), ReleaseSysCache(), TypeName::setof, TypeNameToString(), TypeShellMake(), typeTypeId(), TypeName::typmods, and typname.

Referenced by CreateFunction().

◆ CreateCast()

ObjectAddress CreateCast ( CreateCastStmt stmt)

Definition at line 1521 of file functioncmds.c.

1522 {
1523  Oid sourcetypeid;
1524  Oid targettypeid;
1525  char sourcetyptype;
1526  char targettyptype;
1527  Oid funcid;
1528  Oid incastid = InvalidOid;
1529  Oid outcastid = InvalidOid;
1530  int nargs;
1531  char castcontext;
1532  char castmethod;
1533  HeapTuple tuple;
1534  AclResult aclresult;
1535  ObjectAddress myself;
1536 
1537  sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
1538  targettypeid = typenameTypeId(NULL, stmt->targettype);
1539  sourcetyptype = get_typtype(sourcetypeid);
1540  targettyptype = get_typtype(targettypeid);
1541 
1542  /* No pseudo-types allowed */
1543  if (sourcetyptype == TYPTYPE_PSEUDO)
1544  ereport(ERROR,
1545  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1546  errmsg("source data type %s is a pseudo-type",
1547  TypeNameToString(stmt->sourcetype))));
1548 
1549  if (targettyptype == TYPTYPE_PSEUDO)
1550  ereport(ERROR,
1551  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1552  errmsg("target data type %s is a pseudo-type",
1553  TypeNameToString(stmt->targettype))));
1554 
1555  /* Permission check */
1556  if (!object_ownercheck(TypeRelationId, sourcetypeid, GetUserId())
1557  && !object_ownercheck(TypeRelationId, targettypeid, GetUserId()))
1558  ereport(ERROR,
1559  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1560  errmsg("must be owner of type %s or type %s",
1561  format_type_be(sourcetypeid),
1562  format_type_be(targettypeid))));
1563 
1564  aclresult = object_aclcheck(TypeRelationId, sourcetypeid, GetUserId(), ACL_USAGE);
1565  if (aclresult != ACLCHECK_OK)
1566  aclcheck_error_type(aclresult, sourcetypeid);
1567 
1568  aclresult = object_aclcheck(TypeRelationId, targettypeid, GetUserId(), ACL_USAGE);
1569  if (aclresult != ACLCHECK_OK)
1570  aclcheck_error_type(aclresult, targettypeid);
1571 
1572  /* Domains are allowed for historical reasons, but we warn */
1573  if (sourcetyptype == TYPTYPE_DOMAIN)
1574  ereport(WARNING,
1575  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1576  errmsg("cast will be ignored because the source data type is a domain")));
1577 
1578  else if (targettyptype == TYPTYPE_DOMAIN)
1579  ereport(WARNING,
1580  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1581  errmsg("cast will be ignored because the target data type is a domain")));
1582 
1583  /* Determine the cast method */
1584  if (stmt->func != NULL)
1585  castmethod = COERCION_METHOD_FUNCTION;
1586  else if (stmt->inout)
1587  castmethod = COERCION_METHOD_INOUT;
1588  else
1589  castmethod = COERCION_METHOD_BINARY;
1590 
1591  if (castmethod == COERCION_METHOD_FUNCTION)
1592  {
1593  Form_pg_proc procstruct;
1594 
1595  funcid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->func, false);
1596 
1597  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1598  if (!HeapTupleIsValid(tuple))
1599  elog(ERROR, "cache lookup failed for function %u", funcid);
1600 
1601  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1602  nargs = procstruct->pronargs;
1603  if (nargs < 1 || nargs > 3)
1604  ereport(ERROR,
1605  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1606  errmsg("cast function must take one to three arguments")));
1607  if (!IsBinaryCoercibleWithCast(sourcetypeid,
1608  procstruct->proargtypes.values[0],
1609  &incastid))
1610  ereport(ERROR,
1611  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1612  errmsg("argument of cast function must match or be binary-coercible from source data type")));
1613  if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
1614  ereport(ERROR,
1615  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1616  errmsg("second argument of cast function must be type %s",
1617  "integer")));
1618  if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)
1619  ereport(ERROR,
1620  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1621  errmsg("third argument of cast function must be type %s",
1622  "boolean")));
1623  if (!IsBinaryCoercibleWithCast(procstruct->prorettype,
1624  targettypeid,
1625  &outcastid))
1626  ereport(ERROR,
1627  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1628  errmsg("return data type of cast function must match or be binary-coercible to target data type")));
1629 
1630  /*
1631  * Restricting the volatility of a cast function may or may not be a
1632  * good idea in the abstract, but it definitely breaks many old
1633  * user-defined types. Disable this check --- tgl 2/1/03
1634  */
1635 #ifdef NOT_USED
1636  if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1637  ereport(ERROR,
1638  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1639  errmsg("cast function must not be volatile")));
1640 #endif
1641  if (procstruct->prokind != PROKIND_FUNCTION)
1642  ereport(ERROR,
1643  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1644  errmsg("cast function must be a normal function")));
1645  if (procstruct->proretset)
1646  ereport(ERROR,
1647  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1648  errmsg("cast function must not return a set")));
1649 
1650  ReleaseSysCache(tuple);
1651  }
1652  else
1653  {
1654  funcid = InvalidOid;
1655  nargs = 0;
1656  }
1657 
1658  if (castmethod == COERCION_METHOD_BINARY)
1659  {
1660  int16 typ1len;
1661  int16 typ2len;
1662  bool typ1byval;
1663  bool typ2byval;
1664  char typ1align;
1665  char typ2align;
1666 
1667  /*
1668  * Must be superuser to create binary-compatible casts, since
1669  * erroneous casts can easily crash the backend.
1670  */
1671  if (!superuser())
1672  ereport(ERROR,
1673  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1674  errmsg("must be superuser to create a cast WITHOUT FUNCTION")));
1675 
1676  /*
1677  * Also, insist that the types match as to size, alignment, and
1678  * pass-by-value attributes; this provides at least a crude check that
1679  * they have similar representations. A pair of types that fail this
1680  * test should certainly not be equated.
1681  */
1682  get_typlenbyvalalign(sourcetypeid, &typ1len, &typ1byval, &typ1align);
1683  get_typlenbyvalalign(targettypeid, &typ2len, &typ2byval, &typ2align);
1684  if (typ1len != typ2len ||
1685  typ1byval != typ2byval ||
1686  typ1align != typ2align)
1687  ereport(ERROR,
1688  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1689  errmsg("source and target data types are not physically compatible")));
1690 
1691  /*
1692  * We know that composite, enum and array types are never binary-
1693  * compatible with each other. They all have OIDs embedded in them.
1694  *
1695  * Theoretically you could build a user-defined base type that is
1696  * binary-compatible with a composite, enum, or array type. But we
1697  * disallow that too, as in practice such a cast is surely a mistake.
1698  * You can always work around that by writing a cast function.
1699  */
1700  if (sourcetyptype == TYPTYPE_COMPOSITE ||
1701  targettyptype == TYPTYPE_COMPOSITE)
1702  ereport(ERROR,
1703  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1704  errmsg("composite data types are not binary-compatible")));
1705 
1706  if (sourcetyptype == TYPTYPE_ENUM ||
1707  targettyptype == TYPTYPE_ENUM)
1708  ereport(ERROR,
1709  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1710  errmsg("enum data types are not binary-compatible")));
1711 
1712  if (OidIsValid(get_element_type(sourcetypeid)) ||
1713  OidIsValid(get_element_type(targettypeid)))
1714  ereport(ERROR,
1715  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1716  errmsg("array data types are not binary-compatible")));
1717 
1718  /*
1719  * We also disallow creating binary-compatibility casts involving
1720  * domains. Casting from a domain to its base type is already
1721  * allowed, and casting the other way ought to go through domain
1722  * coercion to permit constraint checking. Again, if you're intent on
1723  * having your own semantics for that, create a no-op cast function.
1724  *
1725  * NOTE: if we were to relax this, the above checks for composites
1726  * etc. would have to be modified to look through domains to their
1727  * base types.
1728  */
1729  if (sourcetyptype == TYPTYPE_DOMAIN ||
1730  targettyptype == TYPTYPE_DOMAIN)
1731  ereport(ERROR,
1732  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1733  errmsg("domain data types must not be marked binary-compatible")));
1734  }
1735 
1736  /*
1737  * Allow source and target types to be same only for length coercion
1738  * functions. We assume a multi-arg function does length coercion.
1739  */
1740  if (sourcetypeid == targettypeid && nargs < 2)
1741  ereport(ERROR,
1742  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1743  errmsg("source data type and target data type are the same")));
1744 
1745  /* convert CoercionContext enum to char value for castcontext */
1746  switch (stmt->context)
1747  {
1748  case COERCION_IMPLICIT:
1749  castcontext = COERCION_CODE_IMPLICIT;
1750  break;
1751  case COERCION_ASSIGNMENT:
1752  castcontext = COERCION_CODE_ASSIGNMENT;
1753  break;
1754  /* COERCION_PLPGSQL is intentionally not covered here */
1755  case COERCION_EXPLICIT:
1756  castcontext = COERCION_CODE_EXPLICIT;
1757  break;
1758  default:
1759  elog(ERROR, "unrecognized CoercionContext: %d", stmt->context);
1760  castcontext = 0; /* keep compiler quiet */
1761  break;
1762  }
1763 
1764  myself = CastCreate(sourcetypeid, targettypeid, funcid, incastid, outcastid,
1765  castcontext, castmethod, DEPENDENCY_NORMAL);
1766  return myself;
1767 }
signed short int16
Definition: c.h:493
#define WARNING
Definition: elog.h:36
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2759
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2271
char get_typtype(Oid typid)
Definition: lsyscache.c:2629
bool IsBinaryCoercibleWithCast(Oid srctype, Oid targettype, Oid *castoid)
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:291
@ OBJECT_FUNCTION
Definition: parsenodes.h:2280
ObjectAddress CastCreate(Oid sourcetypeid, Oid targettypeid, Oid funcid, Oid incastid, Oid outcastid, char castcontext, char castmethod, DependencyType behavior)
Definition: pg_cast.c:49
#define InvalidOid
Definition: postgres_ext.h:36
@ COERCION_ASSIGNMENT
Definition: primnodes.h:715
@ COERCION_EXPLICIT
Definition: primnodes.h:717
@ COERCION_IMPLICIT
Definition: primnodes.h:714

References ACL_USAGE, aclcheck_error_type(), ACLCHECK_OK, CastCreate(), COERCION_ASSIGNMENT, COERCION_EXPLICIT, COERCION_IMPLICIT, DEPENDENCY_NORMAL, elog, ereport, errcode(), errmsg(), ERROR, format_type_be(), get_element_type(), get_typlenbyvalalign(), get_typtype(), GETSTRUCT, GetUserId(), HeapTupleIsValid, InvalidOid, IsBinaryCoercibleWithCast(), LookupFuncWithArgs(), object_aclcheck(), OBJECT_FUNCTION, object_ownercheck(), ObjectIdGetDatum(), OidIsValid, ReleaseSysCache(), SearchSysCache1(), stmt, superuser(), TypeNameToString(), typenameTypeId(), and WARNING.

Referenced by ProcessUtilitySlow().

◆ CreateFunction()

ObjectAddress CreateFunction ( ParseState pstate,
CreateFunctionStmt stmt 
)

Definition at line 1011 of file functioncmds.c.

1012 {
1013  char *probin_str;
1014  char *prosrc_str;
1015  Node *prosqlbody;
1016  Oid prorettype;
1017  bool returnsSet;
1018  char *language;
1019  Oid languageOid;
1020  Oid languageValidator;
1021  Node *transformDefElem = NULL;
1022  char *funcname;
1023  Oid namespaceId;
1024  AclResult aclresult;
1025  oidvector *parameterTypes;
1026  List *parameterTypes_list = NIL;
1027  ArrayType *allParameterTypes;
1028  ArrayType *parameterModes;
1029  ArrayType *parameterNames;
1030  List *inParameterNames_list = NIL;
1031  List *parameterDefaults;
1032  Oid variadicArgType;
1033  List *trftypes_list = NIL;
1034  ArrayType *trftypes;
1035  Oid requiredResultType;
1036  bool isWindowFunc,
1037  isStrict,
1038  security,
1039  isLeakProof;
1040  char volatility;
1041  ArrayType *proconfig;
1042  float4 procost;
1043  float4 prorows;
1044  Oid prosupport;
1045  HeapTuple languageTuple;
1046  Form_pg_language languageStruct;
1047  List *as_clause;
1048  char parallel;
1049 
1050  /* Convert list of names to a name and namespace */
1051  namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
1052  &funcname);
1053 
1054  /* Check we have creation rights in target namespace */
1055  aclresult = object_aclcheck(NamespaceRelationId, namespaceId, GetUserId(), ACL_CREATE);
1056  if (aclresult != ACLCHECK_OK)
1057  aclcheck_error(aclresult, OBJECT_SCHEMA,
1058  get_namespace_name(namespaceId));
1059 
1060  /* Set default attributes */
1061  as_clause = NIL;
1062  language = NULL;
1063  isWindowFunc = false;
1064  isStrict = false;
1065  security = false;
1066  isLeakProof = false;
1067  volatility = PROVOLATILE_VOLATILE;
1068  proconfig = NULL;
1069  procost = -1; /* indicates not set */
1070  prorows = -1; /* indicates not set */
1071  prosupport = InvalidOid;
1072  parallel = PROPARALLEL_UNSAFE;
1073 
1074  /* Extract non-default attributes from stmt->options list */
1076  stmt->is_procedure,
1077  stmt->options,
1078  &as_clause, &language, &transformDefElem,
1079  &isWindowFunc, &volatility,
1080  &isStrict, &security, &isLeakProof,
1081  &proconfig, &procost, &prorows,
1082  &prosupport, &parallel);
1083 
1084  if (!language)
1085  {
1086  if (stmt->sql_body)
1087  language = "sql";
1088  else
1089  ereport(ERROR,
1090  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1091  errmsg("no language specified")));
1092  }
1093 
1094  /* Look up the language and validate permissions */
1095  languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
1096  if (!HeapTupleIsValid(languageTuple))
1097  ereport(ERROR,
1098  (errcode(ERRCODE_UNDEFINED_OBJECT),
1099  errmsg("language \"%s\" does not exist", language),
1100  (extension_file_exists(language) ?
1101  errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
1102 
1103  languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
1104  languageOid = languageStruct->oid;
1105 
1106  if (languageStruct->lanpltrusted)
1107  {
1108  /* if trusted language, need USAGE privilege */
1109  aclresult = object_aclcheck(LanguageRelationId, languageOid, GetUserId(), ACL_USAGE);
1110  if (aclresult != ACLCHECK_OK)
1111  aclcheck_error(aclresult, OBJECT_LANGUAGE,
1112  NameStr(languageStruct->lanname));
1113  }
1114  else
1115  {
1116  /* if untrusted language, must be superuser */
1117  if (!superuser())
1119  NameStr(languageStruct->lanname));
1120  }
1121 
1122  languageValidator = languageStruct->lanvalidator;
1123 
1124  ReleaseSysCache(languageTuple);
1125 
1126  /*
1127  * Only superuser is allowed to create leakproof functions because
1128  * leakproof functions can see tuples which have not yet been filtered out
1129  * by security barrier views or row-level security policies.
1130  */
1131  if (isLeakProof && !superuser())
1132  ereport(ERROR,
1133  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1134  errmsg("only superuser can define a leakproof function")));
1135 
1136  if (transformDefElem)
1137  {
1138  ListCell *lc;
1139 
1140  foreach(lc, castNode(List, transformDefElem))
1141  {
1142  Oid typeid = typenameTypeId(NULL,
1143  lfirst_node(TypeName, lc));
1144  Oid elt = get_base_element_type(typeid);
1145 
1146  typeid = elt ? elt : typeid;
1147 
1148  get_transform_oid(typeid, languageOid, false);
1149  trftypes_list = lappend_oid(trftypes_list, typeid);
1150  }
1151  }
1152 
1153  /*
1154  * Convert remaining parameters of CREATE to form wanted by
1155  * ProcedureCreate.
1156  */
1158  stmt->parameters,
1159  languageOid,
1160  stmt->is_procedure ? OBJECT_PROCEDURE : OBJECT_FUNCTION,
1161  &parameterTypes,
1162  &parameterTypes_list,
1163  &allParameterTypes,
1164  &parameterModes,
1165  &parameterNames,
1166  &inParameterNames_list,
1167  &parameterDefaults,
1168  &variadicArgType,
1169  &requiredResultType);
1170 
1171  if (stmt->is_procedure)
1172  {
1173  Assert(!stmt->returnType);
1174  prorettype = requiredResultType ? requiredResultType : VOIDOID;
1175  returnsSet = false;
1176  }
1177  else if (stmt->returnType)
1178  {
1179  /* explicit RETURNS clause */
1180  compute_return_type(stmt->returnType, languageOid,
1181  &prorettype, &returnsSet);
1182  if (OidIsValid(requiredResultType) && prorettype != requiredResultType)
1183  ereport(ERROR,
1184  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1185  errmsg("function result type must be %s because of OUT parameters",
1186  format_type_be(requiredResultType))));
1187  }
1188  else if (OidIsValid(requiredResultType))
1189  {
1190  /* default RETURNS clause from OUT parameters */
1191  prorettype = requiredResultType;
1192  returnsSet = false;
1193  }
1194  else
1195  {
1196  ereport(ERROR,
1197  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1198  errmsg("function result type must be specified")));
1199  /* Alternative possibility: default to RETURNS VOID */
1200  prorettype = VOIDOID;
1201  returnsSet = false;
1202  }
1203 
1204  if (trftypes_list != NIL)
1205  {
1206  ListCell *lc;
1207  Datum *arr;
1208  int i;
1209 
1210  arr = palloc(list_length(trftypes_list) * sizeof(Datum));
1211  i = 0;
1212  foreach(lc, trftypes_list)
1213  arr[i++] = ObjectIdGetDatum(lfirst_oid(lc));
1214  trftypes = construct_array_builtin(arr, list_length(trftypes_list), OIDOID);
1215  }
1216  else
1217  {
1218  /* store SQL NULL instead of empty array */
1219  trftypes = NULL;
1220  }
1221 
1222  interpret_AS_clause(languageOid, language, funcname, as_clause, stmt->sql_body,
1223  parameterTypes_list, inParameterNames_list,
1224  &prosrc_str, &probin_str, &prosqlbody,
1225  pstate->p_sourcetext);
1226 
1227  /*
1228  * Set default values for COST and ROWS depending on other parameters;
1229  * reject ROWS if it's not returnsSet. NB: pg_dump knows these default
1230  * values, keep it in sync if you change them.
1231  */
1232  if (procost < 0)
1233  {
1234  /* SQL and PL-language functions are assumed more expensive */
1235  if (languageOid == INTERNALlanguageId ||
1236  languageOid == ClanguageId)
1237  procost = 1;
1238  else
1239  procost = 100;
1240  }
1241  if (prorows < 0)
1242  {
1243  if (returnsSet)
1244  prorows = 1000;
1245  else
1246  prorows = 0; /* dummy value if not returnsSet */
1247  }
1248  else if (!returnsSet)
1249  ereport(ERROR,
1250  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1251  errmsg("ROWS is not applicable when function does not return a set")));
1252 
1253  /*
1254  * And now that we have all the parameters, and know we're permitted to do
1255  * so, go ahead and create the function.
1256  */
1257  return ProcedureCreate(funcname,
1258  namespaceId,
1259  stmt->replace,
1260  returnsSet,
1261  prorettype,
1262  GetUserId(),
1263  languageOid,
1264  languageValidator,
1265  prosrc_str, /* converted to text later */
1266  probin_str, /* converted to text later */
1267  prosqlbody,
1268  stmt->is_procedure ? PROKIND_PROCEDURE : (isWindowFunc ? PROKIND_WINDOW : PROKIND_FUNCTION),
1269  security,
1270  isLeakProof,
1271  isStrict,
1272  volatility,
1273  parallel,
1274  parameterTypes,
1275  PointerGetDatum(allParameterTypes),
1276  PointerGetDatum(parameterModes),
1277  PointerGetDatum(parameterNames),
1278  parameterDefaults,
1279  PointerGetDatum(trftypes),
1280  PointerGetDatum(proconfig),
1281  prosupport,
1282  procost,
1283  prorows);
1284 }
@ ACLCHECK_NO_PRIV
Definition: acl.h:184
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
Definition: arrayfuncs.c:3381
float float4
Definition: c.h:629
int errhint(const char *fmt,...)
Definition: elog.c:1317
bool extension_file_exists(const char *extensionName)
Definition: extension.c:2260
static void compute_return_type(TypeName *returnType, Oid languageOid, Oid *prorettype_p, bool *returnsSet_p)
Definition: functioncmds.c:88
static void compute_function_attributes(ParseState *pstate, bool is_procedure, List *options, List **as, char **language, Node **transform, bool *windowfunc_p, char *volatility_p, bool *strict_p, bool *security_definer, bool *leakproof_p, ArrayType **proconfig, float4 *procost, float4 *prorows, Oid *prosupport, char *parallel_p)
Definition: functioncmds.c:714
void interpret_function_parameter_list(ParseState *pstate, List *parameters, Oid languageOid, ObjectType objtype, oidvector **parameterTypes, List **parameterTypes_list, ArrayType **allParameterTypes, ArrayType **parameterModes, ArrayType **parameterNames, List **inParameterNames_list, List **parameterDefaults, Oid *variadicArgType, Oid *requiredResultType)
Definition: functioncmds.c:183
static void interpret_AS_clause(Oid languageOid, const char *languageName, char *funcname, List *as, Node *sql_body_in, List *parameterTypes, List *inParameterNames, char **prosrc_str_p, char **probin_str_p, Node **sql_body_out, const char *queryString)
Definition: functioncmds.c:851
Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok)
#define funcname
Definition: indent_codes.h:69
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2832
void * palloc(Size size)
Definition: mcxt.c:1317
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
@ OBJECT_PROCEDURE
Definition: parsenodes.h:2290
@ OBJECT_LANGUAGE
Definition: parsenodes.h:2282
FormData_pg_language * Form_pg_language
Definition: pg_language.h:65
#define lfirst_node(type, lc)
Definition: pg_list.h:176
#define lfirst_oid(lc)
Definition: pg_list.h:174
ObjectAddress ProcedureCreate(const char *procedureName, Oid procNamespace, bool replace, bool returnsSet, Oid returnType, Oid proowner, Oid languageObjectId, Oid languageValidator, const char *prosrc, const char *probin, Node *prosqlbody, char prokind, bool security_definer, bool isLeakProof, bool isStrict, char volatility, char parallel, oidvector *parameterTypes, Datum allParameterTypes, Datum parameterModes, Datum parameterNames, List *parameterDefaults, Datum trftypes, Datum proconfig, Oid prosupport, float4 procost, float4 prorows)
Definition: pg_proc.c:70
const char * p_sourcetext
Definition: parse_node.h:193
Definition: c.h:726

References ACL_CREATE, ACL_USAGE, aclcheck_error(), ACLCHECK_NO_PRIV, ACLCHECK_OK, Assert, castNode, compute_function_attributes(), compute_return_type(), construct_array_builtin(), ereport, errcode(), errhint(), errmsg(), ERROR, extension_file_exists(), format_type_be(), funcname, get_base_element_type(), get_namespace_name(), get_transform_oid(), GETSTRUCT, GetUserId(), HeapTupleIsValid, i, interpret_AS_clause(), interpret_function_parameter_list(), InvalidOid, lappend_oid(), lfirst_node, lfirst_oid, list_length(), NameStr, NIL, object_aclcheck(), OBJECT_FUNCTION, OBJECT_LANGUAGE, OBJECT_PROCEDURE, OBJECT_SCHEMA, ObjectIdGetDatum(), OidIsValid, ParseState::p_sourcetext, palloc(), PointerGetDatum(), ProcedureCreate(), QualifiedNameGetCreationNamespace(), ReleaseSysCache(), SearchSysCache1(), stmt, superuser(), and typenameTypeId().

Referenced by ProcessUtilitySlow().

◆ CreateTransform()

ObjectAddress CreateTransform ( CreateTransformStmt stmt)

Definition at line 1801 of file functioncmds.c.

1802 {
1803  Oid typeid;
1804  char typtype;
1805  Oid langid;
1806  Oid fromsqlfuncid;
1807  Oid tosqlfuncid;
1808  AclResult aclresult;
1809  Form_pg_proc procstruct;
1810  Datum values[Natts_pg_transform];
1811  bool nulls[Natts_pg_transform] = {0};
1812  bool replaces[Natts_pg_transform] = {0};
1813  Oid transformid;
1814  HeapTuple tuple;
1815  HeapTuple newtuple;
1816  Relation relation;
1817  ObjectAddress myself,
1818  referenced;
1819  ObjectAddresses *addrs;
1820  bool is_replace;
1821 
1822  /*
1823  * Get the type
1824  */
1825  typeid = typenameTypeId(NULL, stmt->type_name);
1826  typtype = get_typtype(typeid);
1827 
1828  if (typtype == TYPTYPE_PSEUDO)
1829  ereport(ERROR,
1830  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1831  errmsg("data type %s is a pseudo-type",
1832  TypeNameToString(stmt->type_name))));
1833 
1834  if (typtype == TYPTYPE_DOMAIN)
1835  ereport(ERROR,
1836  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1837  errmsg("data type %s is a domain",
1838  TypeNameToString(stmt->type_name))));
1839 
1840  if (!object_ownercheck(TypeRelationId, typeid, GetUserId()))
1842 
1843  aclresult = object_aclcheck(TypeRelationId, typeid, GetUserId(), ACL_USAGE);
1844  if (aclresult != ACLCHECK_OK)
1845  aclcheck_error_type(aclresult, typeid);
1846 
1847  /*
1848  * Get the language
1849  */
1850  langid = get_language_oid(stmt->lang, false);
1851 
1852  aclresult = object_aclcheck(LanguageRelationId, langid, GetUserId(), ACL_USAGE);
1853  if (aclresult != ACLCHECK_OK)
1854  aclcheck_error(aclresult, OBJECT_LANGUAGE, stmt->lang);
1855 
1856  /*
1857  * Get the functions
1858  */
1859  if (stmt->fromsql)
1860  {
1861  fromsqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->fromsql, false);
1862 
1863  if (!object_ownercheck(ProcedureRelationId, fromsqlfuncid, GetUserId()))
1865 
1866  aclresult = object_aclcheck(ProcedureRelationId, fromsqlfuncid, GetUserId(), ACL_EXECUTE);
1867  if (aclresult != ACLCHECK_OK)
1868  aclcheck_error(aclresult, OBJECT_FUNCTION, NameListToString(stmt->fromsql->objname));
1869 
1870  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fromsqlfuncid));
1871  if (!HeapTupleIsValid(tuple))
1872  elog(ERROR, "cache lookup failed for function %u", fromsqlfuncid);
1873  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1874  if (procstruct->prorettype != INTERNALOID)
1875  ereport(ERROR,
1876  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1877  errmsg("return data type of FROM SQL function must be %s",
1878  "internal")));
1879  check_transform_function(procstruct);
1880  ReleaseSysCache(tuple);
1881  }
1882  else
1883  fromsqlfuncid = InvalidOid;
1884 
1885  if (stmt->tosql)
1886  {
1887  tosqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->tosql, false);
1888 
1889  if (!object_ownercheck(ProcedureRelationId, tosqlfuncid, GetUserId()))
1891 
1892  aclresult = object_aclcheck(ProcedureRelationId, tosqlfuncid, GetUserId(), ACL_EXECUTE);
1893  if (aclresult != ACLCHECK_OK)
1894  aclcheck_error(aclresult, OBJECT_FUNCTION, NameListToString(stmt->tosql->objname));
1895 
1896  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(tosqlfuncid));
1897  if (!HeapTupleIsValid(tuple))
1898  elog(ERROR, "cache lookup failed for function %u", tosqlfuncid);
1899  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1900  if (procstruct->prorettype != typeid)
1901  ereport(ERROR,
1902  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1903  errmsg("return data type of TO SQL function must be the transform data type")));
1904  check_transform_function(procstruct);
1905  ReleaseSysCache(tuple);
1906  }
1907  else
1908  tosqlfuncid = InvalidOid;
1909 
1910  /*
1911  * Ready to go
1912  */
1913  values[Anum_pg_transform_trftype - 1] = ObjectIdGetDatum(typeid);
1914  values[Anum_pg_transform_trflang - 1] = ObjectIdGetDatum(langid);
1915  values[Anum_pg_transform_trffromsql - 1] = ObjectIdGetDatum(fromsqlfuncid);
1916  values[Anum_pg_transform_trftosql - 1] = ObjectIdGetDatum(tosqlfuncid);
1917 
1918  relation = table_open(TransformRelationId, RowExclusiveLock);
1919 
1920  tuple = SearchSysCache2(TRFTYPELANG,
1921  ObjectIdGetDatum(typeid),
1922  ObjectIdGetDatum(langid));
1923  if (HeapTupleIsValid(tuple))
1924  {
1926 
1927  if (!stmt->replace)
1928  ereport(ERROR,
1930  errmsg("transform for type %s language \"%s\" already exists",
1931  format_type_be(typeid),
1932  stmt->lang)));
1933 
1934  replaces[Anum_pg_transform_trffromsql - 1] = true;
1935  replaces[Anum_pg_transform_trftosql - 1] = true;
1936 
1937  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
1938  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
1939 
1940  transformid = form->oid;
1941  ReleaseSysCache(tuple);
1942  is_replace = true;
1943  }
1944  else
1945  {
1946  transformid = GetNewOidWithIndex(relation, TransformOidIndexId,
1947  Anum_pg_transform_oid);
1948  values[Anum_pg_transform_oid - 1] = ObjectIdGetDatum(transformid);
1949  newtuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
1950  CatalogTupleInsert(relation, newtuple);
1951  is_replace = false;
1952  }
1953 
1954  if (is_replace)
1955  deleteDependencyRecordsFor(TransformRelationId, transformid, true);
1956 
1957  addrs = new_object_addresses();
1958 
1959  /* make dependency entries */
1960  ObjectAddressSet(myself, TransformRelationId, transformid);
1961 
1962  /* dependency on language */
1963  ObjectAddressSet(referenced, LanguageRelationId, langid);
1964  add_exact_object_address(&referenced, addrs);
1965 
1966  /* dependency on type */
1967  ObjectAddressSet(referenced, TypeRelationId, typeid);
1968  add_exact_object_address(&referenced, addrs);
1969 
1970  /* dependencies on functions */
1971  if (OidIsValid(fromsqlfuncid))
1972  {
1973  ObjectAddressSet(referenced, ProcedureRelationId, fromsqlfuncid);
1974  add_exact_object_address(&referenced, addrs);
1975  }
1976  if (OidIsValid(tosqlfuncid))
1977  {
1978  ObjectAddressSet(referenced, ProcedureRelationId, tosqlfuncid);
1979  add_exact_object_address(&referenced, addrs);
1980  }
1981 
1983  free_object_addresses(addrs);
1984 
1985  /* dependency on extension */
1986  recordDependencyOnCurrentExtension(&myself, is_replace);
1987 
1988  /* Post creation hook for new transform */
1989  InvokeObjectPostCreateHook(TransformRelationId, transformid, 0);
1990 
1991  heap_freetuple(newtuple);
1992 
1993  table_close(relation, RowExclusiveLock);
1994 
1995  return myself;
1996 }
static Datum values[MAXATTR]
Definition: bootstrap.c:150
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:412
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2742
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2487
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2533
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2773
static void check_transform_function(Form_pg_proc procstruct)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1116
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:173
#define ACL_EXECUTE
Definition: parsenodes.h:83
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:302
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:194
FormData_pg_transform * Form_pg_transform
Definition: pg_transform.h:43
Oid get_language_oid(const char *langname, bool missing_ok)
Definition: proclang.c:226
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:229

References ACL_EXECUTE, ACL_USAGE, aclcheck_error(), aclcheck_error_type(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, add_exact_object_address(), CatalogTupleInsert(), CatalogTupleUpdate(), check_transform_function(), deleteDependencyRecordsFor(), DEPENDENCY_NORMAL, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, format_type_be(), free_object_addresses(), get_language_oid(), get_typtype(), GetNewOidWithIndex(), GETSTRUCT, GetUserId(), heap_form_tuple(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, InvalidOid, InvokeObjectPostCreateHook, LookupFuncWithArgs(), NameListToString(), new_object_addresses(), object_aclcheck(), OBJECT_FUNCTION, OBJECT_LANGUAGE, object_ownercheck(), ObjectAddressSet, ObjectIdGetDatum(), OidIsValid, record_object_address_dependencies(), recordDependencyOnCurrentExtension(), RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), SearchSysCache2(), stmt, HeapTupleData::t_self, table_close(), table_open(), TypeNameToString(), typenameTypeId(), and values.

Referenced by ProcessUtilitySlow().

◆ ExecuteCallStmt()

void ExecuteCallStmt ( CallStmt stmt,
ParamListInfo  params,
bool  atomic,
DestReceiver dest 
)

Definition at line 2175 of file functioncmds.c.

2176 {
2177  LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
2178  ListCell *lc;
2179  FuncExpr *fexpr;
2180  int nargs;
2181  int i;
2182  AclResult aclresult;
2183  FmgrInfo flinfo;
2184  CallContext *callcontext;
2185  EState *estate;
2186  ExprContext *econtext;
2187  HeapTuple tp;
2188  PgStat_FunctionCallUsage fcusage;
2189  Datum retval;
2190 
2191  fexpr = stmt->funcexpr;
2192  Assert(fexpr);
2193  Assert(IsA(fexpr, FuncExpr));
2194 
2195  aclresult = object_aclcheck(ProcedureRelationId, fexpr->funcid, GetUserId(), ACL_EXECUTE);
2196  if (aclresult != ACLCHECK_OK)
2197  aclcheck_error(aclresult, OBJECT_PROCEDURE, get_func_name(fexpr->funcid));
2198 
2199  /* Prep the context object we'll pass to the procedure */
2200  callcontext = makeNode(CallContext);
2201  callcontext->atomic = atomic;
2202 
2203  tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
2204  if (!HeapTupleIsValid(tp))
2205  elog(ERROR, "cache lookup failed for function %u", fexpr->funcid);
2206 
2207  /*
2208  * If proconfig is set we can't allow transaction commands because of the
2209  * way the GUC stacking works: The transaction boundary would have to pop
2210  * the proconfig setting off the stack. That restriction could be lifted
2211  * by redesigning the GUC nesting mechanism a bit.
2212  */
2213  if (!heap_attisnull(tp, Anum_pg_proc_proconfig, NULL))
2214  callcontext->atomic = true;
2215 
2216  /*
2217  * In security definer procedures, we can't allow transaction commands.
2218  * StartTransaction() insists that the security context stack is empty,
2219  * and AbortTransaction() resets the security context. This could be
2220  * reorganized, but right now it doesn't work.
2221  */
2222  if (((Form_pg_proc) GETSTRUCT(tp))->prosecdef)
2223  callcontext->atomic = true;
2224 
2225  ReleaseSysCache(tp);
2226 
2227  /* safety check; see ExecInitFunc() */
2228  nargs = list_length(fexpr->args);
2229  if (nargs > FUNC_MAX_ARGS)
2230  ereport(ERROR,
2231  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2232  errmsg_plural("cannot pass more than %d argument to a procedure",
2233  "cannot pass more than %d arguments to a procedure",
2234  FUNC_MAX_ARGS,
2235  FUNC_MAX_ARGS)));
2236 
2237  /* Initialize function call structure */
2239  fmgr_info(fexpr->funcid, &flinfo);
2240  fmgr_info_set_expr((Node *) fexpr, &flinfo);
2241  InitFunctionCallInfoData(*fcinfo, &flinfo, nargs, fexpr->inputcollid,
2242  (Node *) callcontext, NULL);
2243 
2244  /*
2245  * Evaluate procedure arguments inside a suitable execution context. Note
2246  * we can't free this context till the procedure returns.
2247  */
2248  estate = CreateExecutorState();
2249  estate->es_param_list_info = params;
2250  econtext = CreateExprContext(estate);
2251 
2252  /*
2253  * If we're called in non-atomic context, we also have to ensure that the
2254  * argument expressions run with an up-to-date snapshot. Our caller will
2255  * have provided a current snapshot in atomic contexts, but not in
2256  * non-atomic contexts, because the possibility of a COMMIT/ROLLBACK
2257  * destroying the snapshot makes higher-level management too complicated.
2258  */
2259  if (!atomic)
2261 
2262  i = 0;
2263  foreach(lc, fexpr->args)
2264  {
2265  ExprState *exprstate;
2266  Datum val;
2267  bool isnull;
2268 
2269  exprstate = ExecPrepareExpr(lfirst(lc), estate);
2270 
2271  val = ExecEvalExprSwitchContext(exprstate, econtext, &isnull);
2272 
2273  fcinfo->args[i].value = val;
2274  fcinfo->args[i].isnull = isnull;
2275 
2276  i++;
2277  }
2278 
2279  /* Get rid of temporary snapshot for arguments, if we made one */
2280  if (!atomic)
2282 
2283  /* Here we actually call the procedure */
2284  pgstat_init_function_usage(fcinfo, &fcusage);
2285  retval = FunctionCallInvoke(fcinfo);
2286  pgstat_end_function_usage(&fcusage, true);
2287 
2288  /* Handle the procedure's outputs */
2289  if (fexpr->funcresulttype == VOIDOID)
2290  {
2291  /* do nothing */
2292  }
2293  else if (fexpr->funcresulttype == RECORDOID)
2294  {
2295  /* send tuple to client */
2296  HeapTupleHeader td;
2297  Oid tupType;
2298  int32 tupTypmod;
2299  TupleDesc retdesc;
2300  HeapTupleData rettupdata;
2301  TupOutputState *tstate;
2302  TupleTableSlot *slot;
2303 
2304  if (fcinfo->isnull)
2305  elog(ERROR, "procedure returned null record");
2306 
2307  /*
2308  * Ensure there's an active snapshot whilst we execute whatever's
2309  * involved here. Note that this is *not* sufficient to make the
2310  * world safe for TOAST pointers to be included in the returned data:
2311  * the referenced data could have gone away while we didn't hold a
2312  * snapshot. Hence, it's incumbent on PLs that can do COMMIT/ROLLBACK
2313  * to not return TOAST pointers, unless those pointers were fetched
2314  * after the last COMMIT/ROLLBACK in the procedure.
2315  *
2316  * XXX that is a really nasty, hard-to-test requirement. Is there a
2317  * way to remove it?
2318  */
2320 
2321  td = DatumGetHeapTupleHeader(retval);
2322  tupType = HeapTupleHeaderGetTypeId(td);
2323  tupTypmod = HeapTupleHeaderGetTypMod(td);
2324  retdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
2325 
2326  tstate = begin_tup_output_tupdesc(dest, retdesc,
2327  &TTSOpsHeapTuple);
2328 
2329  rettupdata.t_len = HeapTupleHeaderGetDatumLength(td);
2330  ItemPointerSetInvalid(&(rettupdata.t_self));
2331  rettupdata.t_tableOid = InvalidOid;
2332  rettupdata.t_data = td;
2333 
2334  slot = ExecStoreHeapTuple(&rettupdata, tstate->slot, false);
2335  tstate->dest->receiveSlot(slot, tstate->dest);
2336 
2337  end_tup_output(tstate);
2338 
2339  ReleaseTupleDesc(retdesc);
2340  }
2341  else
2342  elog(ERROR, "unexpected result type for procedure: %u",
2343  fexpr->funcresulttype);
2344 
2345  FreeExecutorState(estate);
2346 }
signed int int32
Definition: c.h:494
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1180
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition: execExpr.c:739
void end_tup_output(TupOutputState *tstate)
Definition: execTuples.c:2420
TupleTableSlot * ExecStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:1439
const TupleTableSlotOps TTSOpsHeapTuple
Definition: execTuples.c:85
TupOutputState * begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:2342
EState * CreateExecutorState(void)
Definition: execUtils.c:88
ExprContext * CreateExprContext(EState *estate)
Definition: execUtils.c:304
void FreeExecutorState(EState *estate)
Definition: execUtils.c:189
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:348
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:127
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:172
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:135
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:455
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:466
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:456
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:450
long val
Definition: informix.c:670
static void ItemPointerSetInvalid(ItemPointerData *pointer)
Definition: itemptr.h:184
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define makeNode(_type_)
Definition: nodes.h:155
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:213
#define FUNC_MAX_ARGS
void pgstat_init_function_usage(FunctionCallInfo fcinfo, PgStat_FunctionCallUsage *fcu)
void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize)
void EnsurePortalSnapshotExists(void)
Definition: pquery.c:1780
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:216
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:648
void PopActiveSnapshot(void)
Definition: snapmgr.c:743
ParamListInfo es_param_list_info
Definition: execnodes.h:661
Definition: fmgr.h:57
List * args
Definition: primnodes.h:768
uint32 t_len
Definition: htup.h:64
HeapTupleHeader t_data
Definition: htup.h:68
Oid t_tableOid
Definition: htup.h:66
TupleTableSlot * slot
Definition: executor.h:506
DestReceiver * dest
Definition: executor.h:507
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h:118
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:122
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1833

References ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, FuncExpr::args, Assert, CallContext::atomic, begin_tup_output_tupdesc(), CreateExecutorState(), CreateExprContext(), DatumGetHeapTupleHeader, generate_unaccent_rules::dest, TupOutputState::dest, elog, end_tup_output(), EnsurePortalSnapshotExists(), ereport, errcode(), errmsg_plural(), ERROR, EState::es_param_list_info, ExecEvalExprSwitchContext(), ExecPrepareExpr(), ExecStoreHeapTuple(), fmgr_info(), fmgr_info_set_expr, FreeExecutorState(), FUNC_MAX_ARGS, FuncExpr::funcid, FunctionCallInvoke, get_func_name(), GETSTRUCT, GetTransactionSnapshot(), GetUserId(), heap_attisnull(), HeapTupleHeaderGetDatumLength, HeapTupleHeaderGetTypeId, HeapTupleHeaderGetTypMod, HeapTupleIsValid, i, InitFunctionCallInfoData, InvalidOid, InvokeFunctionExecuteHook, IsA, ItemPointerSetInvalid(), lfirst, list_length(), LOCAL_FCINFO, lookup_rowtype_tupdesc(), makeNode, object_aclcheck(), OBJECT_PROCEDURE, ObjectIdGetDatum(), pgstat_end_function_usage(), pgstat_init_function_usage(), PopActiveSnapshot(), PushActiveSnapshot(), _DestReceiver::receiveSlot, ReleaseSysCache(), ReleaseTupleDesc, SearchSysCache1(), TupOutputState::slot, stmt, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, TTSOpsHeapTuple, and val.

Referenced by standard_ProcessUtility().

◆ ExecuteDoStmt()

void ExecuteDoStmt ( ParseState pstate,
DoStmt stmt,
bool  atomic 
)

Definition at line 2053 of file functioncmds.c.

2054 {
2056  ListCell *arg;
2057  DefElem *as_item = NULL;
2058  DefElem *language_item = NULL;
2059  char *language;
2060  Oid laninline;
2061  HeapTuple languageTuple;
2062  Form_pg_language languageStruct;
2063 
2064  /* Process options we got from gram.y */
2065  foreach(arg, stmt->args)
2066  {
2067  DefElem *defel = (DefElem *) lfirst(arg);
2068 
2069  if (strcmp(defel->defname, "as") == 0)
2070  {
2071  if (as_item)
2072  errorConflictingDefElem(defel, pstate);
2073  as_item = defel;
2074  }
2075  else if (strcmp(defel->defname, "language") == 0)
2076  {
2077  if (language_item)
2078  errorConflictingDefElem(defel, pstate);
2079  language_item = defel;
2080  }
2081  else
2082  elog(ERROR, "option \"%s\" not recognized",
2083  defel->defname);
2084  }
2085 
2086  if (as_item)
2087  codeblock->source_text = strVal(as_item->arg);
2088  else
2089  ereport(ERROR,
2090  (errcode(ERRCODE_SYNTAX_ERROR),
2091  errmsg("no inline code specified")));
2092 
2093  /* if LANGUAGE option wasn't specified, use the default */
2094  if (language_item)
2095  language = strVal(language_item->arg);
2096  else
2097  language = "plpgsql";
2098 
2099  /* Look up the language and validate permissions */
2100  languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
2101  if (!HeapTupleIsValid(languageTuple))
2102  ereport(ERROR,
2103  (errcode(ERRCODE_UNDEFINED_OBJECT),
2104  errmsg("language \"%s\" does not exist", language),
2105  (extension_file_exists(language) ?
2106  errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
2107 
2108  languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
2109  codeblock->langOid = languageStruct->oid;
2110  codeblock->langIsTrusted = languageStruct->lanpltrusted;
2111  codeblock->atomic = atomic;
2112 
2113  if (languageStruct->lanpltrusted)
2114  {
2115  /* if trusted language, need USAGE privilege */
2116  AclResult aclresult;
2117 
2118  aclresult = object_aclcheck(LanguageRelationId, codeblock->langOid, GetUserId(),
2119  ACL_USAGE);
2120  if (aclresult != ACLCHECK_OK)
2121  aclcheck_error(aclresult, OBJECT_LANGUAGE,
2122  NameStr(languageStruct->lanname));
2123  }
2124  else
2125  {
2126  /* if untrusted language, must be superuser */
2127  if (!superuser())
2129  NameStr(languageStruct->lanname));
2130  }
2131 
2132  /* get the handler function's OID */
2133  laninline = languageStruct->laninline;
2134  if (!OidIsValid(laninline))
2135  ereport(ERROR,
2136  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2137  errmsg("language \"%s\" does not support inline code execution",
2138  NameStr(languageStruct->lanname))));
2139 
2140  ReleaseSysCache(languageTuple);
2141 
2142  /* execute the inline handler */
2143  OidFunctionCall1(laninline, PointerGetDatum(codeblock));
2144 }
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:680
void * arg
char * source_text
Definition: parsenodes.h:3490

References ACL_USAGE, aclcheck_error(), ACLCHECK_NO_PRIV, ACLCHECK_OK, arg, DefElem::arg, InlineCodeBlock::atomic, DefElem::defname, elog, ereport, errcode(), errhint(), errmsg(), ERROR, errorConflictingDefElem(), extension_file_exists(), GETSTRUCT, GetUserId(), HeapTupleIsValid, InlineCodeBlock::langIsTrusted, InlineCodeBlock::langOid, lfirst, makeNode, NameStr, object_aclcheck(), OBJECT_LANGUAGE, OidFunctionCall1, OidIsValid, PointerGetDatum(), ReleaseSysCache(), SearchSysCache1(), InlineCodeBlock::source_text, stmt, strVal, and superuser().

Referenced by standard_ProcessUtility().

◆ get_transform_oid()

Oid get_transform_oid ( Oid  type_id,
Oid  lang_id,
bool  missing_ok 
)

Definition at line 2006 of file functioncmds.c.

2007 {
2008  Oid oid;
2009 
2010  oid = GetSysCacheOid2(TRFTYPELANG, Anum_pg_transform_oid,
2011  ObjectIdGetDatum(type_id),
2012  ObjectIdGetDatum(lang_id));
2013  if (!OidIsValid(oid) && !missing_ok)
2014  ereport(ERROR,
2015  (errcode(ERRCODE_UNDEFINED_OBJECT),
2016  errmsg("transform for type %s language \"%s\" does not exist",
2017  format_type_be(type_id),
2018  get_language_name(lang_id, false))));
2019  return oid;
2020 }
char * get_language_name(Oid langoid, bool missing_ok)
Definition: lsyscache.c:1161
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:106

References ereport, errcode(), errmsg(), ERROR, format_type_be(), get_language_name(), GetSysCacheOid2, ObjectIdGetDatum(), and OidIsValid.

Referenced by CreateFunction(), get_object_address(), and ProcedureCreate().

◆ interpret_AS_clause()

static void interpret_AS_clause ( Oid  languageOid,
const char *  languageName,
char *  funcname,
List as,
Node sql_body_in,
List parameterTypes,
List inParameterNames,
char **  prosrc_str_p,
char **  probin_str_p,
Node **  sql_body_out,
const char *  queryString 
)
static

Definition at line 851 of file functioncmds.c.

857 {
858  if (!sql_body_in && !as)
859  ereport(ERROR,
860  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
861  errmsg("no function body specified")));
862 
863  if (sql_body_in && as)
864  ereport(ERROR,
865  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
866  errmsg("duplicate function body specified")));
867 
868  if (sql_body_in && languageOid != SQLlanguageId)
869  ereport(ERROR,
870  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
871  errmsg("inline SQL function body only valid for language SQL")));
872 
873  *sql_body_out = NULL;
874 
875  if (languageOid == ClanguageId)
876  {
877  /*
878  * For "C" language, store the file name in probin and, when given,
879  * the link symbol name in prosrc. If link symbol is omitted,
880  * substitute procedure name. We also allow link symbol to be
881  * specified as "-", since that was the habit in PG versions before
882  * 8.4, and there might be dump files out there that don't translate
883  * that back to "omitted".
884  */
885  *probin_str_p = strVal(linitial(as));
886  if (list_length(as) == 1)
887  *prosrc_str_p = funcname;
888  else
889  {
890  *prosrc_str_p = strVal(lsecond(as));
891  if (strcmp(*prosrc_str_p, "-") == 0)
892  *prosrc_str_p = funcname;
893  }
894  }
895  else if (sql_body_in)
896  {
898 
900 
901  pinfo->fname = funcname;
902  pinfo->nargs = list_length(parameterTypes);
903  pinfo->argtypes = (Oid *) palloc(pinfo->nargs * sizeof(Oid));
904  pinfo->argnames = (char **) palloc(pinfo->nargs * sizeof(char *));
905  for (int i = 0; i < list_length(parameterTypes); i++)
906  {
907  char *s = strVal(list_nth(inParameterNames, i));
908 
909  pinfo->argtypes[i] = list_nth_oid(parameterTypes, i);
910  if (IsPolymorphicType(pinfo->argtypes[i]))
911  ereport(ERROR,
912  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
913  errmsg("SQL function with unquoted function body cannot have polymorphic arguments")));
914 
915  if (s[0] != '\0')
916  pinfo->argnames[i] = s;
917  else
918  pinfo->argnames[i] = NULL;
919  }
920 
921  if (IsA(sql_body_in, List))
922  {
923  List *stmts = linitial_node(List, castNode(List, sql_body_in));
924  ListCell *lc;
925  List *transformed_stmts = NIL;
926 
927  foreach(lc, stmts)
928  {
929  Node *stmt = lfirst(lc);
930  Query *q;
931  ParseState *pstate = make_parsestate(NULL);
932 
933  pstate->p_sourcetext = queryString;
934  sql_fn_parser_setup(pstate, pinfo);
935  q = transformStmt(pstate, stmt);
936  if (q->commandType == CMD_UTILITY)
937  ereport(ERROR,
938  errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
939  errmsg("%s is not yet supported in unquoted SQL function body",
941  transformed_stmts = lappend(transformed_stmts, q);
942  free_parsestate(pstate);
943  }
944 
945  *sql_body_out = (Node *) list_make1(transformed_stmts);
946  }
947  else
948  {
949  Query *q;
950  ParseState *pstate = make_parsestate(NULL);
951 
952  pstate->p_sourcetext = queryString;
953  sql_fn_parser_setup(pstate, pinfo);
954  q = transformStmt(pstate, sql_body_in);
955  if (q->commandType == CMD_UTILITY)
956  ereport(ERROR,
957  errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
958  errmsg("%s is not yet supported in unquoted SQL function body",
960  free_parsestate(pstate);
961 
962  *sql_body_out = (Node *) q;
963  }
964 
965  /*
966  * We must put something in prosrc. For the moment, just record an
967  * empty string. It might be useful to store the original text of the
968  * CREATE FUNCTION statement --- but to make actual use of that in
969  * error reports, we'd also have to adjust readfuncs.c to not throw
970  * away node location fields when reading prosqlbody.
971  */
972  *prosrc_str_p = pstrdup("");
973 
974  /* But we definitely don't need probin. */
975  *probin_str_p = NULL;
976  }
977  else
978  {
979  /* Everything else wants the given string in prosrc. */
980  *prosrc_str_p = strVal(linitial(as));
981  *probin_str_p = NULL;
982 
983  if (list_length(as) != 1)
984  ereport(ERROR,
985  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
986  errmsg("only one AS item needed for language \"%s\"",
987  languageName)));
988 
989  if (languageOid == INTERNALlanguageId)
990  {
991  /*
992  * In PostgreSQL versions before 6.5, the SQL name of the created
993  * function could not be different from the internal name, and
994  * "prosrc" wasn't used. So there is code out there that does
995  * CREATE FUNCTION xyz AS '' LANGUAGE internal. To preserve some
996  * modicum of backwards compatibility, accept an empty "prosrc"
997  * value as meaning the supplied SQL function name.
998  */
999  if (strlen(*prosrc_str_p) == 0)
1000  *prosrc_str_p = funcname;
1001  }
1002  }
1003 }
const char * GetCommandTagName(CommandTag commandTag)
Definition: cmdtag.c:47
void sql_fn_parser_setup(struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)
Definition: functions.c:265
SQLFunctionParseInfo * SQLFunctionParseInfoPtr
Definition: functions.h:35
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void * palloc0(Size size)
Definition: mcxt.c:1347
@ CMD_UTILITY
Definition: nodes.h:270
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:72
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:39
Query * transformStmt(ParseState *pstate, Node *parseTree)
Definition: analyze.c:311
#define linitial_node(type, l)
Definition: pg_list.h:181
static Oid list_nth_oid(const List *list, int n)
Definition: pg_list.h:321
#define list_make1(x1)
Definition: pg_list.h:212
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
CmdType commandType
Definition: parsenodes.h:121
Node * utilityStmt
Definition: parsenodes.h:136
CommandTag CreateCommandTag(Node *parsetree)
Definition: utility.c:2359

References SQLFunctionParseInfo::argnames, SQLFunctionParseInfo::argtypes, castNode, CMD_UTILITY, Query::commandType, CreateCommandTag(), ereport, errcode(), errmsg(), ERROR, SQLFunctionParseInfo::fname, free_parsestate(), funcname, GetCommandTagName(), i, IsA, lappend(), lfirst, linitial, linitial_node, list_length(), list_make1, list_nth(), list_nth_oid(), lsecond, make_parsestate(), SQLFunctionParseInfo::nargs, NIL, ParseState::p_sourcetext, palloc(), palloc0(), pstrdup(), sql_fn_parser_setup(), stmt, strVal, transformStmt(), and Query::utilityStmt.

Referenced by CreateFunction().

◆ interpret_func_parallel()

static char interpret_func_parallel ( DefElem defel)
static

Definition at line 620 of file functioncmds.c.

621 {
622  char *str = strVal(defel->arg);
623 
624  if (strcmp(str, "safe") == 0)
625  return PROPARALLEL_SAFE;
626  else if (strcmp(str, "unsafe") == 0)
627  return PROPARALLEL_UNSAFE;
628  else if (strcmp(str, "restricted") == 0)
629  return PROPARALLEL_RESTRICTED;
630  else
631  {
632  ereport(ERROR,
633  (errcode(ERRCODE_SYNTAX_ERROR),
634  errmsg("parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE")));
635  return PROPARALLEL_UNSAFE; /* keep compiler quiet */
636  }
637 }
const char * str

References DefElem::arg, ereport, errcode(), errmsg(), ERROR, str, and strVal.

Referenced by AlterFunction(), and compute_function_attributes().

◆ interpret_func_support()

static Oid interpret_func_support ( DefElem defel)
static

Definition at line 670 of file functioncmds.c.

671 {
672  List *procName = defGetQualifiedName(defel);
673  Oid procOid;
674  Oid argList[1];
675 
676  /*
677  * Support functions always take one INTERNAL argument and return
678  * INTERNAL.
679  */
680  argList[0] = INTERNALOID;
681 
682  procOid = LookupFuncName(procName, 1, argList, true);
683  if (!OidIsValid(procOid))
684  ereport(ERROR,
685  (errcode(ERRCODE_UNDEFINED_FUNCTION),
686  errmsg("function %s does not exist",
687  func_signature_string(procName, 1, NIL, argList))));
688 
689  if (get_func_rettype(procOid) != INTERNALOID)
690  ereport(ERROR,
691  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
692  errmsg("support function %s must return type %s",
693  NameListToString(procName), "internal")));
694 
695  /*
696  * Someday we might want an ACL check here; but for now, we insist that
697  * you be superuser to specify a support function, so privilege on the
698  * support function is moot.
699  */
700  if (!superuser())
701  ereport(ERROR,
702  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
703  errmsg("must be superuser to specify a support function")));
704 
705  return procOid;
706 }
List * defGetQualifiedName(DefElem *def)
Definition: define.c:252
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1655
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:2030
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
Definition: parse_func.c:2144

References defGetQualifiedName(), ereport, errcode(), errmsg(), ERROR, func_signature_string(), get_func_rettype(), LookupFuncName(), NameListToString(), NIL, OidIsValid, and superuser().

Referenced by AlterFunction(), and compute_function_attributes().

◆ interpret_func_volatility()

static char interpret_func_volatility ( DefElem defel)
static

Definition at line 602 of file functioncmds.c.

603 {
604  char *str = strVal(defel->arg);
605 
606  if (strcmp(str, "immutable") == 0)
607  return PROVOLATILE_IMMUTABLE;
608  else if (strcmp(str, "stable") == 0)
609  return PROVOLATILE_STABLE;
610  else if (strcmp(str, "volatile") == 0)
611  return PROVOLATILE_VOLATILE;
612  else
613  {
614  elog(ERROR, "invalid volatility \"%s\"", str);
615  return 0; /* keep compiler quiet */
616  }
617 }

References DefElem::arg, elog, ERROR, str, and strVal.

Referenced by AlterFunction(), and compute_function_attributes().

◆ interpret_function_parameter_list()

void interpret_function_parameter_list ( ParseState pstate,
List parameters,
Oid  languageOid,
ObjectType  objtype,
oidvector **  parameterTypes,
List **  parameterTypes_list,
ArrayType **  allParameterTypes,
ArrayType **  parameterModes,
ArrayType **  parameterNames,
List **  inParameterNames_list,
List **  parameterDefaults,
Oid variadicArgType,
Oid requiredResultType 
)

Definition at line 183 of file functioncmds.c.

196 {
197  int parameterCount = list_length(parameters);
198  Oid *inTypes;
199  int inCount = 0;
200  Datum *allTypes;
201  Datum *paramModes;
202  Datum *paramNames;
203  int outCount = 0;
204  int varCount = 0;
205  bool have_names = false;
206  bool have_defaults = false;
207  ListCell *x;
208  int i;
209 
210  *variadicArgType = InvalidOid; /* default result */
211  *requiredResultType = InvalidOid; /* default result */
212 
213  inTypes = (Oid *) palloc(parameterCount * sizeof(Oid));
214  allTypes = (Datum *) palloc(parameterCount * sizeof(Datum));
215  paramModes = (Datum *) palloc(parameterCount * sizeof(Datum));
216  paramNames = (Datum *) palloc0(parameterCount * sizeof(Datum));
217  *parameterDefaults = NIL;
218 
219  /* Scan the list and extract data into work arrays */
220  i = 0;
221  foreach(x, parameters)
222  {
224  TypeName *t = fp->argType;
225  FunctionParameterMode fpmode = fp->mode;
226  bool isinput = false;
227  Oid toid;
228  Type typtup;
229  AclResult aclresult;
230 
231  /* For our purposes here, a defaulted mode spec is identical to IN */
232  if (fpmode == FUNC_PARAM_DEFAULT)
233  fpmode = FUNC_PARAM_IN;
234 
235  typtup = LookupTypeName(NULL, t, NULL, false);
236  if (typtup)
237  {
238  if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
239  {
240  /* As above, hard error if language is SQL */
241  if (languageOid == SQLlanguageId)
242  ereport(ERROR,
243  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
244  errmsg("SQL function cannot accept shell type %s",
245  TypeNameToString(t))));
246  /* We don't allow creating aggregates on shell types either */
247  else if (objtype == OBJECT_AGGREGATE)
248  ereport(ERROR,
249  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
250  errmsg("aggregate cannot accept shell type %s",
251  TypeNameToString(t))));
252  else
253  ereport(NOTICE,
254  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
255  errmsg("argument type %s is only a shell",
256  TypeNameToString(t))));
257  }
258  toid = typeTypeId(typtup);
259  ReleaseSysCache(typtup);
260  }
261  else
262  {
263  ereport(ERROR,
264  (errcode(ERRCODE_UNDEFINED_OBJECT),
265  errmsg("type %s does not exist",
266  TypeNameToString(t))));
267  toid = InvalidOid; /* keep compiler quiet */
268  }
269 
270  aclresult = object_aclcheck(TypeRelationId, toid, GetUserId(), ACL_USAGE);
271  if (aclresult != ACLCHECK_OK)
272  aclcheck_error_type(aclresult, toid);
273 
274  if (t->setof)
275  {
276  if (objtype == OBJECT_AGGREGATE)
277  ereport(ERROR,
278  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
279  errmsg("aggregates cannot accept set arguments")));
280  else if (objtype == OBJECT_PROCEDURE)
281  ereport(ERROR,
282  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
283  errmsg("procedures cannot accept set arguments")));
284  else
285  ereport(ERROR,
286  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
287  errmsg("functions cannot accept set arguments")));
288  }
289 
290  /* handle input parameters */
291  if (fpmode != FUNC_PARAM_OUT && fpmode != FUNC_PARAM_TABLE)
292  {
293  /* other input parameters can't follow a VARIADIC parameter */
294  if (varCount > 0)
295  ereport(ERROR,
296  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
297  errmsg("VARIADIC parameter must be the last input parameter")));
298  inTypes[inCount++] = toid;
299  isinput = true;
300  if (parameterTypes_list)
301  *parameterTypes_list = lappend_oid(*parameterTypes_list, toid);
302  }
303 
304  /* handle output parameters */
305  if (fpmode != FUNC_PARAM_IN && fpmode != FUNC_PARAM_VARIADIC)
306  {
307  if (objtype == OBJECT_PROCEDURE)
308  {
309  /*
310  * We disallow OUT-after-VARIADIC only for procedures. While
311  * such a case causes no confusion in ordinary function calls,
312  * it would cause confusion in a CALL statement.
313  */
314  if (varCount > 0)
315  ereport(ERROR,
316  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
317  errmsg("VARIADIC parameter must be the last parameter")));
318  /* Procedures with output parameters always return RECORD */
319  *requiredResultType = RECORDOID;
320  }
321  else if (outCount == 0) /* save first output param's type */
322  *requiredResultType = toid;
323  outCount++;
324  }
325 
326  if (fpmode == FUNC_PARAM_VARIADIC)
327  {
328  *variadicArgType = toid;
329  varCount++;
330  /* validate variadic parameter type */
331  switch (toid)
332  {
333  case ANYARRAYOID:
334  case ANYCOMPATIBLEARRAYOID:
335  case ANYOID:
336  /* okay */
337  break;
338  default:
339  if (!OidIsValid(get_element_type(toid)))
340  ereport(ERROR,
341  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
342  errmsg("VARIADIC parameter must be an array")));
343  break;
344  }
345  }
346 
347  allTypes[i] = ObjectIdGetDatum(toid);
348 
349  paramModes[i] = CharGetDatum(fpmode);
350 
351  if (fp->name && fp->name[0])
352  {
353  ListCell *px;
354 
355  /*
356  * As of Postgres 9.0 we disallow using the same name for two
357  * input or two output function parameters. Depending on the
358  * function's language, conflicting input and output names might
359  * be bad too, but we leave it to the PL to complain if so.
360  */
361  foreach(px, parameters)
362  {
364  FunctionParameterMode prevfpmode;
365 
366  if (prevfp == fp)
367  break;
368  /* as above, default mode is IN */
369  prevfpmode = prevfp->mode;
370  if (prevfpmode == FUNC_PARAM_DEFAULT)
371  prevfpmode = FUNC_PARAM_IN;
372  /* pure in doesn't conflict with pure out */
373  if ((fpmode == FUNC_PARAM_IN ||
374  fpmode == FUNC_PARAM_VARIADIC) &&
375  (prevfpmode == FUNC_PARAM_OUT ||
376  prevfpmode == FUNC_PARAM_TABLE))
377  continue;
378  if ((prevfpmode == FUNC_PARAM_IN ||
379  prevfpmode == FUNC_PARAM_VARIADIC) &&
380  (fpmode == FUNC_PARAM_OUT ||
381  fpmode == FUNC_PARAM_TABLE))
382  continue;
383  if (prevfp->name && prevfp->name[0] &&
384  strcmp(prevfp->name, fp->name) == 0)
385  ereport(ERROR,
386  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
387  errmsg("parameter name \"%s\" used more than once",
388  fp->name)));
389  }
390 
391  paramNames[i] = CStringGetTextDatum(fp->name);
392  have_names = true;
393  }
394 
395  if (inParameterNames_list)
396  *inParameterNames_list = lappend(*inParameterNames_list, makeString(fp->name ? fp->name : pstrdup("")));
397 
398  if (fp->defexpr)
399  {
400  Node *def;
401 
402  if (!isinput)
403  ereport(ERROR,
404  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
405  errmsg("only input parameters can have default values")));
406 
407  def = transformExpr(pstate, fp->defexpr,
409  def = coerce_to_specific_type(pstate, def, toid, "DEFAULT");
410  assign_expr_collations(pstate, def);
411 
412  /*
413  * Make sure no variables are referred to (this is probably dead
414  * code now that add_missing_from is history).
415  */
416  if (pstate->p_rtable != NIL ||
417  contain_var_clause(def))
418  ereport(ERROR,
419  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
420  errmsg("cannot use table references in parameter default value")));
421 
422  /*
423  * transformExpr() should have already rejected subqueries,
424  * aggregates, and window functions, based on the EXPR_KIND_ for a
425  * default expression.
426  *
427  * It can't return a set either --- but coerce_to_specific_type
428  * already checked that for us.
429  *
430  * Note: the point of these restrictions is to ensure that an
431  * expression that, on its face, hasn't got subplans, aggregates,
432  * etc cannot suddenly have them after function default arguments
433  * are inserted.
434  */
435 
436  *parameterDefaults = lappend(*parameterDefaults, def);
437  have_defaults = true;
438  }
439  else
440  {
441  if (isinput && have_defaults)
442  ereport(ERROR,
443  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
444  errmsg("input parameters after one with a default value must also have defaults")));
445 
446  /*
447  * For procedures, we also can't allow OUT parameters after one
448  * with a default, because the same sort of confusion arises in a
449  * CALL statement.
450  */
451  if (objtype == OBJECT_PROCEDURE && have_defaults)
452  ereport(ERROR,
453  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
454  errmsg("procedure OUT parameters cannot appear after one with a default value")));
455  }
456 
457  i++;
458  }
459 
460  /* Now construct the proper outputs as needed */
461  *parameterTypes = buildoidvector(inTypes, inCount);
462 
463  if (outCount > 0 || varCount > 0)
464  {
465  *allParameterTypes = construct_array_builtin(allTypes, parameterCount, OIDOID);
466  *parameterModes = construct_array_builtin(paramModes, parameterCount, CHAROID);
467  if (outCount > 1)
468  *requiredResultType = RECORDOID;
469  /* otherwise we set requiredResultType correctly above */
470  }
471  else
472  {
473  *allParameterTypes = NULL;
474  *parameterModes = NULL;
475  }
476 
477  if (have_names)
478  {
479  for (i = 0; i < parameterCount; i++)
480  {
481  if (paramNames[i] == PointerGetDatum(NULL))
482  paramNames[i] = CStringGetTextDatum("");
483  }
484  *parameterNames = construct_array_builtin(paramNames, parameterCount, TEXTOID);
485  }
486  else
487  *parameterNames = NULL;
488 }
#define CStringGetTextDatum(s)
Definition: builtins.h:97
void px(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
int x
Definition: isn.c:71
oidvector * buildoidvector(const Oid *oids, int n)
Definition: oid.c:87
Node * coerce_to_specific_type(ParseState *pstate, Node *node, Oid targetTypeId, const char *constructName)
void assign_expr_collations(ParseState *pstate, Node *expr)
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:120
@ EXPR_KIND_FUNCTION_DEFAULT
Definition: parse_node.h:71
FunctionParameterMode
Definition: parsenodes.h:3445
@ FUNC_PARAM_IN
Definition: parsenodes.h:3447
@ FUNC_PARAM_DEFAULT
Definition: parsenodes.h:3453
@ FUNC_PARAM_OUT
Definition: parsenodes.h:3448
@ FUNC_PARAM_TABLE
Definition: parsenodes.h:3451
@ FUNC_PARAM_VARIADIC
Definition: parsenodes.h:3450
@ OBJECT_AGGREGATE
Definition: parsenodes.h:2262
static Datum CharGetDatum(char X)
Definition: postgres.h:122
TypeName * argType
Definition: parsenodes.h:3460
FunctionParameterMode mode
Definition: parsenodes.h:3461
List * p_rtable
Definition: parse_node.h:194
String * makeString(char *str)
Definition: value.c:63
bool contain_var_clause(Node *node)
Definition: var.c:403

References ACL_USAGE, aclcheck_error_type(), ACLCHECK_OK, FunctionParameter::argType, assign_expr_collations(), buildoidvector(), CharGetDatum(), coerce_to_specific_type(), construct_array_builtin(), contain_var_clause(), CStringGetTextDatum, FunctionParameter::defexpr, ereport, errcode(), errmsg(), ERROR, EXPR_KIND_FUNCTION_DEFAULT, FUNC_PARAM_DEFAULT, FUNC_PARAM_IN, FUNC_PARAM_OUT, FUNC_PARAM_TABLE, FUNC_PARAM_VARIADIC, get_element_type(), GETSTRUCT, GetUserId(), i, InvalidOid, lappend(), lappend_oid(), lfirst, list_length(), LookupTypeName(), makeString(), FunctionParameter::mode, FunctionParameter::name, NIL, NOTICE, object_aclcheck(), OBJECT_AGGREGATE, OBJECT_PROCEDURE, ObjectIdGetDatum(), OidIsValid, ParseState::p_rtable, palloc(), palloc0(), PointerGetDatum(), pstrdup(), px(), ReleaseSysCache(), TypeName::setof, transformExpr(), TypeNameToString(), typeTypeId(), and x.

Referenced by CreateFunction(), and DefineAggregate().

◆ IsThereFunctionInNamespace()

void IsThereFunctionInNamespace ( const char *  proname,
int  pronargs,
oidvector proargtypes,
Oid  nspOid 
)

Definition at line 2030 of file functioncmds.c.

2032 {
2033  /* check for duplicate name (more friendly than unique-index failure) */
2034  if (SearchSysCacheExists3(PROCNAMEARGSNSP,
2036  PointerGetDatum(proargtypes),
2037  ObjectIdGetDatum(nspOid)))
2038  ereport(ERROR,
2039  (errcode(ERRCODE_DUPLICATE_FUNCTION),
2040  errmsg("function %s already exists in schema \"%s\"",
2042  NIL, proargtypes->values),
2043  get_namespace_name(nspOid))));
2044 }
const char * funcname_signature_string(const char *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:1993
int16 pronargs
Definition: pg_proc.h:81
NameData proname
Definition: pg_proc.h:35
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:733
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:99

References CStringGetDatum(), ereport, errcode(), errmsg(), ERROR, funcname_signature_string(), get_namespace_name(), NIL, ObjectIdGetDatum(), PointerGetDatum(), proname, pronargs, SearchSysCacheExists3, and oidvector::values.

Referenced by AlterObjectNamespace_internal(), and AlterObjectRename_internal().

◆ RemoveFunctionById()

void RemoveFunctionById ( Oid  funcOid)

Definition at line 1293 of file functioncmds.c.

1294 {
1295  Relation relation;
1296  HeapTuple tup;
1297  char prokind;
1298 
1299  /*
1300  * Delete the pg_proc tuple.
1301  */
1302  relation = table_open(ProcedureRelationId, RowExclusiveLock);
1303 
1304  tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
1305  if (!HeapTupleIsValid(tup)) /* should not happen */
1306  elog(ERROR, "cache lookup failed for function %u", funcOid);
1307 
1308  prokind = ((Form_pg_proc) GETSTRUCT(tup))->prokind;
1309 
1310  CatalogTupleDelete(relation, &tup->t_self);
1311 
1312  ReleaseSysCache(tup);
1313 
1314  table_close(relation, RowExclusiveLock);
1315 
1316  pgstat_drop_function(funcOid);
1317 
1318  /*
1319  * If there's a pg_aggregate tuple, delete that too.
1320  */
1321  if (prokind == PROKIND_AGGREGATE)
1322  {
1323  relation = table_open(AggregateRelationId, RowExclusiveLock);
1324 
1325  tup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(funcOid));
1326  if (!HeapTupleIsValid(tup)) /* should not happen */
1327  elog(ERROR, "cache lookup failed for pg_aggregate tuple for function %u", funcOid);
1328 
1329  CatalogTupleDelete(relation, &tup->t_self);
1330 
1331  ReleaseSysCache(tup);
1332 
1333  table_close(relation, RowExclusiveLock);
1334  }
1335 }
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:365
void pgstat_drop_function(Oid proid)

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

Referenced by doDeletion().

◆ update_proconfig_value()

static ArrayType* update_proconfig_value ( ArrayType a,
List set_items 
)
static

Definition at line 645 of file functioncmds.c.

646 {
647  ListCell *l;
648 
649  foreach(l, set_items)
650  {
652 
653  if (sstmt->kind == VAR_RESET_ALL)
654  a = NULL;
655  else
656  {
657  char *valuestr = ExtractSetVariableArgs(sstmt);
658 
659  if (valuestr)
660  a = GUCArrayAdd(a, sstmt->name, valuestr);
661  else /* RESET */
662  a = GUCArrayDelete(a, sstmt->name);
663  }
664  }
665 
666  return a;
667 }
ArrayType * GUCArrayAdd(ArrayType *array, const char *name, const char *value)
Definition: guc.c:6444
ArrayType * GUCArrayDelete(ArrayType *array, const char *name)
Definition: guc.c:6522
char * ExtractSetVariableArgs(VariableSetStmt *stmt)
Definition: guc_funcs.c:167
@ VAR_RESET_ALL
Definition: parsenodes.h:2620
VariableSetKind kind
Definition: parsenodes.h:2626

References a, ExtractSetVariableArgs(), GUCArrayAdd(), GUCArrayDelete(), VariableSetStmt::kind, lfirst_node, VariableSetStmt::name, and VAR_RESET_ALL.

Referenced by AlterFunction(), and compute_function_attributes().