29 #include "utils/fmgroids.h" 70 #define FUNCS_PER_USER 128 83 #include "plerrcodes.h" 104 ColumnRef *cref,
bool error_if_no_field);
116 Oid *argtypes,
char *argmodes,
117 Node *call_expr,
bool forValidator,
143 bool function_valid =
false;
144 bool hashkey_valid =
false;
151 elog(
ERROR,
"cache lookup failed for function %u", funcOid);
165 hashkey_valid =
true;
176 function_valid =
true;
224 function =
do_compile(fcinfo, procTup,
function,
225 &hashkey, forValidator);
286 int num_out_args = 0;
290 int *in_arg_varnos = NULL;
300 Anum_pg_proc_prosrc, &isnull);
312 plerrcontext.
arg = forValidator ? proc_source : NULL;
327 if (
function == NULL)
337 plpgsql_curr_compile =
function;
352 function->fn_tid = procTup->
t_self;
353 function->fn_input_collation = fcinfo->
fncollation;
354 function->fn_cxt = func_cxt;
355 function->out_param_varno = -1;
364 else if (is_event_trigger)
369 function->fn_prokind = procStruct->prokind;
371 function->nstatements = 0;
372 function->requires_procedure_resowner =
false;
399 &argtypes, &argnames, &argmodes);
406 in_arg_varnos = (
int *)
palloc(numargs *
sizeof(
int));
414 for (i = 0; i < numargs; i++)
417 Oid argtypeid = argtypes[
i];
418 char argmode = argmodes ? argmodes[
i] : PROARGMODE_IN;
424 snprintf(buf,
sizeof(buf),
"$%d", i + 1);
437 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
438 errmsg(
"PL/pgSQL functions cannot accept type %s",
446 argnames[i][0] !=
'\0') ?
461 if (argmode == PROARGMODE_IN ||
462 argmode == PROARGMODE_INOUT ||
464 argmode == PROARGMODE_VARIADIC)
465 in_arg_varnos[num_in_args++] = argvariable->
dno;
466 if (argmode == PROARGMODE_OUT ||
467 argmode == PROARGMODE_INOUT ||
468 argmode == PROARGMODE_TABLE)
469 out_arg_variables[num_out_args++] = argvariable;
475 if (argnames && argnames[i][0] !=
'\0')
486 if (num_out_args > 1 ||
493 function->out_param_varno = row->
dno;
495 else if (num_out_args == 1)
496 function->out_param_varno = out_arg_variables[0]->
dno;
508 rettypeid = procStruct->prorettype;
509 if (IsPolymorphicType(rettypeid))
513 if (rettypeid == ANYARRAYOID ||
514 rettypeid == ANYCOMPATIBLEARRAYOID)
515 rettypeid = INT4ARRAYOID;
516 else if (rettypeid == ANYRANGEOID ||
517 rettypeid == ANYCOMPATIBLERANGEOID)
518 rettypeid = INT4RANGEOID;
519 else if (rettypeid == ANYMULTIRANGEOID)
520 rettypeid = INT4MULTIRANGEOID;
530 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
531 errmsg(
"could not determine actual return type " 532 "for polymorphic function \"%s\"",
540 function->fn_rettype = rettypeid;
541 function->fn_retset = procStruct->proretset;
548 elog(
ERROR,
"cache lookup failed for type %u", rettypeid);
553 if (typeStruct->typtype == TYPTYPE_PSEUDO)
555 if (rettypeid == VOIDOID ||
556 rettypeid == RECORDOID)
558 else if (rettypeid == TRIGGEROID || rettypeid == EVENT_TRIGGEROID)
560 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
561 errmsg(
"trigger functions can only be called as triggers")));
564 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
565 errmsg(
"PL/pgSQL functions cannot return type %s",
570 function->fn_retisdomain = (typeStruct->typtype == TYPTYPE_DOMAIN);
571 function->fn_retbyval = typeStruct->typbyval;
572 function->fn_rettyplen = typeStruct->typlen;
579 if (IsPolymorphicType(procStruct->prorettype) &&
596 function->fn_retbyval =
false;
597 function->fn_retistuple =
true;
598 function->fn_retisdomain =
false;
599 function->fn_retset =
false;
602 if (procStruct->pronargs != 0)
604 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
605 errmsg(
"trigger functions cannot have declared arguments"),
606 errhint(
"The arguments of the trigger can be accessed through TG_NARGS and TG_ARGV instead.")));
610 function->new_varno = rec->
dno;
614 function->old_varno = rec->
dno;
729 function->fn_rettype = VOIDOID;
730 function->fn_retbyval =
false;
731 function->fn_retistuple =
true;
732 function->fn_retisdomain =
false;
733 function->fn_retset =
false;
736 if (procStruct->pronargs != 0)
738 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
739 errmsg(
"event trigger functions cannot have declared arguments")));
766 elog(
ERROR,
"unrecognized function typecode: %d",
772 function->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
783 function->found_varno = var->
dno;
790 elog(
ERROR,
"plpgsql parser returned %d", parse_rc);
809 function->fn_nargs = procStruct->pronargs;
810 for (i = 0; i <
function->fn_nargs; i++)
833 plpgsql_compile_tmp_cxt = NULL;
850 char *func_name =
"inline_code_block";
870 plerrcontext.
arg = proc_source;
880 plpgsql_curr_compile =
function;
887 "PL/pgSQL inline code context",
891 function->fn_signature =
pstrdup(func_name);
894 function->fn_cxt = func_cxt;
895 function->out_param_varno = -1;
903 function->extra_warnings = 0;
904 function->extra_errors = 0;
906 function->nstatements = 0;
907 function->requires_procedure_resowner =
false;
915 function->fn_rettype = VOIDOID;
916 function->fn_retset =
false;
917 function->fn_retistuple =
false;
918 function->fn_retisdomain =
false;
919 function->fn_prokind = PROKIND_FUNCTION;
921 function->fn_retbyval =
true;
922 function->fn_rettyplen =
sizeof(
int32);
928 function->fn_readonly =
false;
939 function->found_varno = var->
dno;
946 elog(
ERROR,
"plpgsql parser returned %d", parse_rc);
961 function->fn_nargs = 0;
974 plpgsql_compile_tmp_cxt = NULL;
1003 errcontext(
"compilation of PL/pgSQL function \"%s\" near line %d",
1025 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1026 errmsg(
"parameter name \"%s\" used more than once",
1050 new->stmtid = ++
function->nstatements;
1053 function->action =
new;
1062 new->stmtid = ++
function->nstatements;
1064 new->retvarno =
function->out_param_varno;
1130 if (myvar != NULL && var != NULL)
1137 (
errcode(ERRCODE_AMBIGUOUS_COLUMN),
1138 errmsg(
"column reference \"%s\" is ambiguous",
1140 errdetail(
"It could refer to either a PL/pgSQL variable or a table column."),
1179 ColumnRef *cref,
bool error_if_no_field)
1184 const char *name2 = NULL;
1185 const char *name3 = NULL;
1186 const char *colname = NULL;
1188 int nnames_scalar = 0;
1189 int nnames_wholerow = 0;
1190 int nnames_field = 0;
1218 nnames_wholerow = 1;
1234 nnames_wholerow = 1;
1242 nnames_wholerow = 2;
1262 nnames_wholerow = 2;
1278 name1, name2, name3,
1287 if (nnames == nnames_scalar)
1291 if (nnames == nnames_wholerow)
1293 if (nnames == nnames_field)
1307 if (strcmp(fld->
fieldname, colname) == 0)
1320 if (error_if_no_field)
1322 (
errcode(ERRCODE_UNDEFINED_COLUMN),
1323 errmsg(
"record \"%s\" has no field \"%s\"",
1324 (nnames_field == 1) ? name1 : name2,
1351 Assert(dno >= 0 && dno < estate->ndatums);
1352 datum = estate->
datums[dno];
1371 return (
Node *) param;
1421 wdatum->
ident = word1;
1422 wdatum->
quoted = (yytxt[0] ==
'"');
1428 elog(
ERROR,
"unrecognized plpgsql itemtype: %d",
1438 word->
ident = word1;
1439 word->
quoted = (yytxt[0] ==
'"');
1481 wdatum->
ident = NULL;
1508 wdatum->
ident = NULL;
1552 word1, word2, word3,
1586 wdatum->
ident = NULL;
1653 if (!typeStruct->typisdefined ||
1685 const char *fldname;
1749 if (classStruct->relkind != RELKIND_RELATION &&
1750 classStruct->relkind != RELKIND_SEQUENCE &&
1751 classStruct->relkind != RELKIND_VIEW &&
1752 classStruct->relkind != RELKIND_MATVIEW &&
1753 classStruct->relkind != RELKIND_COMPOSITE_TYPE &&
1754 classStruct->relkind != RELKIND_FOREIGN_TABLE &&
1755 classStruct->relkind != RELKIND_PARTITIONED_TABLE)
1769 elog(
ERROR,
"cache lookup failed for type %u", attrStruct->atttypid);
1778 attrStruct->atttypmod,
1779 attrStruct->attcollation,
1817 errmsg(
"relation \"%s\" does not exist", ident)));
1823 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1824 errmsg(
"relation \"%s\" does not have a composite type",
1865 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1866 errmsg(
"relation \"%s\" does not have a composite type",
1891 switch (dtype->
ttype)
1931 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1932 errmsg(
"variable \"%s\" has pseudo-type %s",
1983 row->
refname =
"(unnamed row)";
1990 for (i = 0; i < numvars; i++)
2005 typmod = ((
PLpgSQL_var *) var)->datatype->atttypmod;
2006 typcoll = ((
PLpgSQL_var *) var)->datatype->collation;
2056 if (strcmp(fld->
fieldname, fldname) == 0)
2098 elog(
ERROR,
"cache lookup failed for type %u", typeOid);
2118 if (!typeStruct->typisdefined)
2120 (
errcode(ERRCODE_UNDEFINED_OBJECT),
2121 errmsg(
"type \"%s\" is only a shell",
2122 NameStr(typeStruct->typname))));
2127 typ->
typoid = typeStruct->oid;
2128 switch (typeStruct->typtype)
2133 case TYPTYPE_MULTIRANGE:
2136 case TYPTYPE_COMPOSITE:
2139 case TYPTYPE_DOMAIN:
2145 case TYPTYPE_PSEUDO:
2146 if (typ->
typoid == RECORDOID)
2153 (
int) typeStruct->typtype);
2156 typ->
typlen = typeStruct->typlen;
2157 typ->
typbyval = typeStruct->typbyval;
2158 typ->
typtype = typeStruct->typtype;
2159 typ->
collation = typeStruct->typcollation;
2164 if (typeStruct->typtype == TYPTYPE_BASE)
2170 typ->
typisarray = (IsTrueArrayType(typeStruct) &&
2171 typeStruct->typstorage != TYPSTORAGE_PLAIN);
2173 else if (typeStruct->typtype == TYPTYPE_DOMAIN)
2176 typ->
typisarray = (typeStruct->typlen == -1 &&
2177 typeStruct->typstorage != TYPSTORAGE_PLAIN &&
2197 if (typentry->
typtype == TYPTYPE_DOMAIN)
2200 if (typentry->
tupDesc == NULL)
2202 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
2203 errmsg(
"type %s is not composite",
2234 if (strlen(condname) == 5 &&
2235 strspn(condname,
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") == 5)
2243 for (i = 0; exception_label_map[
i].
label != NULL; i++)
2245 if (strcmp(condname, exception_label_map[i].
label) == 0)
2250 (
errcode(ERRCODE_UNDEFINED_OBJECT),
2251 errmsg(
"unrecognized exception condition \"%s\"",
2279 if (strcmp(condname,
"others") == 0)
2282 new->sqlerrstate = 0;
2283 new->condname = condname;
2289 for (i = 0; exception_label_map[
i].
label != NULL; i++)
2291 if (strcmp(condname, exception_label_map[i].
label) == 0)
2295 new->condname = condname;
2303 (
errcode(ERRCODE_UNDEFINED_OBJECT),
2304 errmsg(
"unrecognized exception condition \"%s\"",
2351 Size copiable_size = 0;
2358 function->datums[
i] = plpgsql_Datums[
i];
2374 function->copiable_size = copiable_size;
2404 switch (plpgsql_Datums[i]->dtype)
2420 *varnos = (
int *)
palloc(
sizeof(
int) * n);
2425 switch (plpgsql_Datums[i]->dtype)
2429 (*varnos)[n++] = plpgsql_Datums[
i]->
dno;
2478 if (hashkey->
isTrigger && !forValidator)
2488 if (procStruct->pronargs > 0)
2491 memcpy(hashkey->
argtypes, procStruct->proargtypes.values,
2492 procStruct->pronargs *
sizeof(
Oid));
2500 NameStr(procStruct->proname));
2512 Oid *argtypes,
char *argmodes,
2513 Node *call_expr,
bool forValidator,
2524 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2525 errmsg(
"could not determine actual argument " 2526 "type for polymorphic function \"%s\"",
2532 for (i = 0; i < numargs; i++)
2534 switch (argtypes[i])
2537 case ANYNONARRAYOID:
2539 case ANYCOMPATIBLEOID:
2540 case ANYCOMPATIBLENONARRAYOID:
2541 argtypes[
i] = INT4OID;
2544 case ANYCOMPATIBLEARRAYOID:
2545 argtypes[
i] = INT4ARRAYOID;
2548 case ANYCOMPATIBLERANGEOID:
2549 argtypes[
i] = INT4RANGEOID;
2551 case ANYMULTIRANGEOID:
2552 argtypes[
i] = INT4MULTIRANGEOID;
2593 Assert(plpgsql_HashTable == NULL);
2597 plpgsql_HashTable =
hash_create(
"PLpgSQL function hash",
2630 elog(
WARNING,
"trying to insert a function that already exists");
2647 (
void *)
function->fn_hashkey,
2651 elog(
WARNING,
"trying to delete function that does not exist");
2654 function->fn_hashkey = NULL;
#define list_make2(x1, x2)
Value * makeString(char *str)
bool resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, Node *call_expr)
Type LookupTypeName(ParseState *pstate, const TypeName *typeName, int32 *typmod_p, bool missing_ok)
PLpgSQL_function * plpgsql_compile_inline(char *proc_source)
#define list_make3(x1, x2, x3)
int plpgsql_yyparse(void)
int plpgsql_latest_lineno(void)
void plpgsql_free_function_memory(PLpgSQL_function *func)
int fn_argvarnos[FUNC_MAX_ARGS]
Oid argtypes[FUNC_MAX_ARGS]
#define CALLED_AS_EVENT_TRIGGER(fcinfo)
#define IsA(nodeptr, _type_)
PLpgSQL_datum ** plpgsql_Datums
#define AllocSetContextCreate
PLpgSQL_func_hashkey * fn_hashkey
PLpgSQL_type * plpgsql_parse_wordrowtype(char *ident)
int errhint(const char *fmt,...)
static PLpgSQL_function * do_compile(FunctionCallInfo fcinfo, HeapTuple procTup, PLpgSQL_function *function, PLpgSQL_func_hashkey *hashkey, bool forValidator)
PLpgSQL_nsitem * plpgsql_ns_top(void)
bool plpgsql_parse_dblword(char *word1, char *word2, PLwdatum *wdatum, PLcword *cword)
#define ERRCODE_UNDEFINED_TABLE
static void compute_function_hashkey(FunctionCallInfo fcinfo, Form_pg_proc procStruct, PLpgSQL_func_hashkey *hashkey, bool forValidator)
TupleDesc CreateTemplateTupleDesc(int natts)
PLpgSQL_rec * plpgsql_build_record(const char *refname, int lineno, PLpgSQL_type *dtype, Oid rectypeid, bool add2namespace)
PLpgSQL_stmt_block * action
Oid RelnameGetRelid(const char *relname)
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation, TypeName *origtypname)
#define MAKE_SQLSTATE(ch1, ch2, ch3, ch4, ch5)
static Node * plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref)
#define RangeVarGetRelid(relation, lockmode, missing_ok)
PLpgSQL_nsitem * plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode, const char *name1, const char *name2, const char *name3, int *names_used)
char * pstrdup(const char *in)
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
void plpgsql_ns_additem(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
void plpgsql_HashTableInit(void)
PLpgSQL_recfield * plpgsql_build_recfield(PLpgSQL_rec *rec, const char *fldname)
int plpgsql_recognize_err_condition(const char *condname, bool allow_sqlstate)
ExpandedRecordHeader * erh
PLpgSQL_type * plpgsql_parse_wordtype(char *ident)
int errcode(int sqlerrcode)
#define MemSet(start, val, len)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
bool check_function_bodies
void plpgsql_dumptree(PLpgSQL_function *func)
void(* callback)(void *arg)
struct ErrorContextCallback * previous
#define OidIsValid(objectId)
#define INVALID_TUPLEDESC_IDENTIFIER
static void plpgsql_resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, Node *call_expr, bool forValidator, const char *proname)
static void plpgsql_HashTableInsert(PLpgSQL_function *function, PLpgSQL_func_hashkey *func_key)
static void plpgsql_start_datums(void)
PostParseColumnRefHook p_post_columnref_hook
void plpgsql_adddatum(PLpgSQL_datum *newdatum)
PLpgSQL_resolve_option resolve_option
static HTAB * plpgsql_HashTable
ErrorContextCallback * error_context_stack
static void delete_function(PLpgSQL_function *func)
struct plpgsql_hashent plpgsql_HashEnt
void plpgsql_scanner_finish(void)
static PLpgSQL_function * plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key)
void pfree(void *pointer)
PLpgSQL_function * plpgsql_compile(FunctionCallInfo fcinfo, bool forValidator)
bool plpgsql_check_syntax
#define ObjectIdGetDatum(X)
char * plpgsql_error_funcname
struct PLpgSQL_execstate * cur_estate
struct PLpgSQL_func_hashkey PLpgSQL_func_hashkey
bool plpgsql_DumpExecTree
PLpgSQL_type * plpgsql_parse_cwordtype(List *idents)
static void add_parameter_name(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
int plpgsql_extra_warnings
#define ALLOCSET_DEFAULT_SIZES
struct PLpgSQL_nsitem * ns
void plpgsql_parser_setup(struct ParseState *pstate, PLpgSQL_expr *expr)
static void add_dummy_return(PLpgSQL_function *function)
ParseParamRefHook p_paramref_hook
int errdetail(const char *fmt,...)
static Node * plpgsql_param_ref(ParseState *pstate, ParamRef *pref)
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
FormData_pg_attribute * Form_pg_attribute
MemoryContext CurrentMemoryContext
void plpgsql_ns_init(void)
bool type_is_rowtype(Oid typid)
PLpgSQL_function * function
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
void plpgsql_exec_get_datum_type_info(PLpgSQL_execstate *estate, PLpgSQL_datum *datum, Oid *typeId, int32 *typMod, Oid *collation)
MemoryContext TopMemoryContext
List * lappend(List *list, void *datum)
#define TYPECACHE_DOMAIN_BASE_INFO
HeapTuple SearchSysCache1(int cacheId, Datum key1)
char * NameListToString(List *names)
#define TextDatumGetCString(d)
void * palloc0(Size size)
static void plpgsql_HashTableDelete(PLpgSQL_function *function)
IdentifierLookup plpgsql_IdentifierLookup
Oid get_fn_expr_rettype(FmgrInfo *flinfo)
void ReleaseSysCache(HeapTuple tuple)
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation, TypeName *origtypname)
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Oid get_rel_type_id(Oid relid)
FormData_pg_proc * Form_pg_proc
void * MemoryContextAllocZero(MemoryContext context, Size size)
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
struct PLpgSQL_function * func
TypeName * makeTypeName(char *typnam)
#define ereport(elevel,...)
PLpgSQL_trigtype fn_is_trigger
bool plpgsql_print_strict_params
char * format_procedure(Oid procedure_oid)
static void plpgsql_compile_error_callback(void *arg)
int plpgsql_variable_conflict
#define HeapTupleIsValid(tuple)
#define CALLED_AS_TRIGGER(fcinfo)
PLpgSQL_type * plpgsql_parse_cwordrowtype(List *idents)
#define Assert(condition)
bool plpgsql_parse_word(char *word1, const char *yytxt, bool lookup, PLwdatum *wdatum, PLword *word)
PLpgSQL_exception_block * exceptions
static Node * resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr, ColumnRef *cref, bool error_if_no_field)
bool function_parse_error_transpose(const char *prosrc)
FormData_pg_type * Form_pg_type
void plpgsql_ns_push(const char *label, PLpgSQL_label_type label_type)
static int list_length(const List *l)
int parser_errposition(ParseState *pstate, int location)
PLpgSQL_stmt_block * plpgsql_parse_result
PLpgSQL_variable * plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype, bool add2namespace)
static const ExceptionLabelMap exception_label_map[]
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
#define HeapTupleHeaderGetRawXmin(tup)
uint64 tupDesc_identifier
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Bitmapset * bms_add_member(Bitmapset *a, int x)
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
void * repalloc(void *pointer, Size size)
static void word(struct vars *, int, struct state *, struct state *)
int plpgsql_add_initdatums(int **varnos)
void plpgsql_scanner_init(const char *str)
FormData_pg_class * Form_pg_class
Oid get_base_element_type(Oid typid)
int errmsg(const char *fmt,...)
static void plpgsql_finish_datums(PLpgSQL_function *function)
void * MemoryContextAlloc(MemoryContext context, Size size)
PLpgSQL_nsitem_type itemtype
bool plpgsql_parse_tripword(char *word1, char *word2, char *word3, PLwdatum *wdatum, PLcword *cword)
TypeName * makeTypeNameFromNameList(List *names)
MemoryContext plpgsql_compile_tmp_cxt
PreParseColumnRefHook p_pre_columnref_hook
PLpgSQL_condition * plpgsql_parse_err_condition(char *condname)
static PLpgSQL_row * build_row_from_vars(PLpgSQL_variable **vars, int numvars)
static Node * plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
#define TYPECACHE_TUPDESC
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
PLpgSQL_function * plpgsql_curr_compile
static Node * make_datum_param(PLpgSQL_expr *expr, int dno, int location)