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

1346 {
1347  HeapTuple tup;
1348  Oid funcOid;
1349  Form_pg_proc procForm;
1350  bool is_procedure;
1351  Relation rel;
1352  ListCell *l;
1353  DefElem *volatility_item = NULL;
1354  DefElem *strict_item = NULL;
1355  DefElem *security_def_item = NULL;
1356  DefElem *leakproof_item = NULL;
1357  List *set_items = NIL;
1358  DefElem *cost_item = NULL;
1359  DefElem *rows_item = NULL;
1360  DefElem *support_item = NULL;
1361  DefElem *parallel_item = NULL;
1362  ObjectAddress address;
1363 
1364  rel = table_open(ProcedureRelationId, RowExclusiveLock);
1365 
1366  funcOid = LookupFuncWithArgs(stmt->objtype, stmt->func, false);
1367 
1368  ObjectAddressSet(address, ProcedureRelationId, funcOid);
1369 
1370  tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1371  if (!HeapTupleIsValid(tup)) /* should not happen */
1372  elog(ERROR, "cache lookup failed for function %u", funcOid);
1373 
1374  procForm = (Form_pg_proc) GETSTRUCT(tup);
1375 
1376  /* Permission check: must own function */
1377  if (!pg_proc_ownercheck(funcOid, GetUserId()))
1379  NameListToString(stmt->func->objname));
1380 
1381  if (procForm->prokind == PROKIND_AGGREGATE)
1382  ereport(ERROR,
1383  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1384  errmsg("\"%s\" is an aggregate function",
1385  NameListToString(stmt->func->objname))));
1386 
1387  is_procedure = (procForm->prokind == PROKIND_PROCEDURE);
1388 
1389  /* Examine requested actions. */
1390  foreach(l, stmt->actions)
1391  {
1392  DefElem *defel = (DefElem *) lfirst(l);
1393 
1394  if (compute_common_attribute(pstate,
1395  is_procedure,
1396  defel,
1397  &volatility_item,
1398  &strict_item,
1399  &security_def_item,
1400  &leakproof_item,
1401  &set_items,
1402  &cost_item,
1403  &rows_item,
1404  &support_item,
1405  &parallel_item) == false)
1406  elog(ERROR, "option \"%s\" not recognized", defel->defname);
1407  }
1408 
1409  if (volatility_item)
1410  procForm->provolatile = interpret_func_volatility(volatility_item);
1411  if (strict_item)
1412  procForm->proisstrict = intVal(strict_item->arg);
1413  if (security_def_item)
1414  procForm->prosecdef = intVal(security_def_item->arg);
1415  if (leakproof_item)
1416  {
1417  procForm->proleakproof = intVal(leakproof_item->arg);
1418  if (procForm->proleakproof && !superuser())
1419  ereport(ERROR,
1420  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1421  errmsg("only superuser can define a leakproof function")));
1422  }
1423  if (cost_item)
1424  {
1425  procForm->procost = defGetNumeric(cost_item);
1426  if (procForm->procost <= 0)
1427  ereport(ERROR,
1428  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1429  errmsg("COST must be positive")));
1430  }
1431  if (rows_item)
1432  {
1433  procForm->prorows = defGetNumeric(rows_item);
1434  if (procForm->prorows <= 0)
1435  ereport(ERROR,
1436  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1437  errmsg("ROWS must be positive")));
1438  if (!procForm->proretset)
1439  ereport(ERROR,
1440  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1441  errmsg("ROWS is not applicable when function does not return a set")));
1442  }
1443  if (support_item)
1444  {
1445  /* interpret_func_support handles the privilege check */
1446  Oid newsupport = interpret_func_support(support_item);
1447 
1448  /* Add or replace dependency on support function */
1449  if (OidIsValid(procForm->prosupport))
1450  changeDependencyFor(ProcedureRelationId, funcOid,
1451  ProcedureRelationId, procForm->prosupport,
1452  newsupport);
1453  else
1454  {
1455  ObjectAddress referenced;
1456 
1457  referenced.classId = ProcedureRelationId;
1458  referenced.objectId = newsupport;
1459  referenced.objectSubId = 0;
1460  recordDependencyOn(&address, &referenced, DEPENDENCY_NORMAL);
1461  }
1462 
1463  procForm->prosupport = newsupport;
1464  }
1465  if (set_items)
1466  {
1467  Datum datum;
1468  bool isnull;
1469  ArrayType *a;
1470  Datum repl_val[Natts_pg_proc];
1471  bool repl_null[Natts_pg_proc];
1472  bool repl_repl[Natts_pg_proc];
1473 
1474  /* extract existing proconfig setting */
1475  datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proconfig, &isnull);
1476  a = isnull ? NULL : DatumGetArrayTypeP(datum);
1477 
1478  /* update according to each SET or RESET item, left to right */
1479  a = update_proconfig_value(a, set_items);
1480 
1481  /* update the tuple */
1482  memset(repl_repl, false, sizeof(repl_repl));
1483  repl_repl[Anum_pg_proc_proconfig - 1] = true;
1484 
1485  if (a == NULL)
1486  {
1487  repl_val[Anum_pg_proc_proconfig - 1] = (Datum) 0;
1488  repl_null[Anum_pg_proc_proconfig - 1] = true;
1489  }
1490  else
1491  {
1492  repl_val[Anum_pg_proc_proconfig - 1] = PointerGetDatum(a);
1493  repl_null[Anum_pg_proc_proconfig - 1] = false;
1494  }
1495 
1496  tup = heap_modify_tuple(tup, RelationGetDescr(rel),
1497  repl_val, repl_null, repl_repl);
1498  }
1499  if (parallel_item)
1500  procForm->proparallel = interpret_func_parallel(parallel_item);
1501 
1502  /* Do the update */
1503  CatalogTupleUpdate(rel, &tup->t_self, tup);
1504 
1505  InvokeObjectPostAlterHook(ProcedureRelationId, funcOid, 0);
1506 
1507  table_close(rel, NoLock);
1508  heap_freetuple(tup);
1509 
1510  return address;
1511 }
#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:495
Oid GetUserId(void)
Definition: miscinit.c:478
#define PointerGetDatum(X)
Definition: postgres.h:600
double defGetNumeric(DefElem *def)
Definition: define.c:85
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:43
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:3313
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
static Oid interpret_func_support(DefElem *defel)
Definition: functioncmds.c:659
ItemPointerData t_self
Definition: htup.h:65
ObjectType objtype
Definition: parsenodes.h:2973
#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:591
Node * arg
Definition: parsenodes.h:747
char * NameListToString(List *names)
Definition: namespace.c:3101
uintptr_t Datum
Definition: postgres.h:411
static ArrayType * update_proconfig_value(ArrayType *a, List *set_items)
Definition: functioncmds.c:634
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:2974
#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:52
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:388
#define elog(elevel,...)
Definition: elog.h:232
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2177
char * defname
Definition: parsenodes.h:746
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:482
bool pg_proc_ownercheck(Oid proc_oid, Oid roleid)
Definition: aclchk.c:4901
static char interpret_func_parallel(DefElem *defel)
Definition: functioncmds.c:609
#define DatumGetArrayTypeP(X)
Definition: array.h:254

◆ CallStmtResultDesc()

TupleDesc CallStmtResultDesc ( CallStmt stmt)

Definition at line 2353 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().

2354 {
2355  FuncExpr *fexpr;
2356  HeapTuple tuple;
2357  TupleDesc tupdesc;
2358 
2359  fexpr = stmt->funcexpr;
2360 
2361  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
2362  if (!HeapTupleIsValid(tuple))
2363  elog(ERROR, "cache lookup failed for procedure %u", fexpr->funcid);
2364 
2365  tupdesc = build_function_result_tupdesc_t(tuple);
2366 
2367  ReleaseSysCache(tuple);
2368 
2369  return tupdesc;
2370 }
FuncExpr * funcexpr
Definition: parsenodes.h:3007
TupleDesc build_function_result_tupdesc_t(HeapTuple procTuple)
Definition: funcapi.c:1604
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 1762 of file functioncmds.c.

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

Referenced by CreateTransform().

1763 {
1764  if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1765  ereport(ERROR,
1766  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1767  errmsg("transform function must not be volatile")));
1768  if (procstruct->prokind != PROKIND_FUNCTION)
1769  ereport(ERROR,
1770  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1771  errmsg("transform function must be a normal function")));
1772  if (procstruct->proretset)
1773  ereport(ERROR,
1774  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1775  errmsg("transform function must not return a set")));
1776  if (procstruct->pronargs != 1)
1777  ereport(ERROR,
1778  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1779  errmsg("transform function must take one argument")));
1780  if (procstruct->proargtypes.values[0] != INTERNALOID)
1781  ereport(ERROR,
1782  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1783  errmsg("first argument of transform function must be type %s",
1784  "internal")));
1785 }
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 482 of file functioncmds.c.

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

Referenced by AlterFunction(), and compute_function_attributes().

494 {
495  if (strcmp(defel->defname, "volatility") == 0)
496  {
497  if (is_procedure)
498  goto procedure_error;
499  if (*volatility_item)
500  goto duplicate_error;
501 
502  *volatility_item = defel;
503  }
504  else if (strcmp(defel->defname, "strict") == 0)
505  {
506  if (is_procedure)
507  goto procedure_error;
508  if (*strict_item)
509  goto duplicate_error;
510 
511  *strict_item = defel;
512  }
513  else if (strcmp(defel->defname, "security") == 0)
514  {
515  if (*security_item)
516  goto duplicate_error;
517 
518  *security_item = defel;
519  }
520  else if (strcmp(defel->defname, "leakproof") == 0)
521  {
522  if (is_procedure)
523  goto procedure_error;
524  if (*leakproof_item)
525  goto duplicate_error;
526 
527  *leakproof_item = defel;
528  }
529  else if (strcmp(defel->defname, "set") == 0)
530  {
531  *set_items = lappend(*set_items, defel->arg);
532  }
533  else if (strcmp(defel->defname, "cost") == 0)
534  {
535  if (is_procedure)
536  goto procedure_error;
537  if (*cost_item)
538  goto duplicate_error;
539 
540  *cost_item = defel;
541  }
542  else if (strcmp(defel->defname, "rows") == 0)
543  {
544  if (is_procedure)
545  goto procedure_error;
546  if (*rows_item)
547  goto duplicate_error;
548 
549  *rows_item = defel;
550  }
551  else if (strcmp(defel->defname, "support") == 0)
552  {
553  if (is_procedure)
554  goto procedure_error;
555  if (*support_item)
556  goto duplicate_error;
557 
558  *support_item = defel;
559  }
560  else if (strcmp(defel->defname, "parallel") == 0)
561  {
562  if (is_procedure)
563  goto procedure_error;
564  if (*parallel_item)
565  goto duplicate_error;
566 
567  *parallel_item = defel;
568  }
569  else
570  return false;
571 
572  /* Recognized an option */
573  return true;
574 
575 duplicate_error:
576  ereport(ERROR,
577  (errcode(ERRCODE_SYNTAX_ERROR),
578  errmsg("conflicting or redundant options"),
579  parser_errposition(pstate, defel->location)));
580  return false; /* keep compiler quiet */
581 
582 procedure_error:
583  ereport(ERROR,
584  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
585  errmsg("invalid attribute in procedure definition"),
586  parser_errposition(pstate, defel->location)));
587  return false;
588 }
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ERROR
Definition: elog.h:46
int location
Definition: parsenodes.h:749
Node * arg
Definition: parsenodes.h:747
List * lappend(List *list, void *datum)
Definition: list.c:336
#define ereport(elevel,...)
Definition: elog.h:157
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:746

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

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

Referenced by CreateFunction().

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

◆ compute_return_type()

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

Definition at line 91 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().

93 {
94  Oid rettype;
95  Type typtup;
96  AclResult aclresult;
97 
98  typtup = LookupTypeName(NULL, returnType, NULL, false);
99 
100  if (typtup)
101  {
102  if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
103  {
104  if (languageOid == SQLlanguageId)
105  ereport(ERROR,
106  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
107  errmsg("SQL function cannot return shell type %s",
108  TypeNameToString(returnType))));
109  else
110  ereport(NOTICE,
111  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
112  errmsg("return type %s is only a shell",
113  TypeNameToString(returnType))));
114  }
115  rettype = typeTypeId(typtup);
116  ReleaseSysCache(typtup);
117  }
118  else
119  {
120  char *typnam = TypeNameToString(returnType);
121  Oid namespaceId;
122  AclResult aclresult;
123  char *typname;
124  ObjectAddress address;
125 
126  /*
127  * Only C-coded functions can be I/O functions. We enforce this
128  * restriction here mainly to prevent littering the catalogs with
129  * shell types due to simple typos in user-defined function
130  * definitions.
131  */
132  if (languageOid != INTERNALlanguageId &&
133  languageOid != ClanguageId)
134  ereport(ERROR,
135  (errcode(ERRCODE_UNDEFINED_OBJECT),
136  errmsg("type \"%s\" does not exist", typnam)));
137 
138  /* Reject if there's typmod decoration, too */
139  if (returnType->typmods != NIL)
140  ereport(ERROR,
141  (errcode(ERRCODE_SYNTAX_ERROR),
142  errmsg("type modifier cannot be specified for shell type \"%s\"",
143  typnam)));
144 
145  /* Otherwise, go ahead and make a shell type */
146  ereport(NOTICE,
147  (errcode(ERRCODE_UNDEFINED_OBJECT),
148  errmsg("type \"%s\" is not yet defined", typnam),
149  errdetail("Creating a shell type definition.")));
150  namespaceId = QualifiedNameGetCreationNamespace(returnType->names,
151  &typname);
152  aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
153  ACL_CREATE);
154  if (aclresult != ACLCHECK_OK)
155  aclcheck_error(aclresult, OBJECT_SCHEMA,
156  get_namespace_name(namespaceId));
157  address = TypeShellMake(typname, namespaceId, GetUserId());
158  rettype = address.objectId;
159  Assert(OidIsValid(rettype));
160  }
161 
162  aclresult = pg_type_aclcheck(rettype, GetUserId(), ACL_USAGE);
163  if (aclresult != ACLCHECK_OK)
164  aclcheck_error_type(aclresult, rettype);
165 
166  *prorettype_p = rettype;
167  *returnsSet_p = returnType->setof;
168 }
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:478
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2994
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:476
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:4761
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3626
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3313
#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:4811
Oid typeTypeId(Type tp)
Definition: parse_type.c:588

◆ CreateCast()

ObjectAddress CreateCast ( CreateCastStmt stmt)

Definition at line 1518 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().

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

◆ CreateFunction()

ObjectAddress CreateFunction ( ParseState pstate,
CreateFunctionStmt stmt 
)

Definition at line 1012 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().

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

Referenced by ProcessUtilitySlow().

1793 {
1794  Oid typeid;
1795  char typtype;
1796  Oid langid;
1797  Oid fromsqlfuncid;
1798  Oid tosqlfuncid;
1799  AclResult aclresult;
1800  Form_pg_proc procstruct;
1801  Datum values[Natts_pg_transform];
1802  bool nulls[Natts_pg_transform];
1803  bool replaces[Natts_pg_transform];
1804  Oid transformid;
1805  HeapTuple tuple;
1806  HeapTuple newtuple;
1807  Relation relation;
1808  ObjectAddress myself,
1809  referenced;
1810  ObjectAddresses *addrs;
1811  bool is_replace;
1812 
1813  /*
1814  * Get the type
1815  */
1816  typeid = typenameTypeId(NULL, stmt->type_name);
1817  typtype = get_typtype(typeid);
1818 
1819  if (typtype == TYPTYPE_PSEUDO)
1820  ereport(ERROR,
1821  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1822  errmsg("data type %s is a pseudo-type",
1823  TypeNameToString(stmt->type_name))));
1824 
1825  if (typtype == TYPTYPE_DOMAIN)
1826  ereport(ERROR,
1827  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1828  errmsg("data type %s is a domain",
1829  TypeNameToString(stmt->type_name))));
1830 
1831  if (!pg_type_ownercheck(typeid, GetUserId()))
1833 
1834  aclresult = pg_type_aclcheck(typeid, GetUserId(), ACL_USAGE);
1835  if (aclresult != ACLCHECK_OK)
1836  aclcheck_error_type(aclresult, typeid);
1837 
1838  /*
1839  * Get the language
1840  */
1841  langid = get_language_oid(stmt->lang, false);
1842 
1843  aclresult = pg_language_aclcheck(langid, GetUserId(), ACL_USAGE);
1844  if (aclresult != ACLCHECK_OK)
1845  aclcheck_error(aclresult, OBJECT_LANGUAGE, stmt->lang);
1846 
1847  /*
1848  * Get the functions
1849  */
1850  if (stmt->fromsql)
1851  {
1852  fromsqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->fromsql, false);
1853 
1854  if (!pg_proc_ownercheck(fromsqlfuncid, GetUserId()))
1856 
1857  aclresult = pg_proc_aclcheck(fromsqlfuncid, GetUserId(), ACL_EXECUTE);
1858  if (aclresult != ACLCHECK_OK)
1860 
1861  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fromsqlfuncid));
1862  if (!HeapTupleIsValid(tuple))
1863  elog(ERROR, "cache lookup failed for function %u", fromsqlfuncid);
1864  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1865  if (procstruct->prorettype != INTERNALOID)
1866  ereport(ERROR,
1867  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1868  errmsg("return data type of FROM SQL function must be %s",
1869  "internal")));
1870  check_transform_function(procstruct);
1871  ReleaseSysCache(tuple);
1872  }
1873  else
1874  fromsqlfuncid = InvalidOid;
1875 
1876  if (stmt->tosql)
1877  {
1878  tosqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->tosql, false);
1879 
1880  if (!pg_proc_ownercheck(tosqlfuncid, GetUserId()))
1882 
1883  aclresult = pg_proc_aclcheck(tosqlfuncid, GetUserId(), ACL_EXECUTE);
1884  if (aclresult != ACLCHECK_OK)
1886 
1887  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(tosqlfuncid));
1888  if (!HeapTupleIsValid(tuple))
1889  elog(ERROR, "cache lookup failed for function %u", tosqlfuncid);
1890  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1891  if (procstruct->prorettype != typeid)
1892  ereport(ERROR,
1893  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1894  errmsg("return data type of TO SQL function must be the transform data type")));
1895  check_transform_function(procstruct);
1896  ReleaseSysCache(tuple);
1897  }
1898  else
1899  tosqlfuncid = InvalidOid;
1900 
1901  /*
1902  * Ready to go
1903  */
1904  values[Anum_pg_transform_trftype - 1] = ObjectIdGetDatum(typeid);
1905  values[Anum_pg_transform_trflang - 1] = ObjectIdGetDatum(langid);
1906  values[Anum_pg_transform_trffromsql - 1] = ObjectIdGetDatum(fromsqlfuncid);
1907  values[Anum_pg_transform_trftosql - 1] = ObjectIdGetDatum(tosqlfuncid);
1908 
1909  MemSet(nulls, false, sizeof(nulls));
1910 
1911  relation = table_open(TransformRelationId, RowExclusiveLock);
1912 
1913  tuple = SearchSysCache2(TRFTYPELANG,
1914  ObjectIdGetDatum(typeid),
1915  ObjectIdGetDatum(langid));
1916  if (HeapTupleIsValid(tuple))
1917  {
1919 
1920  if (!stmt->replace)
1921  ereport(ERROR,
1923  errmsg("transform for type %s language \"%s\" already exists",
1924  format_type_be(typeid),
1925  stmt->lang)));
1926 
1927  MemSet(replaces, false, sizeof(replaces));
1928  replaces[Anum_pg_transform_trffromsql - 1] = true;
1929  replaces[Anum_pg_transform_trftosql - 1] = true;
1930 
1931  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
1932  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
1933 
1934  transformid = form->oid;
1935  ReleaseSysCache(tuple);
1936  is_replace = true;
1937  }
1938  else
1939  {
1940  transformid = GetNewOidWithIndex(relation, TransformOidIndexId,
1941  Anum_pg_transform_oid);
1942  values[Anum_pg_transform_oid - 1] = ObjectIdGetDatum(transformid);
1943  newtuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
1944  CatalogTupleInsert(relation, newtuple);
1945  is_replace = false;
1946  }
1947 
1948  if (is_replace)
1949  deleteDependencyRecordsFor(TransformRelationId, transformid, true);
1950 
1951  addrs = new_object_addresses();
1952 
1953  /* make dependency entries */
1954  ObjectAddressSet(myself, TransformRelationId, transformid);
1955 
1956  /* dependency on language */
1957  ObjectAddressSet(referenced, LanguageRelationId, langid);
1958  add_exact_object_address(&referenced, addrs);
1959 
1960  /* dependency on type */
1961  ObjectAddressSet(referenced, TypeRelationId, typeid);
1962  add_exact_object_address(&referenced, addrs);
1963 
1964  /* dependencies on functions */
1965  if (OidIsValid(fromsqlfuncid))
1966  {
1967  ObjectAddressSet(referenced, ProcedureRelationId, fromsqlfuncid);
1968  add_exact_object_address(&referenced, addrs);
1969  }
1970  if (OidIsValid(tosqlfuncid))
1971  {
1972  ObjectAddressSet(referenced, ProcedureRelationId, tosqlfuncid);
1973  add_exact_object_address(&referenced, addrs);
1974  }
1975 
1977  free_object_addresses(addrs);
1978 
1979  /* dependency on extension */
1980  recordDependencyOnCurrentExtension(&myself, is_replace);
1981 
1982  /* Post creation hook for new transform */
1983  InvokeObjectPostCreateHook(TransformRelationId, transformid, 0);
1984 
1985  heap_freetuple(newtuple);
1986 
1987  table_close(relation, RowExclusiveLock);
1988 
1989  return myself;
1990 }
#define TransformOidIndexId
Definition: pg_transform.h:46
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:322
ObjectWithArgs * tosql
Definition: parsenodes.h:3508
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:495
Oid GetUserId(void)
Definition: miscinit.c:478
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:476
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2701
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:232
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:2492
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2437
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2732
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:4849
#define OidIsValid(objectId)
Definition: c.h:710
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4735
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3626
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3313
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:3101
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:3507
#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:180
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:3505
static Datum values[MAXATTR]
Definition: bootstrap.c:166
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:4723
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2177
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4811
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:4901
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 2173 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(), ereport, errcode(), errmsg_plural(), ERROR, EState::es_param_list_info, ExecEvalExprSwitchContext(), ExecPrepareExpr(), ExecStoreHeapTuple(), expand_function_arguments(), fmgr_info(), fmgr_info_set_expr, FreeExecutorState(), FUNC_MAX_ARGS, CallStmt::funcexpr, FuncExpr::funcid, FuncExpr::funcresulttype, FunctionCallInvoke, get_func_arg_info(), get_func_name(), GETSTRUCT, 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(), PROCOID, _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().

2174 {
2175  LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
2176  ListCell *lc;
2177  FuncExpr *fexpr;
2178  int nargs;
2179  int i;
2180  AclResult aclresult;
2181  Oid *argtypes;
2182  char **argnames;
2183  char *argmodes;
2184  FmgrInfo flinfo;
2185  CallContext *callcontext;
2186  EState *estate;
2187  ExprContext *econtext;
2188  HeapTuple tp;
2189  PgStat_FunctionCallUsage fcusage;
2190  Datum retval;
2191 
2192  fexpr = stmt->funcexpr;
2193  Assert(fexpr);
2194  Assert(IsA(fexpr, FuncExpr));
2195 
2196  aclresult = pg_proc_aclcheck(fexpr->funcid, GetUserId(), ACL_EXECUTE);
2197  if (aclresult != ACLCHECK_OK)
2198  aclcheck_error(aclresult, OBJECT_PROCEDURE, get_func_name(fexpr->funcid));
2199 
2200  /* Prep the context object we'll pass to the procedure */
2201  callcontext = makeNode(CallContext);
2202  callcontext->atomic = atomic;
2203 
2205  if (!HeapTupleIsValid(tp))
2206  elog(ERROR, "cache lookup failed for function %u", fexpr->funcid);
2207 
2208  /*
2209  * If proconfig is set we can't allow transaction commands because of the
2210  * way the GUC stacking works: The transaction boundary would have to pop
2211  * the proconfig setting off the stack. That restriction could be lifted
2212  * by redesigning the GUC nesting mechanism a bit.
2213  */
2214  if (!heap_attisnull(tp, Anum_pg_proc_proconfig, NULL))
2215  callcontext->atomic = true;
2216 
2217  /*
2218  * In security definer procedures, we can't allow transaction commands.
2219  * StartTransaction() insists that the security context stack is empty,
2220  * and AbortTransaction() resets the security context. This could be
2221  * reorganized, but right now it doesn't work.
2222  */
2223  if (((Form_pg_proc) GETSTRUCT(tp))->prosecdef)
2224  callcontext->atomic = true;
2225 
2226  /*
2227  * Expand named arguments, defaults, etc. We do not want to scribble on
2228  * the passed-in CallStmt parse tree, so first flat-copy fexpr, allowing
2229  * us to replace its args field. (Note that expand_function_arguments
2230  * will not modify any of the passed-in data structure.)
2231  */
2232  {
2233  FuncExpr *nexpr = makeNode(FuncExpr);
2234 
2235  memcpy(nexpr, fexpr, sizeof(FuncExpr));
2236  fexpr = nexpr;
2237  }
2238 
2239  fexpr->args = expand_function_arguments(fexpr->args,
2240  fexpr->funcresulttype,
2241  tp);
2242  nargs = list_length(fexpr->args);
2243 
2244  get_func_arg_info(tp, &argtypes, &argnames, &argmodes);
2245 
2246  ReleaseSysCache(tp);
2247 
2248  /* safety check; see ExecInitFunc() */
2249  if (nargs > FUNC_MAX_ARGS)
2250  ereport(ERROR,
2251  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2252  errmsg_plural("cannot pass more than %d argument to a procedure",
2253  "cannot pass more than %d arguments to a procedure",
2254  FUNC_MAX_ARGS,
2255  FUNC_MAX_ARGS)));
2256 
2257  /* Initialize function call structure */
2259  fmgr_info(fexpr->funcid, &flinfo);
2260  fmgr_info_set_expr((Node *) fexpr, &flinfo);
2261  InitFunctionCallInfoData(*fcinfo, &flinfo, nargs, fexpr->inputcollid,
2262  (Node *) callcontext, NULL);
2263 
2264  /*
2265  * Evaluate procedure arguments inside a suitable execution context. Note
2266  * we can't free this context till the procedure returns.
2267  */
2268  estate = CreateExecutorState();
2269  estate->es_param_list_info = params;
2270  econtext = CreateExprContext(estate);
2271 
2272  i = 0;
2273  foreach(lc, fexpr->args)
2274  {
2275  if (argmodes && argmodes[i] == PROARGMODE_OUT)
2276  {
2277  fcinfo->args[i].value = 0;
2278  fcinfo->args[i].isnull = true;
2279  }
2280  else
2281  {
2282  ExprState *exprstate;
2283  Datum val;
2284  bool isnull;
2285 
2286  exprstate = ExecPrepareExpr(lfirst(lc), estate);
2287 
2288  val = ExecEvalExprSwitchContext(exprstate, econtext, &isnull);
2289 
2290  fcinfo->args[i].value = val;
2291  fcinfo->args[i].isnull = isnull;
2292  }
2293 
2294  i++;
2295  }
2296 
2297  pgstat_init_function_usage(fcinfo, &fcusage);
2298  retval = FunctionCallInvoke(fcinfo);
2299  pgstat_end_function_usage(&fcusage, true);
2300 
2301  if (fexpr->funcresulttype == VOIDOID)
2302  {
2303  /* do nothing */
2304  }
2305  else if (fexpr->funcresulttype == RECORDOID)
2306  {
2307  /*
2308  * send tuple to client
2309  */
2310 
2311  HeapTupleHeader td;
2312  Oid tupType;
2313  int32 tupTypmod;
2314  TupleDesc retdesc;
2315  HeapTupleData rettupdata;
2316  TupOutputState *tstate;
2317  TupleTableSlot *slot;
2318 
2319  if (fcinfo->isnull)
2320  elog(ERROR, "procedure returned null record");
2321 
2322  td = DatumGetHeapTupleHeader(retval);
2323  tupType = HeapTupleHeaderGetTypeId(td);
2324  tupTypmod = HeapTupleHeaderGetTypMod(td);
2325  retdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
2326 
2327  tstate = begin_tup_output_tupdesc(dest, retdesc,
2328  &TTSOpsHeapTuple);
2329 
2330  rettupdata.t_len = HeapTupleHeaderGetDatumLength(td);
2331  ItemPointerSetInvalid(&(rettupdata.t_self));
2332  rettupdata.t_tableOid = InvalidOid;
2333  rettupdata.t_data = td;
2334 
2335  slot = ExecStoreHeapTuple(&rettupdata, tstate->slot, false);
2336  tstate->dest->receiveSlot(slot, tstate->dest);
2337 
2338  end_tup_output(tstate);
2339 
2340  ReleaseTupleDesc(retdesc);
2341  }
2342  else
2343  elog(ERROR, "unexpected result type for procedure: %u",
2344  fexpr->funcresulttype);
2345 
2346  FreeExecutorState(estate);
2347 }
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:590
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:331
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
List * expand_function_arguments(List *args, Oid result_type, HeapTuple func_tuple)
Definition: clauses.c:3916
List * args
Definition: primnodes.h:503
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1826
FuncExpr * funcexpr
Definition: parsenodes.h:3007
Oid GetUserId(void)
Definition: miscinit.c:478
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1019
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
Definition: funcapi.c:1268
Definition: nodes.h:539
int errcode(int sqlerrcode)
Definition: elog.c:698
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
TupleTableSlot * slot
Definition: executor.h:489
unsigned int Oid
Definition: postgres_ext.h:31
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:3313
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:1898
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
#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:587
#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:1969
#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:4723
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:593
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 ( DoStmt stmt,
bool  atomic 
)

Definition at line 2047 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, 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().

2048 {
2050  ListCell *arg;
2051  DefElem *as_item = NULL;
2052  DefElem *language_item = NULL;
2053  char *language;
2054  Oid laninline;
2055  HeapTuple languageTuple;
2056  Form_pg_language languageStruct;
2057 
2058  /* Process options we got from gram.y */
2059  foreach(arg, stmt->args)
2060  {
2061  DefElem *defel = (DefElem *) lfirst(arg);
2062 
2063  if (strcmp(defel->defname, "as") == 0)
2064  {
2065  if (as_item)
2066  ereport(ERROR,
2067  (errcode(ERRCODE_SYNTAX_ERROR),
2068  errmsg("conflicting or redundant options")));
2069  as_item = defel;
2070  }
2071  else if (strcmp(defel->defname, "language") == 0)
2072  {
2073  if (language_item)
2074  ereport(ERROR,
2075  (errcode(ERRCODE_SYNTAX_ERROR),
2076  errmsg("conflicting or redundant options")));
2077  language_item = defel;
2078  }
2079  else
2080  elog(ERROR, "option \"%s\" not recognized",
2081  defel->defname);
2082  }
2083 
2084  if (as_item)
2085  codeblock->source_text = strVal(as_item->arg);
2086  else
2087  ereport(ERROR,
2088  (errcode(ERRCODE_SYNTAX_ERROR),
2089  errmsg("no inline code specified")));
2090 
2091  /* if LANGUAGE option wasn't specified, use the default */
2092  if (language_item)
2093  language = strVal(language_item->arg);
2094  else
2095  language = "plpgsql";
2096 
2097  /* Look up the language and validate permissions */
2098  languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
2099  if (!HeapTupleIsValid(languageTuple))
2100  ereport(ERROR,
2101  (errcode(ERRCODE_UNDEFINED_OBJECT),
2102  errmsg("language \"%s\" does not exist", language),
2103  (extension_file_exists(language) ?
2104  errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
2105 
2106  languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
2107  codeblock->langOid = languageStruct->oid;
2108  codeblock->langIsTrusted = languageStruct->lanpltrusted;
2109  codeblock->atomic = atomic;
2110 
2111  if (languageStruct->lanpltrusted)
2112  {
2113  /* if trusted language, need USAGE privilege */
2114  AclResult aclresult;
2115 
2116  aclresult = pg_language_aclcheck(codeblock->langOid, GetUserId(),
2117  ACL_USAGE);
2118  if (aclresult != ACLCHECK_OK)
2119  aclcheck_error(aclresult, OBJECT_LANGUAGE,
2120  NameStr(languageStruct->lanname));
2121  }
2122  else
2123  {
2124  /* if untrusted language, must be superuser */
2125  if (!superuser())
2127  NameStr(languageStruct->lanname));
2128  }
2129 
2130  /* get the handler function's OID */
2131  laninline = languageStruct->laninline;
2132  if (!OidIsValid(laninline))
2133  ereport(ERROR,
2134  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2135  errmsg("language \"%s\" does not support inline code execution",
2136  NameStr(languageStruct->lanname))));
2137 
2138  ReleaseSysCache(languageTuple);
2139 
2140  /* execute the inline handler */
2141  OidFunctionCall1(laninline, PointerGetDatum(codeblock));
2142 }
int errhint(const char *fmt,...)
Definition: elog.c:1156
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
Oid GetUserId(void)
Definition: miscinit.c:478
#define PointerGetDatum(X)
Definition: postgres.h:600
#define strVal(v)
Definition: value.h:54
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:4735
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3313
#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:747
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
#define makeNode(_type_)
Definition: nodes.h:587
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:169
List * args
Definition: parsenodes.h:2987
bool extension_file_exists(const char *extensionName)
Definition: extension.c:2237
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:2993
char * defname
Definition: parsenodes.h:746

◆ get_transform_oid()

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

Definition at line 2000 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().

2001 {
2002  Oid oid;
2003 
2004  oid = GetSysCacheOid2(TRFTYPELANG, Anum_pg_transform_oid,
2005  ObjectIdGetDatum(type_id),
2006  ObjectIdGetDatum(lang_id));
2007  if (!OidIsValid(oid) && !missing_ok)
2008  ereport(ERROR,
2009  (errcode(ERRCODE_UNDEFINED_OBJECT),
2010  errmsg("transform for type %s language \"%s\" does not exist",
2011  format_type_be(type_id),
2012  get_language_name(lang_id, false))));
2013  return oid;
2014 }
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 852 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().

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

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

Referenced by AlterFunction(), and compute_function_attributes().

610 {
611  char *str = strVal(defel->arg);
612 
613  if (strcmp(str, "safe") == 0)
614  return PROPARALLEL_SAFE;
615  else if (strcmp(str, "unsafe") == 0)
616  return PROPARALLEL_UNSAFE;
617  else if (strcmp(str, "restricted") == 0)
618  return PROPARALLEL_RESTRICTED;
619  else
620  {
621  ereport(ERROR,
622  (errcode(ERRCODE_SYNTAX_ERROR),
623  errmsg("parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE")));
624  return PROPARALLEL_UNSAFE; /* keep compiler quiet */
625  }
626 }
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ERROR
Definition: elog.h:46
Node * arg
Definition: parsenodes.h:747
#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 659 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().

660 {
661  List *procName = defGetQualifiedName(defel);
662  Oid procOid;
663  Oid argList[1];
664 
665  /*
666  * Support functions always take one INTERNAL argument and return
667  * INTERNAL.
668  */
669  argList[0] = INTERNALOID;
670 
671  procOid = LookupFuncName(procName, 1, argList, true);
672  if (!OidIsValid(procOid))
673  ereport(ERROR,
674  (errcode(ERRCODE_UNDEFINED_FUNCTION),
675  errmsg("function %s does not exist",
676  func_signature_string(procName, 1, NIL, argList))));
677 
678  if (get_func_rettype(procOid) != INTERNALOID)
679  ereport(ERROR,
680  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
681  errmsg("support function %s must return type %s",
682  NameListToString(procName), "internal")));
683 
684  /*
685  * Someday we might want an ACL check here; but for now, we insist that
686  * you be superuser to specify a support function, so privilege on the
687  * support function is moot.
688  */
689  if (!superuser())
690  ereport(ERROR,
691  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
692  errmsg("must be superuser to specify a support function")));
693 
694  return procOid;
695 }
#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:2117
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:2029
char * NameListToString(List *names)
Definition: namespace.c:3101
#define ereport(elevel,...)
Definition: elog.h:157
List * defGetQualifiedName(DefElem *def)
Definition: define.c:223
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 591 of file functioncmds.c.

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

Referenced by AlterFunction(), and compute_function_attributes().

592 {
593  char *str = strVal(defel->arg);
594 
595  if (strcmp(str, "immutable") == 0)
596  return PROVOLATILE_IMMUTABLE;
597  else if (strcmp(str, "stable") == 0)
598  return PROVOLATILE_STABLE;
599  else if (strcmp(str, "volatile") == 0)
600  return PROVOLATILE_VOLATILE;
601  else
602  {
603  elog(ERROR, "invalid volatility \"%s\"", str);
604  return 0; /* keep compiler quiet */
605  }
606 }
#define strVal(v)
Definition: value.h:54
#define ERROR
Definition: elog.h:46
Node * arg
Definition: parsenodes.h:747
#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 187 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_IN, FUNC_PARAM_INOUT, 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().

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

◆ IsThereFunctionInNamespace()

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

Definition at line 2024 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().

2026 {
2027  /* check for duplicate name (more friendly than unique-index failure) */
2030  PointerGetDatum(proargtypes),
2031  ObjectIdGetDatum(nspOid)))
2032  ereport(ERROR,
2033  (errcode(ERRCODE_DUPLICATE_FUNCTION),
2034  errmsg("function %s already exists in schema \"%s\"",
2036  NIL, proargtypes->values),
2037  get_namespace_name(nspOid))));
2038 }
#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:1992
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ RemoveFunctionById()

void RemoveFunctionById ( Oid  funcOid)

Definition at line 1297 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().

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

635 {
636  ListCell *l;
637 
638  foreach(l, set_items)
639  {
641 
642  if (sstmt->kind == VAR_RESET_ALL)
643  a = NULL;
644  else
645  {
646  char *valuestr = ExtractSetVariableArgs(sstmt);
647 
648  if (valuestr)
649  a = GUCArrayAdd(a, sstmt->name, valuestr);
650  else /* RESET */
651  a = GUCArrayDelete(a, sstmt->name);
652  }
653  }
654 
655  return a;
656 }
ArrayType * GUCArrayAdd(ArrayType *array, const char *name, const char *value)
Definition: guc.c:11046
VariableSetKind kind
Definition: parsenodes.h:2129
#define lfirst_node(type, lc)
Definition: pg_list.h:172
ArrayType * GUCArrayDelete(ArrayType *array, const char *name)
Definition: guc.c:11126
char * ExtractSetVariableArgs(VariableSetStmt *stmt)
Definition: guc.c:8786