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)
 
void DropCastById (Oid castOid)
 
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 DropTransformById (Oid transformOid)
 
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 1235 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().

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

◆ CallStmtResultDesc()

TupleDesc CallStmtResultDesc ( CallStmt stmt)

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

2287 {
2288  FuncExpr *fexpr;
2289  HeapTuple tuple;
2290  TupleDesc tupdesc;
2291 
2292  fexpr = stmt->funcexpr;
2293 
2294  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
2295  if (!HeapTupleIsValid(tuple))
2296  elog(ERROR, "cache lookup failed for procedure %u", fexpr->funcid);
2297 
2298  tupdesc = build_function_result_tupdesc_t(tuple);
2299 
2300  ReleaseSysCache(tuple);
2301 
2302  return tupdesc;
2303 }
FuncExpr * funcexpr
Definition: parsenodes.h:2899
TupleDesc build_function_result_tupdesc_t(HeapTuple procTuple)
Definition: funcapi.c:1424
Oid funcid
Definition: primnodes.h:469
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:214

◆ check_transform_function()

static void check_transform_function ( Form_pg_proc  procstruct)
static

Definition at line 1677 of file functioncmds.c.

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

Referenced by CreateTransform().

1678 {
1679  if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1680  ereport(ERROR,
1681  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1682  errmsg("transform function must not be volatile")));
1683  if (procstruct->prokind != PROKIND_FUNCTION)
1684  ereport(ERROR,
1685  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1686  errmsg("transform function must be a normal function")));
1687  if (procstruct->proretset)
1688  ereport(ERROR,
1689  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1690  errmsg("transform function must not return a set")));
1691  if (procstruct->pronargs != 1)
1692  ereport(ERROR,
1693  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1694  errmsg("transform function must take one argument")));
1695  if (procstruct->proargtypes.values[0] != INTERNALOID)
1696  ereport(ERROR,
1697  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1698  errmsg("first argument of transform function must be type %s",
1699  "internal")));
1700 }
int errcode(int sqlerrcode)
Definition: elog.c:610
#define ERROR
Definition: elog.h:43
#define ereport(elevel,...)
Definition: elog.h:144
int errmsg(const char *fmt,...)
Definition: elog.c:824

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

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

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

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

◆ 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:209
Oid GetUserId(void)
Definition: miscinit.c:439
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2995
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:476
int errcode(int sqlerrcode)
Definition: elog.c:610
unsigned int Oid
Definition: postgres_ext.h:31
ObjectAddress TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
Definition: pg_type.c:56
#define OidIsValid(objectId)
Definition: c.h:644
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4691
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3665
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:84
bool setof
Definition: parsenodes.h:211
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3155
int errdetail(const char *fmt,...)
Definition: elog.c:957
#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:1164
List * typmods
Definition: parsenodes.h:213
#define ereport(elevel,...)
Definition: elog.h:144
#define NOTICE
Definition: elog.h:37
#define Assert(condition)
Definition: c.h:738
FormData_pg_type * Form_pg_type
Definition: pg_type.h:255
int errmsg(const char *fmt,...)
Definition: elog.c:824
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4741
Oid typeTypeId(Type tp)
Definition: parse_type.c:588

◆ CreateCast()

ObjectAddress CreateCast ( CreateCastStmt stmt)

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

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

◆ CreateFunction()

ObjectAddress CreateFunction ( ParseState pstate,
CreateFunctionStmt stmt 
)

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

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

◆ CreateTransform()

ObjectAddress CreateTransform ( CreateTransformStmt stmt)

Definition at line 1707 of file functioncmds.c.

References ACL_EXECUTE, ACL_USAGE, aclcheck_error(), aclcheck_error_type(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, CatalogTupleInsert(), CatalogTupleUpdate(), check_transform_function(), ObjectAddress::classId, deleteDependencyRecordsFor(), DEPENDENCY_NORMAL, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, format_type_be(), 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(), OBJECT_FUNCTION, OBJECT_LANGUAGE, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, ObjectWithArgs::objname, OidIsValid, pg_language_aclcheck(), pg_proc_aclcheck(), pg_proc_ownercheck(), pg_type_aclcheck(), pg_type_ownercheck(), PROCOID, recordDependencyOn(), 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().

1708 {
1709  Oid typeid;
1710  char typtype;
1711  Oid langid;
1712  Oid fromsqlfuncid;
1713  Oid tosqlfuncid;
1714  AclResult aclresult;
1715  Form_pg_proc procstruct;
1716  Datum values[Natts_pg_transform];
1717  bool nulls[Natts_pg_transform];
1718  bool replaces[Natts_pg_transform];
1719  Oid transformid;
1720  HeapTuple tuple;
1721  HeapTuple newtuple;
1722  Relation relation;
1723  ObjectAddress myself,
1724  referenced;
1725  bool is_replace;
1726 
1727  /*
1728  * Get the type
1729  */
1730  typeid = typenameTypeId(NULL, stmt->type_name);
1731  typtype = get_typtype(typeid);
1732 
1733  if (typtype == TYPTYPE_PSEUDO)
1734  ereport(ERROR,
1735  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1736  errmsg("data type %s is a pseudo-type",
1737  TypeNameToString(stmt->type_name))));
1738 
1739  if (typtype == TYPTYPE_DOMAIN)
1740  ereport(ERROR,
1741  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1742  errmsg("data type %s is a domain",
1743  TypeNameToString(stmt->type_name))));
1744 
1745  if (!pg_type_ownercheck(typeid, GetUserId()))
1747 
1748  aclresult = pg_type_aclcheck(typeid, GetUserId(), ACL_USAGE);
1749  if (aclresult != ACLCHECK_OK)
1750  aclcheck_error_type(aclresult, typeid);
1751 
1752  /*
1753  * Get the language
1754  */
1755  langid = get_language_oid(stmt->lang, false);
1756 
1757  aclresult = pg_language_aclcheck(langid, GetUserId(), ACL_USAGE);
1758  if (aclresult != ACLCHECK_OK)
1759  aclcheck_error(aclresult, OBJECT_LANGUAGE, stmt->lang);
1760 
1761  /*
1762  * Get the functions
1763  */
1764  if (stmt->fromsql)
1765  {
1766  fromsqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->fromsql, false);
1767 
1768  if (!pg_proc_ownercheck(fromsqlfuncid, GetUserId()))
1770 
1771  aclresult = pg_proc_aclcheck(fromsqlfuncid, GetUserId(), ACL_EXECUTE);
1772  if (aclresult != ACLCHECK_OK)
1774 
1775  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fromsqlfuncid));
1776  if (!HeapTupleIsValid(tuple))
1777  elog(ERROR, "cache lookup failed for function %u", fromsqlfuncid);
1778  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1779  if (procstruct->prorettype != INTERNALOID)
1780  ereport(ERROR,
1781  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1782  errmsg("return data type of FROM SQL function must be %s",
1783  "internal")));
1784  check_transform_function(procstruct);
1785  ReleaseSysCache(tuple);
1786  }
1787  else
1788  fromsqlfuncid = InvalidOid;
1789 
1790  if (stmt->tosql)
1791  {
1792  tosqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->tosql, false);
1793 
1794  if (!pg_proc_ownercheck(tosqlfuncid, GetUserId()))
1796 
1797  aclresult = pg_proc_aclcheck(tosqlfuncid, GetUserId(), ACL_EXECUTE);
1798  if (aclresult != ACLCHECK_OK)
1800 
1801  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(tosqlfuncid));
1802  if (!HeapTupleIsValid(tuple))
1803  elog(ERROR, "cache lookup failed for function %u", tosqlfuncid);
1804  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1805  if (procstruct->prorettype != typeid)
1806  ereport(ERROR,
1807  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1808  errmsg("return data type of TO SQL function must be the transform data type")));
1809  check_transform_function(procstruct);
1810  ReleaseSysCache(tuple);
1811  }
1812  else
1813  tosqlfuncid = InvalidOid;
1814 
1815  /*
1816  * Ready to go
1817  */
1818  values[Anum_pg_transform_trftype - 1] = ObjectIdGetDatum(typeid);
1819  values[Anum_pg_transform_trflang - 1] = ObjectIdGetDatum(langid);
1820  values[Anum_pg_transform_trffromsql - 1] = ObjectIdGetDatum(fromsqlfuncid);
1821  values[Anum_pg_transform_trftosql - 1] = ObjectIdGetDatum(tosqlfuncid);
1822 
1823  MemSet(nulls, false, sizeof(nulls));
1824 
1825  relation = table_open(TransformRelationId, RowExclusiveLock);
1826 
1827  tuple = SearchSysCache2(TRFTYPELANG,
1828  ObjectIdGetDatum(typeid),
1829  ObjectIdGetDatum(langid));
1830  if (HeapTupleIsValid(tuple))
1831  {
1833 
1834  if (!stmt->replace)
1835  ereport(ERROR,
1837  errmsg("transform for type %s language \"%s\" already exists",
1838  format_type_be(typeid),
1839  stmt->lang)));
1840 
1841  MemSet(replaces, false, sizeof(replaces));
1842  replaces[Anum_pg_transform_trffromsql - 1] = true;
1843  replaces[Anum_pg_transform_trftosql - 1] = true;
1844 
1845  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
1846  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
1847 
1848  transformid = form->oid;
1849  ReleaseSysCache(tuple);
1850  is_replace = true;
1851  }
1852  else
1853  {
1854  transformid = GetNewOidWithIndex(relation, TransformOidIndexId,
1855  Anum_pg_transform_oid);
1856  values[Anum_pg_transform_oid - 1] = ObjectIdGetDatum(transformid);
1857  newtuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
1858  CatalogTupleInsert(relation, newtuple);
1859  is_replace = false;
1860  }
1861 
1862  if (is_replace)
1863  deleteDependencyRecordsFor(TransformRelationId, transformid, true);
1864 
1865  /* make dependency entries */
1866  myself.classId = TransformRelationId;
1867  myself.objectId = transformid;
1868  myself.objectSubId = 0;
1869 
1870  /* dependency on language */
1871  referenced.classId = LanguageRelationId;
1872  referenced.objectId = langid;
1873  referenced.objectSubId = 0;
1874  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1875 
1876  /* dependency on type */
1877  referenced.classId = TypeRelationId;
1878  referenced.objectId = typeid;
1879  referenced.objectSubId = 0;
1880  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1881 
1882  /* dependencies on functions */
1883  if (OidIsValid(fromsqlfuncid))
1884  {
1885  referenced.classId = ProcedureRelationId;
1886  referenced.objectId = fromsqlfuncid;
1887  referenced.objectSubId = 0;
1888  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1889  }
1890  if (OidIsValid(tosqlfuncid))
1891  {
1892  referenced.classId = ProcedureRelationId;
1893  referenced.objectId = tosqlfuncid;
1894  referenced.objectSubId = 0;
1895  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1896  }
1897 
1898  /* dependency on extension */
1899  recordDependencyOnCurrentExtension(&myself, is_replace);
1900 
1901  /* Post creation hook for new transform */
1902  InvokeObjectPostCreateHook(TransformRelationId, transformid, 0);
1903 
1904  heap_freetuple(newtuple);
1905 
1906  table_close(relation, RowExclusiveLock);
1907 
1908  return myself;
1909 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:317
ObjectWithArgs * tosql
Definition: parsenodes.h:3411
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
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:482
Oid GetUserId(void)
Definition: miscinit.c:439
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:476
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:190
Oid get_language_oid(const char *langname, bool missing_ok)
Definition: proclang.c:250
int errcode(int sqlerrcode)
Definition: elog.c:610
char get_typtype(Oid typid)
Definition: lsyscache.c:2468
#define MemSet(start, val, len)
Definition: c.h:971
char * format_type_be(Oid type_oid)
Definition: format_type.c:327
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
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:4779
#define OidIsValid(objectId)
Definition: c.h:644
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4665
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3665
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
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 TransformOidIndexId
Definition: indexing.h:246
#define ACL_USAGE
Definition: parsenodes.h:82
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
char * NameListToString(List *names)
Definition: namespace.c:3102
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:133
#define InvalidOid
Definition: postgres_ext.h:36
ObjectWithArgs * fromsql
Definition: parsenodes.h:3410
#define ereport(elevel,...)
Definition: elog.h:144
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:138
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1127
TypeName * type_name
Definition: parsenodes.h:3408
static Datum values[MAXATTR]
Definition: bootstrap.c:167
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define ACL_EXECUTE
Definition: parsenodes.h:81
#define elog(elevel,...)
Definition: elog.h:214
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4653
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2163
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4741
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:31
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183
bool pg_proc_ownercheck(Oid proc_oid, Oid roleid)
Definition: aclchk.c:4831
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:291

◆ DropCastById()

void DropCastById ( Oid  castOid)

Definition at line 1650 of file functioncmds.c.

References BTEqualStrategyNumber, CastOidIndexId, CatalogTupleDelete(), elog, ERROR, HeapTupleIsValid, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by doDeletion().

1651 {
1652  Relation relation;
1653  ScanKeyData scankey;
1654  SysScanDesc scan;
1655  HeapTuple tuple;
1656 
1657  relation = table_open(CastRelationId, RowExclusiveLock);
1658 
1659  ScanKeyInit(&scankey,
1660  Anum_pg_cast_oid,
1661  BTEqualStrategyNumber, F_OIDEQ,
1662  ObjectIdGetDatum(castOid));
1663  scan = systable_beginscan(relation, CastOidIndexId, true,
1664  NULL, 1, &scankey);
1665 
1666  tuple = systable_getnext(scan);
1667  if (!HeapTupleIsValid(tuple))
1668  elog(ERROR, "could not find tuple for cast %u", castOid);
1669  CatalogTupleDelete(relation, &tuple->t_self);
1670 
1671  systable_endscan(scan);
1672  table_close(relation, RowExclusiveLock);
1673 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#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 CastOidIndexId
Definition: indexing.h:109
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:214
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ DropTransformById()

void DropTransformById ( Oid  transformOid)

Definition at line 1937 of file functioncmds.c.

References BTEqualStrategyNumber, CatalogTupleDelete(), elog, ERROR, HeapTupleIsValid, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), table_open(), and TransformOidIndexId.

Referenced by doDeletion().

1938 {
1939  Relation relation;
1940  ScanKeyData scankey;
1941  SysScanDesc scan;
1942  HeapTuple tuple;
1943 
1944  relation = table_open(TransformRelationId, RowExclusiveLock);
1945 
1946  ScanKeyInit(&scankey,
1947  Anum_pg_transform_oid,
1948  BTEqualStrategyNumber, F_OIDEQ,
1949  ObjectIdGetDatum(transformOid));
1950  scan = systable_beginscan(relation, TransformOidIndexId, true,
1951  NULL, 1, &scankey);
1952 
1953  tuple = systable_getnext(scan);
1954  if (!HeapTupleIsValid(tuple))
1955  elog(ERROR, "could not find tuple for transform %u", transformOid);
1956  CatalogTupleDelete(relation, &tuple->t_self);
1957 
1958  systable_endscan(scan);
1959  table_close(relation, RowExclusiveLock);
1960 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#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 TransformOidIndexId
Definition: indexing.h:246
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:214
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ ExecuteCallStmt()

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

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

2120 {
2121  LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
2122  ListCell *lc;
2123  FuncExpr *fexpr;
2124  int nargs;
2125  int i;
2126  AclResult aclresult;
2127  FmgrInfo flinfo;
2128  CallContext *callcontext;
2129  EState *estate;
2130  ExprContext *econtext;
2131  HeapTuple tp;
2132  PgStat_FunctionCallUsage fcusage;
2133  Datum retval;
2134 
2135  fexpr = stmt->funcexpr;
2136  Assert(fexpr);
2137  Assert(IsA(fexpr, FuncExpr));
2138 
2139  aclresult = pg_proc_aclcheck(fexpr->funcid, GetUserId(), ACL_EXECUTE);
2140  if (aclresult != ACLCHECK_OK)
2141  aclcheck_error(aclresult, OBJECT_PROCEDURE, get_func_name(fexpr->funcid));
2142 
2143  /* Prep the context object we'll pass to the procedure */
2144  callcontext = makeNode(CallContext);
2145  callcontext->atomic = atomic;
2146 
2148  if (!HeapTupleIsValid(tp))
2149  elog(ERROR, "cache lookup failed for function %u", fexpr->funcid);
2150 
2151  /*
2152  * If proconfig is set we can't allow transaction commands because of the
2153  * way the GUC stacking works: The transaction boundary would have to pop
2154  * the proconfig setting off the stack. That restriction could be lifted
2155  * by redesigning the GUC nesting mechanism a bit.
2156  */
2157  if (!heap_attisnull(tp, Anum_pg_proc_proconfig, NULL))
2158  callcontext->atomic = true;
2159 
2160  /*
2161  * In security definer procedures, we can't allow transaction commands.
2162  * StartTransaction() insists that the security context stack is empty,
2163  * and AbortTransaction() resets the security context. This could be
2164  * reorganized, but right now it doesn't work.
2165  */
2166  if (((Form_pg_proc) GETSTRUCT(tp))->prosecdef)
2167  callcontext->atomic = true;
2168 
2169  /*
2170  * Expand named arguments, defaults, etc. We do not want to scribble on
2171  * the passed-in CallStmt parse tree, so first flat-copy fexpr, allowing
2172  * us to replace its args field. (Note that expand_function_arguments
2173  * will not modify any of the passed-in data structure.)
2174  */
2175  {
2176  FuncExpr *nexpr = makeNode(FuncExpr);
2177 
2178  memcpy(nexpr, fexpr, sizeof(FuncExpr));
2179  fexpr = nexpr;
2180  }
2181 
2182  fexpr->args = expand_function_arguments(fexpr->args,
2183  fexpr->funcresulttype,
2184  tp);
2185  nargs = list_length(fexpr->args);
2186 
2187  ReleaseSysCache(tp);
2188 
2189  /* safety check; see ExecInitFunc() */
2190  if (nargs > FUNC_MAX_ARGS)
2191  ereport(ERROR,
2192  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2193  errmsg_plural("cannot pass more than %d argument to a procedure",
2194  "cannot pass more than %d arguments to a procedure",
2195  FUNC_MAX_ARGS,
2196  FUNC_MAX_ARGS)));
2197 
2198  /* Initialize function call structure */
2200  fmgr_info(fexpr->funcid, &flinfo);
2201  fmgr_info_set_expr((Node *) fexpr, &flinfo);
2202  InitFunctionCallInfoData(*fcinfo, &flinfo, nargs, fexpr->inputcollid,
2203  (Node *) callcontext, NULL);
2204 
2205  /*
2206  * Evaluate procedure arguments inside a suitable execution context. Note
2207  * we can't free this context till the procedure returns.
2208  */
2209  estate = CreateExecutorState();
2210  estate->es_param_list_info = params;
2211  econtext = CreateExprContext(estate);
2212 
2213  i = 0;
2214  foreach(lc, fexpr->args)
2215  {
2216  ExprState *exprstate;
2217  Datum val;
2218  bool isnull;
2219 
2220  exprstate = ExecPrepareExpr(lfirst(lc), estate);
2221 
2222  val = ExecEvalExprSwitchContext(exprstate, econtext, &isnull);
2223 
2224  fcinfo->args[i].value = val;
2225  fcinfo->args[i].isnull = isnull;
2226 
2227  i++;
2228  }
2229 
2230  pgstat_init_function_usage(fcinfo, &fcusage);
2231  retval = FunctionCallInvoke(fcinfo);
2232  pgstat_end_function_usage(&fcusage, true);
2233 
2234  if (fexpr->funcresulttype == VOIDOID)
2235  {
2236  /* do nothing */
2237  }
2238  else if (fexpr->funcresulttype == RECORDOID)
2239  {
2240  /*
2241  * send tuple to client
2242  */
2243 
2244  HeapTupleHeader td;
2245  Oid tupType;
2246  int32 tupTypmod;
2247  TupleDesc retdesc;
2248  HeapTupleData rettupdata;
2249  TupOutputState *tstate;
2250  TupleTableSlot *slot;
2251 
2252  if (fcinfo->isnull)
2253  elog(ERROR, "procedure returned null record");
2254 
2255  td = DatumGetHeapTupleHeader(retval);
2256  tupType = HeapTupleHeaderGetTypeId(td);
2257  tupTypmod = HeapTupleHeaderGetTypMod(td);
2258  retdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
2259 
2260  tstate = begin_tup_output_tupdesc(dest, retdesc,
2261  &TTSOpsHeapTuple);
2262 
2263  rettupdata.t_len = HeapTupleHeaderGetDatumLength(td);
2264  ItemPointerSetInvalid(&(rettupdata.t_self));
2265  rettupdata.t_tableOid = InvalidOid;
2266  rettupdata.t_data = td;
2267 
2268  slot = ExecStoreHeapTuple(&rettupdata, tstate->slot, false);
2269  tstate->dest->receiveSlot(slot, tstate->dest);
2270 
2271  end_tup_output(tstate);
2272 
2273  ReleaseTupleDesc(retdesc);
2274  }
2275  else
2276  elog(ERROR, "unexpected result type for procedure: %u",
2277  fexpr->funcresulttype);
2278 
2279  FreeExecutorState(estate);
2280 }
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h:119
Oid funcresulttype
Definition: primnodes.h:470
Definition: fmgr.h:56
#define IsA(nodeptr, _type_)
Definition: nodes.h:577
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:305
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
List * expand_function_arguments(List *args, Oid result_type, HeapTuple func_tuple)
Definition: clauses.c:4032
List * args
Definition: primnodes.h:477
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1710
FuncExpr * funcexpr
Definition: parsenodes.h:2899
Oid GetUserId(void)
Definition: miscinit.c:439
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:934
Definition: nodes.h:526
int errcode(int sqlerrcode)
Definition: elog.c:610
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
TupleTableSlot * slot
Definition: executor.h:463
unsigned int Oid
Definition: postgres_ext.h:31
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition: execExpr.c:492
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:289
signed int int32
Definition: c.h:355
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:190
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
void end_tup_output(TupOutputState *tstate)
Definition: execTuples.c:2314
Oid funcid
Definition: primnodes.h:469
#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:1669
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1471
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:167
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:135
Oid t_tableOid
Definition: htup.h:66
EState * CreateExecutorState(void)
Definition: execUtils.c:88
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:191
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#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:144
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define makeNode(_type_)
Definition: nodes.h:574
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
Oid inputcollid
Definition: primnodes.h:476
#define Assert(condition)
Definition: c.h:738
#define lfirst(lc)
Definition: pg_list.h:190
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
static int list_length(const List *l)
Definition: pg_list.h:169
void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize)
Definition: pgstat.c:1741
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:172
#define ACL_EXECUTE
Definition: parsenodes.h:81
#define elog(elevel,...)
Definition: elog.h:214
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4653
int i
const TupleTableSlotOps TTSOpsHeapTuple
Definition: execTuples.c:84
ExprContext * CreateExprContext(EState *estate)
Definition: execUtils.c:244
ParamListInfo es_param_list_info
Definition: execnodes.h:549
DestReceiver * dest
Definition: executor.h:464
#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 1993 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().

1994 {
1996  ListCell *arg;
1997  DefElem *as_item = NULL;
1998  DefElem *language_item = NULL;
1999  char *language;
2000  Oid laninline;
2001  HeapTuple languageTuple;
2002  Form_pg_language languageStruct;
2003 
2004  /* Process options we got from gram.y */
2005  foreach(arg, stmt->args)
2006  {
2007  DefElem *defel = (DefElem *) lfirst(arg);
2008 
2009  if (strcmp(defel->defname, "as") == 0)
2010  {
2011  if (as_item)
2012  ereport(ERROR,
2013  (errcode(ERRCODE_SYNTAX_ERROR),
2014  errmsg("conflicting or redundant options")));
2015  as_item = defel;
2016  }
2017  else if (strcmp(defel->defname, "language") == 0)
2018  {
2019  if (language_item)
2020  ereport(ERROR,
2021  (errcode(ERRCODE_SYNTAX_ERROR),
2022  errmsg("conflicting or redundant options")));
2023  language_item = defel;
2024  }
2025  else
2026  elog(ERROR, "option \"%s\" not recognized",
2027  defel->defname);
2028  }
2029 
2030  if (as_item)
2031  codeblock->source_text = strVal(as_item->arg);
2032  else
2033  ereport(ERROR,
2034  (errcode(ERRCODE_SYNTAX_ERROR),
2035  errmsg("no inline code specified")));
2036 
2037  /* if LANGUAGE option wasn't specified, use the default */
2038  if (language_item)
2039  language = strVal(language_item->arg);
2040  else
2041  language = "plpgsql";
2042 
2043  /* Look up the language and validate permissions */
2044  languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
2045  if (!HeapTupleIsValid(languageTuple))
2046  ereport(ERROR,
2047  (errcode(ERRCODE_UNDEFINED_OBJECT),
2048  errmsg("language \"%s\" does not exist", language),
2049  (extension_file_exists(language) ?
2050  errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
2051 
2052  languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
2053  codeblock->langOid = languageStruct->oid;
2054  codeblock->langIsTrusted = languageStruct->lanpltrusted;
2055  codeblock->atomic = atomic;
2056 
2057  if (languageStruct->lanpltrusted)
2058  {
2059  /* if trusted language, need USAGE privilege */
2060  AclResult aclresult;
2061 
2062  aclresult = pg_language_aclcheck(codeblock->langOid, GetUserId(),
2063  ACL_USAGE);
2064  if (aclresult != ACLCHECK_OK)
2065  aclcheck_error(aclresult, OBJECT_LANGUAGE,
2066  NameStr(languageStruct->lanname));
2067  }
2068  else
2069  {
2070  /* if untrusted language, must be superuser */
2071  if (!superuser())
2073  NameStr(languageStruct->lanname));
2074  }
2075 
2076  /* get the handler function's OID */
2077  laninline = languageStruct->laninline;
2078  if (!OidIsValid(laninline))
2079  ereport(ERROR,
2080  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2081  errmsg("language \"%s\" does not support inline code execution",
2082  NameStr(languageStruct->lanname))));
2083 
2084  ReleaseSysCache(languageTuple);
2085 
2086  /* execute the inline handler */
2087  OidFunctionCall1(laninline, PointerGetDatum(codeblock));
2088 }
int errhint(const char *fmt,...)
Definition: elog.c:1071
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Oid GetUserId(void)
Definition: miscinit.c:439
#define PointerGetDatum(X)
Definition: postgres.h:556
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:610
bool superuser(void)
Definition: superuser.c:46
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:644
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4665
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352
#define ERROR
Definition: elog.h:43
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:657
#define ACL_USAGE
Definition: parsenodes.h:82
Node * arg
Definition: parsenodes.h:732
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
AclResult
Definition: acl.h:177
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define ereport(elevel,...)
Definition: elog.h:144
#define makeNode(_type_)
Definition: nodes.h:574
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:190
List * args
Definition: parsenodes.h:2879
bool extension_file_exists(const char *extensionName)
Definition: extension.c:2224
FormData_pg_language * Form_pg_language
Definition: pg_language.h:65
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214
#define NameStr(name)
Definition: c.h:615
void * arg
char * source_text
Definition: parsenodes.h:2885
char * defname
Definition: parsenodes.h:731

◆ get_transform_oid()

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

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

1920 {
1921  Oid oid;
1922 
1923  oid = GetSysCacheOid2(TRFTYPELANG, Anum_pg_transform_oid,
1924  ObjectIdGetDatum(type_id),
1925  ObjectIdGetDatum(lang_id));
1926  if (!OidIsValid(oid) && !missing_ok)
1927  ereport(ERROR,
1928  (errcode(ERRCODE_UNDEFINED_OBJECT),
1929  errmsg("transform for type %s language \"%s\" does not exist",
1930  format_type_be(type_id),
1931  get_language_name(lang_id, false))));
1932  return oid;
1933 }
char * get_language_name(Oid langoid, bool missing_ok)
Definition: lsyscache.c:1051
int errcode(int sqlerrcode)
Definition: elog.c:610
char * format_type_be(Oid type_oid)
Definition: format_type.c:327
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:644
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define ereport(elevel,...)
Definition: elog.h:144
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:194
int errmsg(const char *fmt,...)
Definition: elog.c:824

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

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

Referenced by CreateFunction().

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

◆ interpret_func_parallel()

static char interpret_func_parallel ( DefElem defel)
static

Definition at line 601 of file functioncmds.c.

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

Referenced by AlterFunction(), and compute_function_attributes().

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

◆ interpret_func_support()

static Oid interpret_func_support ( DefElem defel)
static

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

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

◆ interpret_func_volatility()

static char interpret_func_volatility ( DefElem defel)
static

Definition at line 583 of file functioncmds.c.

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

Referenced by AlterFunction(), and compute_function_attributes().

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

◆ 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(), errhint(), errmsg(), ERROR, EXPR_KIND_FUNCTION_DEFAULT, FUNC_PARAM_IN, 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 *inTypes;
198  int inCount = 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  inTypes = (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  if (objtype == OBJECT_PROCEDURE)
285  {
286  if (fp->mode == FUNC_PARAM_OUT)
287  ereport(ERROR,
288  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
289  errmsg("procedures cannot have OUT arguments"),
290  errhint("INOUT arguments are permitted.")));
291  }
292 
293  /* handle input parameters */
294  if (fp->mode != FUNC_PARAM_OUT && fp->mode != FUNC_PARAM_TABLE)
295  {
296  /* other input parameters can't follow a VARIADIC parameter */
297  if (varCount > 0)
298  ereport(ERROR,
299  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
300  errmsg("VARIADIC parameter must be the last input parameter")));
301  inTypes[inCount++] = toid;
302  isinput = true;
303  }
304 
305  /* handle output parameters */
306  if (fp->mode != FUNC_PARAM_IN && fp->mode != FUNC_PARAM_VARIADIC)
307  {
308  if (objtype == OBJECT_PROCEDURE)
309  *requiredResultType = RECORDOID;
310  else if (outCount == 0) /* save first output param's type */
311  *requiredResultType = toid;
312  outCount++;
313  }
314 
315  if (fp->mode == FUNC_PARAM_VARIADIC)
316  {
317  *variadicArgType = toid;
318  varCount++;
319  /* validate variadic parameter type */
320  switch (toid)
321  {
322  case ANYARRAYOID:
323  case ANYCOMPATIBLEARRAYOID:
324  case ANYOID:
325  /* okay */
326  break;
327  default:
328  if (!OidIsValid(get_element_type(toid)))
329  ereport(ERROR,
330  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
331  errmsg("VARIADIC parameter must be an array")));
332  break;
333  }
334  }
335 
336  allTypes[i] = ObjectIdGetDatum(toid);
337 
338  paramModes[i] = CharGetDatum(fp->mode);
339 
340  if (fp->name && fp->name[0])
341  {
342  ListCell *px;
343 
344  /*
345  * As of Postgres 9.0 we disallow using the same name for two
346  * input or two output function parameters. Depending on the
347  * function's language, conflicting input and output names might
348  * be bad too, but we leave it to the PL to complain if so.
349  */
350  foreach(px, parameters)
351  {
352  FunctionParameter *prevfp = (FunctionParameter *) lfirst(px);
353 
354  if (prevfp == fp)
355  break;
356  /* pure in doesn't conflict with pure out */
357  if ((fp->mode == FUNC_PARAM_IN ||
358  fp->mode == FUNC_PARAM_VARIADIC) &&
359  (prevfp->mode == FUNC_PARAM_OUT ||
360  prevfp->mode == FUNC_PARAM_TABLE))
361  continue;
362  if ((prevfp->mode == FUNC_PARAM_IN ||
363  prevfp->mode == FUNC_PARAM_VARIADIC) &&
364  (fp->mode == FUNC_PARAM_OUT ||
365  fp->mode == FUNC_PARAM_TABLE))
366  continue;
367  if (prevfp->name && prevfp->name[0] &&
368  strcmp(prevfp->name, fp->name) == 0)
369  ereport(ERROR,
370  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
371  errmsg("parameter name \"%s\" used more than once",
372  fp->name)));
373  }
374 
375  paramNames[i] = CStringGetTextDatum(fp->name);
376  have_names = true;
377  }
378 
379  if (fp->defexpr)
380  {
381  Node *def;
382 
383  if (!isinput)
384  ereport(ERROR,
385  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
386  errmsg("only input parameters can have default values")));
387 
388  def = transformExpr(pstate, fp->defexpr,
390  def = coerce_to_specific_type(pstate, def, toid, "DEFAULT");
391  assign_expr_collations(pstate, def);
392 
393  /*
394  * Make sure no variables are referred to (this is probably dead
395  * code now that add_missing_from is history).
396  */
397  if (list_length(pstate->p_rtable) != 0 ||
398  contain_var_clause(def))
399  ereport(ERROR,
400  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
401  errmsg("cannot use table references in parameter default value")));
402 
403  /*
404  * transformExpr() should have already rejected subqueries,
405  * aggregates, and window functions, based on the EXPR_KIND_ for a
406  * default expression.
407  *
408  * It can't return a set either --- but coerce_to_specific_type
409  * already checked that for us.
410  *
411  * Note: the point of these restrictions is to ensure that an
412  * expression that, on its face, hasn't got subplans, aggregates,
413  * etc cannot suddenly have them after function default arguments
414  * are inserted.
415  */
416 
417  *parameterDefaults = lappend(*parameterDefaults, def);
418  have_defaults = true;
419  }
420  else
421  {
422  if (isinput && have_defaults)
423  ereport(ERROR,
424  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
425  errmsg("input parameters after one with a default value must also have defaults")));
426  }
427 
428  i++;
429  }
430 
431  /* Now construct the proper outputs as needed */
432  *parameterTypes = buildoidvector(inTypes, inCount);
433 
434  if (outCount > 0 || varCount > 0)
435  {
436  *allParameterTypes = construct_array(allTypes, parameterCount, OIDOID,
437  sizeof(Oid), true, TYPALIGN_INT);
438  *parameterModes = construct_array(paramModes, parameterCount, CHAROID,
439  1, true, TYPALIGN_CHAR);
440  if (outCount > 1)
441  *requiredResultType = RECORDOID;
442  /* otherwise we set requiredResultType correctly above */
443  }
444  else
445  {
446  *allParameterTypes = NULL;
447  *parameterModes = NULL;
448  }
449 
450  if (have_names)
451  {
452  for (i = 0; i < parameterCount; i++)
453  {
454  if (paramNames[i] == PointerGetDatum(NULL))
455  paramNames[i] = CStringGetTextDatum("");
456  }
457  *parameterNames = construct_array(paramNames, parameterCount, TEXTOID,
458  -1, false, TYPALIGN_INT);
459  }
460  else
461  *parameterNames = NULL;
462 }
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
int errhint(const char *fmt,...)
Definition: elog.c:1071
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Oid GetUserId(void)
Definition: miscinit.c:439
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2587
#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:145
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3291
Definition: nodes.h:526
int errcode(int sqlerrcode)
Definition: elog.c:610
bool contain_var_clause(Node *node)
Definition: var.c:331
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:644
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3665
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:211
#define ACL_USAGE
Definition: parsenodes.h:82
TypeName * argType
Definition: parsenodes.h:2857
List * lappend(List *list, void *datum)
Definition: list.c:322
void * palloc0(Size size)
Definition: mcxt.c:980
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#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:144
#define NOTICE
Definition: elog.h:37
oidvector * buildoidvector(const Oid *oids, int n)
Definition: oid.c:167
#define lfirst(lc)
Definition: pg_list.h:190
FormData_pg_type * Form_pg_type
Definition: pg_type.h:255
static int list_length(const List *l)
Definition: pg_list.h:169
#define CharGetDatum(X)
Definition: postgres.h:416
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:824
int i
Node * coerce_to_specific_type(ParseState *pstate, Node *node, Oid targetTypeId, const char *constructName)
#define CStringGetTextDatum(s)
Definition: builtins.h:87
FunctionParameterMode mode
Definition: parsenodes.h:2858
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4741
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 1970 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().

1972 {
1973  /* check for duplicate name (more friendly than unique-index failure) */
1976  PointerGetDatum(proargtypes),
1977  ObjectIdGetDatum(nspOid)))
1978  ereport(ERROR,
1979  (errcode(ERRCODE_DUPLICATE_FUNCTION),
1980  errmsg("function %s already exists in schema \"%s\"",
1982  NIL, proargtypes->values),
1983  get_namespace_name(nspOid))));
1984 }
#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:610
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:3155
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:602
#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:1978
#define ereport(elevel,...)
Definition: elog.h:144
int errmsg(const char *fmt,...)
Definition: elog.c:824

◆ RemoveFunctionById()

void RemoveFunctionById ( Oid  funcOid)

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

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

627 {
628  ListCell *l;
629 
630  foreach(l, set_items)
631  {
633 
634  if (sstmt->kind == VAR_RESET_ALL)
635  a = NULL;
636  else
637  {
638  char *valuestr = ExtractSetVariableArgs(sstmt);
639 
640  if (valuestr)
641  a = GUCArrayAdd(a, sstmt->name, valuestr);
642  else /* RESET */
643  a = GUCArrayDelete(a, sstmt->name);
644  }
645  }
646 
647  return a;
648 }
ArrayType * GUCArrayAdd(ArrayType *array, const char *name, const char *value)
Definition: guc.c:10595
VariableSetKind kind
Definition: parsenodes.h:2040
#define lfirst_node(type, lc)
Definition: pg_list.h:193
ArrayType * GUCArrayDelete(ArrayType *array, const char *name)
Definition: guc.c:10675
char * ExtractSetVariableArgs(VariableSetStmt *stmt)
Definition: guc.c:8441