PostgreSQL Source Code  git master
functioncmds.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/htup_details.h"
#include "access/sysattr.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/alter.h"
#include "commands/defrem.h"
#include "commands/extension.h"
#include "commands/proclang.h"
#include "executor/execdesc.h"
#include "executor/executor.h"
#include "executor/functions.h"
#include "funcapi.h"
#include "miscadmin.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/fmgroids.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/memutils.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 1353 of file functioncmds.c.

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

Referenced by ProcessUtilitySlow().

1354 {
1355  HeapTuple tup;
1356  Oid funcOid;
1357  Form_pg_proc procForm;
1358  bool is_procedure;
1359  Relation rel;
1360  ListCell *l;
1361  DefElem *volatility_item = NULL;
1362  DefElem *strict_item = NULL;
1363  DefElem *security_def_item = NULL;
1364  DefElem *leakproof_item = NULL;
1365  List *set_items = NIL;
1366  DefElem *cost_item = NULL;
1367  DefElem *rows_item = NULL;
1368  DefElem *support_item = NULL;
1369  DefElem *parallel_item = NULL;
1370  ObjectAddress address;
1371 
1372  rel = table_open(ProcedureRelationId, RowExclusiveLock);
1373 
1374  funcOid = LookupFuncWithArgs(stmt->objtype, stmt->func, false);
1375 
1376  ObjectAddressSet(address, ProcedureRelationId, funcOid);
1377 
1378  tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1379  if (!HeapTupleIsValid(tup)) /* should not happen */
1380  elog(ERROR, "cache lookup failed for function %u", funcOid);
1381 
1382  procForm = (Form_pg_proc) GETSTRUCT(tup);
1383 
1384  /* Permission check: must own function */
1385  if (!pg_proc_ownercheck(funcOid, GetUserId()))
1387  NameListToString(stmt->func->objname));
1388 
1389  if (procForm->prokind == PROKIND_AGGREGATE)
1390  ereport(ERROR,
1391  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1392  errmsg("\"%s\" is an aggregate function",
1393  NameListToString(stmt->func->objname))));
1394 
1395  is_procedure = (procForm->prokind == PROKIND_PROCEDURE);
1396 
1397  /* Examine requested actions. */
1398  foreach(l, stmt->actions)
1399  {
1400  DefElem *defel = (DefElem *) lfirst(l);
1401 
1402  if (compute_common_attribute(pstate,
1403  is_procedure,
1404  defel,
1405  &volatility_item,
1406  &strict_item,
1407  &security_def_item,
1408  &leakproof_item,
1409  &set_items,
1410  &cost_item,
1411  &rows_item,
1412  &support_item,
1413  &parallel_item) == false)
1414  elog(ERROR, "option \"%s\" not recognized", defel->defname);
1415  }
1416 
1417  if (volatility_item)
1418  procForm->provolatile = interpret_func_volatility(volatility_item);
1419  if (strict_item)
1420  procForm->proisstrict = intVal(strict_item->arg);
1421  if (security_def_item)
1422  procForm->prosecdef = intVal(security_def_item->arg);
1423  if (leakproof_item)
1424  {
1425  procForm->proleakproof = intVal(leakproof_item->arg);
1426  if (procForm->proleakproof && !superuser())
1427  ereport(ERROR,
1428  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1429  errmsg("only superuser can define a leakproof function")));
1430  }
1431  if (cost_item)
1432  {
1433  procForm->procost = defGetNumeric(cost_item);
1434  if (procForm->procost <= 0)
1435  ereport(ERROR,
1436  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1437  errmsg("COST must be positive")));
1438  }
1439  if (rows_item)
1440  {
1441  procForm->prorows = defGetNumeric(rows_item);
1442  if (procForm->prorows <= 0)
1443  ereport(ERROR,
1444  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1445  errmsg("ROWS must be positive")));
1446  if (!procForm->proretset)
1447  ereport(ERROR,
1448  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1449  errmsg("ROWS is not applicable when function does not return a set")));
1450  }
1451  if (support_item)
1452  {
1453  /* interpret_func_support handles the privilege check */
1454  Oid newsupport = interpret_func_support(support_item);
1455 
1456  /* Add or replace dependency on support function */
1457  if (OidIsValid(procForm->prosupport))
1458  changeDependencyFor(ProcedureRelationId, funcOid,
1459  ProcedureRelationId, procForm->prosupport,
1460  newsupport);
1461  else
1462  {
1463  ObjectAddress referenced;
1464 
1465  referenced.classId = ProcedureRelationId;
1466  referenced.objectId = newsupport;
1467  referenced.objectSubId = 0;
1468  recordDependencyOn(&address, &referenced, DEPENDENCY_NORMAL);
1469  }
1470 
1471  procForm->prosupport = newsupport;
1472  }
1473  if (set_items)
1474  {
1475  Datum datum;
1476  bool isnull;
1477  ArrayType *a;
1478  Datum repl_val[Natts_pg_proc];
1479  bool repl_null[Natts_pg_proc];
1480  bool repl_repl[Natts_pg_proc];
1481 
1482  /* extract existing proconfig setting */
1483  datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proconfig, &isnull);
1484  a = isnull ? NULL : DatumGetArrayTypeP(datum);
1485 
1486  /* update according to each SET or RESET item, left to right */
1487  a = update_proconfig_value(a, set_items);
1488 
1489  /* update the tuple */
1490  memset(repl_repl, false, sizeof(repl_repl));
1491  repl_repl[Anum_pg_proc_proconfig - 1] = true;
1492 
1493  if (a == NULL)
1494  {
1495  repl_val[Anum_pg_proc_proconfig - 1] = (Datum) 0;
1496  repl_null[Anum_pg_proc_proconfig - 1] = true;
1497  }
1498  else
1499  {
1500  repl_val[Anum_pg_proc_proconfig - 1] = PointerGetDatum(a);
1501  repl_null[Anum_pg_proc_proconfig - 1] = false;
1502  }
1503 
1504  tup = heap_modify_tuple(tup, RelationGetDescr(rel),
1505  repl_val, repl_null, repl_repl);
1506  }
1507  if (parallel_item)
1508  procForm->proparallel = interpret_func_parallel(parallel_item);
1509 
1510  /* Do the update */
1511  CatalogTupleUpdate(rel, &tup->t_self, tup);
1512 
1513  InvokeObjectPostAlterHook(ProcedureRelationId, funcOid, 0);
1514 
1515  table_close(rel, NoLock);
1516  heap_freetuple(tup);
1517 
1518  return address;
1519 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetDescr(relation)
Definition: rel.h:503
Oid GetUserId(void)
Definition: miscinit.c:495
#define PointerGetDatum(X)
Definition: postgres.h:600
double defGetNumeric(DefElem *def)
Definition: define.c:80
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3308
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
static Oid interpret_func_support(DefElem *defel)
Definition: functioncmds.c:679
ItemPointerData t_self
Definition: htup.h:65
ObjectType objtype
Definition: parsenodes.h:2999
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
static char interpret_func_volatility(DefElem *defel)
Definition: functioncmds.c:611
Node * arg
Definition: parsenodes.h:759
char * NameListToString(List *names)
Definition: namespace.c:3147
uintptr_t Datum
Definition: postgres.h:411
static ArrayType * update_proconfig_value(ArrayType *a, List *set_items)
Definition: functioncmds.c:654
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
#define ereport(elevel,...)
Definition: elog.h:157
ObjectWithArgs * func
Definition: parsenodes.h:3000
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:169
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:175
#define intVal(v)
Definition: value.h:63
int errmsg(const char *fmt,...)
Definition: elog.c:909
long changeDependencyFor(Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
Definition: pg_depend.c:399
#define elog(elevel,...)
Definition: elog.h:232
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2207
char * defname
Definition: parsenodes.h:758
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
Definition: pg_list.h:50
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:509
bool pg_proc_ownercheck(Oid proc_oid, Oid roleid)
Definition: aclchk.c:4896
static char interpret_func_parallel(DefElem *defel)
Definition: functioncmds.c:629
#define DatumGetArrayTypeP(X)
Definition: array.h:254

◆ CallStmtResultDesc()

TupleDesc CallStmtResultDesc ( CallStmt stmt)

Definition at line 2354 of file functioncmds.c.

References build_function_result_tupdesc_t(), elog, ERROR, CallStmt::funcexpr, FuncExpr::funcid, HeapTupleIsValid, ObjectIdGetDatum, PROCOID, ReleaseSysCache(), and SearchSysCache1().

Referenced by UtilityTupleDescriptor().

2355 {
2356  FuncExpr *fexpr;
2357  HeapTuple tuple;
2358  TupleDesc tupdesc;
2359 
2360  fexpr = stmt->funcexpr;
2361 
2362  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
2363  if (!HeapTupleIsValid(tuple))
2364  elog(ERROR, "cache lookup failed for procedure %u", fexpr->funcid);
2365 
2366  tupdesc = build_function_result_tupdesc_t(tuple);
2367 
2368  ReleaseSysCache(tuple);
2369 
2370  return tupdesc;
2371 }
FuncExpr * funcexpr
Definition: parsenodes.h:3038
TupleDesc build_function_result_tupdesc_t(HeapTuple procTuple)
Definition: funcapi.c:1602
Oid funcid
Definition: primnodes.h:495
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:232

◆ check_transform_function()

static void check_transform_function ( Form_pg_proc  procstruct)
static

Definition at line 1770 of file functioncmds.c.

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

Referenced by CreateTransform().

1771 {
1772  if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1773  ereport(ERROR,
1774  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1775  errmsg("transform function must not be volatile")));
1776  if (procstruct->prokind != PROKIND_FUNCTION)
1777  ereport(ERROR,
1778  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1779  errmsg("transform function must be a normal function")));
1780  if (procstruct->proretset)
1781  ereport(ERROR,
1782  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1783  errmsg("transform function must not return a set")));
1784  if (procstruct->pronargs != 1)
1785  ereport(ERROR,
1786  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1787  errmsg("transform function must take one argument")));
1788  if (procstruct->proargtypes.values[0] != INTERNALOID)
1789  ereport(ERROR,
1790  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1791  errmsg("first argument of transform function must be type %s",
1792  "internal")));
1793 }
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ERROR
Definition: elog.h:46
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ 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 509 of file functioncmds.c.

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

Referenced by AlterFunction(), and compute_function_attributes().

521 {
522  if (strcmp(defel->defname, "volatility") == 0)
523  {
524  if (is_procedure)
525  goto procedure_error;
526  if (*volatility_item)
527  errorConflictingDefElem(defel, pstate);
528 
529  *volatility_item = defel;
530  }
531  else if (strcmp(defel->defname, "strict") == 0)
532  {
533  if (is_procedure)
534  goto procedure_error;
535  if (*strict_item)
536  errorConflictingDefElem(defel, pstate);
537 
538  *strict_item = defel;
539  }
540  else if (strcmp(defel->defname, "security") == 0)
541  {
542  if (*security_item)
543  errorConflictingDefElem(defel, pstate);
544 
545  *security_item = defel;
546  }
547  else if (strcmp(defel->defname, "leakproof") == 0)
548  {
549  if (is_procedure)
550  goto procedure_error;
551  if (*leakproof_item)
552  errorConflictingDefElem(defel, pstate);
553 
554  *leakproof_item = defel;
555  }
556  else if (strcmp(defel->defname, "set") == 0)
557  {
558  *set_items = lappend(*set_items, defel->arg);
559  }
560  else if (strcmp(defel->defname, "cost") == 0)
561  {
562  if (is_procedure)
563  goto procedure_error;
564  if (*cost_item)
565  errorConflictingDefElem(defel, pstate);
566 
567  *cost_item = defel;
568  }
569  else if (strcmp(defel->defname, "rows") == 0)
570  {
571  if (is_procedure)
572  goto procedure_error;
573  if (*rows_item)
574  errorConflictingDefElem(defel, pstate);
575 
576  *rows_item = defel;
577  }
578  else if (strcmp(defel->defname, "support") == 0)
579  {
580  if (is_procedure)
581  goto procedure_error;
582  if (*support_item)
583  errorConflictingDefElem(defel, pstate);
584 
585  *support_item = defel;
586  }
587  else if (strcmp(defel->defname, "parallel") == 0)
588  {
589  if (is_procedure)
590  goto procedure_error;
591  if (*parallel_item)
592  errorConflictingDefElem(defel, pstate);
593 
594  *parallel_item = defel;
595  }
596  else
597  return false;
598 
599  /* Recognized an option */
600  return true;
601 
602 procedure_error:
603  ereport(ERROR,
604  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
605  errmsg("invalid attribute in procedure definition"),
606  parser_errposition(pstate, defel->location)));
607  return false;
608 }
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ERROR
Definition: elog.h:46
int location
Definition: parsenodes.h:761
Node * arg
Definition: parsenodes.h:759
List * lappend(List *list, void *datum)
Definition: list.c:336
#define ereport(elevel,...)
Definition: elog.h:157
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:350
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
int errmsg(const char *fmt,...)
Definition: elog.c:909
char * defname
Definition: parsenodes.h:758

◆ 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 723 of file functioncmds.c.

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

Referenced by CreateFunction().

739 {
740  ListCell *option;
741  DefElem *as_item = NULL;
742  DefElem *language_item = NULL;
743  DefElem *transform_item = NULL;
744  DefElem *windowfunc_item = NULL;
745  DefElem *volatility_item = NULL;
746  DefElem *strict_item = NULL;
747  DefElem *security_item = NULL;
748  DefElem *leakproof_item = NULL;
749  List *set_items = NIL;
750  DefElem *cost_item = NULL;
751  DefElem *rows_item = NULL;
752  DefElem *support_item = NULL;
753  DefElem *parallel_item = NULL;
754 
755  foreach(option, options)
756  {
757  DefElem *defel = (DefElem *) lfirst(option);
758 
759  if (strcmp(defel->defname, "as") == 0)
760  {
761  if (as_item)
762  errorConflictingDefElem(defel, pstate);
763  as_item = defel;
764  }
765  else if (strcmp(defel->defname, "language") == 0)
766  {
767  if (language_item)
768  errorConflictingDefElem(defel, pstate);
769  language_item = defel;
770  }
771  else if (strcmp(defel->defname, "transform") == 0)
772  {
773  if (transform_item)
774  errorConflictingDefElem(defel, pstate);
775  transform_item = defel;
776  }
777  else if (strcmp(defel->defname, "window") == 0)
778  {
779  if (windowfunc_item)
780  errorConflictingDefElem(defel, pstate);
781  if (is_procedure)
782  ereport(ERROR,
783  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
784  errmsg("invalid attribute in procedure definition"),
785  parser_errposition(pstate, defel->location)));
786  windowfunc_item = defel;
787  }
788  else if (compute_common_attribute(pstate,
789  is_procedure,
790  defel,
791  &volatility_item,
792  &strict_item,
793  &security_item,
794  &leakproof_item,
795  &set_items,
796  &cost_item,
797  &rows_item,
798  &support_item,
799  &parallel_item))
800  {
801  /* recognized common option */
802  continue;
803  }
804  else
805  elog(ERROR, "option \"%s\" not recognized",
806  defel->defname);
807  }
808 
809  if (as_item)
810  *as = (List *) as_item->arg;
811  if (language_item)
812  *language = strVal(language_item->arg);
813  if (transform_item)
814  *transform = transform_item->arg;
815  if (windowfunc_item)
816  *windowfunc_p = intVal(windowfunc_item->arg);
817  if (volatility_item)
818  *volatility_p = interpret_func_volatility(volatility_item);
819  if (strict_item)
820  *strict_p = intVal(strict_item->arg);
821  if (security_item)
822  *security_definer = intVal(security_item->arg);
823  if (leakproof_item)
824  *leakproof_p = intVal(leakproof_item->arg);
825  if (set_items)
826  *proconfig = update_proconfig_value(NULL, set_items);
827  if (cost_item)
828  {
829  *procost = defGetNumeric(cost_item);
830  if (*procost <= 0)
831  ereport(ERROR,
832  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
833  errmsg("COST must be positive")));
834  }
835  if (rows_item)
836  {
837  *prorows = defGetNumeric(rows_item);
838  if (*prorows <= 0)
839  ereport(ERROR,
840  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
841  errmsg("ROWS must be positive")));
842  }
843  if (support_item)
844  *prosupport = interpret_func_support(support_item);
845  if (parallel_item)
846  *parallel_p = interpret_func_parallel(parallel_item);
847 }
#define NIL
Definition: pg_list.h:65
double defGetNumeric(DefElem *def)
Definition: define.c:80
#define strVal(v)
Definition: value.h:65
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ERROR
Definition: elog.h:46
static Oid interpret_func_support(DefElem *defel)
Definition: functioncmds.c:679
int location
Definition: parsenodes.h:761
static char interpret_func_volatility(DefElem *defel)
Definition: functioncmds.c:611
Node * arg
Definition: parsenodes.h:759
static ArrayType * update_proconfig_value(ArrayType *a, List *set_items)
Definition: functioncmds.c:654
#define ereport(elevel,...)
Definition: elog.h:157
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:350
#define lfirst(lc)
Definition: pg_list.h:169
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
#define intVal(v)
Definition: value.h:63
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
char * defname
Definition: parsenodes.h:758
Definition: pg_list.h:50
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:509
static char interpret_func_parallel(DefElem *defel)
Definition: functioncmds.c:629

◆ compute_return_type()

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

Definition at line 93 of file functioncmds.c.

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_SCHEMA, ObjectAddress::objectId, OidIsValid, pg_namespace_aclcheck(), pg_type_aclcheck(), QualifiedNameGetCreationNamespace(), ReleaseSysCache(), TypeName::setof, TypeNameToString(), TypeShellMake(), typeTypeId(), TypeName::typmods, and typname.

Referenced by CreateFunction().

95 {
96  Oid rettype;
97  Type typtup;
98  AclResult aclresult;
99 
100  typtup = LookupTypeName(NULL, returnType, NULL, false);
101 
102  if (typtup)
103  {
104  if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
105  {
106  if (languageOid == SQLlanguageId)
107  ereport(ERROR,
108  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
109  errmsg("SQL function cannot return shell type %s",
110  TypeNameToString(returnType))));
111  else
112  ereport(NOTICE,
113  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
114  errmsg("return type %s is only a shell",
115  TypeNameToString(returnType))));
116  }
117  rettype = typeTypeId(typtup);
118  ReleaseSysCache(typtup);
119  }
120  else
121  {
122  char *typnam = TypeNameToString(returnType);
123  Oid namespaceId;
124  AclResult aclresult;
125  char *typname;
126  ObjectAddress address;
127 
128  /*
129  * Only C-coded functions can be I/O functions. We enforce this
130  * restriction here mainly to prevent littering the catalogs with
131  * shell types due to simple typos in user-defined function
132  * definitions.
133  */
134  if (languageOid != INTERNALlanguageId &&
135  languageOid != ClanguageId)
136  ereport(ERROR,
137  (errcode(ERRCODE_UNDEFINED_OBJECT),
138  errmsg("type \"%s\" does not exist", typnam)));
139 
140  /* Reject if there's typmod decoration, too */
141  if (returnType->typmods != NIL)
142  ereport(ERROR,
143  (errcode(ERRCODE_SYNTAX_ERROR),
144  errmsg("type modifier cannot be specified for shell type \"%s\"",
145  typnam)));
146 
147  /* Otherwise, go ahead and make a shell type */
148  ereport(NOTICE,
149  (errcode(ERRCODE_UNDEFINED_OBJECT),
150  errmsg("type \"%s\" is not yet defined", typnam),
151  errdetail("Creating a shell type definition.")));
152  namespaceId = QualifiedNameGetCreationNamespace(returnType->names,
153  &typname);
154  aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
155  ACL_CREATE);
156  if (aclresult != ACLCHECK_OK)
157  aclcheck_error(aclresult, OBJECT_SCHEMA,
158  get_namespace_name(namespaceId));
159  address = TypeShellMake(typname, namespaceId, GetUserId());
160  rettype = address.objectId;
161  Assert(OidIsValid(rettype));
162  }
163 
164  aclresult = pg_type_aclcheck(rettype, GetUserId(), ACL_USAGE);
165  if (aclresult != ACLCHECK_OK)
166  aclcheck_error_type(aclresult, rettype);
167 
168  *prorettype_p = rettype;
169  *returnsSet_p = returnType->setof;
170 }
Type LookupTypeName(ParseState *pstate, const TypeName *typeName, int32 *typmod_p, bool missing_ok)
Definition: parse_type.c:38
#define NIL
Definition: pg_list.h:65
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
List * names
Definition: parsenodes.h:221
Oid GetUserId(void)
Definition: miscinit.c:495
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:3040
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:480
int errcode(int sqlerrcode)
Definition: elog.c:698
unsigned int Oid
Definition: postgres_ext.h:31
ObjectAddress TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
Definition: pg_type.c:60
#define OidIsValid(objectId)
Definition: c.h:710
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4756
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3621
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3308
#define ERROR
Definition: elog.h:46
#define ACL_CREATE
Definition: parsenodes.h:92
bool setof
Definition: parsenodes.h:223
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3316
int errdetail(const char *fmt,...)
Definition: elog.c:1042
#define ACL_USAGE
Definition: parsenodes.h:90
NameData typname
Definition: pg_type.h:41
AclResult
Definition: acl.h:177
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
List * typmods
Definition: parsenodes.h:225
#define ereport(elevel,...)
Definition: elog.h:157
#define NOTICE
Definition: elog.h:37
#define Assert(condition)
Definition: c.h:804
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
int errmsg(const char *fmt,...)
Definition: elog.c:909
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4806
Oid typeTypeId(Type tp)
Definition: parse_type.c:592

◆ CreateCast()

ObjectAddress CreateCast ( CreateCastStmt stmt)

Definition at line 1526 of file functioncmds.c.

References ACL_USAGE, aclcheck_error_type(), ACLCHECK_OK, CastCreate(), COERCION_ASSIGNMENT, COERCION_EXPLICIT, COERCION_IMPLICIT, CreateCastStmt::context, DEPENDENCY_NORMAL, elog, ereport, errcode(), errmsg(), ERROR, format_type_be(), CreateCastStmt::func, get_element_type(), get_typlenbyvalalign(), get_typtype(), GETSTRUCT, GetUserId(), HeapTupleIsValid, CreateCastStmt::inout, InvalidOid, IsBinaryCoercible(), LookupFuncWithArgs(), OBJECT_FUNCTION, ObjectIdGetDatum, OidIsValid, pg_type_aclcheck(), pg_type_ownercheck(), PROCOID, ReleaseSysCache(), SearchSysCache1(), CreateCastStmt::sourcetype, superuser(), CreateCastStmt::targettype, TypeNameToString(), typenameTypeId(), and WARNING.

Referenced by ProcessUtilitySlow().

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

◆ CreateFunction()

ObjectAddress CreateFunction ( ParseState pstate,
CreateFunctionStmt stmt 
)

Definition at line 1020 of file functioncmds.c.

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

Referenced by ProcessUtilitySlow().

1021 {
1022  char *probin_str;
1023  char *prosrc_str;
1024  Node *prosqlbody;
1025  Oid prorettype;
1026  bool returnsSet;
1027  char *language;
1028  Oid languageOid;
1029  Oid languageValidator;
1030  Node *transformDefElem = NULL;
1031  char *funcname;
1032  Oid namespaceId;
1033  AclResult aclresult;
1034  oidvector *parameterTypes;
1035  List *parameterTypes_list = NIL;
1036  ArrayType *allParameterTypes;
1037  ArrayType *parameterModes;
1038  ArrayType *parameterNames;
1039  List *inParameterNames_list = NIL;
1040  List *parameterDefaults;
1041  Oid variadicArgType;
1042  List *trftypes_list = NIL;
1043  ArrayType *trftypes;
1044  Oid requiredResultType;
1045  bool isWindowFunc,
1046  isStrict,
1047  security,
1048  isLeakProof;
1049  char volatility;
1050  ArrayType *proconfig;
1051  float4 procost;
1052  float4 prorows;
1053  Oid prosupport;
1054  HeapTuple languageTuple;
1055  Form_pg_language languageStruct;
1056  List *as_clause;
1057  char parallel;
1058 
1059  /* Convert list of names to a name and namespace */
1060  namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
1061  &funcname);
1062 
1063  /* Check we have creation rights in target namespace */
1064  aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
1065  if (aclresult != ACLCHECK_OK)
1066  aclcheck_error(aclresult, OBJECT_SCHEMA,
1067  get_namespace_name(namespaceId));
1068 
1069  /* Set default attributes */
1070  as_clause = NIL;
1071  language = NULL;
1072  isWindowFunc = false;
1073  isStrict = false;
1074  security = false;
1075  isLeakProof = false;
1076  volatility = PROVOLATILE_VOLATILE;
1077  proconfig = NULL;
1078  procost = -1; /* indicates not set */
1079  prorows = -1; /* indicates not set */
1080  prosupport = InvalidOid;
1081  parallel = PROPARALLEL_UNSAFE;
1082 
1083  /* Extract non-default attributes from stmt->options list */
1085  stmt->is_procedure,
1086  stmt->options,
1087  &as_clause, &language, &transformDefElem,
1088  &isWindowFunc, &volatility,
1089  &isStrict, &security, &isLeakProof,
1090  &proconfig, &procost, &prorows,
1091  &prosupport, &parallel);
1092 
1093  if (!language)
1094  {
1095  if (stmt->sql_body)
1096  language = "sql";
1097  else
1098  ereport(ERROR,
1099  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1100  errmsg("no language specified")));
1101  }
1102 
1103  /* Look up the language and validate permissions */
1104  languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
1105  if (!HeapTupleIsValid(languageTuple))
1106  ereport(ERROR,
1107  (errcode(ERRCODE_UNDEFINED_OBJECT),
1108  errmsg("language \"%s\" does not exist", language),
1109  (extension_file_exists(language) ?
1110  errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
1111 
1112  languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
1113  languageOid = languageStruct->oid;
1114 
1115  if (languageStruct->lanpltrusted)
1116  {
1117  /* if trusted language, need USAGE privilege */
1118  AclResult aclresult;
1119 
1120  aclresult = pg_language_aclcheck(languageOid, GetUserId(), ACL_USAGE);
1121  if (aclresult != ACLCHECK_OK)
1122  aclcheck_error(aclresult, OBJECT_LANGUAGE,
1123  NameStr(languageStruct->lanname));
1124  }
1125  else
1126  {
1127  /* if untrusted language, must be superuser */
1128  if (!superuser())
1130  NameStr(languageStruct->lanname));
1131  }
1132 
1133  languageValidator = languageStruct->lanvalidator;
1134 
1135  ReleaseSysCache(languageTuple);
1136 
1137  /*
1138  * Only superuser is allowed to create leakproof functions because
1139  * leakproof functions can see tuples which have not yet been filtered out
1140  * by security barrier views or row-level security policies.
1141  */
1142  if (isLeakProof && !superuser())
1143  ereport(ERROR,
1144  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1145  errmsg("only superuser can define a leakproof function")));
1146 
1147  if (transformDefElem)
1148  {
1149  ListCell *lc;
1150 
1151  foreach(lc, castNode(List, transformDefElem))
1152  {
1153  Oid typeid = typenameTypeId(NULL,
1154  lfirst_node(TypeName, lc));
1155  Oid elt = get_base_element_type(typeid);
1156 
1157  typeid = elt ? elt : typeid;
1158 
1159  get_transform_oid(typeid, languageOid, false);
1160  trftypes_list = lappend_oid(trftypes_list, typeid);
1161  }
1162  }
1163 
1164  /*
1165  * Convert remaining parameters of CREATE to form wanted by
1166  * ProcedureCreate.
1167  */
1169  stmt->parameters,
1170  languageOid,
1172  &parameterTypes,
1173  &parameterTypes_list,
1174  &allParameterTypes,
1175  &parameterModes,
1176  &parameterNames,
1177  &inParameterNames_list,
1178  &parameterDefaults,
1179  &variadicArgType,
1180  &requiredResultType);
1181 
1182  if (stmt->is_procedure)
1183  {
1184  Assert(!stmt->returnType);
1185  prorettype = requiredResultType ? requiredResultType : VOIDOID;
1186  returnsSet = false;
1187  }
1188  else if (stmt->returnType)
1189  {
1190  /* explicit RETURNS clause */
1191  compute_return_type(stmt->returnType, languageOid,
1192  &prorettype, &returnsSet);
1193  if (OidIsValid(requiredResultType) && prorettype != requiredResultType)
1194  ereport(ERROR,
1195  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1196  errmsg("function result type must be %s because of OUT parameters",
1197  format_type_be(requiredResultType))));
1198  }
1199  else if (OidIsValid(requiredResultType))
1200  {
1201  /* default RETURNS clause from OUT parameters */
1202  prorettype = requiredResultType;
1203  returnsSet = false;
1204  }
1205  else
1206  {
1207  ereport(ERROR,
1208  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1209  errmsg("function result type must be specified")));
1210  /* Alternative possibility: default to RETURNS VOID */
1211  prorettype = VOIDOID;
1212  returnsSet = false;
1213  }
1214 
1215  if (list_length(trftypes_list) > 0)
1216  {
1217  ListCell *lc;
1218  Datum *arr;
1219  int i;
1220 
1221  arr = palloc(list_length(trftypes_list) * sizeof(Datum));
1222  i = 0;
1223  foreach(lc, trftypes_list)
1224  arr[i++] = ObjectIdGetDatum(lfirst_oid(lc));
1225  trftypes = construct_array(arr, list_length(trftypes_list),
1226  OIDOID, sizeof(Oid), true, TYPALIGN_INT);
1227  }
1228  else
1229  {
1230  /* store SQL NULL instead of empty array */
1231  trftypes = NULL;
1232  }
1233 
1234  interpret_AS_clause(languageOid, language, funcname, as_clause, stmt->sql_body,
1235  parameterTypes_list, inParameterNames_list,
1236  &prosrc_str, &probin_str, &prosqlbody,
1237  pstate->p_sourcetext);
1238 
1239  /*
1240  * Set default values for COST and ROWS depending on other parameters;
1241  * reject ROWS if it's not returnsSet. NB: pg_dump knows these default
1242  * values, keep it in sync if you change them.
1243  */
1244  if (procost < 0)
1245  {
1246  /* SQL and PL-language functions are assumed more expensive */
1247  if (languageOid == INTERNALlanguageId ||
1248  languageOid == ClanguageId)
1249  procost = 1;
1250  else
1251  procost = 100;
1252  }
1253  if (prorows < 0)
1254  {
1255  if (returnsSet)
1256  prorows = 1000;
1257  else
1258  prorows = 0; /* dummy value if not returnsSet */
1259  }
1260  else if (!returnsSet)
1261  ereport(ERROR,
1262  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1263  errmsg("ROWS is not applicable when function does not return a set")));
1264 
1265  /*
1266  * And now that we have all the parameters, and know we're permitted to do
1267  * so, go ahead and create the function.
1268  */
1269  return ProcedureCreate(funcname,
1270  namespaceId,
1271  stmt->replace,
1272  returnsSet,
1273  prorettype,
1274  GetUserId(),
1275  languageOid,
1276  languageValidator,
1277  prosrc_str, /* converted to text later */
1278  probin_str, /* converted to text later */
1279  prosqlbody,
1280  stmt->is_procedure ? PROKIND_PROCEDURE : (isWindowFunc ? PROKIND_WINDOW : PROKIND_FUNCTION),
1281  security,
1282  isLeakProof,
1283  isStrict,
1284  volatility,
1285  parallel,
1286  parameterTypes,
1287  PointerGetDatum(allParameterTypes),
1288  PointerGetDatum(parameterModes),
1289  PointerGetDatum(parameterNames),
1290  parameterDefaults,
1291  PointerGetDatum(trftypes),
1292  PointerGetDatum(proconfig),
1293  prosupport,
1294  procost,
1295  prorows);
1296 }
#define NIL
Definition: pg_list.h:65
Definition: c.h:660
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:860
int errhint(const char *fmt,...)
Definition: elog.c:1156
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
Oid GetUserId(void)
Definition: miscinit.c:495
#define castNode(_type_, nodeptr)
Definition: nodes.h:605
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:3040
#define PointerGetDatum(X)
Definition: postgres.h:600
static void compute_return_type(TypeName *returnType, Oid languageOid, Oid *prorettype_p, bool *returnsSet_p)
Definition: functioncmds.c:93
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3319
Definition: nodes.h:536
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
#define OidIsValid(objectId)
Definition: c.h:710
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4756
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4730
Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok)
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3308
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define ACL_CREATE
Definition: parsenodes.h:92
#define lfirst_node(type, lc)
Definition: pg_list.h:172
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3316
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:723
#define ACL_USAGE
Definition: parsenodes.h:90
const char * p_sourcetext
Definition: parse_node.h:181
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
float float4
Definition: c.h:564
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:411
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
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:189
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
TypeName * returnType
Definition: parsenodes.h:2970
static int list_length(const List *l)
Definition: pg_list.h:149
bool extension_file_exists(const char *extensionName)
Definition: extension.c:2229
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2779
FormData_pg_language * Form_pg_language
Definition: pg_language.h:65
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i
#define NameStr(name)
Definition: c.h:681
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:71
Definition: pg_list.h:50
#define lfirst_oid(lc)
Definition: pg_list.h:171
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:291

◆ CreateTransform()

ObjectAddress CreateTransform ( CreateTransformStmt stmt)

Definition at line 1800 of file functioncmds.c.

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(), CreateTransformStmt::fromsql, get_language_oid(), get_typtype(), GetNewOidWithIndex(), GETSTRUCT, GetUserId(), heap_form_tuple(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, InvalidOid, InvokeObjectPostCreateHook, CreateTransformStmt::lang, LookupFuncWithArgs(), MemSet, NameListToString(), new_object_addresses(), OBJECT_FUNCTION, OBJECT_LANGUAGE, ObjectAddressSet, ObjectIdGetDatum, ObjectWithArgs::objname, OidIsValid, pg_language_aclcheck(), pg_proc_aclcheck(), pg_proc_ownercheck(), pg_type_aclcheck(), pg_type_ownercheck(), PROCOID, record_object_address_dependencies(), recordDependencyOnCurrentExtension(), RelationGetDescr, ReleaseSysCache(), CreateTransformStmt::replace, RowExclusiveLock, SearchSysCache1(), SearchSysCache2(), HeapTupleData::t_self, table_close(), table_open(), CreateTransformStmt::tosql, TRFTYPELANG, CreateTransformStmt::type_name, TypeNameToString(), typenameTypeId(), and values.

Referenced by ProcessUtilitySlow().

1801 {
1802  Oid typeid;
1803  char typtype;
1804  Oid langid;
1805  Oid fromsqlfuncid;
1806  Oid tosqlfuncid;
1807  AclResult aclresult;
1808  Form_pg_proc procstruct;
1809  Datum values[Natts_pg_transform];
1810  bool nulls[Natts_pg_transform];
1811  bool replaces[Natts_pg_transform];
1812  Oid transformid;
1813  HeapTuple tuple;
1814  HeapTuple newtuple;
1815  Relation relation;
1816  ObjectAddress myself,
1817  referenced;
1818  ObjectAddresses *addrs;
1819  bool is_replace;
1820 
1821  /*
1822  * Get the type
1823  */
1824  typeid = typenameTypeId(NULL, stmt->type_name);
1825  typtype = get_typtype(typeid);
1826 
1827  if (typtype == TYPTYPE_PSEUDO)
1828  ereport(ERROR,
1829  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1830  errmsg("data type %s is a pseudo-type",
1831  TypeNameToString(stmt->type_name))));
1832 
1833  if (typtype == TYPTYPE_DOMAIN)
1834  ereport(ERROR,
1835  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1836  errmsg("data type %s is a domain",
1837  TypeNameToString(stmt->type_name))));
1838 
1839  if (!pg_type_ownercheck(typeid, GetUserId()))
1841 
1842  aclresult = pg_type_aclcheck(typeid, GetUserId(), ACL_USAGE);
1843  if (aclresult != ACLCHECK_OK)
1844  aclcheck_error_type(aclresult, typeid);
1845 
1846  /*
1847  * Get the language
1848  */
1849  langid = get_language_oid(stmt->lang, false);
1850 
1851  aclresult = pg_language_aclcheck(langid, GetUserId(), ACL_USAGE);
1852  if (aclresult != ACLCHECK_OK)
1853  aclcheck_error(aclresult, OBJECT_LANGUAGE, stmt->lang);
1854 
1855  /*
1856  * Get the functions
1857  */
1858  if (stmt->fromsql)
1859  {
1860  fromsqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->fromsql, false);
1861 
1862  if (!pg_proc_ownercheck(fromsqlfuncid, GetUserId()))
1864 
1865  aclresult = pg_proc_aclcheck(fromsqlfuncid, GetUserId(), ACL_EXECUTE);
1866  if (aclresult != ACLCHECK_OK)
1868 
1869  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fromsqlfuncid));
1870  if (!HeapTupleIsValid(tuple))
1871  elog(ERROR, "cache lookup failed for function %u", fromsqlfuncid);
1872  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1873  if (procstruct->prorettype != INTERNALOID)
1874  ereport(ERROR,
1875  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1876  errmsg("return data type of FROM SQL function must be %s",
1877  "internal")));
1878  check_transform_function(procstruct);
1879  ReleaseSysCache(tuple);
1880  }
1881  else
1882  fromsqlfuncid = InvalidOid;
1883 
1884  if (stmt->tosql)
1885  {
1886  tosqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->tosql, false);
1887 
1888  if (!pg_proc_ownercheck(tosqlfuncid, GetUserId()))
1890 
1891  aclresult = pg_proc_aclcheck(tosqlfuncid, GetUserId(), ACL_EXECUTE);
1892  if (aclresult != ACLCHECK_OK)
1894 
1895  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(tosqlfuncid));
1896  if (!HeapTupleIsValid(tuple))
1897  elog(ERROR, "cache lookup failed for function %u", tosqlfuncid);
1898  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1899  if (procstruct->prorettype != typeid)
1900  ereport(ERROR,
1901  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1902  errmsg("return data type of TO SQL function must be the transform data type")));
1903  check_transform_function(procstruct);
1904  ReleaseSysCache(tuple);
1905  }
1906  else
1907  tosqlfuncid = InvalidOid;
1908 
1909  /*
1910  * Ready to go
1911  */
1912  values[Anum_pg_transform_trftype - 1] = ObjectIdGetDatum(typeid);
1913  values[Anum_pg_transform_trflang - 1] = ObjectIdGetDatum(langid);
1914  values[Anum_pg_transform_trffromsql - 1] = ObjectIdGetDatum(fromsqlfuncid);
1915  values[Anum_pg_transform_trftosql - 1] = ObjectIdGetDatum(tosqlfuncid);
1916 
1917  MemSet(nulls, false, sizeof(nulls));
1918 
1919  relation = table_open(TransformRelationId, RowExclusiveLock);
1920 
1921  tuple = SearchSysCache2(TRFTYPELANG,
1922  ObjectIdGetDatum(typeid),
1923  ObjectIdGetDatum(langid));
1924  if (HeapTupleIsValid(tuple))
1925  {
1927 
1928  if (!stmt->replace)
1929  ereport(ERROR,
1931  errmsg("transform for type %s language \"%s\" already exists",
1932  format_type_be(typeid),
1933  stmt->lang)));
1934 
1935  MemSet(replaces, false, sizeof(replaces));
1936  replaces[Anum_pg_transform_trffromsql - 1] = true;
1937  replaces[Anum_pg_transform_trftosql - 1] = true;
1938 
1939  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
1940  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
1941 
1942  transformid = form->oid;
1943  ReleaseSysCache(tuple);
1944  is_replace = true;
1945  }
1946  else
1947  {
1948  transformid = GetNewOidWithIndex(relation, TransformOidIndexId,
1949  Anum_pg_transform_oid);
1950  values[Anum_pg_transform_oid - 1] = ObjectIdGetDatum(transformid);
1951  newtuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
1952  CatalogTupleInsert(relation, newtuple);
1953  is_replace = false;
1954  }
1955 
1956  if (is_replace)
1957  deleteDependencyRecordsFor(TransformRelationId, transformid, true);
1958 
1959  addrs = new_object_addresses();
1960 
1961  /* make dependency entries */
1962  ObjectAddressSet(myself, TransformRelationId, transformid);
1963 
1964  /* dependency on language */
1965  ObjectAddressSet(referenced, LanguageRelationId, langid);
1966  add_exact_object_address(&referenced, addrs);
1967 
1968  /* dependency on type */
1969  ObjectAddressSet(referenced, TypeRelationId, typeid);
1970  add_exact_object_address(&referenced, addrs);
1971 
1972  /* dependencies on functions */
1973  if (OidIsValid(fromsqlfuncid))
1974  {
1975  ObjectAddressSet(referenced, ProcedureRelationId, fromsqlfuncid);
1976  add_exact_object_address(&referenced, addrs);
1977  }
1978  if (OidIsValid(tosqlfuncid))
1979  {
1980  ObjectAddressSet(referenced, ProcedureRelationId, tosqlfuncid);
1981  add_exact_object_address(&referenced, addrs);
1982  }
1983 
1985  free_object_addresses(addrs);
1986 
1987  /* dependency on extension */
1988  recordDependencyOnCurrentExtension(&myself, is_replace);
1989 
1990  /* Post creation hook for new transform */
1991  InvokeObjectPostCreateHook(TransformRelationId, transformid, 0);
1992 
1993  heap_freetuple(newtuple);
1994 
1995  table_close(relation, RowExclusiveLock);
1996 
1997  return myself;
1998 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:381
ObjectWithArgs * tosql
Definition: parsenodes.h:3540
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
static void check_transform_function(Form_pg_proc procstruct)
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
#define RelationGetDescr(relation)
Definition: rel.h:503
Oid GetUserId(void)
Definition: miscinit.c:495
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:480
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2694
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:243
Oid get_language_oid(const char *langname, bool missing_ok)
Definition: proclang.c:228
int errcode(int sqlerrcode)
Definition: elog.c:698
char get_typtype(Oid typid)
Definition: lsyscache.c:2576
#define MemSet(start, val, len)
Definition: c.h:1008
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2485
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2430
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2725
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
bool pg_type_ownercheck(Oid type_oid, Oid roleid)
Definition: aclchk.c:4844
#define OidIsValid(objectId)
Definition: c.h:710
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4730
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3621
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3308
FormData_pg_transform * Form_pg_transform
Definition: pg_transform.h:43
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ACL_USAGE
Definition: parsenodes.h:90
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
char * NameListToString(List *names)
Definition: namespace.c:3147
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:411
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
#define InvalidOid
Definition: postgres_ext.h:36
ObjectWithArgs * fromsql
Definition: parsenodes.h:3539
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:191
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1138
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
TypeName * type_name
Definition: parsenodes.h:3537
static Datum values[MAXATTR]
Definition: bootstrap.c:156
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define ACL_EXECUTE
Definition: parsenodes.h:89
#define elog(elevel,...)
Definition: elog.h:232
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4718
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2207
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4806
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
bool pg_proc_ownercheck(Oid proc_oid, Oid roleid)
Definition: aclchk.c:4896
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:291

◆ ExecuteCallStmt()

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

Definition at line 2177 of file functioncmds.c.

References ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, FuncExpr::args, Assert, CallContext::atomic, begin_tup_output_tupdesc(), CreateExecutorState(), CreateExprContext(), DatumGetHeapTupleHeader, 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, CallStmt::funcexpr, 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_PROCEDURE, ObjectIdGetDatum, pg_proc_aclcheck(), pgstat_end_function_usage(), pgstat_init_function_usage(), PopActiveSnapshot(), PROCOID, PushActiveSnapshot(), _DestReceiver::receiveSlot, ReleaseSysCache(), ReleaseTupleDesc, SearchSysCache1(), TupOutputState::slot, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, TTSOpsHeapTuple, and val.

Referenced by standard_ProcessUtility().

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

◆ ExecuteDoStmt()

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

Definition at line 2055 of file functioncmds.c.

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

Referenced by standard_ProcessUtility().

2056 {
2058  ListCell *arg;
2059  DefElem *as_item = NULL;
2060  DefElem *language_item = NULL;
2061  char *language;
2062  Oid laninline;
2063  HeapTuple languageTuple;
2064  Form_pg_language languageStruct;
2065 
2066  /* Process options we got from gram.y */
2067  foreach(arg, stmt->args)
2068  {
2069  DefElem *defel = (DefElem *) lfirst(arg);
2070 
2071  if (strcmp(defel->defname, "as") == 0)
2072  {
2073  if (as_item)
2074  errorConflictingDefElem(defel, pstate);
2075  as_item = defel;
2076  }
2077  else if (strcmp(defel->defname, "language") == 0)
2078  {
2079  if (language_item)
2080  errorConflictingDefElem(defel, pstate);
2081  language_item = defel;
2082  }
2083  else
2084  elog(ERROR, "option \"%s\" not recognized",
2085  defel->defname);
2086  }
2087 
2088  if (as_item)
2089  codeblock->source_text = strVal(as_item->arg);
2090  else
2091  ereport(ERROR,
2092  (errcode(ERRCODE_SYNTAX_ERROR),
2093  errmsg("no inline code specified")));
2094 
2095  /* if LANGUAGE option wasn't specified, use the default */
2096  if (language_item)
2097  language = strVal(language_item->arg);
2098  else
2099  language = "plpgsql";
2100 
2101  /* Look up the language and validate permissions */
2102  languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
2103  if (!HeapTupleIsValid(languageTuple))
2104  ereport(ERROR,
2105  (errcode(ERRCODE_UNDEFINED_OBJECT),
2106  errmsg("language \"%s\" does not exist", language),
2107  (extension_file_exists(language) ?
2108  errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
2109 
2110  languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
2111  codeblock->langOid = languageStruct->oid;
2112  codeblock->langIsTrusted = languageStruct->lanpltrusted;
2113  codeblock->atomic = atomic;
2114 
2115  if (languageStruct->lanpltrusted)
2116  {
2117  /* if trusted language, need USAGE privilege */
2118  AclResult aclresult;
2119 
2120  aclresult = pg_language_aclcheck(codeblock->langOid, GetUserId(),
2121  ACL_USAGE);
2122  if (aclresult != ACLCHECK_OK)
2123  aclcheck_error(aclresult, OBJECT_LANGUAGE,
2124  NameStr(languageStruct->lanname));
2125  }
2126  else
2127  {
2128  /* if untrusted language, must be superuser */
2129  if (!superuser())
2131  NameStr(languageStruct->lanname));
2132  }
2133 
2134  /* get the handler function's OID */
2135  laninline = languageStruct->laninline;
2136  if (!OidIsValid(laninline))
2137  ereport(ERROR,
2138  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2139  errmsg("language \"%s\" does not support inline code execution",
2140  NameStr(languageStruct->lanname))));
2141 
2142  ReleaseSysCache(languageTuple);
2143 
2144  /* execute the inline handler */
2145  OidFunctionCall1(laninline, PointerGetDatum(codeblock));
2146 }
int errhint(const char *fmt,...)
Definition: elog.c:1156
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
Oid GetUserId(void)
Definition: miscinit.c:495
#define PointerGetDatum(X)
Definition: postgres.h:600
#define strVal(v)
Definition: value.h:65
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4730
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3308
#define ERROR
Definition: elog.h:46
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:664
#define ACL_USAGE
Definition: parsenodes.h:90
Node * arg
Definition: parsenodes.h:759
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
AclResult
Definition: acl.h:177
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define ereport(elevel,...)
Definition: elog.h:157
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:350
#define makeNode(_type_)
Definition: nodes.h:584
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:169
List * args
Definition: parsenodes.h:3013
bool extension_file_exists(const char *extensionName)
Definition: extension.c:2229
FormData_pg_language * Form_pg_language
Definition: pg_language.h:65
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681
void * arg
char * source_text
Definition: parsenodes.h:3019
char * defname
Definition: parsenodes.h:758

◆ get_transform_oid()

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

Definition at line 2008 of file functioncmds.c.

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

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

2009 {
2010  Oid oid;
2011 
2012  oid = GetSysCacheOid2(TRFTYPELANG, Anum_pg_transform_oid,
2013  ObjectIdGetDatum(type_id),
2014  ObjectIdGetDatum(lang_id));
2015  if (!OidIsValid(oid) && !missing_ok)
2016  ereport(ERROR,
2017  (errcode(ERRCODE_UNDEFINED_OBJECT),
2018  errmsg("transform for type %s language \"%s\" does not exist",
2019  format_type_be(type_id),
2020  get_language_name(lang_id, false))));
2021  return oid;
2022 }
char * get_language_name(Oid langoid, bool missing_ok)
Definition: lsyscache.c:1154
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define ereport(elevel,...)
Definition: elog.h:157
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:195
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ 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 860 of file functioncmds.c.

References SQLFunctionParseInfo::argnames, SQLFunctionParseInfo::argtypes, castNode, CMD_UTILITY, Query::commandType, CreateCommandTag(), ereport, errcode(), errmsg(), ERROR, SQLFunctionParseInfo::fname, free_parsestate(), 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(), strVal, transformStmt(), and Query::utilityStmt.

Referenced by CreateFunction().

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

◆ interpret_func_parallel()

static char interpret_func_parallel ( DefElem defel)
static

Definition at line 629 of file functioncmds.c.

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

Referenced by AlterFunction(), and compute_function_attributes().

630 {
631  char *str = strVal(defel->arg);
632 
633  if (strcmp(str, "safe") == 0)
634  return PROPARALLEL_SAFE;
635  else if (strcmp(str, "unsafe") == 0)
636  return PROPARALLEL_UNSAFE;
637  else if (strcmp(str, "restricted") == 0)
638  return PROPARALLEL_RESTRICTED;
639  else
640  {
641  ereport(ERROR,
642  (errcode(ERRCODE_SYNTAX_ERROR),
643  errmsg("parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE")));
644  return PROPARALLEL_UNSAFE; /* keep compiler quiet */
645  }
646 }
#define strVal(v)
Definition: value.h:65
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ERROR
Definition: elog.h:46
Node * arg
Definition: parsenodes.h:759
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ interpret_func_support()

static Oid interpret_func_support ( DefElem defel)
static

Definition at line 679 of file functioncmds.c.

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().

680 {
681  List *procName = defGetQualifiedName(defel);
682  Oid procOid;
683  Oid argList[1];
684 
685  /*
686  * Support functions always take one INTERNAL argument and return
687  * INTERNAL.
688  */
689  argList[0] = INTERNALOID;
690 
691  procOid = LookupFuncName(procName, 1, argList, true);
692  if (!OidIsValid(procOid))
693  ereport(ERROR,
694  (errcode(ERRCODE_UNDEFINED_FUNCTION),
695  errmsg("function %s does not exist",
696  func_signature_string(procName, 1, NIL, argList))));
697 
698  if (get_func_rettype(procOid) != INTERNALOID)
699  ereport(ERROR,
700  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
701  errmsg("support function %s must return type %s",
702  NameListToString(procName), "internal")));
703 
704  /*
705  * Someday we might want an ACL check here; but for now, we insist that
706  * you be superuser to specify a support function, so privilege on the
707  * support function is moot.
708  */
709  if (!superuser())
710  ereport(ERROR,
711  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
712  errmsg("must be superuser to specify a support function")));
713 
714  return procOid;
715 }
#define NIL
Definition: pg_list.h:65
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1626
#define ERROR
Definition: elog.h:46
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
Definition: parse_func.c:2145
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:2031
char * NameListToString(List *names)
Definition: namespace.c:3147
#define ereport(elevel,...)
Definition: elog.h:157
List * defGetQualifiedName(DefElem *def)
Definition: define.c:218
int errmsg(const char *fmt,...)
Definition: elog.c:909
Definition: pg_list.h:50

◆ interpret_func_volatility()

static char interpret_func_volatility ( DefElem defel)
static

Definition at line 611 of file functioncmds.c.

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

Referenced by AlterFunction(), and compute_function_attributes().

612 {
613  char *str = strVal(defel->arg);
614 
615  if (strcmp(str, "immutable") == 0)
616  return PROVOLATILE_IMMUTABLE;
617  else if (strcmp(str, "stable") == 0)
618  return PROVOLATILE_STABLE;
619  else if (strcmp(str, "volatile") == 0)
620  return PROVOLATILE_VOLATILE;
621  else
622  {
623  elog(ERROR, "invalid volatility \"%s\"", str);
624  return 0; /* keep compiler quiet */
625  }
626 }
#define strVal(v)
Definition: value.h:65
#define ERROR
Definition: elog.h:46
Node * arg
Definition: parsenodes.h:759
#define elog(elevel,...)
Definition: elog.h:232

◆ 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 189 of file functioncmds.c.

References ACL_USAGE, aclcheck_error_type(), ACLCHECK_OK, FunctionParameter::argType, assign_expr_collations(), buildoidvector(), CharGetDatum, coerce_to_specific_type(), construct_array(), 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_AGGREGATE, OBJECT_PROCEDURE, ObjectIdGetDatum, OidIsValid, ParseState::p_rtable, palloc(), palloc0(), pg_type_aclcheck(), PointerGetDatum, pstrdup(), px(), ReleaseSysCache(), TypeName::setof, transformExpr(), TypeNameToString(), and typeTypeId().

Referenced by CreateFunction(), and DefineAggregate().

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

◆ IsThereFunctionInNamespace()

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

Definition at line 2032 of file functioncmds.c.

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

Referenced by AlterObjectNamespace_internal(), and AlterObjectRename_internal().

2034 {
2035  /* check for duplicate name (more friendly than unique-index failure) */
2038  PointerGetDatum(proargtypes),
2039  ObjectIdGetDatum(nspOid)))
2040  ereport(ERROR,
2041  (errcode(ERRCODE_DUPLICATE_FUNCTION),
2042  errmsg("function %s already exists in schema \"%s\"",
2044  NIL, proargtypes->values),
2045  get_namespace_name(nspOid))));
2046 }
#define NIL
Definition: pg_list.h:65
NameData proname
Definition: pg_proc.h:35
#define PointerGetDatum(X)
Definition: postgres.h:600
int errcode(int sqlerrcode)
Definition: elog.c:698
int16 pronargs
Definition: pg_proc.h:81
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:188
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3316
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:668
#define CStringGetDatum(X)
Definition: postgres.h:622
const char * funcname_signature_string(const char *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:1994
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ RemoveFunctionById()

void RemoveFunctionById ( Oid  funcOid)

Definition at line 1305 of file functioncmds.c.

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

Referenced by doDeletion().

1306 {
1307  Relation relation;
1308  HeapTuple tup;
1309  char prokind;
1310 
1311  /*
1312  * Delete the pg_proc tuple.
1313  */
1314  relation = table_open(ProcedureRelationId, RowExclusiveLock);
1315 
1316  tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
1317  if (!HeapTupleIsValid(tup)) /* should not happen */
1318  elog(ERROR, "cache lookup failed for function %u", funcOid);
1319 
1320  prokind = ((Form_pg_proc) GETSTRUCT(tup))->prokind;
1321 
1322  CatalogTupleDelete(relation, &tup->t_self);
1323 
1324  ReleaseSysCache(tup);
1325 
1326  table_close(relation, RowExclusiveLock);
1327 
1328  /*
1329  * If there's a pg_aggregate tuple, delete that too.
1330  */
1331  if (prokind == PROKIND_AGGREGATE)
1332  {
1333  relation = table_open(AggregateRelationId, RowExclusiveLock);
1334 
1335  tup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(funcOid));
1336  if (!HeapTupleIsValid(tup)) /* should not happen */
1337  elog(ERROR, "cache lookup failed for pg_aggregate tuple for function %u", funcOid);
1338 
1339  CatalogTupleDelete(relation, &tup->t_self);
1340 
1341  ReleaseSysCache(tup);
1342 
1343  table_close(relation, RowExclusiveLock);
1344  }
1345 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:232
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ update_proconfig_value()

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

Definition at line 654 of file functioncmds.c.

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

Referenced by AlterFunction(), and compute_function_attributes().

655 {
656  ListCell *l;
657 
658  foreach(l, set_items)
659  {
661 
662  if (sstmt->kind == VAR_RESET_ALL)
663  a = NULL;
664  else
665  {
666  char *valuestr = ExtractSetVariableArgs(sstmt);
667 
668  if (valuestr)
669  a = GUCArrayAdd(a, sstmt->name, valuestr);
670  else /* RESET */
671  a = GUCArrayDelete(a, sstmt->name);
672  }
673  }
674 
675  return a;
676 }
ArrayType * GUCArrayAdd(ArrayType *array, const char *name, const char *value)
Definition: guc.c:11105
VariableSetKind kind
Definition: parsenodes.h:2153
#define lfirst_node(type, lc)
Definition: pg_list.h:172
ArrayType * GUCArrayDelete(ArrayType *array, const char *name)
Definition: guc.c:11185
char * ExtractSetVariableArgs(VariableSetStmt *stmt)
Definition: guc.c:8845