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 "funcapi.h"
#include "miscadmin.h"
#include "optimizer/optimizer.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 "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, ArrayType **allParameterTypes, ArrayType **parameterModes, ArrayType **parameterNames, 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, char **prosrc_str_p, char **probin_str_p)
 
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 1231 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().

1232 {
1233  HeapTuple tup;
1234  Oid funcOid;
1235  Form_pg_proc procForm;
1236  bool is_procedure;
1237  Relation rel;
1238  ListCell *l;
1239  DefElem *volatility_item = NULL;
1240  DefElem *strict_item = NULL;
1241  DefElem *security_def_item = NULL;
1242  DefElem *leakproof_item = NULL;
1243  List *set_items = NIL;
1244  DefElem *cost_item = NULL;
1245  DefElem *rows_item = NULL;
1246  DefElem *support_item = NULL;
1247  DefElem *parallel_item = NULL;
1248  ObjectAddress address;
1249 
1250  rel = table_open(ProcedureRelationId, RowExclusiveLock);
1251 
1252  funcOid = LookupFuncWithArgs(stmt->objtype, stmt->func, false);
1253 
1254  ObjectAddressSet(address, ProcedureRelationId, funcOid);
1255 
1256  tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1257  if (!HeapTupleIsValid(tup)) /* should not happen */
1258  elog(ERROR, "cache lookup failed for function %u", funcOid);
1259 
1260  procForm = (Form_pg_proc) GETSTRUCT(tup);
1261 
1262  /* Permission check: must own function */
1263  if (!pg_proc_ownercheck(funcOid, GetUserId()))
1265  NameListToString(stmt->func->objname));
1266 
1267  if (procForm->prokind == PROKIND_AGGREGATE)
1268  ereport(ERROR,
1269  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1270  errmsg("\"%s\" is an aggregate function",
1271  NameListToString(stmt->func->objname))));
1272 
1273  is_procedure = (procForm->prokind == PROKIND_PROCEDURE);
1274 
1275  /* Examine requested actions. */
1276  foreach(l, stmt->actions)
1277  {
1278  DefElem *defel = (DefElem *) lfirst(l);
1279 
1280  if (compute_common_attribute(pstate,
1281  is_procedure,
1282  defel,
1283  &volatility_item,
1284  &strict_item,
1285  &security_def_item,
1286  &leakproof_item,
1287  &set_items,
1288  &cost_item,
1289  &rows_item,
1290  &support_item,
1291  &parallel_item) == false)
1292  elog(ERROR, "option \"%s\" not recognized", defel->defname);
1293  }
1294 
1295  if (volatility_item)
1296  procForm->provolatile = interpret_func_volatility(volatility_item);
1297  if (strict_item)
1298  procForm->proisstrict = intVal(strict_item->arg);
1299  if (security_def_item)
1300  procForm->prosecdef = intVal(security_def_item->arg);
1301  if (leakproof_item)
1302  {
1303  procForm->proleakproof = intVal(leakproof_item->arg);
1304  if (procForm->proleakproof && !superuser())
1305  ereport(ERROR,
1306  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1307  errmsg("only superuser can define a leakproof function")));
1308  }
1309  if (cost_item)
1310  {
1311  procForm->procost = defGetNumeric(cost_item);
1312  if (procForm->procost <= 0)
1313  ereport(ERROR,
1314  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1315  errmsg("COST must be positive")));
1316  }
1317  if (rows_item)
1318  {
1319  procForm->prorows = defGetNumeric(rows_item);
1320  if (procForm->prorows <= 0)
1321  ereport(ERROR,
1322  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1323  errmsg("ROWS must be positive")));
1324  if (!procForm->proretset)
1325  ereport(ERROR,
1326  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1327  errmsg("ROWS is not applicable when function does not return a set")));
1328  }
1329  if (support_item)
1330  {
1331  /* interpret_func_support handles the privilege check */
1332  Oid newsupport = interpret_func_support(support_item);
1333 
1334  /* Add or replace dependency on support function */
1335  if (OidIsValid(procForm->prosupport))
1336  changeDependencyFor(ProcedureRelationId, funcOid,
1337  ProcedureRelationId, procForm->prosupport,
1338  newsupport);
1339  else
1340  {
1341  ObjectAddress referenced;
1342 
1343  referenced.classId = ProcedureRelationId;
1344  referenced.objectId = newsupport;
1345  referenced.objectSubId = 0;
1346  recordDependencyOn(&address, &referenced, DEPENDENCY_NORMAL);
1347  }
1348 
1349  procForm->prosupport = newsupport;
1350  }
1351  if (set_items)
1352  {
1353  Datum datum;
1354  bool isnull;
1355  ArrayType *a;
1356  Datum repl_val[Natts_pg_proc];
1357  bool repl_null[Natts_pg_proc];
1358  bool repl_repl[Natts_pg_proc];
1359 
1360  /* extract existing proconfig setting */
1361  datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proconfig, &isnull);
1362  a = isnull ? NULL : DatumGetArrayTypeP(datum);
1363 
1364  /* update according to each SET or RESET item, left to right */
1365  a = update_proconfig_value(a, set_items);
1366 
1367  /* update the tuple */
1368  memset(repl_repl, false, sizeof(repl_repl));
1369  repl_repl[Anum_pg_proc_proconfig - 1] = true;
1370 
1371  if (a == NULL)
1372  {
1373  repl_val[Anum_pg_proc_proconfig - 1] = (Datum) 0;
1374  repl_null[Anum_pg_proc_proconfig - 1] = true;
1375  }
1376  else
1377  {
1378  repl_val[Anum_pg_proc_proconfig - 1] = PointerGetDatum(a);
1379  repl_null[Anum_pg_proc_proconfig - 1] = false;
1380  }
1381 
1382  tup = heap_modify_tuple(tup, RelationGetDescr(rel),
1383  repl_val, repl_null, repl_repl);
1384  }
1385  if (parallel_item)
1386  procForm->proparallel = interpret_func_parallel(parallel_item);
1387 
1388  /* Do the update */
1389  CatalogTupleUpdate(rel, &tup->t_self, tup);
1390 
1391  InvokeObjectPostAlterHook(ProcedureRelationId, funcOid, 0);
1392 
1393  table_close(rel, NoLock);
1394  heap_freetuple(tup);
1395 
1396  return address;
1397 }
#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:655
#define RelationGetDescr(relation)
Definition: rel.h:483
Oid GetUserId(void)
Definition: miscinit.c:476
#define PointerGetDatum(X)
Definition: postgres.h:556
double defGetNumeric(DefElem *def)
Definition: define.c:85
int errcode(int sqlerrcode)
Definition: elog.c:691
bool superuser(void)
Definition: superuser.c:46
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:46
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:706
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3294
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
static Oid interpret_func_support(DefElem *defel)
Definition: functioncmds.c:647
ItemPointerData t_self
Definition: htup.h:65
ObjectType objtype
Definition: parsenodes.h:2866
#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:579
Node * arg
Definition: parsenodes.h:735
char * NameListToString(List *names)
Definition: namespace.c:3101
uintptr_t Datum
Definition: postgres.h:367
static ArrayType * update_proconfig_value(ArrayType *a, List *set_items)
Definition: functioncmds.c:622
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1376
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:133
#define ereport(elevel,...)
Definition: elog.h:155
ObjectWithArgs * func
Definition: parsenodes.h:2867
#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:174
#define intVal(v)
Definition: value.h:52
int errmsg(const char *fmt,...)
Definition: elog.c:902
long changeDependencyFor(Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
Definition: pg_depend.c:428
#define elog(elevel,...)
Definition: elog.h:228
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2171
char * defname
Definition: parsenodes.h:734
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:470
bool pg_proc_ownercheck(Oid proc_oid, Oid roleid)
Definition: aclchk.c:4765
static char interpret_func_parallel(DefElem *defel)
Definition: functioncmds.c:597
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ CallStmtResultDesc()

TupleDesc CallStmtResultDesc ( CallStmt stmt)

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

2239 {
2240  FuncExpr *fexpr;
2241  HeapTuple tuple;
2242  TupleDesc tupdesc;
2243 
2244  fexpr = stmt->funcexpr;
2245 
2246  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
2247  if (!HeapTupleIsValid(tuple))
2248  elog(ERROR, "cache lookup failed for procedure %u", fexpr->funcid);
2249 
2250  tupdesc = build_function_result_tupdesc_t(tuple);
2251 
2252  ReleaseSysCache(tuple);
2253 
2254  return tupdesc;
2255 }
FuncExpr * funcexpr
Definition: parsenodes.h:2900
TupleDesc build_function_result_tupdesc_t(HeapTuple procTuple)
Definition: funcapi.c:1429
Oid funcid
Definition: primnodes.h:481
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1115
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1163
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:228

◆ check_transform_function()

static void check_transform_function ( Form_pg_proc  procstruct)
static

Definition at line 1647 of file functioncmds.c.

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

Referenced by CreateTransform().

1648 {
1649  if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1650  ereport(ERROR,
1651  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1652  errmsg("transform function must not be volatile")));
1653  if (procstruct->prokind != PROKIND_FUNCTION)
1654  ereport(ERROR,
1655  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1656  errmsg("transform function must be a normal function")));
1657  if (procstruct->proretset)
1658  ereport(ERROR,
1659  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1660  errmsg("transform function must not return a set")));
1661  if (procstruct->pronargs != 1)
1662  ereport(ERROR,
1663  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1664  errmsg("transform function must take one argument")));
1665  if (procstruct->proargtypes.values[0] != INTERNALOID)
1666  ereport(ERROR,
1667  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1668  errmsg("first argument of transform function must be type %s",
1669  "internal")));
1670 }
int errcode(int sqlerrcode)
Definition: elog.c:691
#define ERROR
Definition: elog.h:43
#define ereport(elevel,...)
Definition: elog.h:155
int errmsg(const char *fmt,...)
Definition: elog.c:902

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

482 {
483  if (strcmp(defel->defname, "volatility") == 0)
484  {
485  if (is_procedure)
486  goto procedure_error;
487  if (*volatility_item)
488  goto duplicate_error;
489 
490  *volatility_item = defel;
491  }
492  else if (strcmp(defel->defname, "strict") == 0)
493  {
494  if (is_procedure)
495  goto procedure_error;
496  if (*strict_item)
497  goto duplicate_error;
498 
499  *strict_item = defel;
500  }
501  else if (strcmp(defel->defname, "security") == 0)
502  {
503  if (*security_item)
504  goto duplicate_error;
505 
506  *security_item = defel;
507  }
508  else if (strcmp(defel->defname, "leakproof") == 0)
509  {
510  if (is_procedure)
511  goto procedure_error;
512  if (*leakproof_item)
513  goto duplicate_error;
514 
515  *leakproof_item = defel;
516  }
517  else if (strcmp(defel->defname, "set") == 0)
518  {
519  *set_items = lappend(*set_items, defel->arg);
520  }
521  else if (strcmp(defel->defname, "cost") == 0)
522  {
523  if (is_procedure)
524  goto procedure_error;
525  if (*cost_item)
526  goto duplicate_error;
527 
528  *cost_item = defel;
529  }
530  else if (strcmp(defel->defname, "rows") == 0)
531  {
532  if (is_procedure)
533  goto procedure_error;
534  if (*rows_item)
535  goto duplicate_error;
536 
537  *rows_item = defel;
538  }
539  else if (strcmp(defel->defname, "support") == 0)
540  {
541  if (is_procedure)
542  goto procedure_error;
543  if (*support_item)
544  goto duplicate_error;
545 
546  *support_item = defel;
547  }
548  else if (strcmp(defel->defname, "parallel") == 0)
549  {
550  if (is_procedure)
551  goto procedure_error;
552  if (*parallel_item)
553  goto duplicate_error;
554 
555  *parallel_item = defel;
556  }
557  else
558  return false;
559 
560  /* Recognized an option */
561  return true;
562 
563 duplicate_error:
564  ereport(ERROR,
565  (errcode(ERRCODE_SYNTAX_ERROR),
566  errmsg("conflicting or redundant options"),
567  parser_errposition(pstate, defel->location)));
568  return false; /* keep compiler quiet */
569 
570 procedure_error:
571  ereport(ERROR,
572  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
573  errmsg("invalid attribute in procedure definition"),
574  parser_errposition(pstate, defel->location)));
575  return false;
576 }
int errcode(int sqlerrcode)
Definition: elog.c:691
#define ERROR
Definition: elog.h:43
int location
Definition: parsenodes.h:737
Node * arg
Definition: parsenodes.h:735
List * lappend(List *list, void *datum)
Definition: list.c:321
#define ereport(elevel,...)
Definition: elog.h:155
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
int errmsg(const char *fmt,...)
Definition: elog.c:902
char * defname
Definition: parsenodes.h:734

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

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

◆ compute_return_type()

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

Definition at line 88 of file functioncmds.c.

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

90 {
91  Oid rettype;
92  Type typtup;
93  AclResult aclresult;
94 
95  typtup = LookupTypeName(NULL, returnType, NULL, false);
96 
97  if (typtup)
98  {
99  if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
100  {
101  if (languageOid == SQLlanguageId)
102  ereport(ERROR,
103  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
104  errmsg("SQL function cannot return shell type %s",
105  TypeNameToString(returnType))));
106  else
107  ereport(NOTICE,
108  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
109  errmsg("return type %s is only a shell",
110  TypeNameToString(returnType))));
111  }
112  rettype = typeTypeId(typtup);
113  ReleaseSysCache(typtup);
114  }
115  else
116  {
117  char *typnam = TypeNameToString(returnType);
118  Oid namespaceId;
119  AclResult aclresult;
120  char *typname;
121  ObjectAddress address;
122 
123  /*
124  * Only C-coded functions can be I/O functions. We enforce this
125  * restriction here mainly to prevent littering the catalogs with
126  * shell types due to simple typos in user-defined function
127  * definitions.
128  */
129  if (languageOid != INTERNALlanguageId &&
130  languageOid != ClanguageId)
131  ereport(ERROR,
132  (errcode(ERRCODE_UNDEFINED_OBJECT),
133  errmsg("type \"%s\" does not exist", typnam)));
134 
135  /* Reject if there's typmod decoration, too */
136  if (returnType->typmods != NIL)
137  ereport(ERROR,
138  (errcode(ERRCODE_SYNTAX_ERROR),
139  errmsg("type modifier cannot be specified for shell type \"%s\"",
140  typnam)));
141 
142  /* Otherwise, go ahead and make a shell type */
143  ereport(NOTICE,
144  (errcode(ERRCODE_UNDEFINED_OBJECT),
145  errmsg("type \"%s\" is not yet defined", typnam),
146  errdetail("Creating a shell type definition.")));
147  namespaceId = QualifiedNameGetCreationNamespace(returnType->names,
148  &typname);
149  aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
150  ACL_CREATE);
151  if (aclresult != ACLCHECK_OK)
152  aclcheck_error(aclresult, OBJECT_SCHEMA,
153  get_namespace_name(namespaceId));
154  address = TypeShellMake(typname, namespaceId, GetUserId());
155  rettype = address.objectId;
156  Assert(OidIsValid(rettype));
157  }
158 
159  aclresult = pg_type_aclcheck(rettype, GetUserId(), ACL_USAGE);
160  if (aclresult != ACLCHECK_OK)
161  aclcheck_error_type(aclresult, rettype);
162 
163  *prorettype_p = rettype;
164  *returnsSet_p = returnType->setof;
165 }
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:655
List * names
Definition: parsenodes.h:210
Oid GetUserId(void)
Definition: miscinit.c:476
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:691
unsigned int Oid
Definition: postgres_ext.h:31
ObjectAddress TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
Definition: pg_type.c:57
#define OidIsValid(objectId)
Definition: c.h:706
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4625
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3607
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3294
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:84
bool setof
Definition: parsenodes.h:212
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3196
int errdetail(const char *fmt,...)
Definition: elog.c:1035
#define ACL_USAGE
Definition: parsenodes.h:82
NameData typname
Definition: pg_type.h:41
AclResult
Definition: acl.h:177
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1163
List * typmods
Definition: parsenodes.h:214
#define ereport(elevel,...)
Definition: elog.h:155
#define NOTICE
Definition: elog.h:37
#define Assert(condition)
Definition: c.h:800
FormData_pg_type * Form_pg_type
Definition: pg_type.h:255
int errmsg(const char *fmt,...)
Definition: elog.c:902
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4675
Oid typeTypeId(Type tp)
Definition: parse_type.c:588

◆ CreateCast()

ObjectAddress CreateCast ( CreateCastStmt stmt)

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

1405 {
1406  Oid sourcetypeid;
1407  Oid targettypeid;
1408  char sourcetyptype;
1409  char targettyptype;
1410  Oid funcid;
1411  int nargs;
1412  char castcontext;
1413  char castmethod;
1414  HeapTuple tuple;
1415  AclResult aclresult;
1416  ObjectAddress myself;
1417 
1418  sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
1419  targettypeid = typenameTypeId(NULL, stmt->targettype);
1420  sourcetyptype = get_typtype(sourcetypeid);
1421  targettyptype = get_typtype(targettypeid);
1422 
1423  /* No pseudo-types allowed */
1424  if (sourcetyptype == TYPTYPE_PSEUDO)
1425  ereport(ERROR,
1426  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1427  errmsg("source data type %s is a pseudo-type",
1428  TypeNameToString(stmt->sourcetype))));
1429 
1430  if (targettyptype == TYPTYPE_PSEUDO)
1431  ereport(ERROR,
1432  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1433  errmsg("target data type %s is a pseudo-type",
1434  TypeNameToString(stmt->targettype))));
1435 
1436  /* Permission check */
1437  if (!pg_type_ownercheck(sourcetypeid, GetUserId())
1438  && !pg_type_ownercheck(targettypeid, GetUserId()))
1439  ereport(ERROR,
1440  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1441  errmsg("must be owner of type %s or type %s",
1442  format_type_be(sourcetypeid),
1443  format_type_be(targettypeid))));
1444 
1445  aclresult = pg_type_aclcheck(sourcetypeid, GetUserId(), ACL_USAGE);
1446  if (aclresult != ACLCHECK_OK)
1447  aclcheck_error_type(aclresult, sourcetypeid);
1448 
1449  aclresult = pg_type_aclcheck(targettypeid, GetUserId(), ACL_USAGE);
1450  if (aclresult != ACLCHECK_OK)
1451  aclcheck_error_type(aclresult, targettypeid);
1452 
1453  /* Domains are allowed for historical reasons, but we warn */
1454  if (sourcetyptype == TYPTYPE_DOMAIN)
1455  ereport(WARNING,
1456  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1457  errmsg("cast will be ignored because the source data type is a domain")));
1458 
1459  else if (targettyptype == TYPTYPE_DOMAIN)
1460  ereport(WARNING,
1461  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1462  errmsg("cast will be ignored because the target data type is a domain")));
1463 
1464  /* Determine the cast method */
1465  if (stmt->func != NULL)
1466  castmethod = COERCION_METHOD_FUNCTION;
1467  else if (stmt->inout)
1468  castmethod = COERCION_METHOD_INOUT;
1469  else
1470  castmethod = COERCION_METHOD_BINARY;
1471 
1472  if (castmethod == COERCION_METHOD_FUNCTION)
1473  {
1474  Form_pg_proc procstruct;
1475 
1476  funcid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->func, false);
1477 
1478  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1479  if (!HeapTupleIsValid(tuple))
1480  elog(ERROR, "cache lookup failed for function %u", funcid);
1481 
1482  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1483  nargs = procstruct->pronargs;
1484  if (nargs < 1 || nargs > 3)
1485  ereport(ERROR,
1486  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1487  errmsg("cast function must take one to three arguments")));
1488  if (!IsBinaryCoercible(sourcetypeid, procstruct->proargtypes.values[0]))
1489  ereport(ERROR,
1490  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1491  errmsg("argument of cast function must match or be binary-coercible from source data type")));
1492  if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
1493  ereport(ERROR,
1494  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1495  errmsg("second argument of cast function must be type %s",
1496  "integer")));
1497  if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)
1498  ereport(ERROR,
1499  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1500  errmsg("third argument of cast function must be type %s",
1501  "boolean")));
1502  if (!IsBinaryCoercible(procstruct->prorettype, targettypeid))
1503  ereport(ERROR,
1504  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1505  errmsg("return data type of cast function must match or be binary-coercible to target data type")));
1506 
1507  /*
1508  * Restricting the volatility of a cast function may or may not be a
1509  * good idea in the abstract, but it definitely breaks many old
1510  * user-defined types. Disable this check --- tgl 2/1/03
1511  */
1512 #ifdef NOT_USED
1513  if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1514  ereport(ERROR,
1515  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1516  errmsg("cast function must not be volatile")));
1517 #endif
1518  if (procstruct->prokind != PROKIND_FUNCTION)
1519  ereport(ERROR,
1520  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1521  errmsg("cast function must be a normal function")));
1522  if (procstruct->proretset)
1523  ereport(ERROR,
1524  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1525  errmsg("cast function must not return a set")));
1526 
1527  ReleaseSysCache(tuple);
1528  }
1529  else
1530  {
1531  funcid = InvalidOid;
1532  nargs = 0;
1533  }
1534 
1535  if (castmethod == COERCION_METHOD_BINARY)
1536  {
1537  int16 typ1len;
1538  int16 typ2len;
1539  bool typ1byval;
1540  bool typ2byval;
1541  char typ1align;
1542  char typ2align;
1543 
1544  /*
1545  * Must be superuser to create binary-compatible casts, since
1546  * erroneous casts can easily crash the backend.
1547  */
1548  if (!superuser())
1549  ereport(ERROR,
1550  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1551  errmsg("must be superuser to create a cast WITHOUT FUNCTION")));
1552 
1553  /*
1554  * Also, insist that the types match as to size, alignment, and
1555  * pass-by-value attributes; this provides at least a crude check that
1556  * they have similar representations. A pair of types that fail this
1557  * test should certainly not be equated.
1558  */
1559  get_typlenbyvalalign(sourcetypeid, &typ1len, &typ1byval, &typ1align);
1560  get_typlenbyvalalign(targettypeid, &typ2len, &typ2byval, &typ2align);
1561  if (typ1len != typ2len ||
1562  typ1byval != typ2byval ||
1563  typ1align != typ2align)
1564  ereport(ERROR,
1565  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1566  errmsg("source and target data types are not physically compatible")));
1567 
1568  /*
1569  * We know that composite, enum and array types are never binary-
1570  * compatible with each other. They all have OIDs embedded in them.
1571  *
1572  * Theoretically you could build a user-defined base type that is
1573  * binary-compatible with a composite, enum, or array type. But we
1574  * disallow that too, as in practice such a cast is surely a mistake.
1575  * You can always work around that by writing a cast function.
1576  */
1577  if (sourcetyptype == TYPTYPE_COMPOSITE ||
1578  targettyptype == TYPTYPE_COMPOSITE)
1579  ereport(ERROR,
1580  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1581  errmsg("composite data types are not binary-compatible")));
1582 
1583  if (sourcetyptype == TYPTYPE_ENUM ||
1584  targettyptype == TYPTYPE_ENUM)
1585  ereport(ERROR,
1586  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1587  errmsg("enum data types are not binary-compatible")));
1588 
1589  if (OidIsValid(get_element_type(sourcetypeid)) ||
1590  OidIsValid(get_element_type(targettypeid)))
1591  ereport(ERROR,
1592  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1593  errmsg("array data types are not binary-compatible")));
1594 
1595  /*
1596  * We also disallow creating binary-compatibility casts involving
1597  * domains. Casting from a domain to its base type is already
1598  * allowed, and casting the other way ought to go through domain
1599  * coercion to permit constraint checking. Again, if you're intent on
1600  * having your own semantics for that, create a no-op cast function.
1601  *
1602  * NOTE: if we were to relax this, the above checks for composites
1603  * etc. would have to be modified to look through domains to their
1604  * base types.
1605  */
1606  if (sourcetyptype == TYPTYPE_DOMAIN ||
1607  targettyptype == TYPTYPE_DOMAIN)
1608  ereport(ERROR,
1609  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1610  errmsg("domain data types must not be marked binary-compatible")));
1611  }
1612 
1613  /*
1614  * Allow source and target types to be same only for length coercion
1615  * functions. We assume a multi-arg function does length coercion.
1616  */
1617  if (sourcetypeid == targettypeid && nargs < 2)
1618  ereport(ERROR,
1619  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1620  errmsg("source data type and target data type are the same")));
1621 
1622  /* convert CoercionContext enum to char value for castcontext */
1623  switch (stmt->context)
1624  {
1625  case COERCION_IMPLICIT:
1626  castcontext = COERCION_CODE_IMPLICIT;
1627  break;
1628  case COERCION_ASSIGNMENT:
1629  castcontext = COERCION_CODE_ASSIGNMENT;
1630  break;
1631  case COERCION_EXPLICIT:
1632  castcontext = COERCION_CODE_EXPLICIT;
1633  break;
1634  default:
1635  elog(ERROR, "unrecognized CoercionContext: %d", stmt->context);
1636  castcontext = 0; /* keep compiler quiet */
1637  break;
1638  }
1639 
1640  myself = CastCreate(sourcetypeid, targettypeid, funcid, castcontext,
1641  castmethod, DEPENDENCY_NORMAL);
1642  return myself;
1643 }
signed short int16
Definition: c.h:416
TypeName * sourcetype
Definition: parsenodes.h:3396
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Oid GetUserId(void)
Definition: miscinit.c:476
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:2641
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2164
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:476
int errcode(int sqlerrcode)
Definition: elog.c:691
bool superuser(void)
Definition: superuser.c:46
char get_typtype(Oid typid)
Definition: lsyscache.c:2522
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:4713
#define OidIsValid(objectId)
Definition: c.h:706
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3607
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
CoercionContext context
Definition: parsenodes.h:3399
#define ACL_USAGE
Definition: parsenodes.h:82
bool IsBinaryCoercible(Oid srctype, Oid targettype)
#define WARNING
Definition: elog.h:40
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1115
AclResult
Definition: acl.h:177
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1163
ObjectWithArgs * func
Definition: parsenodes.h:3398
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:133
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:155
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
int errmsg(const char *fmt,...)
Definition: elog.c:902
#define elog(elevel,...)
Definition: elog.h:228
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2171
TypeName * targettype
Definition: parsenodes.h:3397
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4675
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:291

◆ CreateFunction()

ObjectAddress CreateFunction ( ParseState pstate,
CreateFunctionStmt stmt 
)

Definition at line 918 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, palloc(), CreateFunctionStmt::parameters, pg_language_aclcheck(), pg_namespace_aclcheck(), PointerGetDatum, ProcedureCreate(), QualifiedNameGetCreationNamespace(), ReleaseSysCache(), CreateFunctionStmt::replace, CreateFunctionStmt::returnType, SearchSysCache1(), superuser(), and typenameTypeId().

Referenced by ProcessUtilitySlow().

919 {
920  char *probin_str;
921  char *prosrc_str;
922  Oid prorettype;
923  bool returnsSet;
924  char *language;
925  Oid languageOid;
926  Oid languageValidator;
927  Node *transformDefElem = NULL;
928  char *funcname;
929  Oid namespaceId;
930  AclResult aclresult;
931  oidvector *parameterTypes;
932  ArrayType *allParameterTypes;
933  ArrayType *parameterModes;
934  ArrayType *parameterNames;
935  List *parameterDefaults;
936  Oid variadicArgType;
937  List *trftypes_list = NIL;
938  ArrayType *trftypes;
939  Oid requiredResultType;
940  bool isWindowFunc,
941  isStrict,
942  security,
943  isLeakProof;
944  char volatility;
945  ArrayType *proconfig;
946  float4 procost;
947  float4 prorows;
948  Oid prosupport;
949  HeapTuple languageTuple;
950  Form_pg_language languageStruct;
951  List *as_clause;
952  char parallel;
953 
954  /* Convert list of names to a name and namespace */
955  namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
956  &funcname);
957 
958  /* Check we have creation rights in target namespace */
959  aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
960  if (aclresult != ACLCHECK_OK)
961  aclcheck_error(aclresult, OBJECT_SCHEMA,
962  get_namespace_name(namespaceId));
963 
964  /* Set default attributes */
965  isWindowFunc = false;
966  isStrict = false;
967  security = false;
968  isLeakProof = false;
969  volatility = PROVOLATILE_VOLATILE;
970  proconfig = NULL;
971  procost = -1; /* indicates not set */
972  prorows = -1; /* indicates not set */
973  prosupport = InvalidOid;
974  parallel = PROPARALLEL_UNSAFE;
975 
976  /* Extract non-default attributes from stmt->options list */
978  stmt->is_procedure,
979  stmt->options,
980  &as_clause, &language, &transformDefElem,
981  &isWindowFunc, &volatility,
982  &isStrict, &security, &isLeakProof,
983  &proconfig, &procost, &prorows,
984  &prosupport, &parallel);
985 
986  /* Look up the language and validate permissions */
987  languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
988  if (!HeapTupleIsValid(languageTuple))
989  ereport(ERROR,
990  (errcode(ERRCODE_UNDEFINED_OBJECT),
991  errmsg("language \"%s\" does not exist", language),
992  (extension_file_exists(language) ?
993  errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
994 
995  languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
996  languageOid = languageStruct->oid;
997 
998  if (languageStruct->lanpltrusted)
999  {
1000  /* if trusted language, need USAGE privilege */
1001  AclResult aclresult;
1002 
1003  aclresult = pg_language_aclcheck(languageOid, GetUserId(), ACL_USAGE);
1004  if (aclresult != ACLCHECK_OK)
1005  aclcheck_error(aclresult, OBJECT_LANGUAGE,
1006  NameStr(languageStruct->lanname));
1007  }
1008  else
1009  {
1010  /* if untrusted language, must be superuser */
1011  if (!superuser())
1013  NameStr(languageStruct->lanname));
1014  }
1015 
1016  languageValidator = languageStruct->lanvalidator;
1017 
1018  ReleaseSysCache(languageTuple);
1019 
1020  /*
1021  * Only superuser is allowed to create leakproof functions because
1022  * leakproof functions can see tuples which have not yet been filtered out
1023  * by security barrier views or row level security policies.
1024  */
1025  if (isLeakProof && !superuser())
1026  ereport(ERROR,
1027  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1028  errmsg("only superuser can define a leakproof function")));
1029 
1030  if (transformDefElem)
1031  {
1032  ListCell *lc;
1033 
1034  foreach(lc, castNode(List, transformDefElem))
1035  {
1036  Oid typeid = typenameTypeId(NULL,
1037  lfirst_node(TypeName, lc));
1038  Oid elt = get_base_element_type(typeid);
1039 
1040  typeid = elt ? elt : typeid;
1041 
1042  get_transform_oid(typeid, languageOid, false);
1043  trftypes_list = lappend_oid(trftypes_list, typeid);
1044  }
1045  }
1046 
1047  /*
1048  * Convert remaining parameters of CREATE to form wanted by
1049  * ProcedureCreate.
1050  */
1052  stmt->parameters,
1053  languageOid,
1055  &parameterTypes,
1056  &allParameterTypes,
1057  &parameterModes,
1058  &parameterNames,
1059  &parameterDefaults,
1060  &variadicArgType,
1061  &requiredResultType);
1062 
1063  if (stmt->is_procedure)
1064  {
1065  Assert(!stmt->returnType);
1066  prorettype = requiredResultType ? requiredResultType : VOIDOID;
1067  returnsSet = false;
1068  }
1069  else if (stmt->returnType)
1070  {
1071  /* explicit RETURNS clause */
1072  compute_return_type(stmt->returnType, languageOid,
1073  &prorettype, &returnsSet);
1074  if (OidIsValid(requiredResultType) && prorettype != requiredResultType)
1075  ereport(ERROR,
1076  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1077  errmsg("function result type must be %s because of OUT parameters",
1078  format_type_be(requiredResultType))));
1079  }
1080  else if (OidIsValid(requiredResultType))
1081  {
1082  /* default RETURNS clause from OUT parameters */
1083  prorettype = requiredResultType;
1084  returnsSet = false;
1085  }
1086  else
1087  {
1088  ereport(ERROR,
1089  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1090  errmsg("function result type must be specified")));
1091  /* Alternative possibility: default to RETURNS VOID */
1092  prorettype = VOIDOID;
1093  returnsSet = false;
1094  }
1095 
1096  if (list_length(trftypes_list) > 0)
1097  {
1098  ListCell *lc;
1099  Datum *arr;
1100  int i;
1101 
1102  arr = palloc(list_length(trftypes_list) * sizeof(Datum));
1103  i = 0;
1104  foreach(lc, trftypes_list)
1105  arr[i++] = ObjectIdGetDatum(lfirst_oid(lc));
1106  trftypes = construct_array(arr, list_length(trftypes_list),
1107  OIDOID, sizeof(Oid), true, TYPALIGN_INT);
1108  }
1109  else
1110  {
1111  /* store SQL NULL instead of empty array */
1112  trftypes = NULL;
1113  }
1114 
1115  interpret_AS_clause(languageOid, language, funcname, as_clause,
1116  &prosrc_str, &probin_str);
1117 
1118  /*
1119  * Set default values for COST and ROWS depending on other parameters;
1120  * reject ROWS if it's not returnsSet. NB: pg_dump knows these default
1121  * values, keep it in sync if you change them.
1122  */
1123  if (procost < 0)
1124  {
1125  /* SQL and PL-language functions are assumed more expensive */
1126  if (languageOid == INTERNALlanguageId ||
1127  languageOid == ClanguageId)
1128  procost = 1;
1129  else
1130  procost = 100;
1131  }
1132  if (prorows < 0)
1133  {
1134  if (returnsSet)
1135  prorows = 1000;
1136  else
1137  prorows = 0; /* dummy value if not returnsSet */
1138  }
1139  else if (!returnsSet)
1140  ereport(ERROR,
1141  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1142  errmsg("ROWS is not applicable when function does not return a set")));
1143 
1144  /*
1145  * And now that we have all the parameters, and know we're permitted to do
1146  * so, go ahead and create the function.
1147  */
1148  return ProcedureCreate(funcname,
1149  namespaceId,
1150  stmt->replace,
1151  returnsSet,
1152  prorettype,
1153  GetUserId(),
1154  languageOid,
1155  languageValidator,
1156  prosrc_str, /* converted to text later */
1157  probin_str, /* converted to text later */
1158  stmt->is_procedure ? PROKIND_PROCEDURE : (isWindowFunc ? PROKIND_WINDOW : PROKIND_FUNCTION),
1159  security,
1160  isLeakProof,
1161  isStrict,
1162  volatility,
1163  parallel,
1164  parameterTypes,
1165  PointerGetDatum(allParameterTypes),
1166  PointerGetDatum(parameterModes),
1167  PointerGetDatum(parameterNames),
1168  parameterDefaults,
1169  PointerGetDatum(trftypes),
1170  PointerGetDatum(proconfig),
1171  prosupport,
1172  procost,
1173  prorows);
1174 }
#define NIL
Definition: pg_list.h:65
Definition: c.h:656
int errhint(const char *fmt,...)
Definition: elog.c:1149
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Oid GetUserId(void)
Definition: miscinit.c:476
#define castNode(_type_, nodeptr)
Definition: nodes.h:596
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2994
#define PointerGetDatum(X)
Definition: postgres.h:556
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, 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:69
static void compute_return_type(TypeName *returnType, Oid languageOid, Oid *prorettype_p, bool *returnsSet_p)
Definition: functioncmds.c:88
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3313
Definition: nodes.h:527
int errcode(int sqlerrcode)
Definition: elog.c:691
bool superuser(void)
Definition: superuser.c:46
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
static void interpret_AS_clause(Oid languageOid, const char *languageName, char *funcname, List *as, char **prosrc_str_p, char **probin_str_p)
Definition: functioncmds.c:858
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:357
#define OidIsValid(objectId)
Definition: c.h:706
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4625
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4599
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:3294
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:84
#define lfirst_node(type, lc)
Definition: pg_list.h:172
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3196
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:691
#define ACL_USAGE
Definition: parsenodes.h:82
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1115
float float4
Definition: c.h:552
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1163
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:155
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:800
TypeName * returnType
Definition: parsenodes.h:2840
void interpret_function_parameter_list(ParseState *pstate, List *parameters, Oid languageOid, ObjectType objtype, oidvector **parameterTypes, ArrayType **allParameterTypes, ArrayType **parameterModes, ArrayType **parameterNames, List **parameterDefaults, Oid *variadicArgType, Oid *requiredResultType)
Definition: functioncmds.c:184
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:2714
FormData_pg_language * Form_pg_language
Definition: pg_language.h:65
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:902
int i
#define NameStr(name)
Definition: c.h:677
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 1677 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().

1678 {
1679  Oid typeid;
1680  char typtype;
1681  Oid langid;
1682  Oid fromsqlfuncid;
1683  Oid tosqlfuncid;
1684  AclResult aclresult;
1685  Form_pg_proc procstruct;
1686  Datum values[Natts_pg_transform];
1687  bool nulls[Natts_pg_transform];
1688  bool replaces[Natts_pg_transform];
1689  Oid transformid;
1690  HeapTuple tuple;
1691  HeapTuple newtuple;
1692  Relation relation;
1693  ObjectAddress myself,
1694  referenced;
1695  ObjectAddresses *addrs;
1696  bool is_replace;
1697 
1698  /*
1699  * Get the type
1700  */
1701  typeid = typenameTypeId(NULL, stmt->type_name);
1702  typtype = get_typtype(typeid);
1703 
1704  if (typtype == TYPTYPE_PSEUDO)
1705  ereport(ERROR,
1706  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1707  errmsg("data type %s is a pseudo-type",
1708  TypeNameToString(stmt->type_name))));
1709 
1710  if (typtype == TYPTYPE_DOMAIN)
1711  ereport(ERROR,
1712  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1713  errmsg("data type %s is a domain",
1714  TypeNameToString(stmt->type_name))));
1715 
1716  if (!pg_type_ownercheck(typeid, GetUserId()))
1718 
1719  aclresult = pg_type_aclcheck(typeid, GetUserId(), ACL_USAGE);
1720  if (aclresult != ACLCHECK_OK)
1721  aclcheck_error_type(aclresult, typeid);
1722 
1723  /*
1724  * Get the language
1725  */
1726  langid = get_language_oid(stmt->lang, false);
1727 
1728  aclresult = pg_language_aclcheck(langid, GetUserId(), ACL_USAGE);
1729  if (aclresult != ACLCHECK_OK)
1730  aclcheck_error(aclresult, OBJECT_LANGUAGE, stmt->lang);
1731 
1732  /*
1733  * Get the functions
1734  */
1735  if (stmt->fromsql)
1736  {
1737  fromsqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->fromsql, false);
1738 
1739  if (!pg_proc_ownercheck(fromsqlfuncid, GetUserId()))
1741 
1742  aclresult = pg_proc_aclcheck(fromsqlfuncid, GetUserId(), ACL_EXECUTE);
1743  if (aclresult != ACLCHECK_OK)
1745 
1746  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fromsqlfuncid));
1747  if (!HeapTupleIsValid(tuple))
1748  elog(ERROR, "cache lookup failed for function %u", fromsqlfuncid);
1749  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1750  if (procstruct->prorettype != INTERNALOID)
1751  ereport(ERROR,
1752  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1753  errmsg("return data type of FROM SQL function must be %s",
1754  "internal")));
1755  check_transform_function(procstruct);
1756  ReleaseSysCache(tuple);
1757  }
1758  else
1759  fromsqlfuncid = InvalidOid;
1760 
1761  if (stmt->tosql)
1762  {
1763  tosqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->tosql, false);
1764 
1765  if (!pg_proc_ownercheck(tosqlfuncid, GetUserId()))
1767 
1768  aclresult = pg_proc_aclcheck(tosqlfuncid, GetUserId(), ACL_EXECUTE);
1769  if (aclresult != ACLCHECK_OK)
1771 
1772  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(tosqlfuncid));
1773  if (!HeapTupleIsValid(tuple))
1774  elog(ERROR, "cache lookup failed for function %u", tosqlfuncid);
1775  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1776  if (procstruct->prorettype != typeid)
1777  ereport(ERROR,
1778  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1779  errmsg("return data type of TO SQL function must be the transform data type")));
1780  check_transform_function(procstruct);
1781  ReleaseSysCache(tuple);
1782  }
1783  else
1784  tosqlfuncid = InvalidOid;
1785 
1786  /*
1787  * Ready to go
1788  */
1789  values[Anum_pg_transform_trftype - 1] = ObjectIdGetDatum(typeid);
1790  values[Anum_pg_transform_trflang - 1] = ObjectIdGetDatum(langid);
1791  values[Anum_pg_transform_trffromsql - 1] = ObjectIdGetDatum(fromsqlfuncid);
1792  values[Anum_pg_transform_trftosql - 1] = ObjectIdGetDatum(tosqlfuncid);
1793 
1794  MemSet(nulls, false, sizeof(nulls));
1795 
1796  relation = table_open(TransformRelationId, RowExclusiveLock);
1797 
1798  tuple = SearchSysCache2(TRFTYPELANG,
1799  ObjectIdGetDatum(typeid),
1800  ObjectIdGetDatum(langid));
1801  if (HeapTupleIsValid(tuple))
1802  {
1804 
1805  if (!stmt->replace)
1806  ereport(ERROR,
1808  errmsg("transform for type %s language \"%s\" already exists",
1809  format_type_be(typeid),
1810  stmt->lang)));
1811 
1812  MemSet(replaces, false, sizeof(replaces));
1813  replaces[Anum_pg_transform_trffromsql - 1] = true;
1814  replaces[Anum_pg_transform_trftosql - 1] = true;
1815 
1816  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
1817  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
1818 
1819  transformid = form->oid;
1820  ReleaseSysCache(tuple);
1821  is_replace = true;
1822  }
1823  else
1824  {
1825  transformid = GetNewOidWithIndex(relation, TransformOidIndexId,
1826  Anum_pg_transform_oid);
1827  values[Anum_pg_transform_oid - 1] = ObjectIdGetDatum(transformid);
1828  newtuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
1829  CatalogTupleInsert(relation, newtuple);
1830  is_replace = false;
1831  }
1832 
1833  if (is_replace)
1834  deleteDependencyRecordsFor(TransformRelationId, transformid, true);
1835 
1836  addrs = new_object_addresses();
1837 
1838  /* make dependency entries */
1839  ObjectAddressSet(myself, TransformRelationId, transformid);
1840 
1841  /* dependency on language */
1842  ObjectAddressSet(referenced, LanguageRelationId, langid);
1843  add_exact_object_address(&referenced, addrs);
1844 
1845  /* dependency on type */
1846  ObjectAddressSet(referenced, TypeRelationId, typeid);
1847  add_exact_object_address(&referenced, addrs);
1848 
1849  /* dependencies on functions */
1850  if (OidIsValid(fromsqlfuncid))
1851  {
1852  ObjectAddressSet(referenced, ProcedureRelationId, fromsqlfuncid);
1853  add_exact_object_address(&referenced, addrs);
1854  }
1855  if (OidIsValid(tosqlfuncid))
1856  {
1857  ObjectAddressSet(referenced, ProcedureRelationId, tosqlfuncid);
1858  add_exact_object_address(&referenced, addrs);
1859  }
1860 
1862  free_object_addresses(addrs);
1863 
1864  /* dependency on extension */
1865  recordDependencyOnCurrentExtension(&myself, is_replace);
1866 
1867  /* Post creation hook for new transform */
1868  InvokeObjectPostCreateHook(TransformRelationId, transformid, 0);
1869 
1870  heap_freetuple(newtuple);
1871 
1872  table_close(relation, RowExclusiveLock);
1873 
1874  return myself;
1875 }
#define TransformOidIndexId
Definition: pg_transform.h:46
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:315
ObjectWithArgs * tosql
Definition: parsenodes.h:3414
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:655
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
#define RelationGetDescr(relation)
Definition: rel.h:483
Oid GetUserId(void)
Definition: miscinit.c:476
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:2803
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:272
Oid get_language_oid(const char *langname, bool missing_ok)
Definition: proclang.c:228
int errcode(int sqlerrcode)
Definition: elog.c:691
char get_typtype(Oid typid)
Definition: lsyscache.c:2522
#define MemSet(start, val, len)
Definition: c.h:1004
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:2594
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2539
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2835
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:4713
#define OidIsValid(objectId)
Definition: c.h:706
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4599
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3607
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3294
FormData_pg_transform * Form_pg_transform
Definition: pg_transform.h:43
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ACL_USAGE
Definition: parsenodes.h:82
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1115
char * NameListToString(List *names)
Definition: namespace.c:3101
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1163
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:133
#define InvalidOid
Definition: postgres_ext.h:36
ObjectWithArgs * fromsql
Definition: parsenodes.h:3413
#define ereport(elevel,...)
Definition: elog.h:155
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:220
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1126
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
TypeName * type_name
Definition: parsenodes.h:3411
static Datum values[MAXATTR]
Definition: bootstrap.c:165
int errmsg(const char *fmt,...)
Definition: elog.c:902
#define ACL_EXECUTE
Definition: parsenodes.h:81
#define elog(elevel,...)
Definition: elog.h:228
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4587
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2171
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4675
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:4765
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 2058 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().

2059 {
2060  LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
2061  ListCell *lc;
2062  FuncExpr *fexpr;
2063  int nargs;
2064  int i;
2065  AclResult aclresult;
2066  Oid *argtypes;
2067  char **argnames;
2068  char *argmodes;
2069  FmgrInfo flinfo;
2070  CallContext *callcontext;
2071  EState *estate;
2072  ExprContext *econtext;
2073  HeapTuple tp;
2074  PgStat_FunctionCallUsage fcusage;
2075  Datum retval;
2076 
2077  fexpr = stmt->funcexpr;
2078  Assert(fexpr);
2079  Assert(IsA(fexpr, FuncExpr));
2080 
2081  aclresult = pg_proc_aclcheck(fexpr->funcid, GetUserId(), ACL_EXECUTE);
2082  if (aclresult != ACLCHECK_OK)
2083  aclcheck_error(aclresult, OBJECT_PROCEDURE, get_func_name(fexpr->funcid));
2084 
2085  /* Prep the context object we'll pass to the procedure */
2086  callcontext = makeNode(CallContext);
2087  callcontext->atomic = atomic;
2088 
2090  if (!HeapTupleIsValid(tp))
2091  elog(ERROR, "cache lookup failed for function %u", fexpr->funcid);
2092 
2093  /*
2094  * If proconfig is set we can't allow transaction commands because of the
2095  * way the GUC stacking works: The transaction boundary would have to pop
2096  * the proconfig setting off the stack. That restriction could be lifted
2097  * by redesigning the GUC nesting mechanism a bit.
2098  */
2099  if (!heap_attisnull(tp, Anum_pg_proc_proconfig, NULL))
2100  callcontext->atomic = true;
2101 
2102  /*
2103  * In security definer procedures, we can't allow transaction commands.
2104  * StartTransaction() insists that the security context stack is empty,
2105  * and AbortTransaction() resets the security context. This could be
2106  * reorganized, but right now it doesn't work.
2107  */
2108  if (((Form_pg_proc) GETSTRUCT(tp))->prosecdef)
2109  callcontext->atomic = true;
2110 
2111  /*
2112  * Expand named arguments, defaults, etc. We do not want to scribble on
2113  * the passed-in CallStmt parse tree, so first flat-copy fexpr, allowing
2114  * us to replace its args field. (Note that expand_function_arguments
2115  * will not modify any of the passed-in data structure.)
2116  */
2117  {
2118  FuncExpr *nexpr = makeNode(FuncExpr);
2119 
2120  memcpy(nexpr, fexpr, sizeof(FuncExpr));
2121  fexpr = nexpr;
2122  }
2123 
2124  fexpr->args = expand_function_arguments(fexpr->args,
2125  fexpr->funcresulttype,
2126  tp);
2127  nargs = list_length(fexpr->args);
2128 
2129  get_func_arg_info(tp, &argtypes, &argnames, &argmodes);
2130 
2131  ReleaseSysCache(tp);
2132 
2133  /* safety check; see ExecInitFunc() */
2134  if (nargs > FUNC_MAX_ARGS)
2135  ereport(ERROR,
2136  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2137  errmsg_plural("cannot pass more than %d argument to a procedure",
2138  "cannot pass more than %d arguments to a procedure",
2139  FUNC_MAX_ARGS,
2140  FUNC_MAX_ARGS)));
2141 
2142  /* Initialize function call structure */
2144  fmgr_info(fexpr->funcid, &flinfo);
2145  fmgr_info_set_expr((Node *) fexpr, &flinfo);
2146  InitFunctionCallInfoData(*fcinfo, &flinfo, nargs, fexpr->inputcollid,
2147  (Node *) callcontext, NULL);
2148 
2149  /*
2150  * Evaluate procedure arguments inside a suitable execution context. Note
2151  * we can't free this context till the procedure returns.
2152  */
2153  estate = CreateExecutorState();
2154  estate->es_param_list_info = params;
2155  econtext = CreateExprContext(estate);
2156 
2157  i = 0;
2158  foreach(lc, fexpr->args)
2159  {
2160  if (argmodes && argmodes[i] == PROARGMODE_OUT)
2161  {
2162  fcinfo->args[i].value = 0;
2163  fcinfo->args[i].isnull = true;
2164  }
2165  else
2166  {
2167  ExprState *exprstate;
2168  Datum val;
2169  bool isnull;
2170 
2171  exprstate = ExecPrepareExpr(lfirst(lc), estate);
2172 
2173  val = ExecEvalExprSwitchContext(exprstate, econtext, &isnull);
2174 
2175  fcinfo->args[i].value = val;
2176  fcinfo->args[i].isnull = isnull;
2177  }
2178 
2179  i++;
2180  }
2181 
2182  pgstat_init_function_usage(fcinfo, &fcusage);
2183  retval = FunctionCallInvoke(fcinfo);
2184  pgstat_end_function_usage(&fcusage, true);
2185 
2186  if (fexpr->funcresulttype == VOIDOID)
2187  {
2188  /* do nothing */
2189  }
2190  else if (fexpr->funcresulttype == RECORDOID)
2191  {
2192  /*
2193  * send tuple to client
2194  */
2195 
2196  HeapTupleHeader td;
2197  Oid tupType;
2198  int32 tupTypmod;
2199  TupleDesc retdesc;
2200  HeapTupleData rettupdata;
2201  TupOutputState *tstate;
2202  TupleTableSlot *slot;
2203 
2204  if (fcinfo->isnull)
2205  elog(ERROR, "procedure returned null record");
2206 
2207  td = DatumGetHeapTupleHeader(retval);
2208  tupType = HeapTupleHeaderGetTypeId(td);
2209  tupTypmod = HeapTupleHeaderGetTypMod(td);
2210  retdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
2211 
2212  tstate = begin_tup_output_tupdesc(dest, retdesc,
2213  &TTSOpsHeapTuple);
2214 
2215  rettupdata.t_len = HeapTupleHeaderGetDatumLength(td);
2216  ItemPointerSetInvalid(&(rettupdata.t_self));
2217  rettupdata.t_tableOid = InvalidOid;
2218  rettupdata.t_data = td;
2219 
2220  slot = ExecStoreHeapTuple(&rettupdata, tstate->slot, false);
2221  tstate->dest->receiveSlot(slot, tstate->dest);
2222 
2223  end_tup_output(tstate);
2224 
2225  ReleaseTupleDesc(retdesc);
2226  }
2227  else
2228  elog(ERROR, "unexpected result type for procedure: %u",
2229  fexpr->funcresulttype);
2230 
2231  FreeExecutorState(estate);
2232 }
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h:119
Oid funcresulttype
Definition: primnodes.h:482
Definition: fmgr.h:56
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:307
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
List * expand_function_arguments(List *args, Oid result_type, HeapTuple func_tuple)
Definition: clauses.c:3727
List * args
Definition: primnodes.h:489
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1741
FuncExpr * funcexpr
Definition: parsenodes.h:2900
Oid GetUserId(void)
Definition: miscinit.c:476
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1012
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
Definition: funcapi.c:1094
Definition: nodes.h:527
int errcode(int sqlerrcode)
Definition: elog.c:691
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
TupleTableSlot * slot
Definition: executor.h:465
unsigned int Oid
Definition: postgres_ext.h:31
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition: execExpr.c:491
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
signed int int32
Definition: c.h:417
HeapTupleHeader t_data
Definition: htup.h:68
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:468
#define FUNC_MAX_ARGS
void FreeExecutorState(EState *estate)
Definition: execUtils.c:185
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3294
void end_tup_output(TupOutputState *tstate)
Definition: execTuples.c:2314
Oid funcid
Definition: primnodes.h:481
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
void pgstat_init_function_usage(FunctionCallInfo fcinfo, PgStat_FunctionCallUsage *fcu)
Definition: pgstat.c:1789
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1525
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:2236
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:89
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:191
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1115
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1163
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:458
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:133
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:155
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define makeNode(_type_)
Definition: nodes.h:575
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
Oid inputcollid
Definition: primnodes.h:488
#define Assert(condition)
Definition: c.h:800
#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:1861
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:172
#define ACL_EXECUTE
Definition: parsenodes.h:81
#define elog(elevel,...)
Definition: elog.h:228
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4587
int i
const TupleTableSlotOps TTSOpsHeapTuple
Definition: execTuples.c:84
ExprContext * CreateExprContext(EState *estate)
Definition: execUtils.c:300
ParamListInfo es_param_list_info
Definition: execnodes.h:553
DestReceiver * dest
Definition: executor.h:466
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:122
long val
Definition: informix.c:664
TupleTableSlot * ExecStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:1322
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:452

◆ ExecuteDoStmt()

void ExecuteDoStmt ( DoStmt stmt,
bool  atomic 
)

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

1933 {
1935  ListCell *arg;
1936  DefElem *as_item = NULL;
1937  DefElem *language_item = NULL;
1938  char *language;
1939  Oid laninline;
1940  HeapTuple languageTuple;
1941  Form_pg_language languageStruct;
1942 
1943  /* Process options we got from gram.y */
1944  foreach(arg, stmt->args)
1945  {
1946  DefElem *defel = (DefElem *) lfirst(arg);
1947 
1948  if (strcmp(defel->defname, "as") == 0)
1949  {
1950  if (as_item)
1951  ereport(ERROR,
1952  (errcode(ERRCODE_SYNTAX_ERROR),
1953  errmsg("conflicting or redundant options")));
1954  as_item = defel;
1955  }
1956  else if (strcmp(defel->defname, "language") == 0)
1957  {
1958  if (language_item)
1959  ereport(ERROR,
1960  (errcode(ERRCODE_SYNTAX_ERROR),
1961  errmsg("conflicting or redundant options")));
1962  language_item = defel;
1963  }
1964  else
1965  elog(ERROR, "option \"%s\" not recognized",
1966  defel->defname);
1967  }
1968 
1969  if (as_item)
1970  codeblock->source_text = strVal(as_item->arg);
1971  else
1972  ereport(ERROR,
1973  (errcode(ERRCODE_SYNTAX_ERROR),
1974  errmsg("no inline code specified")));
1975 
1976  /* if LANGUAGE option wasn't specified, use the default */
1977  if (language_item)
1978  language = strVal(language_item->arg);
1979  else
1980  language = "plpgsql";
1981 
1982  /* Look up the language and validate permissions */
1983  languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
1984  if (!HeapTupleIsValid(languageTuple))
1985  ereport(ERROR,
1986  (errcode(ERRCODE_UNDEFINED_OBJECT),
1987  errmsg("language \"%s\" does not exist", language),
1988  (extension_file_exists(language) ?
1989  errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
1990 
1991  languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
1992  codeblock->langOid = languageStruct->oid;
1993  codeblock->langIsTrusted = languageStruct->lanpltrusted;
1994  codeblock->atomic = atomic;
1995 
1996  if (languageStruct->lanpltrusted)
1997  {
1998  /* if trusted language, need USAGE privilege */
1999  AclResult aclresult;
2000 
2001  aclresult = pg_language_aclcheck(codeblock->langOid, GetUserId(),
2002  ACL_USAGE);
2003  if (aclresult != ACLCHECK_OK)
2004  aclcheck_error(aclresult, OBJECT_LANGUAGE,
2005  NameStr(languageStruct->lanname));
2006  }
2007  else
2008  {
2009  /* if untrusted language, must be superuser */
2010  if (!superuser())
2012  NameStr(languageStruct->lanname));
2013  }
2014 
2015  /* get the handler function's OID */
2016  laninline = languageStruct->laninline;
2017  if (!OidIsValid(laninline))
2018  ereport(ERROR,
2019  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2020  errmsg("language \"%s\" does not support inline code execution",
2021  NameStr(languageStruct->lanname))));
2022 
2023  ReleaseSysCache(languageTuple);
2024 
2025  /* execute the inline handler */
2026  OidFunctionCall1(laninline, PointerGetDatum(codeblock));
2027 }
int errhint(const char *fmt,...)
Definition: elog.c:1149
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Oid GetUserId(void)
Definition: miscinit.c:476
#define PointerGetDatum(X)
Definition: postgres.h:556
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:691
bool superuser(void)
Definition: superuser.c:46
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:706
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4599
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3294
#define ERROR
Definition: elog.h:43
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:664
#define ACL_USAGE
Definition: parsenodes.h:82
Node * arg
Definition: parsenodes.h:735
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1115
AclResult
Definition: acl.h:177
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1163
#define ereport(elevel,...)
Definition: elog.h:155
#define makeNode(_type_)
Definition: nodes.h:575
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:169
List * args
Definition: parsenodes.h:2880
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:902
#define elog(elevel,...)
Definition: elog.h:228
#define NameStr(name)
Definition: c.h:677
void * arg
char * source_text
Definition: parsenodes.h:2886
char * defname
Definition: parsenodes.h:734

◆ get_transform_oid()

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

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

1886 {
1887  Oid oid;
1888 
1889  oid = GetSysCacheOid2(TRFTYPELANG, Anum_pg_transform_oid,
1890  ObjectIdGetDatum(type_id),
1891  ObjectIdGetDatum(lang_id));
1892  if (!OidIsValid(oid) && !missing_ok)
1893  ereport(ERROR,
1894  (errcode(ERRCODE_UNDEFINED_OBJECT),
1895  errmsg("transform for type %s language \"%s\" does not exist",
1896  format_type_be(type_id),
1897  get_language_name(lang_id, false))));
1898  return oid;
1899 }
char * get_language_name(Oid langoid, bool missing_ok)
Definition: lsyscache.c:1100
int errcode(int sqlerrcode)
Definition: elog.c:691
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:706
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define ereport(elevel,...)
Definition: elog.h:155
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:194
int errmsg(const char *fmt,...)
Definition: elog.c:902

◆ interpret_AS_clause()

static void interpret_AS_clause ( Oid  languageOid,
const char *  languageName,
char *  funcname,
List as,
char **  prosrc_str_p,
char **  probin_str_p 
)
static

Definition at line 858 of file functioncmds.c.

References Assert, ereport, errcode(), errmsg(), ERROR, linitial, list_length(), lsecond, NIL, and strVal.

Referenced by CreateFunction().

861 {
862  Assert(as != NIL);
863 
864  if (languageOid == ClanguageId)
865  {
866  /*
867  * For "C" language, store the file name in probin and, when given,
868  * the link symbol name in prosrc. If link symbol is omitted,
869  * substitute procedure name. We also allow link symbol to be
870  * specified as "-", since that was the habit in PG versions before
871  * 8.4, and there might be dump files out there that don't translate
872  * that back to "omitted".
873  */
874  *probin_str_p = strVal(linitial(as));
875  if (list_length(as) == 1)
876  *prosrc_str_p = funcname;
877  else
878  {
879  *prosrc_str_p = strVal(lsecond(as));
880  if (strcmp(*prosrc_str_p, "-") == 0)
881  *prosrc_str_p = funcname;
882  }
883  }
884  else
885  {
886  /* Everything else wants the given string in prosrc. */
887  *prosrc_str_p = strVal(linitial(as));
888  *probin_str_p = NULL;
889 
890  if (list_length(as) != 1)
891  ereport(ERROR,
892  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
893  errmsg("only one AS item needed for language \"%s\"",
894  languageName)));
895 
896  if (languageOid == INTERNALlanguageId)
897  {
898  /*
899  * In PostgreSQL versions before 6.5, the SQL name of the created
900  * function could not be different from the internal name, and
901  * "prosrc" wasn't used. So there is code out there that does
902  * CREATE FUNCTION xyz AS '' LANGUAGE internal. To preserve some
903  * modicum of backwards compatibility, accept an empty "prosrc"
904  * value as meaning the supplied SQL function name.
905  */
906  if (strlen(*prosrc_str_p) == 0)
907  *prosrc_str_p = funcname;
908  }
909  }
910 }
#define NIL
Definition: pg_list.h:65
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:691
#define lsecond(l)
Definition: pg_list.h:179
#define linitial(l)
Definition: pg_list.h:174
#define ERROR
Definition: elog.h:43
#define ereport(elevel,...)
Definition: elog.h:155
#define Assert(condition)
Definition: c.h:800
static int list_length(const List *l)
Definition: pg_list.h:149
int errmsg(const char *fmt,...)
Definition: elog.c:902

◆ interpret_func_parallel()

static char interpret_func_parallel ( DefElem defel)
static

Definition at line 597 of file functioncmds.c.

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

Referenced by AlterFunction(), and compute_function_attributes().

598 {
599  char *str = strVal(defel->arg);
600 
601  if (strcmp(str, "safe") == 0)
602  return PROPARALLEL_SAFE;
603  else if (strcmp(str, "unsafe") == 0)
604  return PROPARALLEL_UNSAFE;
605  else if (strcmp(str, "restricted") == 0)
606  return PROPARALLEL_RESTRICTED;
607  else
608  {
609  ereport(ERROR,
610  (errcode(ERRCODE_SYNTAX_ERROR),
611  errmsg("parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE")));
612  return PROPARALLEL_UNSAFE; /* keep compiler quiet */
613  }
614 }
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:691
#define ERROR
Definition: elog.h:43
Node * arg
Definition: parsenodes.h:735
#define ereport(elevel,...)
Definition: elog.h:155
int errmsg(const char *fmt,...)
Definition: elog.c:902

◆ interpret_func_support()

static Oid interpret_func_support ( DefElem defel)
static

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

648 {
649  List *procName = defGetQualifiedName(defel);
650  Oid procOid;
651  Oid argList[1];
652 
653  /*
654  * Support functions always take one INTERNAL argument and return
655  * INTERNAL.
656  */
657  argList[0] = INTERNALOID;
658 
659  procOid = LookupFuncName(procName, 1, argList, true);
660  if (!OidIsValid(procOid))
661  ereport(ERROR,
662  (errcode(ERRCODE_UNDEFINED_FUNCTION),
663  errmsg("function %s does not exist",
664  func_signature_string(procName, 1, NIL, argList))));
665 
666  if (get_func_rettype(procOid) != INTERNALOID)
667  ereport(ERROR,
668  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
669  errmsg("support function %s must return type %s",
670  NameListToString(procName), "internal")));
671 
672  /*
673  * Someday we might want an ACL check here; but for now, we insist that
674  * you be superuser to specify a support function, so privilege on the
675  * support function is moot.
676  */
677  if (!superuser())
678  ereport(ERROR,
679  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
680  errmsg("must be superuser to specify a support function")));
681 
682  return procOid;
683 }
#define NIL
Definition: pg_list.h:65
int errcode(int sqlerrcode)
Definition: elog.c:691
bool superuser(void)
Definition: superuser.c:46
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:706
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1572
#define ERROR
Definition: elog.h:43
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
Definition: parse_func.c:2111
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:2023
char * NameListToString(List *names)
Definition: namespace.c:3101
#define ereport(elevel,...)
Definition: elog.h:155
List * defGetQualifiedName(DefElem *def)
Definition: define.c:223
int errmsg(const char *fmt,...)
Definition: elog.c:902
Definition: pg_list.h:50

◆ interpret_func_volatility()

static char interpret_func_volatility ( DefElem defel)
static

Definition at line 579 of file functioncmds.c.

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

Referenced by AlterFunction(), and compute_function_attributes().

580 {
581  char *str = strVal(defel->arg);
582 
583  if (strcmp(str, "immutable") == 0)
584  return PROVOLATILE_IMMUTABLE;
585  else if (strcmp(str, "stable") == 0)
586  return PROVOLATILE_STABLE;
587  else if (strcmp(str, "volatile") == 0)
588  return PROVOLATILE_VOLATILE;
589  else
590  {
591  elog(ERROR, "invalid volatility \"%s\"", str);
592  return 0; /* keep compiler quiet */
593  }
594 }
#define strVal(v)
Definition: value.h:54
#define ERROR
Definition: elog.h:43
Node * arg
Definition: parsenodes.h:735
#define elog(elevel,...)
Definition: elog.h:228

◆ interpret_function_parameter_list()

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

Definition at line 184 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(), lfirst, list_length(), LookupTypeName(), FunctionParameter::mode, FunctionParameter::name, NIL, NOTICE, OBJECT_AGGREGATE, OBJECT_PROCEDURE, ObjectIdGetDatum, OidIsValid, ParseState::p_rtable, palloc(), palloc0(), pg_type_aclcheck(), PointerGetDatum, px(), ReleaseSysCache(), TypeName::setof, transformExpr(), TypeNameToString(), and typeTypeId().

Referenced by CreateFunction(), and DefineAggregate().

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

◆ IsThereFunctionInNamespace()

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

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

1911 {
1912  /* check for duplicate name (more friendly than unique-index failure) */
1915  PointerGetDatum(proargtypes),
1916  ObjectIdGetDatum(nspOid)))
1917  ereport(ERROR,
1918  (errcode(ERRCODE_DUPLICATE_FUNCTION),
1919  errmsg("function %s already exists in schema \"%s\"",
1921  NIL, proargtypes->values),
1922  get_namespace_name(nspOid))));
1923 }
#define NIL
Definition: pg_list.h:65
NameData proname
Definition: pg_proc.h:35
#define PointerGetDatum(X)
Definition: postgres.h:556
int errcode(int sqlerrcode)
Definition: elog.c:691
int16 pronargs
Definition: pg_proc.h:81
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:187
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3196
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:664
#define CStringGetDatum(X)
Definition: postgres.h:578
const char * funcname_signature_string(const char *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:1986
#define ereport(elevel,...)
Definition: elog.h:155
int errmsg(const char *fmt,...)
Definition: elog.c:902

◆ RemoveFunctionById()

void RemoveFunctionById ( Oid  funcOid)

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

1184 {
1185  Relation relation;
1186  HeapTuple tup;
1187  char prokind;
1188 
1189  /*
1190  * Delete the pg_proc tuple.
1191  */
1192  relation = table_open(ProcedureRelationId, RowExclusiveLock);
1193 
1194  tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
1195  if (!HeapTupleIsValid(tup)) /* should not happen */
1196  elog(ERROR, "cache lookup failed for function %u", funcOid);
1197 
1198  prokind = ((Form_pg_proc) GETSTRUCT(tup))->prokind;
1199 
1200  CatalogTupleDelete(relation, &tup->t_self);
1201 
1202  ReleaseSysCache(tup);
1203 
1204  table_close(relation, RowExclusiveLock);
1205 
1206  /*
1207  * If there's a pg_aggregate tuple, delete that too.
1208  */
1209  if (prokind == PROKIND_AGGREGATE)
1210  {
1211  relation = table_open(AggregateRelationId, RowExclusiveLock);
1212 
1213  tup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(funcOid));
1214  if (!HeapTupleIsValid(tup)) /* should not happen */
1215  elog(ERROR, "cache lookup failed for pg_aggregate tuple for function %u", funcOid);
1216 
1217  CatalogTupleDelete(relation, &tup->t_self);
1218 
1219  ReleaseSysCache(tup);
1220 
1221  table_close(relation, RowExclusiveLock);
1222  }
1223 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1115
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1163
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:133
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:228
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 622 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().

623 {
624  ListCell *l;
625 
626  foreach(l, set_items)
627  {
629 
630  if (sstmt->kind == VAR_RESET_ALL)
631  a = NULL;
632  else
633  {
634  char *valuestr = ExtractSetVariableArgs(sstmt);
635 
636  if (valuestr)
637  a = GUCArrayAdd(a, sstmt->name, valuestr);
638  else /* RESET */
639  a = GUCArrayDelete(a, sstmt->name);
640  }
641  }
642 
643  return a;
644 }
ArrayType * GUCArrayAdd(ArrayType *array, const char *name, const char *value)
Definition: guc.c:10719
VariableSetKind kind
Definition: parsenodes.h:2040
#define lfirst_node(type, lc)
Definition: pg_list.h:172
ArrayType * GUCArrayDelete(ArrayType *array, const char *name)
Definition: guc.c:10799
char * ExtractSetVariableArgs(VariableSetStmt *stmt)
Definition: guc.c:8565