PostgreSQL Source Code  git master
functioncmds.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/htup_details.h"
#include "access/table.h"
#include "access/sysattr.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/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)
 
void SetFunctionReturnType (Oid funcOid, Oid newRetType)
 
void SetFunctionArgType (Oid funcOid, int argIndex, Oid newArgType)
 
ObjectAddress CreateCast (CreateCastStmt *stmt)
 
Oid get_cast_oid (Oid sourcetypeid, Oid targettypeid, bool missing_ok)
 
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 1233 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().

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

◆ CallStmtResultDesc()

TupleDesc CallStmtResultDesc ( CallStmt stmt)

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

2466 {
2467  FuncExpr *fexpr;
2468  HeapTuple tuple;
2469  TupleDesc tupdesc;
2470 
2471  fexpr = stmt->funcexpr;
2472 
2473  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
2474  if (!HeapTupleIsValid(tuple))
2475  elog(ERROR, "cache lookup failed for procedure %u", fexpr->funcid);
2476 
2477  tupdesc = build_function_result_tupdesc_t(tuple);
2478 
2479  ReleaseSysCache(tuple);
2480 
2481  return tupdesc;
2482 }
FuncExpr * funcexpr
Definition: parsenodes.h:2875
TupleDesc build_function_result_tupdesc_t(HeapTuple procTuple)
Definition: funcapi.c:1161
Oid funcid
Definition: primnodes.h:455
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:226

◆ check_transform_function()

static void check_transform_function ( Form_pg_proc  procstruct)
static

Definition at line 1856 of file functioncmds.c.

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

Referenced by CreateTransform().

1857 {
1858  if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1859  ereport(ERROR,
1860  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1861  errmsg("transform function must not be volatile")));
1862  if (procstruct->prokind != PROKIND_FUNCTION)
1863  ereport(ERROR,
1864  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1865  errmsg("transform function must be a normal function")));
1866  if (procstruct->proretset)
1867  ereport(ERROR,
1868  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1869  errmsg("transform function must not return a set")));
1870  if (procstruct->pronargs != 1)
1871  ereport(ERROR,
1872  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1873  errmsg("transform function must take one argument")));
1874  if (procstruct->proargtypes.values[0] != INTERNALOID)
1875  ereport(ERROR,
1876  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1877  errmsg("first argument of transform function must be type %s",
1878  "internal")));
1879 }
int errcode(int sqlerrcode)
Definition: elog.c:570
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
int errmsg(const char *fmt,...)
Definition: elog.c:784

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

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

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

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

◆ compute_return_type()

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

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

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

◆ CreateCast()

ObjectAddress CreateCast ( CreateCastStmt stmt)

Definition at line 1493 of file functioncmds.c.

References ACL_USAGE, aclcheck_error_type(), ACLCHECK_OK, CastOidIndexId, CASTSOURCETARGET, CatalogTupleInsert(), CharGetDatum, ObjectAddress::classId, COERCION_ASSIGNMENT, COERCION_EXPLICIT, COERCION_IMPLICIT, CreateCastStmt::context, DEPENDENCY_NORMAL, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, format_type_be(), CreateCastStmt::func, get_element_type(), get_typlenbyvalalign(), get_typtype(), GetNewOidWithIndex(), GETSTRUCT, GetUserId(), heap_form_tuple(), heap_freetuple(), HeapTupleIsValid, CreateCastStmt::inout, InvalidOid, InvokeObjectPostCreateHook, IsBinaryCoercible(), LookupFuncWithArgs(), MemSet, OBJECT_FUNCTION, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, pg_type_aclcheck(), pg_type_ownercheck(), PROCOID, recordDependencyOn(), recordDependencyOnCurrentExtension(), RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), SearchSysCache2(), CreateCastStmt::sourcetype, superuser(), table_close(), table_open(), CreateCastStmt::targettype, TypeNameToString(), typenameTypeId(), values, and WARNING.

Referenced by ProcessUtilitySlow().

1494 {
1495  Oid sourcetypeid;
1496  Oid targettypeid;
1497  char sourcetyptype;
1498  char targettyptype;
1499  Oid funcid;
1500  Oid castid;
1501  int nargs;
1502  char castcontext;
1503  char castmethod;
1504  Relation relation;
1505  HeapTuple tuple;
1506  Datum values[Natts_pg_cast];
1507  bool nulls[Natts_pg_cast];
1508  ObjectAddress myself,
1509  referenced;
1510  AclResult aclresult;
1511 
1512  sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
1513  targettypeid = typenameTypeId(NULL, stmt->targettype);
1514  sourcetyptype = get_typtype(sourcetypeid);
1515  targettyptype = get_typtype(targettypeid);
1516 
1517  /* No pseudo-types allowed */
1518  if (sourcetyptype == TYPTYPE_PSEUDO)
1519  ereport(ERROR,
1520  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1521  errmsg("source data type %s is a pseudo-type",
1522  TypeNameToString(stmt->sourcetype))));
1523 
1524  if (targettyptype == TYPTYPE_PSEUDO)
1525  ereport(ERROR,
1526  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1527  errmsg("target data type %s is a pseudo-type",
1528  TypeNameToString(stmt->targettype))));
1529 
1530  /* Permission check */
1531  if (!pg_type_ownercheck(sourcetypeid, GetUserId())
1532  && !pg_type_ownercheck(targettypeid, GetUserId()))
1533  ereport(ERROR,
1534  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1535  errmsg("must be owner of type %s or type %s",
1536  format_type_be(sourcetypeid),
1537  format_type_be(targettypeid))));
1538 
1539  aclresult = pg_type_aclcheck(sourcetypeid, GetUserId(), ACL_USAGE);
1540  if (aclresult != ACLCHECK_OK)
1541  aclcheck_error_type(aclresult, sourcetypeid);
1542 
1543  aclresult = pg_type_aclcheck(targettypeid, GetUserId(), ACL_USAGE);
1544  if (aclresult != ACLCHECK_OK)
1545  aclcheck_error_type(aclresult, targettypeid);
1546 
1547  /* Domains are allowed for historical reasons, but we warn */
1548  if (sourcetyptype == TYPTYPE_DOMAIN)
1549  ereport(WARNING,
1550  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1551  errmsg("cast will be ignored because the source data type is a domain")));
1552 
1553  else if (targettyptype == TYPTYPE_DOMAIN)
1554  ereport(WARNING,
1555  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1556  errmsg("cast will be ignored because the target data type is a domain")));
1557 
1558  /* Determine the cast method */
1559  if (stmt->func != NULL)
1560  castmethod = COERCION_METHOD_FUNCTION;
1561  else if (stmt->inout)
1562  castmethod = COERCION_METHOD_INOUT;
1563  else
1564  castmethod = COERCION_METHOD_BINARY;
1565 
1566  if (castmethod == COERCION_METHOD_FUNCTION)
1567  {
1568  Form_pg_proc procstruct;
1569 
1570  funcid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->func, false);
1571 
1572  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1573  if (!HeapTupleIsValid(tuple))
1574  elog(ERROR, "cache lookup failed for function %u", funcid);
1575 
1576  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1577  nargs = procstruct->pronargs;
1578  if (nargs < 1 || nargs > 3)
1579  ereport(ERROR,
1580  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1581  errmsg("cast function must take one to three arguments")));
1582  if (!IsBinaryCoercible(sourcetypeid, procstruct->proargtypes.values[0]))
1583  ereport(ERROR,
1584  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1585  errmsg("argument of cast function must match or be binary-coercible from source data type")));
1586  if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
1587  ereport(ERROR,
1588  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1589  errmsg("second argument of cast function must be type %s",
1590  "integer")));
1591  if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)
1592  ereport(ERROR,
1593  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1594  errmsg("third argument of cast function must be type %s",
1595  "boolean")));
1596  if (!IsBinaryCoercible(procstruct->prorettype, targettypeid))
1597  ereport(ERROR,
1598  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1599  errmsg("return data type of cast function must match or be binary-coercible to target data type")));
1600 
1601  /*
1602  * Restricting the volatility of a cast function may or may not be a
1603  * good idea in the abstract, but it definitely breaks many old
1604  * user-defined types. Disable this check --- tgl 2/1/03
1605  */
1606 #ifdef NOT_USED
1607  if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1608  ereport(ERROR,
1609  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1610  errmsg("cast function must not be volatile")));
1611 #endif
1612  if (procstruct->prokind != PROKIND_FUNCTION)
1613  ereport(ERROR,
1614  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1615  errmsg("cast function must be a normal function")));
1616  if (procstruct->proretset)
1617  ereport(ERROR,
1618  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1619  errmsg("cast function must not return a set")));
1620 
1621  ReleaseSysCache(tuple);
1622  }
1623  else
1624  {
1625  funcid = InvalidOid;
1626  nargs = 0;
1627  }
1628 
1629  if (castmethod == COERCION_METHOD_BINARY)
1630  {
1631  int16 typ1len;
1632  int16 typ2len;
1633  bool typ1byval;
1634  bool typ2byval;
1635  char typ1align;
1636  char typ2align;
1637 
1638  /*
1639  * Must be superuser to create binary-compatible casts, since
1640  * erroneous casts can easily crash the backend.
1641  */
1642  if (!superuser())
1643  ereport(ERROR,
1644  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1645  errmsg("must be superuser to create a cast WITHOUT FUNCTION")));
1646 
1647  /*
1648  * Also, insist that the types match as to size, alignment, and
1649  * pass-by-value attributes; this provides at least a crude check that
1650  * they have similar representations. A pair of types that fail this
1651  * test should certainly not be equated.
1652  */
1653  get_typlenbyvalalign(sourcetypeid, &typ1len, &typ1byval, &typ1align);
1654  get_typlenbyvalalign(targettypeid, &typ2len, &typ2byval, &typ2align);
1655  if (typ1len != typ2len ||
1656  typ1byval != typ2byval ||
1657  typ1align != typ2align)
1658  ereport(ERROR,
1659  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1660  errmsg("source and target data types are not physically compatible")));
1661 
1662  /*
1663  * We know that composite, enum and array types are never binary-
1664  * compatible with each other. They all have OIDs embedded in them.
1665  *
1666  * Theoretically you could build a user-defined base type that is
1667  * binary-compatible with a composite, enum, or array type. But we
1668  * disallow that too, as in practice such a cast is surely a mistake.
1669  * You can always work around that by writing a cast function.
1670  */
1671  if (sourcetyptype == TYPTYPE_COMPOSITE ||
1672  targettyptype == TYPTYPE_COMPOSITE)
1673  ereport(ERROR,
1674  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1675  errmsg("composite data types are not binary-compatible")));
1676 
1677  if (sourcetyptype == TYPTYPE_ENUM ||
1678  targettyptype == TYPTYPE_ENUM)
1679  ereport(ERROR,
1680  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1681  errmsg("enum data types are not binary-compatible")));
1682 
1683  if (OidIsValid(get_element_type(sourcetypeid)) ||
1684  OidIsValid(get_element_type(targettypeid)))
1685  ereport(ERROR,
1686  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1687  errmsg("array data types are not binary-compatible")));
1688 
1689  /*
1690  * We also disallow creating binary-compatibility casts involving
1691  * domains. Casting from a domain to its base type is already
1692  * allowed, and casting the other way ought to go through domain
1693  * coercion to permit constraint checking. Again, if you're intent on
1694  * having your own semantics for that, create a no-op cast function.
1695  *
1696  * NOTE: if we were to relax this, the above checks for composites
1697  * etc. would have to be modified to look through domains to their
1698  * base types.
1699  */
1700  if (sourcetyptype == TYPTYPE_DOMAIN ||
1701  targettyptype == TYPTYPE_DOMAIN)
1702  ereport(ERROR,
1703  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1704  errmsg("domain data types must not be marked binary-compatible")));
1705  }
1706 
1707  /*
1708  * Allow source and target types to be same only for length coercion
1709  * functions. We assume a multi-arg function does length coercion.
1710  */
1711  if (sourcetypeid == targettypeid && nargs < 2)
1712  ereport(ERROR,
1713  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1714  errmsg("source data type and target data type are the same")));
1715 
1716  /* convert CoercionContext enum to char value for castcontext */
1717  switch (stmt->context)
1718  {
1719  case COERCION_IMPLICIT:
1720  castcontext = COERCION_CODE_IMPLICIT;
1721  break;
1722  case COERCION_ASSIGNMENT:
1723  castcontext = COERCION_CODE_ASSIGNMENT;
1724  break;
1725  case COERCION_EXPLICIT:
1726  castcontext = COERCION_CODE_EXPLICIT;
1727  break;
1728  default:
1729  elog(ERROR, "unrecognized CoercionContext: %d", stmt->context);
1730  castcontext = 0; /* keep compiler quiet */
1731  break;
1732  }
1733 
1734  relation = table_open(CastRelationId, RowExclusiveLock);
1735 
1736  /*
1737  * Check for duplicate. This is just to give a friendly error message,
1738  * the unique index would catch it anyway (so no need to sweat about race
1739  * conditions).
1740  */
1742  ObjectIdGetDatum(sourcetypeid),
1743  ObjectIdGetDatum(targettypeid));
1744  if (HeapTupleIsValid(tuple))
1745  ereport(ERROR,
1747  errmsg("cast from type %s to type %s already exists",
1748  format_type_be(sourcetypeid),
1749  format_type_be(targettypeid))));
1750 
1751  /* ready to go */
1752  castid = GetNewOidWithIndex(relation, CastOidIndexId, Anum_pg_cast_oid);
1753  values[Anum_pg_cast_oid - 1] = ObjectIdGetDatum(castid);
1754  values[Anum_pg_cast_castsource - 1] = ObjectIdGetDatum(sourcetypeid);
1755  values[Anum_pg_cast_casttarget - 1] = ObjectIdGetDatum(targettypeid);
1756  values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid);
1757  values[Anum_pg_cast_castcontext - 1] = CharGetDatum(castcontext);
1758  values[Anum_pg_cast_castmethod - 1] = CharGetDatum(castmethod);
1759 
1760  MemSet(nulls, false, sizeof(nulls));
1761 
1762  tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
1763 
1764  CatalogTupleInsert(relation, tuple);
1765 
1766  /* make dependency entries */
1767  myself.classId = CastRelationId;
1768  myself.objectId = castid;
1769  myself.objectSubId = 0;
1770 
1771  /* dependency on source type */
1772  referenced.classId = TypeRelationId;
1773  referenced.objectId = sourcetypeid;
1774  referenced.objectSubId = 0;
1775  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1776 
1777  /* dependency on target type */
1778  referenced.classId = TypeRelationId;
1779  referenced.objectId = targettypeid;
1780  referenced.objectSubId = 0;
1781  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1782 
1783  /* dependency on function */
1784  if (OidIsValid(funcid))
1785  {
1786  referenced.classId = ProcedureRelationId;
1787  referenced.objectId = funcid;
1788  referenced.objectSubId = 0;
1789  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1790  }
1791 
1792  /* dependency on extension */
1793  recordDependencyOnCurrentExtension(&myself, false);
1794 
1795  /* Post creation hook for new cast */
1796  InvokeObjectPostCreateHook(CastRelationId, castid, 0);
1797 
1798  heap_freetuple(tuple);
1799 
1800  table_close(relation, RowExclusiveLock);
1801 
1802  return myself;
1803 }
signed short int16
Definition: c.h:345
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:323
TypeName * sourcetype
Definition: parsenodes.h:3359
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
#define RelationGetDescr(relation)
Definition: rel.h:445
Oid GetUserId(void)
Definition: miscinit.c:380
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2526
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2049
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:477
int errcode(int sqlerrcode)
Definition: elog.c:570
bool superuser(void)
Definition: superuser.c:47
char get_typtype(Oid typid)
Definition: lsyscache.c:2407
#define MemSet(start, val, len)
Definition: c.h:955
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
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:4781
#define OidIsValid(objectId)
Definition: c.h:638
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3666
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
CoercionContext context
Definition: parsenodes.h:3362
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CastOidIndexId
Definition: indexing.h:109
#define ACL_USAGE
Definition: parsenodes.h:82
#define ereport(elevel, rest)
Definition: elog.h:141
bool IsBinaryCoercible(Oid srctype, Oid targettype)
#define WARNING
Definition: elog.h:40
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
ObjectWithArgs * func
Definition: parsenodes.h:3361
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:134
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:138
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1135
#define CharGetDatum(X)
Definition: postgres.h:416
static Datum values[MAXATTR]
Definition: bootstrap.c:167
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define elog(elevel,...)
Definition: elog.h:226
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2160
TypeName * targettype
Definition: parsenodes.h:3360
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4743
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:33
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:292

◆ CreateFunction()

ObjectAddress CreateFunction ( ParseState pstate,
CreateFunctionStmt stmt 
)

Definition at line 920 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, 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(), PLTemplateExists(), PointerGetDatum, ProcedureCreate(), QualifiedNameGetCreationNamespace(), ReleaseSysCache(), CreateFunctionStmt::replace, CreateFunctionStmt::returnType, SearchSysCache1(), superuser(), and typenameTypeId().

Referenced by ProcessUtilitySlow().

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

◆ CreateTransform()

ObjectAddress CreateTransform ( CreateTransformStmt stmt)

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

1887 {
1888  Oid typeid;
1889  char typtype;
1890  Oid langid;
1891  Oid fromsqlfuncid;
1892  Oid tosqlfuncid;
1893  AclResult aclresult;
1894  Form_pg_proc procstruct;
1895  Datum values[Natts_pg_transform];
1896  bool nulls[Natts_pg_transform];
1897  bool replaces[Natts_pg_transform];
1898  Oid transformid;
1899  HeapTuple tuple;
1900  HeapTuple newtuple;
1901  Relation relation;
1902  ObjectAddress myself,
1903  referenced;
1904  bool is_replace;
1905 
1906  /*
1907  * Get the type
1908  */
1909  typeid = typenameTypeId(NULL, stmt->type_name);
1910  typtype = get_typtype(typeid);
1911 
1912  if (typtype == TYPTYPE_PSEUDO)
1913  ereport(ERROR,
1914  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1915  errmsg("data type %s is a pseudo-type",
1916  TypeNameToString(stmt->type_name))));
1917 
1918  if (typtype == TYPTYPE_DOMAIN)
1919  ereport(ERROR,
1920  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1921  errmsg("data type %s is a domain",
1922  TypeNameToString(stmt->type_name))));
1923 
1924  if (!pg_type_ownercheck(typeid, GetUserId()))
1926 
1927  aclresult = pg_type_aclcheck(typeid, GetUserId(), ACL_USAGE);
1928  if (aclresult != ACLCHECK_OK)
1929  aclcheck_error_type(aclresult, typeid);
1930 
1931  /*
1932  * Get the language
1933  */
1934  langid = get_language_oid(stmt->lang, false);
1935 
1936  aclresult = pg_language_aclcheck(langid, GetUserId(), ACL_USAGE);
1937  if (aclresult != ACLCHECK_OK)
1938  aclcheck_error(aclresult, OBJECT_LANGUAGE, stmt->lang);
1939 
1940  /*
1941  * Get the functions
1942  */
1943  if (stmt->fromsql)
1944  {
1945  fromsqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->fromsql, false);
1946 
1947  if (!pg_proc_ownercheck(fromsqlfuncid, GetUserId()))
1949 
1950  aclresult = pg_proc_aclcheck(fromsqlfuncid, GetUserId(), ACL_EXECUTE);
1951  if (aclresult != ACLCHECK_OK)
1953 
1954  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fromsqlfuncid));
1955  if (!HeapTupleIsValid(tuple))
1956  elog(ERROR, "cache lookup failed for function %u", fromsqlfuncid);
1957  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1958  if (procstruct->prorettype != INTERNALOID)
1959  ereport(ERROR,
1960  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1961  errmsg("return data type of FROM SQL function must be %s",
1962  "internal")));
1963  check_transform_function(procstruct);
1964  ReleaseSysCache(tuple);
1965  }
1966  else
1967  fromsqlfuncid = InvalidOid;
1968 
1969  if (stmt->tosql)
1970  {
1971  tosqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->tosql, false);
1972 
1973  if (!pg_proc_ownercheck(tosqlfuncid, GetUserId()))
1975 
1976  aclresult = pg_proc_aclcheck(tosqlfuncid, GetUserId(), ACL_EXECUTE);
1977  if (aclresult != ACLCHECK_OK)
1979 
1980  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(tosqlfuncid));
1981  if (!HeapTupleIsValid(tuple))
1982  elog(ERROR, "cache lookup failed for function %u", tosqlfuncid);
1983  procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1984  if (procstruct->prorettype != typeid)
1985  ereport(ERROR,
1986  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1987  errmsg("return data type of TO SQL function must be the transform data type")));
1988  check_transform_function(procstruct);
1989  ReleaseSysCache(tuple);
1990  }
1991  else
1992  tosqlfuncid = InvalidOid;
1993 
1994  /*
1995  * Ready to go
1996  */
1997  values[Anum_pg_transform_trftype - 1] = ObjectIdGetDatum(typeid);
1998  values[Anum_pg_transform_trflang - 1] = ObjectIdGetDatum(langid);
1999  values[Anum_pg_transform_trffromsql - 1] = ObjectIdGetDatum(fromsqlfuncid);
2000  values[Anum_pg_transform_trftosql - 1] = ObjectIdGetDatum(tosqlfuncid);
2001 
2002  MemSet(nulls, false, sizeof(nulls));
2003 
2004  relation = table_open(TransformRelationId, RowExclusiveLock);
2005 
2006  tuple = SearchSysCache2(TRFTYPELANG,
2007  ObjectIdGetDatum(typeid),
2008  ObjectIdGetDatum(langid));
2009  if (HeapTupleIsValid(tuple))
2010  {
2012 
2013  if (!stmt->replace)
2014  ereport(ERROR,
2016  errmsg("transform for type %s language \"%s\" already exists",
2017  format_type_be(typeid),
2018  stmt->lang)));
2019 
2020  MemSet(replaces, false, sizeof(replaces));
2021  replaces[Anum_pg_transform_trffromsql - 1] = true;
2022  replaces[Anum_pg_transform_trftosql - 1] = true;
2023 
2024  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
2025  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2026 
2027  transformid = form->oid;
2028  ReleaseSysCache(tuple);
2029  is_replace = true;
2030  }
2031  else
2032  {
2033  transformid = GetNewOidWithIndex(relation, TransformOidIndexId,
2034  Anum_pg_transform_oid);
2035  values[Anum_pg_transform_oid - 1] = ObjectIdGetDatum(transformid);
2036  newtuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
2037  CatalogTupleInsert(relation, newtuple);
2038  is_replace = false;
2039  }
2040 
2041  if (is_replace)
2042  deleteDependencyRecordsFor(TransformRelationId, transformid, true);
2043 
2044  /* make dependency entries */
2045  myself.classId = TransformRelationId;
2046  myself.objectId = transformid;
2047  myself.objectSubId = 0;
2048 
2049  /* dependency on language */
2050  referenced.classId = LanguageRelationId;
2051  referenced.objectId = langid;
2052  referenced.objectSubId = 0;
2053  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
2054 
2055  /* dependency on type */
2056  referenced.classId = TypeRelationId;
2057  referenced.objectId = typeid;
2058  referenced.objectSubId = 0;
2059  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
2060 
2061  /* dependencies on functions */
2062  if (OidIsValid(fromsqlfuncid))
2063  {
2064  referenced.classId = ProcedureRelationId;
2065  referenced.objectId = fromsqlfuncid;
2066  referenced.objectSubId = 0;
2067  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
2068  }
2069  if (OidIsValid(tosqlfuncid))
2070  {
2071  referenced.classId = ProcedureRelationId;
2072  referenced.objectId = tosqlfuncid;
2073  referenced.objectSubId = 0;
2074  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
2075  }
2076 
2077  /* dependency on extension */
2078  recordDependencyOnCurrentExtension(&myself, is_replace);
2079 
2080  /* Post creation hook for new transform */
2081  InvokeObjectPostCreateHook(TransformRelationId, transformid, 0);
2082 
2083  heap_freetuple(newtuple);
2084 
2085  table_close(relation, RowExclusiveLock);
2086 
2087  return myself;
2088 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:323
ObjectWithArgs * tosql
Definition: parsenodes.h:3377
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:145
#define RelationGetDescr(relation)
Definition: rel.h:445
Oid GetUserId(void)
Definition: miscinit.c:380
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:477
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:559
int errcode(int sqlerrcode)
Definition: elog.c:570
char get_typtype(Oid typid)
Definition: lsyscache.c:2407
#define MemSet(start, val, len)
Definition: c.h:955
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
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:4781
#define OidIsValid(objectId)
Definition: c.h:638
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4667
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3666
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3353
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:249
#define ACL_USAGE
Definition: parsenodes.h:82
#define ereport(elevel, rest)
Definition: elog.h:141
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
char * NameListToString(List *names)
Definition: namespace.c:3094
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:134
#define InvalidOid
Definition: postgres_ext.h:36
ObjectWithArgs * fromsql
Definition: parsenodes.h:3376
#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:1135
TypeName * type_name
Definition: parsenodes.h:3374
static Datum values[MAXATTR]
Definition: bootstrap.c:167
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define ACL_EXECUTE
Definition: parsenodes.h:81
#define elog(elevel,...)
Definition: elog.h:226
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4655
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2160
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4743
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:33
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183
bool pg_proc_ownercheck(Oid proc_oid, Oid roleid)
Definition: aclchk.c:4833
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:292

◆ DropCastById()

void DropCastById ( Oid  castOid)

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

1830 {
1831  Relation relation;
1832  ScanKeyData scankey;
1833  SysScanDesc scan;
1834  HeapTuple tuple;
1835 
1836  relation = table_open(CastRelationId, RowExclusiveLock);
1837 
1838  ScanKeyInit(&scankey,
1839  Anum_pg_cast_oid,
1840  BTEqualStrategyNumber, F_OIDEQ,
1841  ObjectIdGetDatum(castOid));
1842  scan = systable_beginscan(relation, CastOidIndexId, true,
1843  NULL, 1, &scankey);
1844 
1845  tuple = systable_getnext(scan);
1846  if (!HeapTupleIsValid(tuple))
1847  elog(ERROR, "could not find tuple for cast %u", castOid);
1848  CatalogTupleDelete(relation, &tuple->t_self);
1849 
1850  systable_endscan(scan);
1851  table_close(relation, RowExclusiveLock);
1852 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
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:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#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:226
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 2116 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().

2117 {
2118  Relation relation;
2119  ScanKeyData scankey;
2120  SysScanDesc scan;
2121  HeapTuple tuple;
2122 
2123  relation = table_open(TransformRelationId, RowExclusiveLock);
2124 
2125  ScanKeyInit(&scankey,
2126  Anum_pg_transform_oid,
2127  BTEqualStrategyNumber, F_OIDEQ,
2128  ObjectIdGetDatum(transformOid));
2129  scan = systable_beginscan(relation, TransformOidIndexId, true,
2130  NULL, 1, &scankey);
2131 
2132  tuple = systable_getnext(scan);
2133  if (!HeapTupleIsValid(tuple))
2134  elog(ERROR, "could not find tuple for transform %u", transformOid);
2135  CatalogTupleDelete(relation, &tuple->t_self);
2136 
2137  systable_endscan(scan);
2138  table_close(relation, RowExclusiveLock);
2139 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
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:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#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:249
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:226
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 2298 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().

2299 {
2300  LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
2301  ListCell *lc;
2302  FuncExpr *fexpr;
2303  int nargs;
2304  int i;
2305  AclResult aclresult;
2306  FmgrInfo flinfo;
2307  CallContext *callcontext;
2308  EState *estate;
2309  ExprContext *econtext;
2310  HeapTuple tp;
2311  PgStat_FunctionCallUsage fcusage;
2312  Datum retval;
2313 
2314  fexpr = stmt->funcexpr;
2315  Assert(fexpr);
2316  Assert(IsA(fexpr, FuncExpr));
2317 
2318  aclresult = pg_proc_aclcheck(fexpr->funcid, GetUserId(), ACL_EXECUTE);
2319  if (aclresult != ACLCHECK_OK)
2320  aclcheck_error(aclresult, OBJECT_PROCEDURE, get_func_name(fexpr->funcid));
2321 
2322  /* Prep the context object we'll pass to the procedure */
2323  callcontext = makeNode(CallContext);
2324  callcontext->atomic = atomic;
2325 
2327  if (!HeapTupleIsValid(tp))
2328  elog(ERROR, "cache lookup failed for function %u", fexpr->funcid);
2329 
2330  /*
2331  * If proconfig is set we can't allow transaction commands because of the
2332  * way the GUC stacking works: The transaction boundary would have to pop
2333  * the proconfig setting off the stack. That restriction could be lifted
2334  * by redesigning the GUC nesting mechanism a bit.
2335  */
2336  if (!heap_attisnull(tp, Anum_pg_proc_proconfig, NULL))
2337  callcontext->atomic = true;
2338 
2339  /*
2340  * In security definer procedures, we can't allow transaction commands.
2341  * StartTransaction() insists that the security context stack is empty,
2342  * and AbortTransaction() resets the security context. This could be
2343  * reorganized, but right now it doesn't work.
2344  */
2345  if (((Form_pg_proc) GETSTRUCT(tp))->prosecdef)
2346  callcontext->atomic = true;
2347 
2348  /*
2349  * Expand named arguments, defaults, etc. We do not want to scribble on
2350  * the passed-in CallStmt parse tree, so first flat-copy fexpr, allowing
2351  * us to replace its args field. (Note that expand_function_arguments
2352  * will not modify any of the passed-in data structure.)
2353  */
2354  {
2355  FuncExpr *nexpr = makeNode(FuncExpr);
2356 
2357  memcpy(nexpr, fexpr, sizeof(FuncExpr));
2358  fexpr = nexpr;
2359  }
2360 
2361  fexpr->args = expand_function_arguments(fexpr->args,
2362  fexpr->funcresulttype,
2363  tp);
2364  nargs = list_length(fexpr->args);
2365 
2366  ReleaseSysCache(tp);
2367 
2368  /* safety check; see ExecInitFunc() */
2369  if (nargs > FUNC_MAX_ARGS)
2370  ereport(ERROR,
2371  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2372  errmsg_plural("cannot pass more than %d argument to a procedure",
2373  "cannot pass more than %d arguments to a procedure",
2374  FUNC_MAX_ARGS,
2375  FUNC_MAX_ARGS)));
2376 
2377  /* Initialize function call structure */
2379  fmgr_info(fexpr->funcid, &flinfo);
2380  fmgr_info_set_expr((Node *) fexpr, &flinfo);
2381  InitFunctionCallInfoData(*fcinfo, &flinfo, nargs, fexpr->inputcollid,
2382  (Node *) callcontext, NULL);
2383 
2384  /*
2385  * Evaluate procedure arguments inside a suitable execution context. Note
2386  * we can't free this context till the procedure returns.
2387  */
2388  estate = CreateExecutorState();
2389  estate->es_param_list_info = params;
2390  econtext = CreateExprContext(estate);
2391 
2392  i = 0;
2393  foreach(lc, fexpr->args)
2394  {
2395  ExprState *exprstate;
2396  Datum val;
2397  bool isnull;
2398 
2399  exprstate = ExecPrepareExpr(lfirst(lc), estate);
2400 
2401  val = ExecEvalExprSwitchContext(exprstate, econtext, &isnull);
2402 
2403  fcinfo->args[i].value = val;
2404  fcinfo->args[i].isnull = isnull;
2405 
2406  i++;
2407  }
2408 
2409  pgstat_init_function_usage(fcinfo, &fcusage);
2410  retval = FunctionCallInvoke(fcinfo);
2411  pgstat_end_function_usage(&fcusage, true);
2412 
2413  if (fexpr->funcresulttype == VOIDOID)
2414  {
2415  /* do nothing */
2416  }
2417  else if (fexpr->funcresulttype == RECORDOID)
2418  {
2419  /*
2420  * send tuple to client
2421  */
2422 
2423  HeapTupleHeader td;
2424  Oid tupType;
2425  int32 tupTypmod;
2426  TupleDesc retdesc;
2427  HeapTupleData rettupdata;
2428  TupOutputState *tstate;
2429  TupleTableSlot *slot;
2430 
2431  if (fcinfo->isnull)
2432  elog(ERROR, "procedure returned null record");
2433 
2434  td = DatumGetHeapTupleHeader(retval);
2435  tupType = HeapTupleHeaderGetTypeId(td);
2436  tupTypmod = HeapTupleHeaderGetTypMod(td);
2437  retdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
2438 
2439  tstate = begin_tup_output_tupdesc(dest, retdesc,
2440  &TTSOpsHeapTuple);
2441 
2442  rettupdata.t_len = HeapTupleHeaderGetDatumLength(td);
2443  ItemPointerSetInvalid(&(rettupdata.t_self));
2444  rettupdata.t_tableOid = InvalidOid;
2445  rettupdata.t_data = td;
2446 
2447  slot = ExecStoreHeapTuple(&rettupdata, tstate->slot, false);
2448  tstate->dest->receiveSlot(slot, tstate->dest);
2449 
2450  end_tup_output(tstate);
2451 
2452  ReleaseTupleDesc(retdesc);
2453  }
2454  else
2455  elog(ERROR, "unexpected result type for procedure: %u",
2456  fexpr->funcresulttype);
2457 
2458  FreeExecutorState(estate);
2459 }
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h:118
Oid funcresulttype
Definition: primnodes.h:456
Definition: fmgr.h:56
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:300
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
List * expand_function_arguments(List *args, Oid result_type, HeapTuple func_tuple)
Definition: clauses.c:4048
List * args
Definition: primnodes.h:463
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1652
FuncExpr * funcexpr
Definition: parsenodes.h:2875
Oid GetUserId(void)
Definition: miscinit.c:380
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:837
Definition: nodes.h:525
int errcode(int sqlerrcode)
Definition: elog.c:570
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
TupleTableSlot * slot
Definition: executor.h:458
unsigned int Oid
Definition: postgres_ext.h:31
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition: execExpr.c:490
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:289
signed int int32
Definition: c.h:346
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:3353
void end_tup_output(TupOutputState *tstate)
Definition: execTuples.c:2310
Oid funcid
Definition: primnodes.h:455
#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:1622
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1410
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:124
TupOutputState * begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:2232
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
#define ereport(elevel, rest)
Definition: elog.h:141
EState * CreateExecutorState(void)
Definition: execUtils.c:88
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:179
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:458
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:134
#define InvalidOid
Definition: postgres_ext.h:36
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define makeNode(_type_)
Definition: nodes.h:573
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
Oid inputcollid
Definition: primnodes.h:462
#define Assert(condition)
Definition: c.h:732
#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:1694
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:172
#define ACL_EXECUTE
Definition: parsenodes.h:81
#define elog(elevel,...)
Definition: elog.h:226
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4655
int i
const TupleTableSlotOps TTSOpsHeapTuple
Definition: execTuples.c:85
ExprContext * CreateExprContext(EState *estate)
Definition: execUtils.c:244
ParamListInfo es_param_list_info
Definition: execnodes.h:544
DestReceiver * dest
Definition: executor.h:459
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:122
long val
Definition: informix.c:684
TupleTableSlot * ExecStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:1317
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:452

◆ ExecuteDoStmt()

void ExecuteDoStmt ( DoStmt stmt,
bool  atomic 
)

Definition at line 2172 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, GETSTRUCT, GetUserId(), HeapTupleIsValid, InlineCodeBlock::langIsTrusted, LANGNAME, InlineCodeBlock::langOid, lfirst, makeNode, NameStr, OBJECT_LANGUAGE, OidFunctionCall1, OidIsValid, pg_language_aclcheck(), PLTemplateExists(), PointerGetDatum, ReleaseSysCache(), SearchSysCache1(), InlineCodeBlock::source_text, strVal, and superuser().

Referenced by standard_ProcessUtility().

2173 {
2175  ListCell *arg;
2176  DefElem *as_item = NULL;
2177  DefElem *language_item = NULL;
2178  char *language;
2179  Oid laninline;
2180  HeapTuple languageTuple;
2181  Form_pg_language languageStruct;
2182 
2183  /* Process options we got from gram.y */
2184  foreach(arg, stmt->args)
2185  {
2186  DefElem *defel = (DefElem *) lfirst(arg);
2187 
2188  if (strcmp(defel->defname, "as") == 0)
2189  {
2190  if (as_item)
2191  ereport(ERROR,
2192  (errcode(ERRCODE_SYNTAX_ERROR),
2193  errmsg("conflicting or redundant options")));
2194  as_item = defel;
2195  }
2196  else if (strcmp(defel->defname, "language") == 0)
2197  {
2198  if (language_item)
2199  ereport(ERROR,
2200  (errcode(ERRCODE_SYNTAX_ERROR),
2201  errmsg("conflicting or redundant options")));
2202  language_item = defel;
2203  }
2204  else
2205  elog(ERROR, "option \"%s\" not recognized",
2206  defel->defname);
2207  }
2208 
2209  if (as_item)
2210  codeblock->source_text = strVal(as_item->arg);
2211  else
2212  ereport(ERROR,
2213  (errcode(ERRCODE_SYNTAX_ERROR),
2214  errmsg("no inline code specified")));
2215 
2216  /* if LANGUAGE option wasn't specified, use the default */
2217  if (language_item)
2218  language = strVal(language_item->arg);
2219  else
2220  language = "plpgsql";
2221 
2222  /* Look up the language and validate permissions */
2223  languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
2224  if (!HeapTupleIsValid(languageTuple))
2225  ereport(ERROR,
2226  (errcode(ERRCODE_UNDEFINED_OBJECT),
2227  errmsg("language \"%s\" does not exist", language),
2228  (PLTemplateExists(language) ?
2229  errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
2230 
2231  languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
2232  codeblock->langOid = languageStruct->oid;
2233  codeblock->langIsTrusted = languageStruct->lanpltrusted;
2234  codeblock->atomic = atomic;
2235 
2236  if (languageStruct->lanpltrusted)
2237  {
2238  /* if trusted language, need USAGE privilege */
2239  AclResult aclresult;
2240 
2241  aclresult = pg_language_aclcheck(codeblock->langOid, GetUserId(),
2242  ACL_USAGE);
2243  if (aclresult != ACLCHECK_OK)
2244  aclcheck_error(aclresult, OBJECT_LANGUAGE,
2245  NameStr(languageStruct->lanname));
2246  }
2247  else
2248  {
2249  /* if untrusted language, must be superuser */
2250  if (!superuser())
2252  NameStr(languageStruct->lanname));
2253  }
2254 
2255  /* get the handler function's OID */
2256  laninline = languageStruct->laninline;
2257  if (!OidIsValid(laninline))
2258  ereport(ERROR,
2259  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2260  errmsg("language \"%s\" does not support inline code execution",
2261  NameStr(languageStruct->lanname))));
2262 
2263  ReleaseSysCache(languageTuple);
2264 
2265  /* execute the inline handler */
2266  OidFunctionCall1(laninline, PointerGetDatum(codeblock));
2267 }
int errhint(const char *fmt,...)
Definition: elog.c:974
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Oid GetUserId(void)
Definition: miscinit.c:380
#define PointerGetDatum(X)
Definition: postgres.h:556
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:570
bool superuser(void)
Definition: superuser.c:47
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4667
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3353
#define ERROR
Definition: elog.h:43
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:655
#define ACL_USAGE
Definition: parsenodes.h:82
#define ereport(elevel, rest)
Definition: elog.h:141
Node * arg
Definition: parsenodes.h:731
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
AclResult
Definition: acl.h:177
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
bool PLTemplateExists(const char *languageName)
Definition: proclang.c:525
#define makeNode(_type_)
Definition: nodes.h:573
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:190
List * args
Definition: parsenodes.h:2855
FormData_pg_language * Form_pg_language
Definition: pg_language.h:65
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define elog(elevel,...)
Definition: elog.h:226
#define NameStr(name)
Definition: c.h:609
void * arg
char * source_text
Definition: parsenodes.h:2861
char * defname
Definition: parsenodes.h:730

◆ get_cast_oid()

Oid get_cast_oid ( Oid  sourcetypeid,
Oid  targettypeid,
bool  missing_ok 
)

Definition at line 1812 of file functioncmds.c.

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

Referenced by get_object_address().

1813 {
1814  Oid oid;
1815 
1816  oid = GetSysCacheOid2(CASTSOURCETARGET, Anum_pg_cast_oid,
1817  ObjectIdGetDatum(sourcetypeid),
1818  ObjectIdGetDatum(targettypeid));
1819  if (!OidIsValid(oid) && !missing_ok)
1820  ereport(ERROR,
1821  (errcode(ERRCODE_UNDEFINED_OBJECT),
1822  errmsg("cast from type %s to type %s does not exist",
1823  format_type_be(sourcetypeid),
1824  format_type_be(targettypeid))));
1825  return oid;
1826 }
int errcode(int sqlerrcode)
Definition: elog.c:570
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:194
int errmsg(const char *fmt,...)
Definition: elog.c:784

◆ get_transform_oid()

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

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

2099 {
2100  Oid oid;
2101 
2102  oid = GetSysCacheOid2(TRFTYPELANG, Anum_pg_transform_oid,
2103  ObjectIdGetDatum(type_id),
2104  ObjectIdGetDatum(lang_id));
2105  if (!OidIsValid(oid) && !missing_ok)
2106  ereport(ERROR,
2107  (errcode(ERRCODE_UNDEFINED_OBJECT),
2108  errmsg("transform for type %s language \"%s\" does not exist",
2109  format_type_be(type_id),
2110  get_language_name(lang_id, false))));
2111  return oid;
2112 }
char * get_language_name(Oid langoid, bool missing_ok)
Definition: lsyscache.c:990
int errcode(int sqlerrcode)
Definition: elog.c:570
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:194
int errmsg(const char *fmt,...)
Definition: elog.c:784

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

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

Referenced by CreateFunction().

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

◆ interpret_func_parallel()

static char interpret_func_parallel ( DefElem defel)
static

Definition at line 599 of file functioncmds.c.

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

Referenced by AlterFunction(), and compute_function_attributes().

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

◆ interpret_func_support()

static Oid interpret_func_support ( DefElem defel)
static

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

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

◆ interpret_func_volatility()

static char interpret_func_volatility ( DefElem defel)
static

Definition at line 581 of file functioncmds.c.

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

Referenced by AlterFunction(), and compute_function_attributes().

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

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

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

◆ IsThereFunctionInNamespace()

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

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

2151 {
2152  /* check for duplicate name (more friendly than unique-index failure) */
2155  PointerGetDatum(proargtypes),
2156  ObjectIdGetDatum(nspOid)))
2157  ereport(ERROR,
2158  (errcode(ERRCODE_DUPLICATE_FUNCTION),
2159  errmsg("function %s already exists in schema \"%s\"",
2161  NIL, proargtypes->values),
2162  get_namespace_name(nspOid))));
2163 }
#define NIL
Definition: pg_list.h:65
NameData proname
Definition: pg_proc.h:36
#define PointerGetDatum(X)
Definition: postgres.h:556
int errcode(int sqlerrcode)
Definition: elog.c:570
int16 pronargs
Definition: pg_proc.h:82
#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:3094
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:596
#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:1977
#define ereport(elevel, rest)
Definition: elog.h:141
int errmsg(const char *fmt,...)
Definition: elog.c:784

◆ RemoveFunctionById()

void RemoveFunctionById ( Oid  funcOid)

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

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

◆ SetFunctionArgType()

void SetFunctionArgType ( Oid  funcOid,
int  argIndex,
Oid  newArgType 
)

Definition at line 1451 of file functioncmds.c.

References CatalogTupleUpdate(), DEPENDENCY_NORMAL, elog, ERROR, GETSTRUCT, HeapTupleIsValid, ObjectAddressSet, ObjectIdGetDatum, PROCOID, recordDependencyOn(), RowExclusiveLock, SearchSysCacheCopy1, HeapTupleData::t_self, table_close(), and table_open().

Referenced by findTypeInputFunction(), and findTypeOutputFunction().

1452 {
1453  Relation pg_proc_rel;
1454  HeapTuple tup;
1455  Form_pg_proc procForm;
1456  ObjectAddress func_address;
1457  ObjectAddress type_address;
1458 
1459  pg_proc_rel = table_open(ProcedureRelationId, RowExclusiveLock);
1460 
1461  tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1462  if (!HeapTupleIsValid(tup)) /* should not happen */
1463  elog(ERROR, "cache lookup failed for function %u", funcOid);
1464  procForm = (Form_pg_proc) GETSTRUCT(tup);
1465 
1466  if (argIndex < 0 || argIndex >= procForm->pronargs ||
1467  procForm->proargtypes.values[argIndex] != OPAQUEOID)
1468  elog(ERROR, "function %u doesn't take OPAQUE", funcOid);
1469 
1470  /* okay to overwrite copied tuple */
1471  procForm->proargtypes.values[argIndex] = newArgType;
1472 
1473  /* update the catalog and its indexes */
1474  CatalogTupleUpdate(pg_proc_rel, &tup->t_self, tup);
1475 
1476  table_close(pg_proc_rel, RowExclusiveLock);
1477 
1478  /*
1479  * Also update the dependency to the new type. Opaque is a pinned type, so
1480  * there is no old dependency record for it that we would need to remove.
1481  */
1482  ObjectAddressSet(type_address, TypeRelationId, newArgType);
1483  ObjectAddressSet(func_address, ProcedureRelationId, funcOid);
1484  recordDependencyOn(&func_address, &type_address, DEPENDENCY_NORMAL);
1485 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c: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
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:134
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
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 elog(elevel,...)
Definition: elog.h:226
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ SetFunctionReturnType()

void SetFunctionReturnType ( Oid  funcOid,
Oid  newRetType 
)

Definition at line 1409 of file functioncmds.c.

References CatalogTupleUpdate(), DEPENDENCY_NORMAL, elog, ERROR, GETSTRUCT, HeapTupleIsValid, ObjectAddressSet, ObjectIdGetDatum, PROCOID, recordDependencyOn(), RowExclusiveLock, SearchSysCacheCopy1, HeapTupleData::t_self, table_close(), and table_open().

Referenced by CreateProceduralLanguage(), CreateTrigger(), and DefineType().

1410 {
1411  Relation pg_proc_rel;
1412  HeapTuple tup;
1413  Form_pg_proc procForm;
1414  ObjectAddress func_address;
1415  ObjectAddress type_address;
1416 
1417  pg_proc_rel = table_open(ProcedureRelationId, RowExclusiveLock);
1418 
1419  tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1420  if (!HeapTupleIsValid(tup)) /* should not happen */
1421  elog(ERROR, "cache lookup failed for function %u", funcOid);
1422  procForm = (Form_pg_proc) GETSTRUCT(tup);
1423 
1424  if (procForm->prorettype != OPAQUEOID) /* caller messed up */
1425  elog(ERROR, "function %u doesn't return OPAQUE", funcOid);
1426 
1427  /* okay to overwrite copied tuple */
1428  procForm->prorettype = newRetType;
1429 
1430  /* update the catalog and its indexes */
1431  CatalogTupleUpdate(pg_proc_rel, &tup->t_self, tup);
1432 
1433  table_close(pg_proc_rel, RowExclusiveLock);
1434 
1435  /*
1436  * Also update the dependency to the new type. Opaque is a pinned type, so
1437  * there is no old dependency record for it that we would need to remove.
1438  */
1439  ObjectAddressSet(type_address, TypeRelationId, newRetType);
1440  ObjectAddressSet(func_address, ProcedureRelationId, funcOid);
1441  recordDependencyOn(&func_address, &type_address, DEPENDENCY_NORMAL);
1442 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c: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
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:134
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
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 elog(elevel,...)
Definition: elog.h:226
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 624 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().

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