29#include "utils/fmgroids.h"
69#define FUNCS_PER_USER 128
82#include "plerrcodes.h"
103 ColumnRef *cref,
bool error_if_no_field);
115 Oid *argtypes,
char *argmodes,
116 Node *call_expr,
bool forValidator,
142 bool function_valid =
false;
143 bool hashkey_valid =
false;
150 elog(
ERROR,
"cache lookup failed for function %u", funcOid);
164 hashkey_valid =
true;
175 function_valid =
true;
224 &hashkey, forValidator);
292 int num_out_args = 0;
296 int *in_arg_varnos = NULL;
315 plerrcontext.arg = &cbarg;
367 else if (is_event_trigger)
372 function->fn_prokind = procStruct->prokind;
375 function->requires_procedure_resowner =
false;
402 &argtypes, &argnames, &argmodes);
409 in_arg_varnos = (
int *)
palloc(numargs *
sizeof(
int));
417 for (
i = 0;
i < numargs;
i++)
420 Oid argtypeid = argtypes[
i];
421 char argmode = argmodes ? argmodes[
i] : PROARGMODE_IN;
440 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
441 errmsg(
"PL/pgSQL functions cannot accept type %s",
449 argnames[
i][0] !=
'\0') ?
464 if (argmode == PROARGMODE_IN ||
465 argmode == PROARGMODE_INOUT ||
466 argmode == PROARGMODE_VARIADIC)
467 in_arg_varnos[num_in_args++] = argvariable->
dno;
468 if (argmode == PROARGMODE_OUT ||
469 argmode == PROARGMODE_INOUT ||
470 argmode == PROARGMODE_TABLE)
471 out_arg_variables[num_out_args++] = argvariable;
477 if (argnames && argnames[
i][0] !=
'\0')
488 if (num_out_args > 1 ||
489 (num_out_args == 1 &&
function->fn_prokind == PROKIND_PROCEDURE))
497 else if (num_out_args == 1)
498 function->out_param_varno = out_arg_variables[0]->
dno;
510 rettypeid = procStruct->prorettype;
511 if (IsPolymorphicType(rettypeid))
515 if (rettypeid == ANYARRAYOID ||
516 rettypeid == ANYCOMPATIBLEARRAYOID)
517 rettypeid = INT4ARRAYOID;
518 else if (rettypeid == ANYRANGEOID ||
519 rettypeid == ANYCOMPATIBLERANGEOID)
520 rettypeid = INT4RANGEOID;
521 else if (rettypeid == ANYMULTIRANGEOID)
522 rettypeid = INT4MULTIRANGEOID;
532 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
533 errmsg(
"could not determine actual return type "
534 "for polymorphic function \"%s\"",
543 function->fn_retset = procStruct->proretset;
550 elog(
ERROR,
"cache lookup failed for type %u", rettypeid);
555 if (typeStruct->typtype == TYPTYPE_PSEUDO)
557 if (rettypeid == VOIDOID ||
558 rettypeid == RECORDOID)
560 else if (rettypeid == TRIGGEROID || rettypeid == EVENT_TRIGGEROID)
562 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
563 errmsg(
"trigger functions can only be called as triggers")));
566 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
567 errmsg(
"PL/pgSQL functions cannot return type %s",
572 function->fn_retisdomain = (typeStruct->typtype == TYPTYPE_DOMAIN);
573 function->fn_retbyval = typeStruct->typbyval;
574 function->fn_rettyplen = typeStruct->typlen;
581 if (IsPolymorphicType(procStruct->prorettype) &&
604 if (procStruct->pronargs != 0)
606 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
607 errmsg(
"trigger functions cannot have declared arguments"),
608 errhint(
"The arguments of the trigger can be accessed through TG_NARGS and TG_ARGV instead.")));
738 if (procStruct->pronargs != 0)
740 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
741 errmsg(
"event trigger functions cannot have declared arguments")));
768 elog(
ERROR,
"unrecognized function typecode: %d",
774 function->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
792 elog(
ERROR,
"plpgsql parser returned %d", parse_rc);
804 if (num_out_args > 0 ||
function->fn_rettype == VOIDOID ||
811 function->fn_nargs = procStruct->pronargs;
853 char *func_name =
"inline_code_block";
874 plerrcontext.arg = &cbarg;
891 "PL/pgSQL inline code context",
911 function->requires_procedure_resowner =
false;
923 function->fn_prokind = PROKIND_FUNCTION;
950 elog(
ERROR,
"plpgsql parser returned %d", parse_rc);
959 if (
function->fn_rettype == VOIDOID)
1010 errcontext(
"compilation of PL/pgSQL function \"%s\" near line %d",
1032 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1033 errmsg(
"parameter name \"%s\" used more than once",
1052 if (
function->action->exceptions != NULL ||
1059 new->stmtid = ++
function->nstatements;
1071 new->stmtid = ++
function->nstatements;
1073 new->retvarno =
function->out_param_varno;
1139 if (myvar != NULL && var != NULL)
1146 (
errcode(ERRCODE_AMBIGUOUS_COLUMN),
1147 errmsg(
"column reference \"%s\" is ambiguous",
1149 errdetail(
"It could refer to either a PL/pgSQL variable or a table column."),
1188 ColumnRef *cref,
bool error_if_no_field)
1193 const char *name2 = NULL;
1194 const char *name3 = NULL;
1195 const char *colname = NULL;
1197 int nnames_scalar = 0;
1198 int nnames_wholerow = 0;
1199 int nnames_field = 0;
1226 nnames_wholerow = 1;
1241 nnames_wholerow = 1;
1248 nnames_wholerow = 2;
1266 nnames_wholerow = 2;
1281 name1, name2, name3,
1290 if (nnames == nnames_scalar)
1294 if (nnames == nnames_wholerow)
1296 if (nnames == nnames_field)
1310 if (strcmp(fld->
fieldname, colname) == 0)
1323 if (error_if_no_field)
1325 (
errcode(ERRCODE_UNDEFINED_COLUMN),
1326 errmsg(
"record \"%s\" has no field \"%s\"",
1327 (nnames_field == 1) ? name1 : name2,
1354 Assert(dno >= 0 && dno < estate->ndatums);
1355 datum = estate->
datums[dno];
1370 ¶m->paramtypmod,
1371 ¶m->paramcollid);
1374 return (
Node *) param;
1424 wdatum->
ident = word1;
1425 wdatum->
quoted = (yytxt[0] ==
'"');
1431 elog(
ERROR,
"unrecognized plpgsql itemtype: %d",
1441 word->ident = word1;
1442 word->quoted = (yytxt[0] ==
'"');
1484 wdatum->
ident = NULL;
1511 wdatum->
ident = NULL;
1555 word1, word2, word3,
1589 wdatum->
ident = NULL;
1644 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1645 errmsg(
"variable \"%s\" does not exist",
ident)));
1665 const char *fldname = NULL;
1733 (
errcode(ERRCODE_UNDEFINED_COLUMN),
1734 errmsg(
"column \"%s\" of relation \"%s\" does not exist",
1741 elog(
ERROR,
"cache lookup failed for type %u", attrStruct->atttypid);
1750 attrStruct->atttypmod,
1751 attrStruct->attcollation,
1787 errmsg(
"relation \"%s\" does not exist",
ident)));
1793 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1794 errmsg(
"relation \"%s\" does not have a composite type",
1831 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1832 errmsg(
"relation \"%s\" does not have a composite type",
1857 switch (dtype->
ttype)
1897 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1898 errmsg(
"variable \"%s\" has pseudo-type %s",
1949 row->
refname =
"(unnamed row)";
1956 for (
i = 0;
i < numvars;
i++)
1971 typmod = ((
PLpgSQL_var *) var)->datatype->atttypmod;
1972 typcoll = ((
PLpgSQL_var *) var)->datatype->collation;
2022 if (strcmp(fld->
fieldname, fldname) == 0)
2064 elog(
ERROR,
"cache lookup failed for type %u", typeOid);
2084 if (!typeStruct->typisdefined)
2086 (
errcode(ERRCODE_UNDEFINED_OBJECT),
2087 errmsg(
"type \"%s\" is only a shell",
2088 NameStr(typeStruct->typname))));
2093 typ->
typoid = typeStruct->oid;
2094 switch (typeStruct->typtype)
2099 case TYPTYPE_MULTIRANGE:
2102 case TYPTYPE_COMPOSITE:
2105 case TYPTYPE_DOMAIN:
2111 case TYPTYPE_PSEUDO:
2112 if (typ->
typoid == RECORDOID)
2119 (
int) typeStruct->typtype);
2122 typ->
typlen = typeStruct->typlen;
2123 typ->
typbyval = typeStruct->typbyval;
2124 typ->
typtype = typeStruct->typtype;
2125 typ->
collation = typeStruct->typcollation;
2130 if (typeStruct->typtype == TYPTYPE_BASE)
2136 typ->
typisarray = (IsTrueArrayType(typeStruct) &&
2137 typeStruct->typstorage != TYPSTORAGE_PLAIN);
2139 else if (typeStruct->typtype == TYPTYPE_DOMAIN)
2142 typ->
typisarray = (typeStruct->typlen == -1 &&
2143 typeStruct->typstorage != TYPSTORAGE_PLAIN &&
2163 if (typentry->
typtype == TYPTYPE_DOMAIN)
2166 if (typentry->
tupDesc == NULL)
2168 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
2169 errmsg(
"type %s is not composite",
2204 (
errcode(ERRCODE_UNDEFINED_OBJECT),
2205 errmsg(
"could not find array type for data type %s",
2227 if (strlen(condname) == 5 &&
2228 strspn(condname,
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") == 5)
2243 (
errcode(ERRCODE_UNDEFINED_OBJECT),
2244 errmsg(
"unrecognized exception condition \"%s\"",
2272 if (strcmp(condname,
"others") == 0)
2275 new->sqlerrstate = 0;
2276 new->condname = condname;
2288 new->condname = condname;
2296 (
errcode(ERRCODE_UNDEFINED_OBJECT),
2297 errmsg(
"unrecognized exception condition \"%s\"",
2344 Size copiable_size = 0;
2367 function->copiable_size = copiable_size;
2413 *varnos = (
int *)
palloc(
sizeof(
int) * n);
2471 if (hashkey->
isTrigger && !forValidator)
2481 if (procStruct->pronargs > 0)
2484 memcpy(hashkey->
argtypes, procStruct->proargtypes.values,
2485 procStruct->pronargs *
sizeof(
Oid));
2493 NameStr(procStruct->proname));
2511 Oid *argtypes,
char *argmodes,
2512 Node *call_expr,
bool forValidator,
2525 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2526 errmsg(
"could not determine actual argument "
2527 "type for polymorphic function \"%s\"",
2531 for (
i = 0;
i < numargs;
i++)
2533 char argmode = argmodes ? argmodes[
i] : PROARGMODE_IN;
2535 if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE)
2537 if (argtypes[
i] == RECORDOID || argtypes[
i] == RECORDARRAYOID)
2543 argtypes[
i] = resolvedtype;
2551 for (
i = 0;
i < numargs;
i++)
2553 switch (argtypes[
i])
2556 case ANYNONARRAYOID:
2558 case ANYCOMPATIBLEOID:
2559 case ANYCOMPATIBLENONARRAYOID:
2560 argtypes[
i] = INT4OID;
2563 case ANYCOMPATIBLEARRAYOID:
2564 argtypes[
i] = INT4ARRAYOID;
2567 case ANYCOMPATIBLERANGEOID:
2568 argtypes[
i] = INT4RANGEOID;
2570 case ANYMULTIRANGEOID:
2571 argtypes[
i] = INT4MULTIRANGEOID;
2649 elog(
WARNING,
"trying to insert a function that already exists");
2670 elog(
WARNING,
"trying to delete function that does not exist");
Bitmapset * bms_add_member(Bitmapset *a, int x)
#define TextDatumGetCString(d)
#define Assert(condition)
#define MemSet(start, val, len)
#define OidIsValid(objectId)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
int errdetail(const char *fmt,...)
ErrorContextCallback * error_context_stack
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define MAKE_SQLSTATE(ch1, ch2, ch3, ch4, ch5)
#define ereport(elevel,...)
#define CALLED_AS_EVENT_TRIGGER(fcinfo)
Oid get_call_expr_argtype(Node *expr, int argnum)
Oid get_fn_expr_rettype(FmgrInfo *flinfo)
bool resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, Node *call_expr)
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
bool check_function_bodies
#define HeapTupleIsValid(tuple)
#define HeapTupleHeaderGetRawXmin(tup)
if(TABLE==NULL||TABLE_index==NULL)
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
List * lappend(List *list, void *datum)
List * list_copy(const List *oldlist)
List * list_delete_last(List *list)
bool type_is_rowtype(Oid typid)
Oid get_rel_type_id(Oid relid)
Oid get_base_element_type(Oid typid)
Oid get_array_type(Oid typid)
TypeName * makeTypeNameFromNameList(List *names)
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
TypeName * makeTypeName(char *typnam)
void * MemoryContextAlloc(MemoryContext context, Size size)
void * MemoryContextAllocZero(MemoryContext context, Size size)
char * pstrdup(const char *in)
void * repalloc(void *pointer, Size size)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext TopMemoryContext
MemoryContext CurrentMemoryContext
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
char * NameListToString(const List *names)
RangeVar * makeRangeVarFromNameList(const List *names)
Oid RelnameGetRelid(const char *relname)
#define RangeVarGetRelid(relation, lockmode, missing_ok)
#define IsA(nodeptr, _type_)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
int parser_errposition(ParseState *pstate, int location)
FormData_pg_attribute * Form_pg_attribute
on_exit_nicely_callback function
static int list_length(const List *l)
#define list_make3(x1, x2, x3)
#define list_make2(x1, x2)
bool function_parse_error_transpose(const char *prosrc)
FormData_pg_proc * Form_pg_proc
FormData_pg_type * Form_pg_type
#define ERRCODE_UNDEFINED_TABLE
static void add_dummy_return(PLpgSQL_function *function)
static PLpgSQL_row * build_row_from_vars(PLpgSQL_variable **vars, int numvars)
PLpgSQL_condition * plpgsql_parse_err_condition(char *condname)
void plpgsql_parser_setup(struct ParseState *pstate, PLpgSQL_expr *expr)
PLpgSQL_recfield * plpgsql_build_recfield(PLpgSQL_rec *rec, const char *fldname)
int plpgsql_add_initdatums(int **varnos)
MemoryContext plpgsql_compile_tmp_cxt
static Node * make_datum_param(PLpgSQL_expr *expr, int dno, int location)
static void plpgsql_HashTableInsert(PLpgSQL_function *function, PLpgSQL_func_hashkey *func_key)
int plpgsql_recognize_err_condition(const char *condname, bool allow_sqlstate)
struct plpgsql_hashent plpgsql_HashEnt
static void plpgsql_compile_error_callback(void *arg)
PLpgSQL_type * plpgsql_parse_cwordrowtype(List *idents)
static void compute_function_hashkey(FunctionCallInfo fcinfo, Form_pg_proc procStruct, PLpgSQL_func_hashkey *hashkey, bool forValidator)
void plpgsql_HashTableInit(void)
static Node * plpgsql_param_ref(ParseState *pstate, ParamRef *pref)
static void plpgsql_start_datums(void)
char * plpgsql_error_funcname
static PLpgSQL_function * plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key)
PLpgSQL_stmt_block * plpgsql_parse_result
bool plpgsql_check_syntax
static const ExceptionLabelMap exception_label_map[]
static PLpgSQL_function * do_compile(FunctionCallInfo fcinfo, HeapTuple procTup, PLpgSQL_function *function, PLpgSQL_func_hashkey *hashkey, bool forValidator)
PLpgSQL_type * plpgsql_build_datatype_arrayof(PLpgSQL_type *dtype)
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation, TypeName *origtypname)
static void plpgsql_finish_datums(PLpgSQL_function *function)
PLpgSQL_function * plpgsql_curr_compile
PLpgSQL_function * plpgsql_compile(FunctionCallInfo fcinfo, bool forValidator)
bool plpgsql_parse_dblword(char *word1, char *word2, PLwdatum *wdatum, PLcword *cword)
PLpgSQL_type * plpgsql_parse_wordtype(char *ident)
void plpgsql_adddatum(PLpgSQL_datum *newdatum)
PLpgSQL_datum ** plpgsql_Datums
bool plpgsql_parse_word(char *word1, const char *yytxt, bool lookup, PLwdatum *wdatum, PLword *word)
bool plpgsql_DumpExecTree
PLpgSQL_type * plpgsql_parse_cwordtype(List *idents)
static void plpgsql_resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, Node *call_expr, bool forValidator, const char *proname)
static Node * resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr, ColumnRef *cref, bool error_if_no_field)
PLpgSQL_rec * plpgsql_build_record(const char *refname, int lineno, PLpgSQL_type *dtype, Oid rectypeid, bool add2namespace)
static void add_parameter_name(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
static void plpgsql_HashTableDelete(PLpgSQL_function *function)
bool plpgsql_parse_tripword(char *word1, char *word2, char *word3, PLwdatum *wdatum, PLcword *cword)
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation, TypeName *origtypname)
static Node * plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref)
PLpgSQL_type * plpgsql_parse_wordrowtype(char *ident)
static void delete_function(PLpgSQL_function *func)
static Node * plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
static HTAB * plpgsql_HashTable
PLpgSQL_variable * plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype, bool add2namespace)
PLpgSQL_function * plpgsql_compile_inline(char *proc_source)
void plpgsql_exec_get_datum_type_info(PLpgSQL_execstate *estate, PLpgSQL_datum *datum, Oid *typeId, int32 *typMod, Oid *collation)
void plpgsql_ns_init(void)
PLpgSQL_nsitem * plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode, const char *name1, const char *name2, const char *name3, int *names_used)
void plpgsql_dumptree(PLpgSQL_function *func)
void plpgsql_free_function_memory(PLpgSQL_function *func)
void plpgsql_ns_additem(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
void plpgsql_ns_push(const char *label, PLpgSQL_label_type label_type)
PLpgSQL_nsitem * plpgsql_ns_top(void)
int plpgsql_variable_conflict
int plpgsql_extra_warnings
bool plpgsql_print_strict_params
IdentifierLookup plpgsql_IdentifierLookup
void plpgsql_scanner_finish(yyscan_t yyscanner)
yyscan_t plpgsql_scanner_init(const char *str)
int plpgsql_latest_lineno(yyscan_t yyscanner)
@ PLPGSQL_RESOLVE_VARIABLE
struct PLpgSQL_func_hashkey PLpgSQL_func_hashkey
int plpgsql_yyparse(yyscan_t yyscanner)
@ IDENTIFIER_LOOKUP_DECLARE
@ IDENTIFIER_LOOKUP_NORMAL
@ PLPGSQL_PROMISE_TG_RELID
@ PLPGSQL_PROMISE_TG_WHEN
@ PLPGSQL_PROMISE_TG_ARGV
@ PLPGSQL_PROMISE_TG_TABLE_SCHEMA
@ PLPGSQL_PROMISE_TG_EVENT
@ PLPGSQL_PROMISE_TG_TABLE_NAME
@ PLPGSQL_PROMISE_TG_LEVEL
@ PLPGSQL_PROMISE_TG_NARGS
@ PLPGSQL_PROMISE_TG_NAME
static Datum ObjectIdGetDatum(Oid X)
static void word(struct vars *v, int dir, struct state *lp, struct state *rp)
char * format_procedure(Oid procedure_oid)
struct ErrorContextCallback * previous
struct PLpgSQL_nsitem * ns
struct PLpgSQL_function * func
Oid argtypes[FUNC_MAX_ARGS]
struct PLpgSQL_execstate * cur_estate
PLpgSQL_resolve_option resolve_option
PLpgSQL_nsitem_type itemtype
ExpandedRecordHeader * erh
ParseParamRefHook p_paramref_hook
PreParseColumnRefHook p_pre_columnref_hook
PostParseColumnRefHook p_post_columnref_hook
uint64 tupDesc_identifier
PLpgSQL_function * function
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
#define CALLED_AS_TRIGGER(fcinfo)
TupleDesc CreateTemplateTupleDesc(int natts)
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
#define INVALID_TUPLEDESC_IDENTIFIER
#define TYPECACHE_TUPDESC
#define TYPECACHE_DOMAIN_BASE_INFO
String * makeString(char *str)