PostgreSQL Source Code git master
Loading...
Searching...
No Matches
functioncmds.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/table.h"
#include "access/xact.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/defrem.h"
#include "commands/extension.h"
#include "commands/proclang.h"
#include "executor/executor.h"
#include "executor/functions.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/optimizer.h"
#include "parser/analyze.h"
#include "parser/parse_coerce.h"
#include "parser/parse_collate.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h"
#include "parser/parse_type.h"
#include "pgstat.h"
#include "tcop/pquery.h"
#include "tcop/utility.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
Include dependency graph for functioncmds.c:

Go to the source code of this file.

Functions

static void compute_return_type (TypeName *returnType, Oid languageOid, Oid *prorettype_p, bool *returnsSet_p)
 
void interpret_function_parameter_list (ParseState *pstate, List *parameters, Oid languageOid, ObjectType objtype, oidvector **parameterTypes, List **parameterTypes_list, ArrayType **allParameterTypes, ArrayType **parameterModes, ArrayType **parameterNames, List **inParameterNames_list, List **parameterDefaults, Oid *variadicArgType, Oid *requiredResultType)
 
static bool compute_common_attribute (ParseState *pstate, bool is_procedure, DefElem *defel, DefElem **volatility_item, DefElem **strict_item, DefElem **security_item, DefElem **leakproof_item, List **set_items, DefElem **cost_item, DefElem **rows_item, DefElem **support_item, DefElem **parallel_item)
 
static char interpret_func_volatility (DefElem *defel)
 
static char interpret_func_parallel (DefElem *defel)
 
static ArrayTypeupdate_proconfig_value (ArrayType *a, List *set_items)
 
static Oid interpret_func_support (DefElem *defel)
 
static void compute_function_attributes (ParseState *pstate, bool is_procedure, List *options, List **as, char **language, Node **transform, bool *windowfunc_p, char *volatility_p, bool *strict_p, bool *security_definer, bool *leakproof_p, ArrayType **proconfig, float4 *procost, float4 *prorows, Oid *prosupport, char *parallel_p)
 
static void interpret_AS_clause (Oid languageOid, const char *languageName, char *funcname, List *as, Node *sql_body_in, List *parameterTypes, List *inParameterNames, char **prosrc_str_p, char **probin_str_p, Node **sql_body_out, const char *queryString)
 
ObjectAddress CreateFunction (ParseState *pstate, CreateFunctionStmt *stmt)
 
void RemoveFunctionById (Oid funcOid)
 
ObjectAddress AlterFunction (ParseState *pstate, AlterFunctionStmt *stmt)
 
ObjectAddress CreateCast (CreateCastStmt *stmt)
 
static void check_transform_function (Form_pg_proc procstruct)
 
ObjectAddress CreateTransform (CreateTransformStmt *stmt)
 
Oid get_transform_oid (Oid type_id, Oid lang_id, bool missing_ok)
 
void IsThereFunctionInNamespace (const char *proname, int pronargs, oidvector *proargtypes, Oid nspOid)
 
void ExecuteDoStmt (ParseState *pstate, DoStmt *stmt, bool atomic)
 
void ExecuteCallStmt (CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest)
 
TupleDesc CallStmtResultDesc (CallStmt *stmt)
 

Function Documentation

◆ AlterFunction()

ObjectAddress AlterFunction ( ParseState pstate,
AlterFunctionStmt stmt 
)

Definition at line 1364 of file functioncmds.c.

1365{
1366 HeapTuple tup;
1367 Oid funcOid;
1369 bool is_procedure;
1370 Relation rel;
1371 ListCell *l;
1376 List *set_items = NIL;
1381 ObjectAddress address;
1382
1384
1385 funcOid = LookupFuncWithArgs(stmt->objtype, stmt->func, false);
1386
1387 ObjectAddressSet(address, ProcedureRelationId, funcOid);
1388
1390 if (!HeapTupleIsValid(tup)) /* should not happen */
1391 elog(ERROR, "cache lookup failed for function %u", funcOid);
1392
1394
1395 /* Permission check: must own function */
1398 NameListToString(stmt->func->objname));
1399
1400 if (procForm->prokind == PROKIND_AGGREGATE)
1401 ereport(ERROR,
1403 errmsg("\"%s\" is an aggregate function",
1404 NameListToString(stmt->func->objname))));
1405
1406 is_procedure = (procForm->prokind == PROKIND_PROCEDURE);
1407
1408 /* Examine requested actions. */
1409 foreach(l, stmt->actions)
1410 {
1411 DefElem *defel = (DefElem *) lfirst(l);
1412
1413 if (compute_common_attribute(pstate,
1414 is_procedure,
1415 defel,
1417 &strict_item,
1420 &set_items,
1421 &cost_item,
1422 &rows_item,
1423 &support_item,
1424 &parallel_item) == false)
1425 elog(ERROR, "option \"%s\" not recognized", defel->defname);
1426 }
1427
1428 if (volatility_item)
1430 if (strict_item)
1431 procForm->proisstrict = boolVal(strict_item->arg);
1433 procForm->prosecdef = boolVal(security_def_item->arg);
1434 if (leakproof_item)
1435 {
1436 procForm->proleakproof = boolVal(leakproof_item->arg);
1437 if (procForm->proleakproof && !superuser())
1438 ereport(ERROR,
1440 errmsg("only superuser can define a leakproof function")));
1441 }
1442 if (cost_item)
1443 {
1444 procForm->procost = defGetNumeric(cost_item);
1445 if (procForm->procost <= 0)
1446 ereport(ERROR,
1448 errmsg("COST must be positive")));
1449 }
1450 if (rows_item)
1451 {
1452 procForm->prorows = defGetNumeric(rows_item);
1453 if (procForm->prorows <= 0)
1454 ereport(ERROR,
1456 errmsg("ROWS must be positive")));
1457 if (!procForm->proretset)
1458 ereport(ERROR,
1460 errmsg("ROWS is not applicable when function does not return a set")));
1461 }
1462 if (support_item)
1463 {
1464 /* interpret_func_support handles the privilege check */
1466
1467 /* Add or replace dependency on support function */
1468 if (OidIsValid(procForm->prosupport))
1469 {
1471 ProcedureRelationId, procForm->prosupport,
1472 newsupport) != 1)
1473 elog(ERROR, "could not change support dependency for function %s",
1474 get_func_name(funcOid));
1475 }
1476 else
1477 {
1479
1481 referenced.objectId = newsupport;
1482 referenced.objectSubId = 0;
1484 }
1485
1486 procForm->prosupport = newsupport;
1487 }
1488 if (parallel_item)
1490 if (set_items)
1491 {
1492 Datum datum;
1493 bool isnull;
1494 ArrayType *a;
1498
1499 /* extract existing proconfig setting */
1501 a = isnull ? NULL : DatumGetArrayTypeP(datum);
1502
1503 /* update according to each SET or RESET item, left to right */
1505
1506 /* update the tuple */
1507 memset(repl_repl, false, sizeof(repl_repl));
1509
1510 if (a == NULL)
1511 {
1514 }
1515 else
1516 {
1518 repl_null[Anum_pg_proc_proconfig - 1] = false;
1519 }
1520
1523 }
1524 /* DO NOT put more touches of procForm below here; it's now dangling. */
1525
1526 /* Do the update */
1527 CatalogTupleUpdate(rel, &tup->t_self, tup);
1528
1530
1531 table_close(rel, NoLock);
1533
1534 return address;
1535}
@ ACLCHECK_NOT_OWNER
Definition acl.h:185
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition aclchk.c:2654
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition aclchk.c:4108
#define DatumGetArrayTypeP(X)
Definition array.h:261
#define OidIsValid(objectId)
Definition c.h:800
double defGetNumeric(DefElem *def)
Definition define.c:67
@ DEPENDENCY_NORMAL
Definition dependency.h:33
int errcode(int sqlerrcode)
Definition elog.c:874
int errmsg(const char *fmt,...)
Definition elog.c:1093
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
static Oid interpret_func_support(DefElem *defel)
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 ArrayType * update_proconfig_value(ArrayType *a, List *set_items)
static char interpret_func_parallel(DefElem *defel)
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition heaptuple.c:1210
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1435
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
#define stmt
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
Definition indexing.c:313
int a
Definition isn.c:73
#define NoLock
Definition lockdefs.h:34
#define RowExclusiveLock
Definition lockdefs.h:38
char * get_func_name(Oid funcid)
Definition lsyscache.c:1758
Oid GetUserId(void)
Definition miscinit.c:469
char * NameListToString(const List *names)
Definition namespace.c:3666
#define InvokeObjectPostAlterHook(classId, objectId, subId)
#define ObjectAddressSet(addr, class_id, object_id)
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition pg_depend.c:47
long changeDependencyFor(Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
Definition pg_depend.c:459
#define lfirst(lc)
Definition pg_list.h:172
#define NIL
Definition pg_list.h:68
END_CATALOG_STRUCT typedef FormData_pg_proc * Form_pg_proc
Definition pg_proc.h:140
static Datum PointerGetDatum(const void *X)
Definition postgres.h:352
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:262
uint64_t Datum
Definition postgres.h:70
unsigned int Oid
static int fb(int x)
#define RelationGetDescr(relation)
Definition rel.h:540
Definition pg_list.h:54
bool superuser(void)
Definition superuser.c:47
Datum SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:595
#define SearchSysCacheCopy1(cacheId, key1)
Definition syscache.h:91
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40
#define boolVal(v)
Definition value.h:81

References a, aclcheck_error(), ACLCHECK_NOT_OWNER, boolVal, CatalogTupleUpdate(), changeDependencyFor(), ObjectAddress::classId, compute_common_attribute(), DatumGetArrayTypeP, defGetNumeric(), DEPENDENCY_NORMAL, elog, ereport, errcode(), errmsg(), ERROR, fb(), Form_pg_proc, get_func_name(), GETSTRUCT(), GetUserId(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, interpret_func_parallel(), interpret_func_support(), interpret_func_volatility(), InvokeObjectPostAlterHook, lfirst, LookupFuncWithArgs(), NameListToString(), NIL, NoLock, object_ownercheck(), ObjectAddressSet, ObjectIdGetDatum(), OidIsValid, PointerGetDatum(), recordDependencyOn(), RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy1, stmt, superuser(), SysCacheGetAttr(), table_close(), table_open(), and update_proconfig_value().

Referenced by ProcessUtilitySlow().

◆ CallStmtResultDesc()

TupleDesc CallStmtResultDesc ( CallStmt stmt)

Definition at line 2386 of file functioncmds.c.

2387{
2388 FuncExpr *fexpr;
2389 HeapTuple tuple;
2390 TupleDesc tupdesc;
2391
2392 fexpr = stmt->funcexpr;
2393
2394 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
2395 if (!HeapTupleIsValid(tuple))
2396 elog(ERROR, "cache lookup failed for procedure %u", fexpr->funcid);
2397
2398 tupdesc = build_function_result_tupdesc_t(tuple);
2399
2400 ReleaseSysCache(tuple);
2401
2402 /*
2403 * The result of build_function_result_tupdesc_t has the right column
2404 * names, but it just has the declared output argument types, which is the
2405 * wrong thing in polymorphic cases. Get the correct types by examining
2406 * stmt->outargs. We intentionally keep the atttypmod as -1 and the
2407 * attcollation as the type's default, since that's always the appropriate
2408 * thing for function outputs; there's no point in considering any
2409 * additional info available from outargs. Note that tupdesc is null if
2410 * there are no outargs.
2411 */
2412 if (tupdesc)
2413 {
2414 Assert(tupdesc->natts == list_length(stmt->outargs));
2415 for (int i = 0; i < tupdesc->natts; i++)
2416 {
2418 Node *outarg = (Node *) list_nth(stmt->outargs, i);
2419
2420 TupleDescInitEntry(tupdesc,
2421 i + 1,
2422 NameStr(att->attname),
2424 -1,
2425 0);
2426 }
2427 }
2428
2429 return tupdesc;
2430}
#define NameStr(name)
Definition c.h:777
#define Assert(condition)
Definition c.h:885
TupleDesc build_function_result_tupdesc_t(HeapTuple procTuple)
Definition funcapi.c:1705
int i
Definition isn.c:77
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
FormData_pg_attribute * Form_pg_attribute
static int list_length(const List *l)
Definition pg_list.h:152
static void * list_nth(const List *list, int n)
Definition pg_list.h:299
Definition nodes.h:135
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:264
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:220
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition tupdesc.c:825
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:160

References Assert, build_function_result_tupdesc_t(), elog, ERROR, exprType(), fb(), HeapTupleIsValid, i, list_length(), list_nth(), NameStr, TupleDescData::natts, ObjectIdGetDatum(), ReleaseSysCache(), SearchSysCache1(), stmt, TupleDescAttr(), and TupleDescInitEntry().

Referenced by UtilityTupleDescriptor().

◆ check_transform_function()

static void check_transform_function ( Form_pg_proc  procstruct)
static

Definition at line 1805 of file functioncmds.c.

1806{
1807 if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1808 ereport(ERROR,
1810 errmsg("transform function must not be volatile")));
1811 if (procstruct->prokind != PROKIND_FUNCTION)
1812 ereport(ERROR,
1814 errmsg("transform function must be a normal function")));
1815 if (procstruct->proretset)
1816 ereport(ERROR,
1818 errmsg("transform function must not return a set")));
1819 if (procstruct->pronargs != 1)
1820 ereport(ERROR,
1822 errmsg("transform function must take one argument")));
1823 if (procstruct->proargtypes.values[0] != INTERNALOID)
1824 ereport(ERROR,
1826 errmsg("first argument of transform function must be type %s",
1827 "internal")));
1828}

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

Referenced by CreateTransform().

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

530{
531 if (strcmp(defel->defname, "volatility") == 0)
532 {
533 if (is_procedure)
534 goto procedure_error;
535 if (*volatility_item)
537
539 }
540 else if (strcmp(defel->defname, "strict") == 0)
541 {
542 if (is_procedure)
543 goto procedure_error;
544 if (*strict_item)
546
548 }
549 else if (strcmp(defel->defname, "security") == 0)
550 {
551 if (*security_item)
553
555 }
556 else if (strcmp(defel->defname, "leakproof") == 0)
557 {
558 if (is_procedure)
559 goto procedure_error;
560 if (*leakproof_item)
562
564 }
565 else if (strcmp(defel->defname, "set") == 0)
566 {
567 *set_items = lappend(*set_items, defel->arg);
568 }
569 else if (strcmp(defel->defname, "cost") == 0)
570 {
571 if (is_procedure)
572 goto procedure_error;
573 if (*cost_item)
575
576 *cost_item = defel;
577 }
578 else if (strcmp(defel->defname, "rows") == 0)
579 {
580 if (is_procedure)
581 goto procedure_error;
582 if (*rows_item)
584
585 *rows_item = defel;
586 }
587 else if (strcmp(defel->defname, "support") == 0)
588 {
589 if (is_procedure)
590 goto procedure_error;
591 if (*support_item)
593
595 }
596 else if (strcmp(defel->defname, "parallel") == 0)
597 {
598 if (is_procedure)
599 goto procedure_error;
600 if (*parallel_item)
602
604 }
605 else
606 return false;
607
608 /* Recognized an option */
609 return true;
610
614 errmsg("invalid attribute in procedure definition"),
615 parser_errposition(pstate, defel->location)));
616 return false;
617}
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition define.c:370
List * lappend(List *list, void *datum)
Definition list.c:339
int parser_errposition(ParseState *pstate, int location)
Definition parse_node.c:106

References ereport, errcode(), errmsg(), ERROR, errorConflictingDefElem(), fb(), lappend(), and parser_errposition().

Referenced by AlterFunction(), and compute_function_attributes().

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

748{
758 List *set_items = NIL;
763
764 foreach(option, options)
765 {
767
768 if (strcmp(defel->defname, "as") == 0)
769 {
770 if (as_item)
772 as_item = defel;
773 }
774 else if (strcmp(defel->defname, "language") == 0)
775 {
776 if (language_item)
779 }
780 else if (strcmp(defel->defname, "transform") == 0)
781 {
782 if (transform_item)
785 }
786 else if (strcmp(defel->defname, "window") == 0)
787 {
788 if (windowfunc_item)
790 if (is_procedure)
793 errmsg("invalid attribute in procedure definition"),
794 parser_errposition(pstate, defel->location)));
796 }
797 else if (compute_common_attribute(pstate,
798 is_procedure,
799 defel,
804 &set_items,
805 &cost_item,
806 &rows_item,
809 {
810 /* recognized common option */
811 continue;
812 }
813 else
814 elog(ERROR, "option \"%s\" not recognized",
815 defel->defname);
816 }
817
818 if (as_item)
819 *as = (List *) as_item->arg;
820 if (language_item)
822 if (transform_item)
823 *transform = transform_item->arg;
824 if (windowfunc_item)
826 if (volatility_item)
828 if (strict_item)
830 if (security_item)
832 if (leakproof_item)
834 if (set_items)
836 if (cost_item)
837 {
839 if (*procost <= 0)
842 errmsg("COST must be positive")));
843 }
844 if (rows_item)
845 {
847 if (*prorows <= 0)
850 errmsg("ROWS must be positive")));
851 }
852 if (support_item)
854 if (parallel_item)
856}
#define strVal(v)
Definition value.h:82

References boolVal, compute_common_attribute(), defGetNumeric(), elog, ereport, errcode(), errmsg(), ERROR, errorConflictingDefElem(), fb(), interpret_func_parallel(), interpret_func_support(), interpret_func_volatility(), lfirst, NIL, parser_errposition(), strVal, and update_proconfig_value().

Referenced by CreateFunction().

◆ compute_return_type()

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

Definition at line 89 of file functioncmds.c.

91{
92 Oid rettype;
95
96 typtup = LookupTypeName(NULL, returnType, NULL, false);
97
98 if (typtup)
99 {
101 {
105 errmsg("SQL function cannot return shell type %s",
106 TypeNameToString(returnType))));
107 else
110 errmsg("return type %s is only a shell",
111 TypeNameToString(returnType))));
112 }
113 rettype = typeTypeId(typtup);
115 }
116 else
117 {
118 char *typnam = TypeNameToString(returnType);
120 char *typname;
121 ObjectAddress address;
122
123 /*
124 * Only C-coded functions can be I/O functions. We enforce this
125 * restriction here mainly to prevent littering the catalogs with
126 * shell types due to simple typos in user-defined function
127 * definitions.
128 */
133 errmsg("type \"%s\" does not exist", typnam)));
134
135 /* Reject if there's typmod decoration, too */
136 if (returnType->typmods != NIL)
139 errmsg("type modifier cannot be specified for shell type \"%s\"",
140 typnam)));
141
142 /* Otherwise, go ahead and make a shell type */
145 errmsg("type \"%s\" is not yet defined", typnam),
146 errdetail("Creating a shell type definition.")));
148 &typname);
150 ACL_CREATE);
151 if (aclresult != ACLCHECK_OK)
155 rettype = address.objectId;
156 Assert(OidIsValid(rettype));
157 /* Ensure the new shell type is visible to ProcedureCreate */
159 }
160
162 if (aclresult != ACLCHECK_OK)
164
165 *prorettype_p = rettype;
166 *returnsSet_p = returnType->setof;
167}
AclResult
Definition acl.h:182
@ ACLCHECK_OK
Definition acl.h:183
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition aclchk.c:3854
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition aclchk.c:2973
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define NOTICE
Definition elog.h:35
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3518
Oid QualifiedNameGetCreationNamespace(const List *names, char **objname_p)
Definition namespace.c:3559
char * TypeNameToString(const TypeName *typeName)
Definition parse_type.c:478
Type LookupTypeName(ParseState *pstate, const TypeName *typeName, int32 *typmod_p, bool missing_ok)
Definition parse_type.c:38
Oid typeTypeId(Type tp)
Definition parse_type.c:590
#define ACL_USAGE
Definition parsenodes.h:84
@ OBJECT_SCHEMA
#define ACL_CREATE
Definition parsenodes.h:85
ObjectAddress TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
Definition pg_type.c:57
END_CATALOG_STRUCT typedef FormData_pg_type * Form_pg_type
Definition pg_type.h:265
NameData typname
Definition pg_type.h:43
bool setof
Definition parsenodes.h:287
List * names
Definition parsenodes.h:285
List * typmods
Definition parsenodes.h:289
void CommandCounterIncrement(void)
Definition xact.c:1101

References ACL_CREATE, ACL_USAGE, aclcheck_error(), aclcheck_error_type(), ACLCHECK_OK, Assert, CommandCounterIncrement(), ereport, errcode(), errdetail(), errmsg(), ERROR, fb(), Form_pg_type, get_namespace_name(), GETSTRUCT(), GetUserId(), LookupTypeName(), TypeName::names, NIL, NOTICE, object_aclcheck(), OBJECT_SCHEMA, ObjectAddress::objectId, OidIsValid, QualifiedNameGetCreationNamespace(), ReleaseSysCache(), TypeName::setof, TypeNameToString(), TypeShellMake(), typeTypeId(), TypeName::typmods, and typname.

Referenced by CreateFunction().

◆ CreateCast()

ObjectAddress CreateCast ( CreateCastStmt stmt)

Definition at line 1542 of file functioncmds.c.

1543{
1546 char sourcetyptype;
1547 char targettyptype;
1548 Oid funcid;
1551 int nargs;
1552 char castcontext;
1553 char castmethod;
1554 HeapTuple tuple;
1557
1558 sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
1559 targettypeid = typenameTypeId(NULL, stmt->targettype);
1562
1563 /* No pseudo-types allowed */
1565 ereport(ERROR,
1567 errmsg("source data type %s is a pseudo-type",
1568 TypeNameToString(stmt->sourcetype))));
1569
1571 ereport(ERROR,
1573 errmsg("target data type %s is a pseudo-type",
1574 TypeNameToString(stmt->targettype))));
1575
1576 /* Permission check */
1579 ereport(ERROR,
1581 errmsg("must be owner of type %s or type %s",
1584
1586 if (aclresult != ACLCHECK_OK)
1588
1590 if (aclresult != ACLCHECK_OK)
1592
1593 /* Domains are allowed for historical reasons, but we warn */
1597 errmsg("cast will be ignored because the source data type is a domain")));
1598
1599 else if (targettyptype == TYPTYPE_DOMAIN)
1602 errmsg("cast will be ignored because the target data type is a domain")));
1603
1604 /* Determine the cast method */
1605 if (stmt->func != NULL)
1606 castmethod = COERCION_METHOD_FUNCTION;
1607 else if (stmt->inout)
1608 castmethod = COERCION_METHOD_INOUT;
1609 else
1610 castmethod = COERCION_METHOD_BINARY;
1611
1612 if (castmethod == COERCION_METHOD_FUNCTION)
1613 {
1615
1616 funcid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->func, false);
1617
1618 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1619 if (!HeapTupleIsValid(tuple))
1620 elog(ERROR, "cache lookup failed for function %u", funcid);
1621
1623 nargs = procstruct->pronargs;
1625 ereport(ERROR,
1627 errmsg("cast function must take one to three arguments")));
1629 procstruct->proargtypes.values[0],
1630 &incastid))
1631 ereport(ERROR,
1633 errmsg("argument of cast function must match or be binary-coercible from source data type")));
1634 if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
1635 ereport(ERROR,
1637 errmsg("second argument of cast function must be type %s",
1638 "integer")));
1639 if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)
1640 ereport(ERROR,
1642 errmsg("third argument of cast function must be type %s",
1643 "boolean")));
1644 if (!IsBinaryCoercibleWithCast(procstruct->prorettype,
1646 &outcastid))
1647 ereport(ERROR,
1649 errmsg("return data type of cast function must match or be binary-coercible to target data type")));
1650
1651 /*
1652 * Restricting the volatility of a cast function may or may not be a
1653 * good idea in the abstract, but it definitely breaks many old
1654 * user-defined types. Disable this check --- tgl 2/1/03
1655 */
1656#ifdef NOT_USED
1657 if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1658 ereport(ERROR,
1660 errmsg("cast function must not be volatile")));
1661#endif
1662 if (procstruct->prokind != PROKIND_FUNCTION)
1663 ereport(ERROR,
1665 errmsg("cast function must be a normal function")));
1666 if (procstruct->proretset)
1667 ereport(ERROR,
1669 errmsg("cast function must not return a set")));
1670
1671 ReleaseSysCache(tuple);
1672 }
1673 else
1674 {
1675 funcid = InvalidOid;
1676 nargs = 0;
1677 }
1678
1679 if (castmethod == COERCION_METHOD_BINARY)
1680 {
1681 int16 typ1len;
1682 int16 typ2len;
1683 bool typ1byval;
1684 bool typ2byval;
1685 char typ1align;
1686 char typ2align;
1687
1688 /*
1689 * Must be superuser to create binary-compatible casts, since
1690 * erroneous casts can easily crash the backend.
1691 */
1692 if (!superuser())
1693 ereport(ERROR,
1695 errmsg("must be superuser to create a cast WITHOUT FUNCTION")));
1696
1697 /*
1698 * Also, insist that the types match as to size, alignment, and
1699 * pass-by-value attributes; this provides at least a crude check that
1700 * they have similar representations. A pair of types that fail this
1701 * test should certainly not be equated.
1702 */
1705 if (typ1len != typ2len ||
1706 typ1byval != typ2byval ||
1708 ereport(ERROR,
1710 errmsg("source and target data types are not physically compatible")));
1711
1712 /*
1713 * We know that composite, array, range and enum types are never
1714 * binary-compatible with each other. They all have OIDs embedded in
1715 * them.
1716 *
1717 * Theoretically you could build a user-defined base type that is
1718 * binary-compatible with such a type. But we disallow it anyway, as
1719 * in practice such a cast is surely a mistake. You can always work
1720 * around that by writing a cast function.
1721 *
1722 * NOTE: if we ever have a kind of container type that doesn't need to
1723 * be rejected for this reason, we'd likely need to recursively apply
1724 * all of these same checks to the contained type(s).
1725 */
1728 ereport(ERROR,
1730 errmsg("composite data types are not binary-compatible")));
1731
1734 ereport(ERROR,
1736 errmsg("array data types are not binary-compatible")));
1737
1742 ereport(ERROR,
1744 errmsg("range data types are not binary-compatible")));
1745
1746 if (sourcetyptype == TYPTYPE_ENUM ||
1748 ereport(ERROR,
1750 errmsg("enum data types are not binary-compatible")));
1751
1752 /*
1753 * We also disallow creating binary-compatibility casts involving
1754 * domains. Casting from a domain to its base type is already
1755 * allowed, and casting the other way ought to go through domain
1756 * coercion to permit constraint checking. Again, if you're intent on
1757 * having your own semantics for that, create a no-op cast function.
1758 *
1759 * NOTE: if we were to relax this, the above checks for composites
1760 * etc. would have to be modified to look through domains to their
1761 * base types.
1762 */
1765 ereport(ERROR,
1767 errmsg("domain data types must not be marked binary-compatible")));
1768 }
1769
1770 /*
1771 * Allow source and target types to be same only for length coercion
1772 * functions. We assume a multi-arg function does length coercion.
1773 */
1774 if (sourcetypeid == targettypeid && nargs < 2)
1775 ereport(ERROR,
1777 errmsg("source data type and target data type are the same")));
1778
1779 /* convert CoercionContext enum to char value for castcontext */
1780 switch (stmt->context)
1781 {
1782 case COERCION_IMPLICIT:
1783 castcontext = COERCION_CODE_IMPLICIT;
1784 break;
1786 castcontext = COERCION_CODE_ASSIGNMENT;
1787 break;
1788 /* COERCION_PLPGSQL is intentionally not covered here */
1789 case COERCION_EXPLICIT:
1790 castcontext = COERCION_CODE_EXPLICIT;
1791 break;
1792 default:
1793 elog(ERROR, "unrecognized CoercionContext: %d", stmt->context);
1794 castcontext = 0; /* keep compiler quiet */
1795 break;
1796 }
1797
1799 castcontext, castmethod, DEPENDENCY_NORMAL);
1800 return myself;
1801}
int16_t int16
Definition c.h:553
#define WARNING
Definition elog.h:36
char * format_type_be(Oid type_oid)
Oid get_element_type(Oid typid)
Definition lsyscache.c:2911
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition lsyscache.c:2421
char get_typtype(Oid typid)
Definition lsyscache.c:2781
bool IsBinaryCoercibleWithCast(Oid srctype, Oid targettype, Oid *castoid)
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition parse_type.c:291
@ OBJECT_FUNCTION
ObjectAddress CastCreate(Oid sourcetypeid, Oid targettypeid, Oid funcid, Oid incastid, Oid outcastid, char castcontext, char castmethod, DependencyType behavior)
Definition pg_cast.c:49
#define InvalidOid
@ COERCION_ASSIGNMENT
Definition primnodes.h:748
@ COERCION_EXPLICIT
Definition primnodes.h:750
@ COERCION_IMPLICIT
Definition primnodes.h:747

References ACL_USAGE, aclcheck_error_type(), ACLCHECK_OK, CastCreate(), COERCION_ASSIGNMENT, COERCION_EXPLICIT, COERCION_IMPLICIT, DEPENDENCY_NORMAL, elog, ereport, errcode(), errmsg(), ERROR, fb(), Form_pg_proc, format_type_be(), get_element_type(), get_typlenbyvalalign(), get_typtype(), GETSTRUCT(), GetUserId(), HeapTupleIsValid, InvalidOid, IsBinaryCoercibleWithCast(), LookupFuncWithArgs(), object_aclcheck(), OBJECT_FUNCTION, object_ownercheck(), ObjectIdGetDatum(), OidIsValid, ReleaseSysCache(), SearchSysCache1(), stmt, superuser(), TypeNameToString(), typenameTypeId(), and WARNING.

Referenced by ProcessUtilitySlow().

◆ CreateFunction()

ObjectAddress CreateFunction ( ParseState pstate,
CreateFunctionStmt stmt 
)

Definition at line 1029 of file functioncmds.c.

1030{
1031 char *probin_str;
1032 char *prosrc_str;
1034 Oid prorettype;
1035 bool returnsSet;
1036 char *language;
1040 char *funcname;
1043 oidvector *parameterTypes;
1053 ArrayType *trftypes;
1055 bool isWindowFunc,
1056 isStrict,
1057 security,
1059 char volatility;
1066 List *as_clause;
1067 char parallel;
1068
1069 /* Convert list of names to a name and namespace */
1071 &funcname);
1072
1073 /* Check we have creation rights in target namespace */
1075 if (aclresult != ACLCHECK_OK)
1078
1079 /* Set default attributes */
1080 as_clause = NIL;
1081 language = NULL;
1082 isWindowFunc = false;
1083 isStrict = false;
1084 security = false;
1085 isLeakProof = false;
1087 proconfig = NULL;
1088 procost = -1; /* indicates not set */
1089 prorows = -1; /* indicates not set */
1092
1093 /* Extract non-default attributes from stmt->options list */
1095 stmt->is_procedure,
1096 stmt->options,
1101 &prosupport, &parallel);
1102
1103 if (!language)
1104 {
1105 if (stmt->sql_body)
1106 language = "sql";
1107 else
1108 ereport(ERROR,
1110 errmsg("no language specified")));
1111 }
1112
1113 /* Look up the language and validate permissions */
1116 ereport(ERROR,
1118 errmsg("language \"%s\" does not exist", language),
1120 errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
1121
1124
1125 if (languageStruct->lanpltrusted)
1126 {
1127 /* if trusted language, need USAGE privilege */
1129 if (aclresult != ACLCHECK_OK)
1131 NameStr(languageStruct->lanname));
1132 }
1133 else
1134 {
1135 /* if untrusted language, must be superuser */
1136 if (!superuser())
1138 NameStr(languageStruct->lanname));
1139 }
1140
1141 languageValidator = languageStruct->lanvalidator;
1142
1144
1145 /*
1146 * Only superuser is allowed to create leakproof functions because
1147 * leakproof functions can see tuples which have not yet been filtered out
1148 * by security barrier views or row-level security policies.
1149 */
1150 if (isLeakProof && !superuser())
1151 ereport(ERROR,
1153 errmsg("only superuser can define a leakproof function")));
1154
1155 if (transformDefElem)
1156 {
1157 ListCell *lc;
1158
1159 foreach(lc, castNode(List, transformDefElem))
1160 {
1161 Oid typeid = typenameTypeId(NULL,
1163 Oid elt = get_base_element_type(typeid);
1165
1166 typeid = elt ? elt : typeid;
1167 transformid = get_transform_oid(typeid, languageOid, false);
1170 }
1171 }
1172
1173 /*
1174 * Convert remaining parameters of CREATE to form wanted by
1175 * ProcedureCreate.
1176 */
1178 stmt->parameters,
1180 stmt->is_procedure ? OBJECT_PROCEDURE : OBJECT_FUNCTION,
1181 &parameterTypes,
1190
1191 if (stmt->is_procedure)
1192 {
1193 Assert(!stmt->returnType);
1195 returnsSet = false;
1196 }
1197 else if (stmt->returnType)
1198 {
1199 /* explicit RETURNS clause */
1201 &prorettype, &returnsSet);
1202 if (OidIsValid(requiredResultType) && prorettype != requiredResultType)
1203 ereport(ERROR,
1205 errmsg("function result type must be %s because of OUT parameters",
1207 }
1209 {
1210 /* default RETURNS clause from OUT parameters */
1211 prorettype = requiredResultType;
1212 returnsSet = false;
1213 }
1214 else
1215 {
1216 ereport(ERROR,
1218 errmsg("function result type must be specified")));
1219 /* Alternative possibility: default to RETURNS VOID */
1220 prorettype = VOIDOID;
1221 returnsSet = false;
1222 }
1223
1224 if (trftypes_list != NIL)
1225 {
1226 ListCell *lc;
1227 Datum *arr;
1228 int i;
1229
1230 arr = palloc(list_length(trftypes_list) * sizeof(Datum));
1231 i = 0;
1232 foreach(lc, trftypes_list)
1233 arr[i++] = ObjectIdGetDatum(lfirst_oid(lc));
1235 }
1236 else
1237 {
1238 /* store SQL NULL instead of empty array */
1239 trftypes = NULL;
1240 }
1241
1245 pstate->p_sourcetext);
1246
1247 /*
1248 * Set default values for COST and ROWS depending on other parameters;
1249 * reject ROWS if it's not returnsSet. NB: pg_dump knows these default
1250 * values, keep it in sync if you change them.
1251 */
1252 if (procost < 0)
1253 {
1254 /* SQL and PL-language functions are assumed more expensive */
1257 procost = 1;
1258 else
1259 procost = 100;
1260 }
1261 if (prorows < 0)
1262 {
1263 if (returnsSet)
1264 prorows = 1000;
1265 else
1266 prorows = 0; /* dummy value if not returnsSet */
1267 }
1268 else if (!returnsSet)
1269 ereport(ERROR,
1271 errmsg("ROWS is not applicable when function does not return a set")));
1272
1273 /*
1274 * And now that we have all the parameters, and know we're permitted to do
1275 * so, go ahead and create the function.
1276 */
1279 stmt->replace,
1280 returnsSet,
1281 prorettype,
1282 GetUserId(),
1285 prosrc_str, /* converted to text later */
1286 probin_str, /* converted to text later */
1287 prosqlbody,
1289 security,
1291 isStrict,
1292 volatility,
1293 parallel,
1294 parameterTypes,
1299 PointerGetDatum(trftypes),
1302 prosupport,
1303 procost,
1304 prorows);
1305}
@ ACLCHECK_NO_PRIV
Definition acl.h:184
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
float float4
Definition c.h:655
int errhint(const char *fmt,...) pg_attribute_printf(1
bool extension_file_exists(const char *extensionName)
Definition extension.c:2681
static void compute_return_type(TypeName *returnType, Oid languageOid, Oid *prorettype_p, bool *returnsSet_p)
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)
void interpret_function_parameter_list(ParseState *pstate, List *parameters, Oid languageOid, ObjectType objtype, oidvector **parameterTypes, List **parameterTypes_list, ArrayType **allParameterTypes, ArrayType **parameterModes, ArrayType **parameterNames, List **inParameterNames_list, List **parameterDefaults, Oid *variadicArgType, Oid *requiredResultType)
static void interpret_AS_clause(Oid languageOid, const char *languageName, char *funcname, List *as, Node *sql_body_in, List *parameterTypes, List *inParameterNames, char **prosrc_str_p, char **probin_str_p, Node **sql_body_out, const char *queryString)
Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok)
#define funcname
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
Oid get_base_element_type(Oid typid)
Definition lsyscache.c:2984
void * palloc(Size size)
Definition mcxt.c:1387
#define castNode(_type_, nodeptr)
Definition nodes.h:182
@ OBJECT_PROCEDURE
@ OBJECT_LANGUAGE
END_CATALOG_STRUCT typedef FormData_pg_language * Form_pg_language
Definition pg_language.h:69
#define lfirst_node(type, lc)
Definition pg_list.h:176
#define lfirst_oid(lc)
Definition pg_list.h:174
ObjectAddress ProcedureCreate(const char *procedureName, Oid procNamespace, bool replace, bool returnsSet, Oid returnType, Oid proowner, Oid languageObjectId, Oid languageValidator, const char *prosrc, const char *probin, Node *prosqlbody, char prokind, bool security_definer, bool isLeakProof, bool isStrict, char volatility, char parallel, oidvector *parameterTypes, Datum allParameterTypes, Datum parameterModes, Datum parameterNames, List *parameterDefaults, Datum trftypes, List *trfoids, Datum proconfig, Oid prosupport, float4 procost, float4 prorows)
Definition pg_proc.c:99
const char * p_sourcetext
Definition parse_node.h:191
Definition c.h:757

References ACL_CREATE, ACL_USAGE, aclcheck_error(), ACLCHECK_NO_PRIV, ACLCHECK_OK, Assert, castNode, compute_function_attributes(), compute_return_type(), construct_array_builtin(), ereport, errcode(), errhint(), errmsg(), ERROR, extension_file_exists(), fb(), Form_pg_language, format_type_be(), funcname, get_base_element_type(), get_namespace_name(), get_transform_oid(), GETSTRUCT(), GetUserId(), HeapTupleIsValid, i, interpret_AS_clause(), interpret_function_parameter_list(), InvalidOid, lappend_oid(), lfirst_node, lfirst_oid, list_length(), NameStr, NIL, object_aclcheck(), OBJECT_FUNCTION, OBJECT_LANGUAGE, OBJECT_PROCEDURE, OBJECT_SCHEMA, ObjectIdGetDatum(), OidIsValid, ParseState::p_sourcetext, palloc(), PointerGetDatum(), ProcedureCreate(), QualifiedNameGetCreationNamespace(), ReleaseSysCache(), SearchSysCache1(), stmt, superuser(), and typenameTypeId().

Referenced by ProcessUtilitySlow().

◆ CreateTransform()

ObjectAddress CreateTransform ( CreateTransformStmt stmt)

Definition at line 1835 of file functioncmds.c.

1836{
1837 Oid typeid;
1838 char typtype;
1839 Oid langid;
1845 bool nulls[Natts_pg_transform] = {0};
1846 bool replaces[Natts_pg_transform] = {0};
1848 HeapTuple tuple;
1849 HeapTuple newtuple;
1850 Relation relation;
1852 referenced;
1853 ObjectAddresses *addrs;
1854 bool is_replace;
1855
1856 /*
1857 * Get the type
1858 */
1859 typeid = typenameTypeId(NULL, stmt->type_name);
1860 typtype = get_typtype(typeid);
1861
1862 if (typtype == TYPTYPE_PSEUDO)
1863 ereport(ERROR,
1865 errmsg("data type %s is a pseudo-type",
1866 TypeNameToString(stmt->type_name))));
1867
1868 if (typtype == TYPTYPE_DOMAIN)
1869 ereport(ERROR,
1871 errmsg("data type %s is a domain",
1872 TypeNameToString(stmt->type_name))));
1873
1876
1878 if (aclresult != ACLCHECK_OK)
1880
1881 /*
1882 * Get the language
1883 */
1884 langid = get_language_oid(stmt->lang, false);
1885
1887 if (aclresult != ACLCHECK_OK)
1889
1890 /*
1891 * Get the functions
1892 */
1893 if (stmt->fromsql)
1894 {
1896
1899
1901 if (aclresult != ACLCHECK_OK)
1903
1905 if (!HeapTupleIsValid(tuple))
1906 elog(ERROR, "cache lookup failed for function %u", fromsqlfuncid);
1908 if (procstruct->prorettype != INTERNALOID)
1909 ereport(ERROR,
1911 errmsg("return data type of FROM SQL function must be %s",
1912 "internal")));
1914 ReleaseSysCache(tuple);
1915 }
1916 else
1918
1919 if (stmt->tosql)
1920 {
1922
1925
1927 if (aclresult != ACLCHECK_OK)
1929
1931 if (!HeapTupleIsValid(tuple))
1932 elog(ERROR, "cache lookup failed for function %u", tosqlfuncid);
1934 if (procstruct->prorettype != typeid)
1935 ereport(ERROR,
1937 errmsg("return data type of TO SQL function must be the transform data type")));
1939 ReleaseSysCache(tuple);
1940 }
1941 else
1943
1944 /*
1945 * Ready to go
1946 */
1951
1953
1955 ObjectIdGetDatum(typeid),
1956 ObjectIdGetDatum(langid));
1957 if (HeapTupleIsValid(tuple))
1958 {
1960
1961 if (!stmt->replace)
1962 ereport(ERROR,
1964 errmsg("transform for type %s language \"%s\" already exists",
1965 format_type_be(typeid),
1966 stmt->lang)));
1967
1970
1971 newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
1972 CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
1973
1974 transformid = form->oid;
1975 ReleaseSysCache(tuple);
1976 is_replace = true;
1977 }
1978 else
1979 {
1983 newtuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
1984 CatalogTupleInsert(relation, newtuple);
1985 is_replace = false;
1986 }
1987
1988 if (is_replace)
1990
1991 addrs = new_object_addresses();
1992
1993 /* make dependency entries */
1995
1996 /* dependency on language */
1999
2000 /* dependency on type */
2003
2004 /* dependencies on functions */
2006 {
2009 }
2011 {
2014 }
2015
2017 free_object_addresses(addrs);
2018
2019 /* dependency on extension */
2021
2022 /* Post creation hook for new transform */
2024
2025 heap_freetuple(newtuple);
2026
2027 table_close(relation, RowExclusiveLock);
2028
2029 return myself;
2030}
static Datum values[MAXATTR]
Definition bootstrap.c:147
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition catalog.c:448
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
ObjectAddresses * new_object_addresses(void)
void free_object_addresses(ObjectAddresses *addrs)
static void check_transform_function(Form_pg_proc procstruct)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1117
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition indexing.c:233
#define InvokeObjectPostCreateHook(classId, objectId, subId)
#define ACL_EXECUTE
Definition parsenodes.h:83
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition pg_depend.c:303
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition pg_depend.c:195
END_CATALOG_STRUCT typedef FormData_pg_transform * Form_pg_transform
Oid get_language_oid(const char *langname, bool missing_ok)
Definition proclang.c:227
#define ERRCODE_DUPLICATE_OBJECT
Definition streamutil.c:30
ItemPointerData t_self
Definition htup.h:65
HeapTuple SearchSysCache2(SysCacheIdentifier cacheId, Datum key1, Datum key2)
Definition syscache.c:230

References ACL_EXECUTE, ACL_USAGE, aclcheck_error(), aclcheck_error_type(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, add_exact_object_address(), CatalogTupleInsert(), CatalogTupleUpdate(), check_transform_function(), deleteDependencyRecordsFor(), DEPENDENCY_NORMAL, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, fb(), Form_pg_proc, Form_pg_transform, format_type_be(), free_object_addresses(), get_language_oid(), get_typtype(), GetNewOidWithIndex(), GETSTRUCT(), GetUserId(), heap_form_tuple(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, InvalidOid, InvokeObjectPostCreateHook, LookupFuncWithArgs(), NameListToString(), new_object_addresses(), object_aclcheck(), OBJECT_FUNCTION, OBJECT_LANGUAGE, object_ownercheck(), ObjectAddressSet, ObjectIdGetDatum(), OidIsValid, record_object_address_dependencies(), recordDependencyOnCurrentExtension(), RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), SearchSysCache2(), stmt, HeapTupleData::t_self, table_close(), table_open(), TypeNameToString(), typenameTypeId(), and values.

Referenced by ProcessUtilitySlow().

◆ ExecuteCallStmt()

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

Definition at line 2209 of file functioncmds.c.

2210{
2211 LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
2212 ListCell *lc;
2213 FuncExpr *fexpr;
2214 int nargs;
2215 int i;
2217 FmgrInfo flinfo;
2219 EState *estate;
2220 ExprContext *econtext;
2221 HeapTuple tp;
2223 Datum retval;
2224
2225 fexpr = stmt->funcexpr;
2226 Assert(fexpr);
2228
2230 if (aclresult != ACLCHECK_OK)
2232
2233 /* Prep the context object we'll pass to the procedure */
2235 callcontext->atomic = atomic;
2236
2238 if (!HeapTupleIsValid(tp))
2239 elog(ERROR, "cache lookup failed for function %u", fexpr->funcid);
2240
2241 /*
2242 * If proconfig is set we can't allow transaction commands because of the
2243 * way the GUC stacking works: The transaction boundary would have to pop
2244 * the proconfig setting off the stack. That restriction could be lifted
2245 * by redesigning the GUC nesting mechanism a bit.
2246 */
2248 callcontext->atomic = true;
2249
2250 /*
2251 * In security definer procedures, we can't allow transaction commands.
2252 * StartTransaction() insists that the security context stack is empty,
2253 * and AbortTransaction() resets the security context. This could be
2254 * reorganized, but right now it doesn't work.
2255 */
2256 if (((Form_pg_proc) GETSTRUCT(tp))->prosecdef)
2257 callcontext->atomic = true;
2258
2259 ReleaseSysCache(tp);
2260
2261 /* safety check; see ExecInitFunc() */
2262 nargs = list_length(fexpr->args);
2263 if (nargs > FUNC_MAX_ARGS)
2264 ereport(ERROR,
2266 errmsg_plural("cannot pass more than %d argument to a procedure",
2267 "cannot pass more than %d arguments to a procedure",
2269 FUNC_MAX_ARGS)));
2270
2271 /* Initialize function call structure */
2273 fmgr_info(fexpr->funcid, &flinfo);
2274 fmgr_info_set_expr((Node *) fexpr, &flinfo);
2275 InitFunctionCallInfoData(*fcinfo, &flinfo, nargs, fexpr->inputcollid,
2276 (Node *) callcontext, NULL);
2277
2278 /*
2279 * Evaluate procedure arguments inside a suitable execution context. Note
2280 * we can't free this context till the procedure returns.
2281 */
2282 estate = CreateExecutorState();
2283 estate->es_param_list_info = params;
2284 econtext = CreateExprContext(estate);
2285
2286 /*
2287 * If we're called in non-atomic context, we also have to ensure that the
2288 * argument expressions run with an up-to-date snapshot. Our caller will
2289 * have provided a current snapshot in atomic contexts, but not in
2290 * non-atomic contexts, because the possibility of a COMMIT/ROLLBACK
2291 * destroying the snapshot makes higher-level management too complicated.
2292 */
2293 if (!atomic)
2295
2296 i = 0;
2297 foreach(lc, fexpr->args)
2298 {
2299 ExprState *exprstate;
2300 Datum val;
2301 bool isnull;
2302
2303 exprstate = ExecPrepareExpr(lfirst(lc), estate);
2304
2305 val = ExecEvalExprSwitchContext(exprstate, econtext, &isnull);
2306
2307 fcinfo->args[i].value = val;
2308 fcinfo->args[i].isnull = isnull;
2309
2310 i++;
2311 }
2312
2313 /* Get rid of temporary snapshot for arguments, if we made one */
2314 if (!atomic)
2316
2317 /* Here we actually call the procedure */
2319 retval = FunctionCallInvoke(fcinfo);
2321
2322 /* Handle the procedure's outputs */
2323 if (fexpr->funcresulttype == VOIDOID)
2324 {
2325 /* do nothing */
2326 }
2327 else if (fexpr->funcresulttype == RECORDOID)
2328 {
2329 /* send tuple to client */
2330 HeapTupleHeader td;
2331 Oid tupType;
2336 TupleTableSlot *slot;
2337
2338 if (fcinfo->isnull)
2339 elog(ERROR, "procedure returned null record");
2340
2341 /*
2342 * Ensure there's an active snapshot whilst we execute whatever's
2343 * involved here. Note that this is *not* sufficient to make the
2344 * world safe for TOAST pointers to be included in the returned data:
2345 * the referenced data could have gone away while we didn't hold a
2346 * snapshot. Hence, it's incumbent on PLs that can do COMMIT/ROLLBACK
2347 * to not return TOAST pointers, unless those pointers were fetched
2348 * after the last COMMIT/ROLLBACK in the procedure.
2349 *
2350 * XXX that is a really nasty, hard-to-test requirement. Is there a
2351 * way to remove it?
2352 */
2354
2355 td = DatumGetHeapTupleHeader(retval);
2359
2362
2365 rettupdata.t_tableOid = InvalidOid;
2366 rettupdata.t_data = td;
2367
2368 slot = ExecStoreHeapTuple(&rettupdata, tstate->slot, false);
2369 tstate->dest->receiveSlot(slot, tstate->dest);
2370
2372
2374 }
2375 else
2376 elog(ERROR, "unexpected result type for procedure: %u",
2377 fexpr->funcresulttype);
2378
2379 FreeExecutorState(estate);
2380}
int32_t int32
Definition c.h:554
int int int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...) pg_attribute_printf(1
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition execExpr.c:765
void end_tup_output(TupOutputState *tstate)
const TupleTableSlotOps TTSOpsHeapTuple
Definition execTuples.c:85
TupOutputState * begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
TupleTableSlot * ExecStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot, bool shouldFree)
ExprContext * CreateExprContext(EState *estate)
Definition execUtils.c:307
void FreeExecutorState(EState *estate)
Definition execUtils.c:192
EState * CreateExecutorState(void)
Definition execUtils.c:88
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition executor.h:436
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition fmgr.c:128
#define DatumGetHeapTupleHeader(X)
Definition fmgr.h:296
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition fmgr.h:150
#define LOCAL_FCINFO(name, nargs)
Definition fmgr.h:110
#define FunctionCallInvoke(fcinfo)
Definition fmgr.h:172
#define fmgr_info_set_expr(expr, finfo)
Definition fmgr.h:135
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition heaptuple.c:456
static int32 HeapTupleHeaderGetTypMod(const HeapTupleHeaderData *tup)
static uint32 HeapTupleHeaderGetDatumLength(const HeapTupleHeaderData *tup)
static Oid HeapTupleHeaderGetTypeId(const HeapTupleHeaderData *tup)
long val
Definition informix.c:689
static void ItemPointerSetInvalid(ItemPointerData *pointer)
Definition itemptr.h:184
#define IsA(nodeptr, _type_)
Definition nodes.h:164
#define makeNode(_type_)
Definition nodes.h:161
#define InvokeFunctionExecuteHook(objectId)
#define FUNC_MAX_ARGS
void pgstat_init_function_usage(FunctionCallInfo fcinfo, PgStat_FunctionCallUsage *fcu)
void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize)
void EnsurePortalSnapshotExists(void)
Definition pquery.c:1760
Snapshot GetTransactionSnapshot(void)
Definition snapmgr.c:272
void PushActiveSnapshot(Snapshot snapshot)
Definition snapmgr.c:682
void PopActiveSnapshot(void)
Definition snapmgr.c:775
ParamListInfo es_param_list_info
Definition execnodes.h:707
#define ReleaseTupleDesc(tupdesc)
Definition tupdesc.h:219
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition typcache.c:1924

References ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, Assert, begin_tup_output_tupdesc(), CreateExecutorState(), CreateExprContext(), DatumGetHeapTupleHeader, elog, end_tup_output(), EnsurePortalSnapshotExists(), ereport, errcode(), errmsg_plural(), ERROR, EState::es_param_list_info, ExecEvalExprSwitchContext(), ExecPrepareExpr(), ExecStoreHeapTuple(), fb(), fmgr_info(), fmgr_info_set_expr, Form_pg_proc, FreeExecutorState(), FUNC_MAX_ARGS, FunctionCallInvoke, get_func_name(), GETSTRUCT(), GetTransactionSnapshot(), GetUserId(), heap_attisnull(), HeapTupleHeaderGetDatumLength(), HeapTupleHeaderGetTypeId(), HeapTupleHeaderGetTypMod(), HeapTupleIsValid, i, InitFunctionCallInfoData, InvalidOid, InvokeFunctionExecuteHook, IsA, ItemPointerSetInvalid(), lfirst, list_length(), LOCAL_FCINFO, lookup_rowtype_tupdesc(), makeNode, object_aclcheck(), OBJECT_PROCEDURE, ObjectIdGetDatum(), pgstat_end_function_usage(), pgstat_init_function_usage(), PopActiveSnapshot(), PushActiveSnapshot(), ReleaseSysCache(), ReleaseTupleDesc, SearchSysCache1(), stmt, TTSOpsHeapTuple, and val.

Referenced by standard_ProcessUtility().

◆ ExecuteDoStmt()

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

Definition at line 2087 of file functioncmds.c.

2088{
2090 ListCell *arg;
2091 DefElem *as_item = NULL;
2093 char *language;
2094 Oid laninline;
2097
2098 /* Process options we got from gram.y */
2099 foreach(arg, stmt->args)
2100 {
2101 DefElem *defel = (DefElem *) lfirst(arg);
2102
2103 if (strcmp(defel->defname, "as") == 0)
2104 {
2105 if (as_item)
2107 as_item = defel;
2108 }
2109 else if (strcmp(defel->defname, "language") == 0)
2110 {
2111 if (language_item)
2114 }
2115 else
2116 elog(ERROR, "option \"%s\" not recognized",
2117 defel->defname);
2118 }
2119
2120 if (as_item)
2121 codeblock->source_text = strVal(as_item->arg);
2122 else
2123 ereport(ERROR,
2125 errmsg("no inline code specified")));
2126
2127 /* if LANGUAGE option wasn't specified, use the default */
2128 if (language_item)
2130 else
2131 language = "plpgsql";
2132
2133 /* Look up the language and validate permissions */
2136 ereport(ERROR,
2138 errmsg("language \"%s\" does not exist", language),
2140 errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
2141
2143 codeblock->langOid = languageStruct->oid;
2144 codeblock->langIsTrusted = languageStruct->lanpltrusted;
2145 codeblock->atomic = atomic;
2146
2147 if (languageStruct->lanpltrusted)
2148 {
2149 /* if trusted language, need USAGE privilege */
2151
2153 ACL_USAGE);
2154 if (aclresult != ACLCHECK_OK)
2156 NameStr(languageStruct->lanname));
2157 }
2158 else
2159 {
2160 /* if untrusted language, must be superuser */
2161 if (!superuser())
2163 NameStr(languageStruct->lanname));
2164 }
2165
2166 /* get the handler function's OID */
2167 laninline = languageStruct->laninline;
2168 if (!OidIsValid(laninline))
2169 ereport(ERROR,
2171 errmsg("language \"%s\" does not support inline code execution",
2172 NameStr(languageStruct->lanname))));
2173
2175
2176 /* execute the inline handler */
2178}
Datum arg
Definition elog.c:1322
#define OidFunctionCall1(functionId, arg1)
Definition fmgr.h:722

References ACL_USAGE, aclcheck_error(), ACLCHECK_NO_PRIV, ACLCHECK_OK, arg, elog, ereport, errcode(), errhint(), errmsg(), ERROR, errorConflictingDefElem(), extension_file_exists(), fb(), Form_pg_language, GETSTRUCT(), GetUserId(), HeapTupleIsValid, lfirst, makeNode, NameStr, object_aclcheck(), OBJECT_LANGUAGE, OidFunctionCall1, OidIsValid, PointerGetDatum(), ReleaseSysCache(), SearchSysCache1(), stmt, strVal, and superuser().

Referenced by standard_ProcessUtility().

◆ get_transform_oid()

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

Definition at line 2040 of file functioncmds.c.

2041{
2042 Oid oid;
2043
2045 ObjectIdGetDatum(type_id),
2047 if (!OidIsValid(oid) && !missing_ok)
2048 ereport(ERROR,
2050 errmsg("transform for type %s language \"%s\" does not exist",
2051 format_type_be(type_id),
2052 get_language_name(lang_id, false))));
2053 return oid;
2054}
char * get_language_name(Oid langoid, bool missing_ok)
Definition lsyscache.c:1263
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition syscache.h:111

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

Referenced by CreateFunction(), and get_object_address().

◆ interpret_AS_clause()

static void interpret_AS_clause ( Oid  languageOid,
const char languageName,
char funcname,
List as,
Node sql_body_in,
List parameterTypes,
List inParameterNames,
char **  prosrc_str_p,
char **  probin_str_p,
Node **  sql_body_out,
const char queryString 
)
static

Definition at line 869 of file functioncmds.c.

875{
876 if (!sql_body_in && !as)
879 errmsg("no function body specified")));
880
881 if (sql_body_in && as)
884 errmsg("duplicate function body specified")));
885
889 errmsg("inline SQL function body only valid for language SQL")));
890
892
894 {
895 /*
896 * For "C" language, store the file name in probin and, when given,
897 * the link symbol name in prosrc. If link symbol is omitted,
898 * substitute procedure name. We also allow link symbol to be
899 * specified as "-", since that was the habit in PG versions before
900 * 8.4, and there might be dump files out there that don't translate
901 * that back to "omitted".
902 */
904 if (list_length(as) == 1)
906 else
907 {
909 if (strcmp(*prosrc_str_p, "-") == 0)
911 }
912 }
913 else if (sql_body_in)
914 {
916
918
919 pinfo->fname = funcname;
920 pinfo->nargs = list_length(parameterTypes);
921 pinfo->argtypes = (Oid *) palloc(pinfo->nargs * sizeof(Oid));
922 pinfo->argnames = (char **) palloc(pinfo->nargs * sizeof(char *));
923 for (int i = 0; i < list_length(parameterTypes); i++)
924 {
925 char *s = strVal(list_nth(inParameterNames, i));
926
927 pinfo->argtypes[i] = list_nth_oid(parameterTypes, i);
928 if (IsPolymorphicType(pinfo->argtypes[i]))
931 errmsg("SQL function with unquoted function body cannot have polymorphic arguments")));
932
933 if (s[0] != '\0')
934 pinfo->argnames[i] = s;
935 else
936 pinfo->argnames[i] = NULL;
937 }
938
939 if (IsA(sql_body_in, List))
940 {
942 ListCell *lc;
944
945 foreach(lc, stmts)
946 {
947 Node *stmt = lfirst(lc);
948 Query *q;
950
951 pstate->p_sourcetext = queryString;
952 sql_fn_parser_setup(pstate, pinfo);
953 q = transformStmt(pstate, stmt);
954 if (q->commandType == CMD_UTILITY)
957 errmsg("%s is not yet supported in unquoted SQL function body",
960 free_parsestate(pstate);
961 }
962
964 }
965 else
966 {
967 Query *q;
969
970 pstate->p_sourcetext = queryString;
971 sql_fn_parser_setup(pstate, pinfo);
972 q = transformStmt(pstate, sql_body_in);
973 if (q->commandType == CMD_UTILITY)
976 errmsg("%s is not yet supported in unquoted SQL function body",
978 free_parsestate(pstate);
979
980 *sql_body_out = (Node *) q;
981 }
982
983 /*
984 * We must put something in prosrc. For the moment, just record an
985 * empty string. It might be useful to store the original text of the
986 * CREATE FUNCTION statement --- but to make actual use of that in
987 * error reports, we'd also have to adjust readfuncs.c to not throw
988 * away node location fields when reading prosqlbody.
989 */
990 *prosrc_str_p = pstrdup("");
991
992 /* But we definitely don't need probin. */
994 }
995 else
996 {
997 /* Everything else wants the given string in prosrc. */
1000
1001 if (list_length(as) != 1)
1002 ereport(ERROR,
1004 errmsg("only one AS item needed for language \"%s\"",
1005 languageName)));
1006
1008 {
1009 /*
1010 * In PostgreSQL versions before 6.5, the SQL name of the created
1011 * function could not be different from the internal name, and
1012 * "prosrc" wasn't used. So there is code out there that does
1013 * CREATE FUNCTION xyz AS '' LANGUAGE internal. To preserve some
1014 * modicum of backwards compatibility, accept an empty "prosrc"
1015 * value as meaning the supplied SQL function name.
1016 */
1017 if (strlen(*prosrc_str_p) == 0)
1019 }
1020 }
1021}
const char * GetCommandTagName(CommandTag commandTag)
Definition cmdtag.c:47
#define palloc0_object(type)
Definition fe_memutils.h:75
void sql_fn_parser_setup(struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)
Definition functions.c:340
char * pstrdup(const char *in)
Definition mcxt.c:1781
@ CMD_UTILITY
Definition nodes.h:280
void free_parsestate(ParseState *pstate)
Definition parse_node.c:72
ParseState * make_parsestate(ParseState *parentParseState)
Definition parse_node.c:39
Query * transformStmt(ParseState *pstate, Node *parseTree)
Definition analyze.c:324
#define linitial_node(type, l)
Definition pg_list.h:181
static Oid list_nth_oid(const List *list, int n)
Definition pg_list.h:321
#define list_make1(x1)
Definition pg_list.h:212
#define linitial(l)
Definition pg_list.h:178
#define lsecond(l)
Definition pg_list.h:183
CmdType commandType
Definition parsenodes.h:121
Node * utilityStmt
Definition parsenodes.h:141
CommandTag CreateCommandTag(Node *parsetree)
Definition utility.c:2369

References SQLFunctionParseInfo::argnames, SQLFunctionParseInfo::argtypes, castNode, CMD_UTILITY, Query::commandType, CreateCommandTag(), ereport, errcode(), errmsg(), ERROR, fb(), SQLFunctionParseInfo::fname, free_parsestate(), funcname, GetCommandTagName(), i, IsA, lappend(), lfirst, linitial, linitial_node, list_length(), list_make1, list_nth(), list_nth_oid(), lsecond, make_parsestate(), SQLFunctionParseInfo::nargs, NIL, ParseState::p_sourcetext, palloc(), palloc0_object, pstrdup(), sql_fn_parser_setup(), stmt, strVal, transformStmt(), and Query::utilityStmt.

Referenced by CreateFunction().

◆ interpret_func_parallel()

static char interpret_func_parallel ( DefElem defel)
static

Definition at line 638 of file functioncmds.c.

639{
640 char *str = strVal(defel->arg);
641
642 if (strcmp(str, "safe") == 0)
643 return PROPARALLEL_SAFE;
644 else if (strcmp(str, "unsafe") == 0)
645 return PROPARALLEL_UNSAFE;
646 else if (strcmp(str, "restricted") == 0)
648 else
649 {
652 errmsg("parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE")));
653 return PROPARALLEL_UNSAFE; /* keep compiler quiet */
654 }
655}
const char * str

References ereport, errcode(), errmsg(), ERROR, fb(), str, and strVal.

Referenced by AlterFunction(), and compute_function_attributes().

◆ interpret_func_support()

static Oid interpret_func_support ( DefElem defel)
static

Definition at line 688 of file functioncmds.c.

689{
691 Oid procOid;
692 Oid argList[1];
693
694 /*
695 * Support functions always take one INTERNAL argument and return
696 * INTERNAL.
697 */
698 argList[0] = INTERNALOID;
699
701 if (!OidIsValid(procOid))
704 errmsg("function %s does not exist",
706
710 errmsg("support function %s must return type %s",
711 NameListToString(procName), "internal")));
712
713 /*
714 * Someday we might want an ACL check here; but for now, we insist that
715 * you be superuser to specify a support function, so privilege on the
716 * support function is moot.
717 */
718 if (!superuser())
721 errmsg("must be superuser to specify a support function")));
722
723 return procOid;
724}
List * defGetQualifiedName(DefElem *def)
Definition define.c:238
Oid get_func_rettype(Oid funcid)
Definition lsyscache.c:1805
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)

References defGetQualifiedName(), ereport, errcode(), errmsg(), ERROR, fb(), func_signature_string(), get_func_rettype(), LookupFuncName(), NameListToString(), NIL, OidIsValid, and superuser().

Referenced by AlterFunction(), and compute_function_attributes().

◆ interpret_func_volatility()

static char interpret_func_volatility ( DefElem defel)
static

Definition at line 620 of file functioncmds.c.

621{
622 char *str = strVal(defel->arg);
623
624 if (strcmp(str, "immutable") == 0)
626 else if (strcmp(str, "stable") == 0)
627 return PROVOLATILE_STABLE;
628 else if (strcmp(str, "volatile") == 0)
630 else
631 {
632 elog(ERROR, "invalid volatility \"%s\"", str);
633 return 0; /* keep compiler quiet */
634 }
635}

References elog, ERROR, fb(), str, and strVal.

Referenced by AlterFunction(), and compute_function_attributes().

◆ interpret_function_parameter_list()

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

Definition at line 186 of file functioncmds.c.

199{
200 int parameterCount = list_length(parameters);
201 Oid *inTypes;
202 int inCount = 0;
206 int outCount = 0;
207 int varCount = 0;
208 bool have_names = false;
209 bool have_defaults = false;
210 ListCell *x;
211 int i;
212
213 *variadicArgType = InvalidOid; /* default result */
214 *requiredResultType = InvalidOid; /* default result */
215
216 inTypes = (Oid *) palloc(parameterCount * sizeof(Oid));
217 allTypes = (Datum *) palloc(parameterCount * sizeof(Datum));
218 paramModes = (Datum *) palloc(parameterCount * sizeof(Datum));
221
222 /* Scan the list and extract data into work arrays */
223 i = 0;
224 foreach(x, parameters)
225 {
227 TypeName *t = fp->argType;
229 bool isinput = false;
230 Oid toid;
231 Type typtup;
233
234 /* For our purposes here, a defaulted mode spec is identical to IN */
237
238 typtup = LookupTypeName(pstate, t, NULL, false);
239 if (typtup)
240 {
242 {
243 /* As above, hard error if language is SQL */
247 errmsg("SQL function cannot accept shell type %s",
249 parser_errposition(pstate, t->location)));
250 /* We don't allow creating aggregates on shell types either */
251 else if (objtype == OBJECT_AGGREGATE)
254 errmsg("aggregate cannot accept shell type %s",
256 parser_errposition(pstate, t->location)));
257 else
260 errmsg("argument type %s is only a shell",
262 parser_errposition(pstate, t->location)));
263 }
266 }
267 else
268 {
271 errmsg("type %s does not exist",
273 parser_errposition(pstate, t->location)));
274 toid = InvalidOid; /* keep compiler quiet */
275 }
276
278 if (aclresult != ACLCHECK_OK)
280
281 if (t->setof)
282 {
283 if (objtype == OBJECT_AGGREGATE)
286 errmsg("aggregates cannot accept set arguments"),
287 parser_errposition(pstate, fp->location)));
288 else if (objtype == OBJECT_PROCEDURE)
291 errmsg("procedures cannot accept set arguments"),
292 parser_errposition(pstate, fp->location)));
293 else
296 errmsg("functions cannot accept set arguments"),
297 parser_errposition(pstate, fp->location)));
298 }
299
300 /* handle input parameters */
302 {
303 /* other input parameters can't follow a VARIADIC parameter */
304 if (varCount > 0)
307 errmsg("VARIADIC parameter must be the last input parameter"),
308 parser_errposition(pstate, fp->location)));
309 inTypes[inCount++] = toid;
310 isinput = true;
313 }
314
315 /* handle output parameters */
317 {
318 if (objtype == OBJECT_PROCEDURE)
319 {
320 /*
321 * We disallow OUT-after-VARIADIC only for procedures. While
322 * such a case causes no confusion in ordinary function calls,
323 * it would cause confusion in a CALL statement.
324 */
325 if (varCount > 0)
328 errmsg("VARIADIC parameter must be the last parameter"),
329 parser_errposition(pstate, fp->location)));
330 /* Procedures with output parameters always return RECORD */
332 }
333 else if (outCount == 0) /* save first output param's type */
335 outCount++;
336 }
337
339 {
341 varCount++;
342 /* validate variadic parameter type */
343 switch (toid)
344 {
345 case ANYARRAYOID:
347 case ANYOID:
348 /* okay */
349 break;
350 default:
354 errmsg("VARIADIC parameter must be an array"),
355 parser_errposition(pstate, fp->location)));
356 break;
357 }
358 }
359
361
363
364 if (fp->name && fp->name[0])
365 {
366 ListCell *px;
367
368 /*
369 * As of Postgres 9.0 we disallow using the same name for two
370 * input or two output function parameters. Depending on the
371 * function's language, conflicting input and output names might
372 * be bad too, but we leave it to the PL to complain if so.
373 */
374 foreach(px, parameters)
375 {
378
379 if (prevfp == fp)
380 break;
381 /* as above, default mode is IN */
385 /* pure in doesn't conflict with pure out */
386 if ((fpmode == FUNC_PARAM_IN ||
390 continue;
391 if ((prevfpmode == FUNC_PARAM_IN ||
395 continue;
396 if (prevfp->name && prevfp->name[0] &&
397 strcmp(prevfp->name, fp->name) == 0)
400 errmsg("parameter name \"%s\" used more than once",
401 fp->name),
402 parser_errposition(pstate, fp->location)));
403 }
404
406 have_names = true;
407 }
408
411
412 if (fp->defexpr)
413 {
414 Node *def;
415
416 if (!isinput)
419 errmsg("only input parameters can have default values"),
420 parser_errposition(pstate, fp->location)));
421
422 def = transformExpr(pstate, fp->defexpr,
424 def = coerce_to_specific_type(pstate, def, toid, "DEFAULT");
425 assign_expr_collations(pstate, def);
426
427 /*
428 * Make sure no variables are referred to (this is probably dead
429 * code now that add_missing_from is history).
430 */
431 if (pstate->p_rtable != NIL ||
435 errmsg("cannot use table references in parameter default value"),
436 parser_errposition(pstate, fp->location)));
437
438 /*
439 * transformExpr() should have already rejected subqueries,
440 * aggregates, and window functions, based on the EXPR_KIND_ for a
441 * default expression.
442 *
443 * It can't return a set either --- but coerce_to_specific_type
444 * already checked that for us.
445 *
446 * Note: the point of these restrictions is to ensure that an
447 * expression that, on its face, hasn't got subplans, aggregates,
448 * etc cannot suddenly have them after function default arguments
449 * are inserted.
450 */
451
453 have_defaults = true;
454 }
455 else
456 {
457 if (isinput && have_defaults)
460 errmsg("input parameters after one with a default value must also have defaults"),
461 parser_errposition(pstate, fp->location)));
462
463 /*
464 * For procedures, we also can't allow OUT parameters after one
465 * with a default, because the same sort of confusion arises in a
466 * CALL statement.
467 */
468 if (objtype == OBJECT_PROCEDURE && have_defaults)
471 errmsg("procedure OUT parameters cannot appear after one with a default value"),
472 parser_errposition(pstate, fp->location)));
473 }
474
475 i++;
476 }
477
478 /* Now construct the proper outputs as needed */
479 *parameterTypes = buildoidvector(inTypes, inCount);
480
481 if (outCount > 0 || varCount > 0)
482 {
485 if (outCount > 1)
487 /* otherwise we set requiredResultType correctly above */
488 }
489 else
490 {
493 }
494
495 if (have_names)
496 {
497 for (i = 0; i < parameterCount; i++)
498 {
501 }
503 }
504 else
506}
#define CStringGetTextDatum(s)
Definition builtins.h:98
void px(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
int x
Definition isn.c:75
void * palloc0(Size size)
Definition mcxt.c:1417
oidvector * buildoidvector(const Oid *oids, int n)
Definition oid.c:87
Node * coerce_to_specific_type(ParseState *pstate, Node *node, Oid targetTypeId, const char *constructName)
void assign_expr_collations(ParseState *pstate, Node *expr)
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition parse_expr.c:120
@ EXPR_KIND_FUNCTION_DEFAULT
Definition parse_node.h:71
FunctionParameterMode
@ FUNC_PARAM_IN
@ FUNC_PARAM_DEFAULT
@ FUNC_PARAM_OUT
@ FUNC_PARAM_TABLE
@ FUNC_PARAM_VARIADIC
@ OBJECT_AGGREGATE
static Datum CharGetDatum(char X)
Definition postgres.h:132
TypeName * argType
FunctionParameterMode mode
List * p_rtable
Definition parse_node.h:192
ParseLoc location
Definition parsenodes.h:292
String * makeString(char *str)
Definition value.c:63
bool contain_var_clause(Node *node)
Definition var.c:406

References ACL_USAGE, aclcheck_error_type(), ACLCHECK_OK, FunctionParameter::argType, assign_expr_collations(), buildoidvector(), CharGetDatum(), coerce_to_specific_type(), construct_array_builtin(), contain_var_clause(), CStringGetTextDatum, FunctionParameter::defexpr, ereport, errcode(), errmsg(), ERROR, EXPR_KIND_FUNCTION_DEFAULT, fb(), Form_pg_type, FUNC_PARAM_DEFAULT, FUNC_PARAM_IN, FUNC_PARAM_OUT, FUNC_PARAM_TABLE, FUNC_PARAM_VARIADIC, get_element_type(), GETSTRUCT(), GetUserId(), i, InvalidOid, lappend(), lappend_oid(), lfirst, list_length(), TypeName::location, FunctionParameter::location, LookupTypeName(), makeString(), FunctionParameter::mode, FunctionParameter::name, NIL, NOTICE, object_aclcheck(), OBJECT_AGGREGATE, OBJECT_PROCEDURE, ObjectIdGetDatum(), OidIsValid, ParseState::p_rtable, palloc(), palloc0(), parser_errposition(), PointerGetDatum(), pstrdup(), px(), ReleaseSysCache(), TypeName::setof, transformExpr(), TypeNameToString(), typeTypeId(), and x.

Referenced by CreateFunction(), and DefineAggregate().

◆ IsThereFunctionInNamespace()

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

Definition at line 2064 of file functioncmds.c.

2066{
2067 /* check for duplicate name (more friendly than unique-index failure) */
2072 ereport(ERROR,
2074 errmsg("function %s already exists in schema \"%s\"",
2076 NIL, proargtypes->values),
2078}
const char * funcname_signature_string(const char *funcname, int nargs, List *argnames, const Oid *argtypes)
int16 pronargs
Definition pg_proc.h:83
NameData proname
Definition pg_proc.h:37
static Datum CStringGetDatum(const char *X)
Definition postgres.h:380
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition syscache.h:104

References CStringGetDatum(), ereport, errcode(), errmsg(), ERROR, fb(), funcname_signature_string(), get_namespace_name(), NIL, ObjectIdGetDatum(), PointerGetDatum(), proname, pronargs, and SearchSysCacheExists3.

Referenced by AlterObjectNamespace_internal(), and AlterObjectRename_internal().

◆ RemoveFunctionById()

void RemoveFunctionById ( Oid  funcOid)

Definition at line 1314 of file functioncmds.c.

1315{
1316 Relation relation;
1317 HeapTuple tup;
1318 char prokind;
1319
1320 /*
1321 * Delete the pg_proc tuple.
1322 */
1324
1326 if (!HeapTupleIsValid(tup)) /* should not happen */
1327 elog(ERROR, "cache lookup failed for function %u", funcOid);
1328
1329 prokind = ((Form_pg_proc) GETSTRUCT(tup))->prokind;
1330
1331 CatalogTupleDelete(relation, &tup->t_self);
1332
1334
1335 table_close(relation, RowExclusiveLock);
1336
1337 pgstat_drop_function(funcOid);
1338
1339 /*
1340 * If there's a pg_aggregate tuple, delete that too.
1341 */
1342 if (prokind == PROKIND_AGGREGATE)
1343 {
1345
1347 if (!HeapTupleIsValid(tup)) /* should not happen */
1348 elog(ERROR, "cache lookup failed for pg_aggregate tuple for function %u", funcOid);
1349
1350 CatalogTupleDelete(relation, &tup->t_self);
1351
1353
1354 table_close(relation, RowExclusiveLock);
1355 }
1356}
void CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid)
Definition indexing.c:365
void pgstat_drop_function(Oid proid)

References CatalogTupleDelete(), elog, ERROR, fb(), Form_pg_proc, GETSTRUCT(), HeapTupleIsValid, ObjectIdGetDatum(), pgstat_drop_function(), ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), table_close(), and table_open().

Referenced by doDeletion().

◆ update_proconfig_value()

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

Definition at line 663 of file functioncmds.c.

664{
665 ListCell *l;
666
667 foreach(l, set_items)
668 {
670
671 if (sstmt->kind == VAR_RESET_ALL)
672 a = NULL;
673 else
674 {
676
677 if (valuestr)
678 a = GUCArrayAdd(a, sstmt->name, valuestr);
679 else /* RESET */
680 a = GUCArrayDelete(a, sstmt->name);
681 }
682 }
683
684 return a;
685}
ArrayType * GUCArrayAdd(ArrayType *array, const char *name, const char *value)
Definition guc.c:6328
ArrayType * GUCArrayDelete(ArrayType *array, const char *name)
Definition guc.c:6405
char * ExtractSetVariableArgs(VariableSetStmt *stmt)
Definition guc_funcs.c:167
@ VAR_RESET_ALL

References a, ExtractSetVariableArgs(), fb(), GUCArrayAdd(), GUCArrayDelete(), lfirst_node, and VAR_RESET_ALL.

Referenced by AlterFunction(), and compute_function_attributes().