PostgreSQL Source Code  git master
pl_comp.c File Reference
#include "postgres.h"
#include <ctype.h>
#include "access/htup_details.h"
#include "catalog/namespace.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "nodes/makefuncs.h"
#include "parser/parse_type.h"
#include "plpgsql.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/regproc.h"
#include "utils/rel.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
#include "plerrcodes.h"
Include dependency graph for pl_comp.c:

Go to the source code of this file.

Data Structures

struct  plpgsql_hashent
 
struct  ExceptionLabelMap
 

Macros

#define FUNCS_PER_USER   128 /* initial table size */
 

Typedefs

typedef struct plpgsql_hashent plpgsql_HashEnt
 

Functions

static PLpgSQL_functiondo_compile (FunctionCallInfo fcinfo, HeapTuple procTup, PLpgSQL_function *function, PLpgSQL_func_hashkey *hashkey, bool forValidator)
 
static void plpgsql_compile_error_callback (void *arg)
 
static void add_parameter_name (PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
 
static void add_dummy_return (PLpgSQL_function *function)
 
static Nodeplpgsql_pre_column_ref (ParseState *pstate, ColumnRef *cref)
 
static Nodeplpgsql_post_column_ref (ParseState *pstate, ColumnRef *cref, Node *var)
 
static Nodeplpgsql_param_ref (ParseState *pstate, ParamRef *pref)
 
static Noderesolve_column_ref (ParseState *pstate, PLpgSQL_expr *expr, ColumnRef *cref, bool error_if_no_field)
 
static Nodemake_datum_param (PLpgSQL_expr *expr, int dno, int location)
 
static PLpgSQL_rowbuild_row_from_vars (PLpgSQL_variable **vars, int numvars)
 
static PLpgSQL_typebuild_datatype (HeapTuple typeTup, int32 typmod, Oid collation, TypeName *origtypname)
 
static void plpgsql_start_datums (void)
 
static void plpgsql_finish_datums (PLpgSQL_function *function)
 
static void compute_function_hashkey (FunctionCallInfo fcinfo, Form_pg_proc procStruct, PLpgSQL_func_hashkey *hashkey, bool forValidator)
 
static void plpgsql_resolve_polymorphic_argtypes (int numargs, Oid *argtypes, char *argmodes, Node *call_expr, bool forValidator, const char *proname)
 
static PLpgSQL_functionplpgsql_HashTableLookup (PLpgSQL_func_hashkey *func_key)
 
static void plpgsql_HashTableInsert (PLpgSQL_function *function, PLpgSQL_func_hashkey *func_key)
 
static void plpgsql_HashTableDelete (PLpgSQL_function *function)
 
static void delete_function (PLpgSQL_function *func)
 
PLpgSQL_functionplpgsql_compile (FunctionCallInfo fcinfo, bool forValidator)
 
PLpgSQL_functionplpgsql_compile_inline (char *proc_source)
 
void plpgsql_parser_setup (struct ParseState *pstate, PLpgSQL_expr *expr)
 
bool plpgsql_parse_word (char *word1, const char *yytxt, bool lookup, PLwdatum *wdatum, PLword *word)
 
bool plpgsql_parse_dblword (char *word1, char *word2, PLwdatum *wdatum, PLcword *cword)
 
bool plpgsql_parse_tripword (char *word1, char *word2, char *word3, PLwdatum *wdatum, PLcword *cword)
 
PLpgSQL_typeplpgsql_parse_wordtype (char *ident)
 
PLpgSQL_typeplpgsql_parse_cwordtype (List *idents)
 
PLpgSQL_typeplpgsql_parse_wordrowtype (char *ident)
 
PLpgSQL_typeplpgsql_parse_cwordrowtype (List *idents)
 
PLpgSQL_variableplpgsql_build_variable (const char *refname, int lineno, PLpgSQL_type *dtype, bool add2namespace)
 
PLpgSQL_recplpgsql_build_record (const char *refname, int lineno, PLpgSQL_type *dtype, Oid rectypeid, bool add2namespace)
 
PLpgSQL_recfieldplpgsql_build_recfield (PLpgSQL_rec *rec, const char *fldname)
 
PLpgSQL_typeplpgsql_build_datatype (Oid typeOid, int32 typmod, Oid collation, TypeName *origtypname)
 
int plpgsql_recognize_err_condition (const char *condname, bool allow_sqlstate)
 
PLpgSQL_conditionplpgsql_parse_err_condition (char *condname)
 
void plpgsql_adddatum (PLpgSQL_datum *newdatum)
 
int plpgsql_add_initdatums (int **varnos)
 
void plpgsql_HashTableInit (void)
 

Variables

PLpgSQL_stmt_blockplpgsql_parse_result
 
static int datums_alloc
 
int plpgsql_nDatums
 
PLpgSQL_datum ** plpgsql_Datums
 
static int datums_last
 
char * plpgsql_error_funcname
 
bool plpgsql_DumpExecTree = false
 
bool plpgsql_check_syntax = false
 
PLpgSQL_functionplpgsql_curr_compile
 
MemoryContext plpgsql_compile_tmp_cxt
 
static HTABplpgsql_HashTable = NULL
 
static const ExceptionLabelMap exception_label_map []
 

Macro Definition Documentation

◆ FUNCS_PER_USER

#define FUNCS_PER_USER   128 /* initial table size */

Definition at line 70 of file pl_comp.c.

Referenced by plpgsql_HashTableInit().

Typedef Documentation

◆ plpgsql_HashEnt

Function Documentation

◆ add_dummy_return()

static void add_dummy_return ( PLpgSQL_function function)
static

Definition at line 1036 of file pl_comp.c.

References PLpgSQL_function::action, PLpgSQL_stmt_block::body, PLpgSQL_stmt_block::exceptions, plpgsql_hashent::function, PLpgSQL_stmt_block::label, lappend(), list_make1, llast, NIL, palloc0(), PLPGSQL_STMT_BLOCK, and PLPGSQL_STMT_RETURN.

Referenced by do_compile(), and plpgsql_compile_inline().

1037 {
1038  /*
1039  * If the outer block has an EXCEPTION clause, we need to make a new outer
1040  * block, since the added RETURN shouldn't act like it is inside the
1041  * EXCEPTION clause. Likewise, if it has a label, wrap it in a new outer
1042  * block so that EXIT doesn't skip the RETURN.
1043  */
1044  if (function->action->exceptions != NULL ||
1045  function->action->label != NULL)
1046  {
1047  PLpgSQL_stmt_block *new;
1048 
1049  new = palloc0(sizeof(PLpgSQL_stmt_block));
1050  new->cmd_type = PLPGSQL_STMT_BLOCK;
1051  new->stmtid = ++function->nstatements;
1052  new->body = list_make1(function->action);
1053 
1054  function->action = new;
1055  }
1056  if (function->action->body == NIL ||
1057  ((PLpgSQL_stmt *) llast(function->action->body))->cmd_type != PLPGSQL_STMT_RETURN)
1058  {
1059  PLpgSQL_stmt_return *new;
1060 
1061  new = palloc0(sizeof(PLpgSQL_stmt_return));
1062  new->cmd_type = PLPGSQL_STMT_RETURN;
1063  new->stmtid = ++function->nstatements;
1064  new->expr = NULL;
1065  new->retvarno = function->out_param_varno;
1066 
1067  function->action->body = lappend(function->action->body, new);
1068  }
1069 }
#define NIL
Definition: pg_list.h:65
PLpgSQL_stmt_block * action
Definition: plpgsql.h:1006
#define llast(l)
Definition: pg_list.h:194
#define list_make1(x1)
Definition: pg_list.h:206
List * lappend(List *list, void *datum)
Definition: list.c:336
void * palloc0(Size size)
Definition: mcxt.c:1093
PLpgSQL_exception_block * exceptions
Definition: plpgsql.h:507

◆ add_parameter_name()

static void add_parameter_name ( PLpgSQL_nsitem_type  itemtype,
int  itemno,
const char *  name 
)
static

Definition at line 1011 of file pl_comp.c.

References ereport, errcode(), errmsg(), ERROR, plpgsql_ns_additem(), plpgsql_ns_lookup(), and plpgsql_ns_top().

Referenced by do_compile().

1012 {
1013  /*
1014  * Before adding the name, check for duplicates. We need this even though
1015  * functioncmds.c has a similar check, because that code explicitly
1016  * doesn't complain about conflicting IN and OUT parameter names. In
1017  * plpgsql, such names are in the same namespace, so there is no way to
1018  * disambiguate.
1019  */
1020  if (plpgsql_ns_lookup(plpgsql_ns_top(), true,
1021  name, NULL, NULL,
1022  NULL) != NULL)
1023  ereport(ERROR,
1024  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1025  errmsg("parameter name \"%s\" used more than once",
1026  name)));
1027 
1028  /* OK, add the name */
1029  plpgsql_ns_additem(itemtype, itemno, name);
1030 }
PLpgSQL_nsitem * plpgsql_ns_top(void)
Definition: pl_funcs.c:81
PLpgSQL_nsitem * plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode, const char *name1, const char *name2, const char *name3, int *names_used)
Definition: pl_funcs.c:130
void plpgsql_ns_additem(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
Definition: pl_funcs.c:92
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ERROR
Definition: elog.h:46
#define ereport(elevel,...)
Definition: elog.h:157
const char * name
Definition: encode.c:561
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ build_datatype()

static PLpgSQL_type * build_datatype ( HeapTuple  typeTup,
int32  typmod,
Oid  collation,
TypeName origtypname 
)
static

Definition at line 2113 of file pl_comp.c.

References PLpgSQL_type::atttypmod, PLpgSQL_type::collation, TypeCacheEntry::domainBaseType, elog, ereport, errcode(), errmsg(), ERROR, format_type_be(), get_base_element_type(), GETSTRUCT, lookup_type_cache(), NameStr, OidIsValid, PLpgSQL_type::origtypname, palloc(), PLPGSQL_TTYPE_PSEUDO, PLPGSQL_TTYPE_REC, PLPGSQL_TTYPE_SCALAR, pstrdup(), PLpgSQL_type::tcache, PLpgSQL_type::ttype, TypeCacheEntry::tupDesc, PLpgSQL_type::tupdesc_id, TypeCacheEntry::tupDesc_identifier, PLpgSQL_type::typbyval, type_is_rowtype(), TYPECACHE_DOMAIN_BASE_INFO, TYPECACHE_TUPDESC, PLpgSQL_type::typisarray, PLpgSQL_type::typlen, PLpgSQL_type::typname, PLpgSQL_type::typoid, TypeCacheEntry::typtype, and PLpgSQL_type::typtype.

Referenced by do_compile(), plpgsql_build_datatype(), plpgsql_parse_cwordtype(), and plpgsql_parse_wordtype().

2115 {
2116  Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
2117  PLpgSQL_type *typ;
2118 
2119  if (!typeStruct->typisdefined)
2120  ereport(ERROR,
2121  (errcode(ERRCODE_UNDEFINED_OBJECT),
2122  errmsg("type \"%s\" is only a shell",
2123  NameStr(typeStruct->typname))));
2124 
2125  typ = (PLpgSQL_type *) palloc(sizeof(PLpgSQL_type));
2126 
2127  typ->typname = pstrdup(NameStr(typeStruct->typname));
2128  typ->typoid = typeStruct->oid;
2129  switch (typeStruct->typtype)
2130  {
2131  case TYPTYPE_BASE:
2132  case TYPTYPE_ENUM:
2133  case TYPTYPE_RANGE:
2134  case TYPTYPE_MULTIRANGE:
2135  typ->ttype = PLPGSQL_TTYPE_SCALAR;
2136  break;
2137  case TYPTYPE_COMPOSITE:
2138  typ->ttype = PLPGSQL_TTYPE_REC;
2139  break;
2140  case TYPTYPE_DOMAIN:
2141  if (type_is_rowtype(typeStruct->typbasetype))
2142  typ->ttype = PLPGSQL_TTYPE_REC;
2143  else
2144  typ->ttype = PLPGSQL_TTYPE_SCALAR;
2145  break;
2146  case TYPTYPE_PSEUDO:
2147  if (typ->typoid == RECORDOID)
2148  typ->ttype = PLPGSQL_TTYPE_REC;
2149  else
2150  typ->ttype = PLPGSQL_TTYPE_PSEUDO;
2151  break;
2152  default:
2153  elog(ERROR, "unrecognized typtype: %d",
2154  (int) typeStruct->typtype);
2155  break;
2156  }
2157  typ->typlen = typeStruct->typlen;
2158  typ->typbyval = typeStruct->typbyval;
2159  typ->typtype = typeStruct->typtype;
2160  typ->collation = typeStruct->typcollation;
2161  if (OidIsValid(collation) && OidIsValid(typ->collation))
2162  typ->collation = collation;
2163  /* Detect if type is true array, or domain thereof */
2164  /* NB: this is only used to decide whether to apply expand_array */
2165  if (typeStruct->typtype == TYPTYPE_BASE)
2166  {
2167  /*
2168  * This test should include what get_element_type() checks. We also
2169  * disallow non-toastable array types (i.e. oidvector and int2vector).
2170  */
2171  typ->typisarray = (IsTrueArrayType(typeStruct) &&
2172  typeStruct->typstorage != TYPSTORAGE_PLAIN);
2173  }
2174  else if (typeStruct->typtype == TYPTYPE_DOMAIN)
2175  {
2176  /* we can short-circuit looking up base types if it's not varlena */
2177  typ->typisarray = (typeStruct->typlen == -1 &&
2178  typeStruct->typstorage != TYPSTORAGE_PLAIN &&
2179  OidIsValid(get_base_element_type(typeStruct->typbasetype)));
2180  }
2181  else
2182  typ->typisarray = false;
2183  typ->atttypmod = typmod;
2184 
2185  /*
2186  * If it's a named composite type (or domain over one), find the typcache
2187  * entry and record the current tupdesc ID, so we can detect changes
2188  * (including drops). We don't currently support on-the-fly replacement
2189  * of non-composite types, else we might want to do this for them too.
2190  */
2191  if (typ->ttype == PLPGSQL_TTYPE_REC && typ->typoid != RECORDOID)
2192  {
2193  TypeCacheEntry *typentry;
2194 
2195  typentry = lookup_type_cache(typ->typoid,
2198  if (typentry->typtype == TYPTYPE_DOMAIN)
2199  typentry = lookup_type_cache(typentry->domainBaseType,
2201  if (typentry->tupDesc == NULL)
2202  ereport(ERROR,
2203  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2204  errmsg("type %s is not composite",
2205  format_type_be(typ->typoid))));
2206 
2207  typ->origtypname = origtypname;
2208  typ->tcache = typentry;
2209  typ->tupdesc_id = typentry->tupDesc_identifier;
2210  }
2211  else
2212  {
2213  typ->origtypname = NULL;
2214  typ->tcache = NULL;
2215  typ->tupdesc_id = 0;
2216  }
2217 
2218  return typ;
2219 }
TypeCacheEntry * tcache
Definition: plpgsql.h:210
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
TypeName * origtypname
Definition: plpgsql.h:209
char * pstrdup(const char *in)
Definition: mcxt.c:1299
PLpgSQL_type_type ttype
Definition: plpgsql.h:201
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
uint64 tupdesc_id
Definition: plpgsql.h:211
#define OidIsValid(objectId)
Definition: c.h:710
Oid domainBaseType
Definition: typcache.h:113
#define ERROR
Definition: elog.h:46
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2602
bool typbyval
Definition: plpgsql.h:203
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:148
Oid collation
Definition: plpgsql.h:205
bool typisarray
Definition: plpgsql.h:206
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:339
#define ereport(elevel,...)
Definition: elog.h:157
char typtype
Definition: typcache.h:43
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
char * typname
Definition: plpgsql.h:199
uint64 tupDesc_identifier
Definition: typcache.h:90
char typtype
Definition: plpgsql.h:204
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2779
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
int32 atttypmod
Definition: plpgsql.h:207
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681
int16 typlen
Definition: plpgsql.h:202
TupleDesc tupDesc
Definition: typcache.h:89
#define TYPECACHE_TUPDESC
Definition: typcache.h:144
Oid typoid
Definition: plpgsql.h:200

◆ build_row_from_vars()

static PLpgSQL_row * build_row_from_vars ( PLpgSQL_variable **  vars,
int  numvars 
)
static

Definition at line 1977 of file pl_comp.c.

References Assert, CreateTemplateTupleDesc(), PLpgSQL_variable::dno, PLpgSQL_variable::dtype, PLpgSQL_row::dtype, elog, ERROR, PLpgSQL_row::fieldnames, i, InvalidOid, PLpgSQL_variable::isconst, PLpgSQL_row::lineno, PLpgSQL_row::nfields, palloc(), palloc0(), PLPGSQL_DTYPE_PROMISE, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_ROW, PLPGSQL_DTYPE_VAR, PLpgSQL_variable::refname, PLpgSQL_row::refname, PLpgSQL_row::rowtupdesc, TupleDescInitEntry(), TupleDescInitEntryCollation(), and PLpgSQL_row::varnos.

Referenced by do_compile().

1978 {
1979  PLpgSQL_row *row;
1980  int i;
1981 
1982  row = palloc0(sizeof(PLpgSQL_row));
1983  row->dtype = PLPGSQL_DTYPE_ROW;
1984  row->refname = "(unnamed row)";
1985  row->lineno = -1;
1986  row->rowtupdesc = CreateTemplateTupleDesc(numvars);
1987  row->nfields = numvars;
1988  row->fieldnames = palloc(numvars * sizeof(char *));
1989  row->varnos = palloc(numvars * sizeof(int));
1990 
1991  for (i = 0; i < numvars; i++)
1992  {
1993  PLpgSQL_variable *var = vars[i];
1994  Oid typoid;
1995  int32 typmod;
1996  Oid typcoll;
1997 
1998  /* Member vars of a row should never be const */
1999  Assert(!var->isconst);
2000 
2001  switch (var->dtype)
2002  {
2003  case PLPGSQL_DTYPE_VAR:
2004  case PLPGSQL_DTYPE_PROMISE:
2005  typoid = ((PLpgSQL_var *) var)->datatype->typoid;
2006  typmod = ((PLpgSQL_var *) var)->datatype->atttypmod;
2007  typcoll = ((PLpgSQL_var *) var)->datatype->collation;
2008  break;
2009 
2010  case PLPGSQL_DTYPE_REC:
2011  /* shouldn't need to revalidate rectypeid already... */
2012  typoid = ((PLpgSQL_rec *) var)->rectypeid;
2013  typmod = -1; /* don't know typmod, if it's used at all */
2014  typcoll = InvalidOid; /* composite types have no collation */
2015  break;
2016 
2017  default:
2018  elog(ERROR, "unrecognized dtype: %d", var->dtype);
2019  typoid = InvalidOid; /* keep compiler quiet */
2020  typmod = 0;
2021  typcoll = InvalidOid;
2022  break;
2023  }
2024 
2025  row->fieldnames[i] = var->refname;
2026  row->varnos[i] = var->dno;
2027 
2028  TupleDescInitEntry(row->rowtupdesc, i + 1,
2029  var->refname,
2030  typoid, typmod,
2031  0);
2032  TupleDescInitEntryCollation(row->rowtupdesc, i + 1, typcoll);
2033  }
2034 
2035  return row;
2036 }
char * refname
Definition: plpgsql.h:366
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:45
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:429
#define ERROR
Definition: elog.h:46
char ** fieldnames
Definition: plpgsql.h:381
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition: tupdesc.c:754
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:583
int * varnos
Definition: plpgsql.h:382
void * palloc0(Size size)
Definition: mcxt.c:1093
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:804
int nfields
Definition: plpgsql.h:380
char * refname
Definition: plpgsql.h:290
PLpgSQL_datum_type dtype
Definition: plpgsql.h:288
void * palloc(Size size)
Definition: mcxt.c:1062
#define elog(elevel,...)
Definition: elog.h:232
int i
TupleDesc rowtupdesc
Definition: plpgsql.h:378
PLpgSQL_datum_type dtype
Definition: plpgsql.h:364
int lineno
Definition: plpgsql.h:367

◆ compute_function_hashkey()

static void compute_function_hashkey ( FunctionCallInfo  fcinfo,
Form_pg_proc  procStruct,
PLpgSQL_func_hashkey hashkey,
bool  forValidator 
)
static

Definition at line 2452 of file pl_comp.c.

References PLpgSQL_func_hashkey::argtypes, CALLED_AS_EVENT_TRIGGER, CALLED_AS_TRIGGER, FunctionCallInfoBaseData::context, FunctionCallInfoBaseData::flinfo, FmgrInfo::fn_expr, FmgrInfo::fn_oid, FunctionCallInfoBaseData::fncollation, PLpgSQL_func_hashkey::funcOid, PLpgSQL_func_hashkey::inputCollation, PLpgSQL_func_hashkey::isEventTrigger, PLpgSQL_func_hashkey::isTrigger, MemSet, NameStr, plpgsql_resolve_polymorphic_argtypes(), TriggerData::tg_trigger, Trigger::tgoid, and PLpgSQL_func_hashkey::trigOid.

Referenced by plpgsql_compile().

2456 {
2457  /* Make sure any unused bytes of the struct are zero */
2458  MemSet(hashkey, 0, sizeof(PLpgSQL_func_hashkey));
2459 
2460  /* get function OID */
2461  hashkey->funcOid = fcinfo->flinfo->fn_oid;
2462 
2463  /* get call context */
2464  hashkey->isTrigger = CALLED_AS_TRIGGER(fcinfo);
2465  hashkey->isEventTrigger = CALLED_AS_EVENT_TRIGGER(fcinfo);
2466 
2467  /*
2468  * If DML trigger, include trigger's OID in the hash, so that each trigger
2469  * usage gets a different hash entry, allowing for e.g. different relation
2470  * rowtypes or transition table names. In validation mode we do not know
2471  * what relation or transition table names are intended to be used, so we
2472  * leave trigOid zero; the hash entry built in this case will never be
2473  * used for any actual calls.
2474  *
2475  * We don't currently need to distinguish different event trigger usages
2476  * in the same way, since the special parameter variables don't vary in
2477  * type in that case.
2478  */
2479  if (hashkey->isTrigger && !forValidator)
2480  {
2481  TriggerData *trigdata = (TriggerData *) fcinfo->context;
2482 
2483  hashkey->trigOid = trigdata->tg_trigger->tgoid;
2484  }
2485 
2486  /* get input collation, if known */
2487  hashkey->inputCollation = fcinfo->fncollation;
2488 
2489  if (procStruct->pronargs > 0)
2490  {
2491  /* get the argument types */
2492  memcpy(hashkey->argtypes, procStruct->proargtypes.values,
2493  procStruct->pronargs * sizeof(Oid));
2494 
2495  /* resolve any polymorphic argument types */
2496  plpgsql_resolve_polymorphic_argtypes(procStruct->pronargs,
2497  hashkey->argtypes,
2498  NULL,
2499  fcinfo->flinfo->fn_expr,
2500  forValidator,
2501  NameStr(procStruct->proname));
2502  }
2503 }
Oid argtypes[FUNC_MAX_ARGS]
Definition: plpgsql.h:949
#define CALLED_AS_EVENT_TRIGGER(fcinfo)
Definition: event_trigger.h:41
Oid tgoid
Definition: reltrigger.h:25
#define MemSet(start, val, len)
Definition: c.h:1008
fmNodePtr context
Definition: fmgr.h:88
unsigned int Oid
Definition: postgres_ext.h:31
static void plpgsql_resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, Node *call_expr, bool forValidator, const char *proname)
Definition: pl_comp.c:2512
FmgrInfo * flinfo
Definition: fmgr.h:87
Trigger * tg_trigger
Definition: trigger.h:37
Oid fn_oid
Definition: fmgr.h:59
#define CALLED_AS_TRIGGER(fcinfo)
Definition: trigger.h:25
fmNodePtr fn_expr
Definition: fmgr.h:66
#define NameStr(name)
Definition: c.h:681

◆ delete_function()

static void delete_function ( PLpgSQL_function func)
static

Definition at line 2577 of file pl_comp.c.

References plpgsql_free_function_memory(), plpgsql_HashTableDelete(), and PLpgSQL_function::use_count.

Referenced by plpgsql_compile().

2578 {
2579  /* remove function from hash table (might be done already) */
2581 
2582  /* release the function's storage if safe and not done already */
2583  if (func->use_count == 0)
2585 }
void plpgsql_free_function_memory(PLpgSQL_function *func)
Definition: pl_funcs.c:725
unsigned long use_count
Definition: plpgsql.h:1014
static void plpgsql_HashTableDelete(PLpgSQL_function *function)
Definition: pl_comp.c:2639

◆ do_compile()

static PLpgSQL_function * do_compile ( FunctionCallInfo  fcinfo,
HeapTuple  procTup,
PLpgSQL_function function,
PLpgSQL_func_hashkey hashkey,
bool  forValidator 
)
static

Definition at line 264 of file pl_comp.c.

References add_dummy_return(), add_parameter_name(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, ErrorContextCallback::arg, Assert, buf, build_datatype(), build_row_from_vars(), ErrorContextCallback::callback, CALLED_AS_EVENT_TRIGGER, CALLED_AS_TRIGGER, PLpgSQL_datum::dno, PLpgSQL_variable::dno, PLpgSQL_rec::dno, PLpgSQL_variable::dtype, elog, ereport, errcode(), errhint(), errmsg(), ERROR, error_context_stack, FunctionCallInfoBaseData::flinfo, PLpgSQL_function::fn_argvarnos, FmgrInfo::fn_expr, PLpgSQL_function::fn_input_collation, PLpgSQL_function::fn_is_trigger, FmgrInfo::fn_oid, PLpgSQL_function::fn_prokind, PLpgSQL_function::fn_retset, PLpgSQL_function::fn_rettype, PLpgSQL_function::fn_signature, FunctionCallInfoBaseData::fncollation, format_procedure(), format_type_be(), plpgsql_hashent::function, get_fn_expr_rettype(), get_func_arg_info(), GETSTRUCT, HeapTupleHeaderGetRawXmin, HeapTupleIsValid, i, InvalidOid, MemoryContextAllocZero(), MemoryContextSetIdentifier(), MemoryContextSwitchTo(), NameStr, ObjectIdGetDatum, OidIsValid, palloc(), pfree(), plpgsql_adddatum(), plpgsql_build_datatype(), plpgsql_build_record(), plpgsql_build_variable(), plpgsql_check_syntax, plpgsql_compile_error_callback(), PLPGSQL_DML_TRIGGER, PLPGSQL_DTYPE_PROMISE, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_VAR, plpgsql_DumpExecTree, plpgsql_dumptree(), plpgsql_error_funcname, PLPGSQL_EVENT_TRIGGER, plpgsql_extra_errors, plpgsql_extra_warnings, plpgsql_finish_datums(), plpgsql_HashTableInsert(), PLPGSQL_LABEL_BLOCK, PLPGSQL_NOT_TRIGGER, plpgsql_ns_init(), plpgsql_ns_push(), PLPGSQL_NSTYPE_REC, PLPGSQL_NSTYPE_VAR, plpgsql_parse_result, plpgsql_print_strict_params, PLPGSQL_PROMISE_TG_ARGV, PLPGSQL_PROMISE_TG_EVENT, PLPGSQL_PROMISE_TG_LEVEL, PLPGSQL_PROMISE_TG_NAME, PLPGSQL_PROMISE_TG_NARGS, PLPGSQL_PROMISE_TG_OP, PLPGSQL_PROMISE_TG_RELID, PLPGSQL_PROMISE_TG_TABLE_NAME, PLPGSQL_PROMISE_TG_TABLE_SCHEMA, PLPGSQL_PROMISE_TG_TAG, PLPGSQL_PROMISE_TG_WHEN, plpgsql_resolve_polymorphic_argtypes(), plpgsql_scanner_finish(), plpgsql_scanner_init(), plpgsql_start_datums(), PLPGSQL_TTYPE_PSEUDO, plpgsql_variable_conflict, plpgsql_yyparse(), ErrorContextCallback::previous, PROCOID, pstrdup(), ReleaseSysCache(), SearchSysCache1(), snprintf, SysCacheGetAttr(), HeapTupleData::t_data, HeapTupleData::t_self, TextDatumGetCString, TopMemoryContext, PLpgSQL_type::ttype, type_is_rowtype(), and TYPEOID.

Referenced by plpgsql_compile().

269 {
270  Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
271  bool is_dml_trigger = CALLED_AS_TRIGGER(fcinfo);
272  bool is_event_trigger = CALLED_AS_EVENT_TRIGGER(fcinfo);
273  Datum prosrcdatum;
274  bool isnull;
275  char *proc_source;
276  HeapTuple typeTup;
277  Form_pg_type typeStruct;
278  PLpgSQL_variable *var;
279  PLpgSQL_rec *rec;
280  int i;
281  ErrorContextCallback plerrcontext;
282  int parse_rc;
283  Oid rettypeid;
284  int numargs;
285  int num_in_args = 0;
286  int num_out_args = 0;
287  Oid *argtypes;
288  char **argnames;
289  char *argmodes;
290  int *in_arg_varnos = NULL;
291  PLpgSQL_variable **out_arg_variables;
292  MemoryContext func_cxt;
293 
294  /*
295  * Setup the scanner input and error info. We assume that this function
296  * cannot be invoked recursively, so there's no need to save and restore
297  * the static variables used here.
298  */
299  prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
300  Anum_pg_proc_prosrc, &isnull);
301  if (isnull)
302  elog(ERROR, "null prosrc");
303  proc_source = TextDatumGetCString(prosrcdatum);
304  plpgsql_scanner_init(proc_source);
305 
306  plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname));
307 
308  /*
309  * Setup error traceback support for ereport()
310  */
312  plerrcontext.arg = forValidator ? proc_source : NULL;
313  plerrcontext.previous = error_context_stack;
314  error_context_stack = &plerrcontext;
315 
316  /*
317  * Do extra syntax checks when validating the function definition. We skip
318  * this when actually compiling functions for execution, for performance
319  * reasons.
320  */
321  plpgsql_check_syntax = forValidator;
322 
323  /*
324  * Create the new function struct, if not done already. The function
325  * structs are never thrown away, so keep them in TopMemoryContext.
326  */
327  if (function == NULL)
328  {
329  function = (PLpgSQL_function *)
331  }
332  else
333  {
334  /* re-using a previously existing struct, so clear it out */
335  memset(function, 0, sizeof(PLpgSQL_function));
336  }
337  plpgsql_curr_compile = function;
338 
339  /*
340  * All the permanent output of compilation (e.g. parse tree) is kept in a
341  * per-function memory context, so it can be reclaimed easily.
342  */
344  "PL/pgSQL function",
347 
348  function->fn_signature = format_procedure(fcinfo->flinfo->fn_oid);
349  MemoryContextSetIdentifier(func_cxt, function->fn_signature);
350  function->fn_oid = fcinfo->flinfo->fn_oid;
351  function->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data);
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; /* set up for no OUT param */
356  function->resolve_option = plpgsql_variable_conflict;
357  function->print_strict_params = plpgsql_print_strict_params;
358  /* only promote extra warnings and errors at CREATE FUNCTION time */
359  function->extra_warnings = forValidator ? plpgsql_extra_warnings : 0;
360  function->extra_errors = forValidator ? plpgsql_extra_errors : 0;
361 
362  if (is_dml_trigger)
363  function->fn_is_trigger = PLPGSQL_DML_TRIGGER;
364  else if (is_event_trigger)
365  function->fn_is_trigger = PLPGSQL_EVENT_TRIGGER;
366  else
367  function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
368 
369  function->fn_prokind = procStruct->prokind;
370 
371  function->nstatements = 0;
372  function->requires_procedure_resowner = false;
373 
374  /*
375  * Initialize the compiler, particularly the namespace stack. The
376  * outermost namespace contains function parameters and other special
377  * variables (such as FOUND), and is named after the function itself.
378  */
379  plpgsql_ns_init();
380  plpgsql_ns_push(NameStr(procStruct->proname), PLPGSQL_LABEL_BLOCK);
381  plpgsql_DumpExecTree = false;
383 
384  switch (function->fn_is_trigger)
385  {
386  case PLPGSQL_NOT_TRIGGER:
387 
388  /*
389  * Fetch info about the procedure's parameters. Allocations aren't
390  * needed permanently, so make them in tmp cxt.
391  *
392  * We also need to resolve any polymorphic input or output
393  * argument types. In validation mode we won't be able to, so we
394  * arbitrarily assume we are dealing with integers.
395  */
397 
398  numargs = get_func_arg_info(procTup,
399  &argtypes, &argnames, &argmodes);
400 
401  plpgsql_resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
402  fcinfo->flinfo->fn_expr,
403  forValidator,
405 
406  in_arg_varnos = (int *) palloc(numargs * sizeof(int));
407  out_arg_variables = (PLpgSQL_variable **) palloc(numargs * sizeof(PLpgSQL_variable *));
408 
409  MemoryContextSwitchTo(func_cxt);
410 
411  /*
412  * Create the variables for the procedure's parameters.
413  */
414  for (i = 0; i < numargs; i++)
415  {
416  char buf[32];
417  Oid argtypeid = argtypes[i];
418  char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
419  PLpgSQL_type *argdtype;
420  PLpgSQL_variable *argvariable;
421  PLpgSQL_nsitem_type argitemtype;
422 
423  /* Create $n name for variable */
424  snprintf(buf, sizeof(buf), "$%d", i + 1);
425 
426  /* Create datatype info */
427  argdtype = plpgsql_build_datatype(argtypeid,
428  -1,
429  function->fn_input_collation,
430  NULL);
431 
432  /* Disallow pseudotype argument */
433  /* (note we already replaced polymorphic types) */
434  /* (build_variable would do this, but wrong message) */
435  if (argdtype->ttype == PLPGSQL_TTYPE_PSEUDO)
436  ereport(ERROR,
437  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
438  errmsg("PL/pgSQL functions cannot accept type %s",
439  format_type_be(argtypeid))));
440 
441  /*
442  * Build variable and add to datum list. If there's a name
443  * for the argument, use that as refname, else use $n name.
444  */
445  argvariable = plpgsql_build_variable((argnames &&
446  argnames[i][0] != '\0') ?
447  argnames[i] : buf,
448  0, argdtype, false);
449 
450  if (argvariable->dtype == PLPGSQL_DTYPE_VAR)
451  {
452  argitemtype = PLPGSQL_NSTYPE_VAR;
453  }
454  else
455  {
456  Assert(argvariable->dtype == PLPGSQL_DTYPE_REC);
457  argitemtype = PLPGSQL_NSTYPE_REC;
458  }
459 
460  /* Remember arguments in appropriate arrays */
461  if (argmode == PROARGMODE_IN ||
462  argmode == PROARGMODE_INOUT ||
463  argmode == PROARGMODE_VARIADIC)
464  in_arg_varnos[num_in_args++] = argvariable->dno;
465  if (argmode == PROARGMODE_OUT ||
466  argmode == PROARGMODE_INOUT ||
467  argmode == PROARGMODE_TABLE)
468  out_arg_variables[num_out_args++] = argvariable;
469 
470  /* Add to namespace under the $n name */
471  add_parameter_name(argitemtype, argvariable->dno, buf);
472 
473  /* If there's a name for the argument, make an alias */
474  if (argnames && argnames[i][0] != '\0')
475  add_parameter_name(argitemtype, argvariable->dno,
476  argnames[i]);
477  }
478 
479  /*
480  * If there's just one OUT parameter, out_param_varno points
481  * directly to it. If there's more than one, build a row that
482  * holds all of them. Procedures return a row even for one OUT
483  * parameter.
484  */
485  if (num_out_args > 1 ||
486  (num_out_args == 1 && function->fn_prokind == PROKIND_PROCEDURE))
487  {
488  PLpgSQL_row *row = build_row_from_vars(out_arg_variables,
489  num_out_args);
490 
492  function->out_param_varno = row->dno;
493  }
494  else if (num_out_args == 1)
495  function->out_param_varno = out_arg_variables[0]->dno;
496 
497  /*
498  * Check for a polymorphic returntype. If found, use the actual
499  * returntype type from the caller's FuncExpr node, if we have
500  * one. (In validation mode we arbitrarily assume we are dealing
501  * with integers.)
502  *
503  * Note: errcode is FEATURE_NOT_SUPPORTED because it should always
504  * work; if it doesn't we're in some context that fails to make
505  * the info available.
506  */
507  rettypeid = procStruct->prorettype;
508  if (IsPolymorphicType(rettypeid))
509  {
510  if (forValidator)
511  {
512  if (rettypeid == ANYARRAYOID ||
513  rettypeid == ANYCOMPATIBLEARRAYOID)
514  rettypeid = INT4ARRAYOID;
515  else if (rettypeid == ANYRANGEOID ||
516  rettypeid == ANYCOMPATIBLERANGEOID)
517  rettypeid = INT4RANGEOID;
518  else if (rettypeid == ANYMULTIRANGEOID)
519  rettypeid = INT4MULTIRANGEOID;
520  else /* ANYELEMENT or ANYNONARRAY or ANYCOMPATIBLE */
521  rettypeid = INT4OID;
522  /* XXX what could we use for ANYENUM? */
523  }
524  else
525  {
526  rettypeid = get_fn_expr_rettype(fcinfo->flinfo);
527  if (!OidIsValid(rettypeid))
528  ereport(ERROR,
529  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
530  errmsg("could not determine actual return type "
531  "for polymorphic function \"%s\"",
533  }
534  }
535 
536  /*
537  * Normal function has a defined returntype
538  */
539  function->fn_rettype = rettypeid;
540  function->fn_retset = procStruct->proretset;
541 
542  /*
543  * Lookup the function's return type
544  */
545  typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(rettypeid));
546  if (!HeapTupleIsValid(typeTup))
547  elog(ERROR, "cache lookup failed for type %u", rettypeid);
548  typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
549 
550  /* Disallow pseudotype result, except VOID or RECORD */
551  /* (note we already replaced polymorphic types) */
552  if (typeStruct->typtype == TYPTYPE_PSEUDO)
553  {
554  if (rettypeid == VOIDOID ||
555  rettypeid == RECORDOID)
556  /* okay */ ;
557  else if (rettypeid == TRIGGEROID || rettypeid == EVENT_TRIGGEROID)
558  ereport(ERROR,
559  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
560  errmsg("trigger functions can only be called as triggers")));
561  else
562  ereport(ERROR,
563  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
564  errmsg("PL/pgSQL functions cannot return type %s",
565  format_type_be(rettypeid))));
566  }
567 
568  function->fn_retistuple = type_is_rowtype(rettypeid);
569  function->fn_retisdomain = (typeStruct->typtype == TYPTYPE_DOMAIN);
570  function->fn_retbyval = typeStruct->typbyval;
571  function->fn_rettyplen = typeStruct->typlen;
572 
573  /*
574  * install $0 reference, but only for polymorphic return types,
575  * and not when the return is specified through an output
576  * parameter.
577  */
578  if (IsPolymorphicType(procStruct->prorettype) &&
579  num_out_args == 0)
580  {
581  (void) plpgsql_build_variable("$0", 0,
582  build_datatype(typeTup,
583  -1,
584  function->fn_input_collation,
585  NULL),
586  true);
587  }
588 
589  ReleaseSysCache(typeTup);
590  break;
591 
592  case PLPGSQL_DML_TRIGGER:
593  /* Trigger procedure's return type is unknown yet */
594  function->fn_rettype = InvalidOid;
595  function->fn_retbyval = false;
596  function->fn_retistuple = true;
597  function->fn_retisdomain = false;
598  function->fn_retset = false;
599 
600  /* shouldn't be any declared arguments */
601  if (procStruct->pronargs != 0)
602  ereport(ERROR,
603  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
604  errmsg("trigger functions cannot have declared arguments"),
605  errhint("The arguments of the trigger can be accessed through TG_NARGS and TG_ARGV instead.")));
606 
607  /* Add the record for referencing NEW ROW */
608  rec = plpgsql_build_record("new", 0, NULL, RECORDOID, true);
609  function->new_varno = rec->dno;
610 
611  /* Add the record for referencing OLD ROW */
612  rec = plpgsql_build_record("old", 0, NULL, RECORDOID, true);
613  function->old_varno = rec->dno;
614 
615  /* Add the variable tg_name */
616  var = plpgsql_build_variable("tg_name", 0,
617  plpgsql_build_datatype(NAMEOID,
618  -1,
619  function->fn_input_collation,
620  NULL),
621  true);
622  Assert(var->dtype == PLPGSQL_DTYPE_VAR);
624  ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_NAME;
625 
626  /* Add the variable tg_when */
627  var = plpgsql_build_variable("tg_when", 0,
628  plpgsql_build_datatype(TEXTOID,
629  -1,
630  function->fn_input_collation,
631  NULL),
632  true);
633  Assert(var->dtype == PLPGSQL_DTYPE_VAR);
635  ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_WHEN;
636 
637  /* Add the variable tg_level */
638  var = plpgsql_build_variable("tg_level", 0,
639  plpgsql_build_datatype(TEXTOID,
640  -1,
641  function->fn_input_collation,
642  NULL),
643  true);
644  Assert(var->dtype == PLPGSQL_DTYPE_VAR);
646  ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_LEVEL;
647 
648  /* Add the variable tg_op */
649  var = plpgsql_build_variable("tg_op", 0,
650  plpgsql_build_datatype(TEXTOID,
651  -1,
652  function->fn_input_collation,
653  NULL),
654  true);
655  Assert(var->dtype == PLPGSQL_DTYPE_VAR);
657  ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_OP;
658 
659  /* Add the variable tg_relid */
660  var = plpgsql_build_variable("tg_relid", 0,
661  plpgsql_build_datatype(OIDOID,
662  -1,
663  InvalidOid,
664  NULL),
665  true);
666  Assert(var->dtype == PLPGSQL_DTYPE_VAR);
668  ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_RELID;
669 
670  /* Add the variable tg_relname */
671  var = plpgsql_build_variable("tg_relname", 0,
672  plpgsql_build_datatype(NAMEOID,
673  -1,
674  function->fn_input_collation,
675  NULL),
676  true);
677  Assert(var->dtype == PLPGSQL_DTYPE_VAR);
679  ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_NAME;
680 
681  /* tg_table_name is now preferred to tg_relname */
682  var = plpgsql_build_variable("tg_table_name", 0,
683  plpgsql_build_datatype(NAMEOID,
684  -1,
685  function->fn_input_collation,
686  NULL),
687  true);
688  Assert(var->dtype == PLPGSQL_DTYPE_VAR);
690  ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_NAME;
691 
692  /* add the variable tg_table_schema */
693  var = plpgsql_build_variable("tg_table_schema", 0,
694  plpgsql_build_datatype(NAMEOID,
695  -1,
696  function->fn_input_collation,
697  NULL),
698  true);
699  Assert(var->dtype == PLPGSQL_DTYPE_VAR);
701  ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_SCHEMA;
702 
703  /* Add the variable tg_nargs */
704  var = plpgsql_build_variable("tg_nargs", 0,
705  plpgsql_build_datatype(INT4OID,
706  -1,
707  InvalidOid,
708  NULL),
709  true);
710  Assert(var->dtype == PLPGSQL_DTYPE_VAR);
712  ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_NARGS;
713 
714  /* Add the variable tg_argv */
715  var = plpgsql_build_variable("tg_argv", 0,
716  plpgsql_build_datatype(TEXTARRAYOID,
717  -1,
718  function->fn_input_collation,
719  NULL),
720  true);
721  Assert(var->dtype == PLPGSQL_DTYPE_VAR);
723  ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_ARGV;
724 
725  break;
726 
728  function->fn_rettype = VOIDOID;
729  function->fn_retbyval = false;
730  function->fn_retistuple = true;
731  function->fn_retisdomain = false;
732  function->fn_retset = false;
733 
734  /* shouldn't be any declared arguments */
735  if (procStruct->pronargs != 0)
736  ereport(ERROR,
737  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
738  errmsg("event trigger functions cannot have declared arguments")));
739 
740  /* Add the variable tg_event */
741  var = plpgsql_build_variable("tg_event", 0,
742  plpgsql_build_datatype(TEXTOID,
743  -1,
744  function->fn_input_collation,
745  NULL),
746  true);
747  Assert(var->dtype == PLPGSQL_DTYPE_VAR);
749  ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_EVENT;
750 
751  /* Add the variable tg_tag */
752  var = plpgsql_build_variable("tg_tag", 0,
753  plpgsql_build_datatype(TEXTOID,
754  -1,
755  function->fn_input_collation,
756  NULL),
757  true);
758  Assert(var->dtype == PLPGSQL_DTYPE_VAR);
760  ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TAG;
761 
762  break;
763 
764  default:
765  elog(ERROR, "unrecognized function typecode: %d",
766  (int) function->fn_is_trigger);
767  break;
768  }
769 
770  /* Remember if function is STABLE/IMMUTABLE */
771  function->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
772 
773  /*
774  * Create the magic FOUND variable.
775  */
776  var = plpgsql_build_variable("found", 0,
777  plpgsql_build_datatype(BOOLOID,
778  -1,
779  InvalidOid,
780  NULL),
781  true);
782  function->found_varno = var->dno;
783 
784  /*
785  * Now parse the function's text
786  */
787  parse_rc = plpgsql_yyparse();
788  if (parse_rc != 0)
789  elog(ERROR, "plpgsql parser returned %d", parse_rc);
790  function->action = plpgsql_parse_result;
791 
793  pfree(proc_source);
794 
795  /*
796  * If it has OUT parameters or returns VOID or returns a set, we allow
797  * control to fall off the end without an explicit RETURN statement. The
798  * easiest way to implement this is to add a RETURN statement to the end
799  * of the statement list during parsing.
800  */
801  if (num_out_args > 0 || function->fn_rettype == VOIDOID ||
802  function->fn_retset)
803  add_dummy_return(function);
804 
805  /*
806  * Complete the function's info
807  */
808  function->fn_nargs = procStruct->pronargs;
809  for (i = 0; i < function->fn_nargs; i++)
810  function->fn_argvarnos[i] = in_arg_varnos[i];
811 
812  plpgsql_finish_datums(function);
813 
814  /* Debug dump for completed functions */
816  plpgsql_dumptree(function);
817 
818  /*
819  * add it to the hash table
820  */
821  plpgsql_HashTableInsert(function, hashkey);
822 
823  /*
824  * Pop the error context stack
825  */
826  error_context_stack = plerrcontext.previous;
827  plpgsql_error_funcname = NULL;
828 
829  plpgsql_check_syntax = false;
830 
833  return function;
834 }
int plpgsql_yyparse(void)
int fn_argvarnos[FUNC_MAX_ARGS]
Definition: plpgsql.h:986
#define CALLED_AS_EVENT_TRIGGER(fcinfo)
Definition: event_trigger.h:41
#define AllocSetContextCreate
Definition: memutils.h:173
int errhint(const char *fmt,...)
Definition: elog.c:1156
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
PLpgSQL_rec * plpgsql_build_record(const char *refname, int lineno, PLpgSQL_type *dtype, Oid rectypeid, bool add2namespace)
Definition: pl_comp.c:1950
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:2113
char * pstrdup(const char *in)
Definition: mcxt.c:1299
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
Definition: funcapi.c:1268
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
PLpgSQL_type_type ttype
Definition: plpgsql.h:201
int plpgsql_extra_errors
Definition: pl_handler.c:53
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
void plpgsql_dumptree(PLpgSQL_function *func)
Definition: pl_funcs.c:1598
unsigned int Oid
Definition: postgres_ext.h:31
void(* callback)(void *arg)
Definition: elog.h:247
struct ErrorContextCallback * previous
Definition: elog.h:246
#define OidIsValid(objectId)
Definition: c.h:710
static void plpgsql_resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, Node *call_expr, bool forValidator, const char *proname)
Definition: pl_comp.c:2512
static void plpgsql_HashTableInsert(PLpgSQL_function *function, PLpgSQL_func_hashkey *func_key)
Definition: pl_comp.c:2620
static void plpgsql_start_datums(void)
Definition: pl_comp.c:2316
void plpgsql_adddatum(PLpgSQL_datum *newdatum)
Definition: pl_comp.c:2333
HeapTupleHeader t_data
Definition: htup.h:68
ErrorContextCallback * error_context_stack
Definition: elog.c:93
void plpgsql_scanner_finish(void)
Definition: pl_scanner.c:613
void pfree(void *pointer)
Definition: mcxt.c:1169
bool plpgsql_check_syntax
Definition: pl_comp.c:51
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
char * plpgsql_error_funcname
Definition: pl_comp.c:49
bool plpgsql_DumpExecTree
Definition: pl_comp.c:50
static void add_parameter_name(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
Definition: pl_comp.c:1011
ItemPointerData t_self
Definition: htup.h:65
int plpgsql_extra_warnings
Definition: pl_handler.c:52
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:195
static void add_dummy_return(PLpgSQL_function *function)
Definition: pl_comp.c:1036
static char * buf
Definition: pg_test_fsync.c:68
void plpgsql_ns_init(void)
Definition: pl_funcs.c:43
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2602
MemoryContext TopMemoryContext
Definition: mcxt.c:48
Oid fn_input_collation
Definition: plpgsql.h:972
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
#define TextDatumGetCString(d)
Definition: builtins.h:87
uintptr_t Datum
Definition: postgres.h:411
Oid get_fn_expr_rettype(FmgrInfo *flinfo)
Definition: fmgr.c:1778
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:2091
FmgrInfo * flinfo
Definition: fmgr.h:87
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:906
#define InvalidOid
Definition: postgres_ext.h:36
Oid fn_oid
Definition: fmgr.h:59
#define ereport(elevel,...)
Definition: elog.h:157
PLpgSQL_trigtype fn_is_trigger
Definition: plpgsql.h:971
bool plpgsql_print_strict_params
Definition: pl_handler.c:46
char * format_procedure(Oid procedure_oid)
Definition: regproc.c:323
static void plpgsql_compile_error_callback(void *arg)
Definition: pl_comp.c:984
int plpgsql_variable_conflict
Definition: pl_handler.c:44
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define CALLED_AS_TRIGGER(fcinfo)
Definition: trigger.h:25
#define Assert(condition)
Definition: c.h:804
fmNodePtr fn_expr
Definition: fmgr.h:66
char * fn_signature
Definition: plpgsql.h:967
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
void plpgsql_ns_push(const char *label, PLpgSQL_label_type label_type)
Definition: pl_funcs.c:54
PLpgSQL_stmt_block * plpgsql_parse_result
Definition: pl_comp.c:42
PLpgSQL_variable * plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype, bool add2namespace)
Definition: pl_comp.c:1887
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
Definition: mcxt.c:336
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:308
PLpgSQL_datum_type dtype
Definition: plpgsql.h:288
void plpgsql_scanner_init(const char *str)
Definition: pl_scanner.c:586
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
static void plpgsql_finish_datums(PLpgSQL_function *function)
Definition: pl_comp.c:2350
#define elog(elevel,...)
Definition: elog.h:232
int i
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:56
#define NameStr(name)
Definition: c.h:681
static PLpgSQL_row * build_row_from_vars(PLpgSQL_variable **vars, int numvars)
Definition: pl_comp.c:1977
#define snprintf
Definition: port.h:216
PLpgSQL_function * plpgsql_curr_compile
Definition: pl_comp.c:53
PLpgSQL_nsitem_type
Definition: plpgsql.h:41

◆ make_datum_param()

static Node * make_datum_param ( PLpgSQL_expr expr,
int  dno,
int  location 
)
static

Definition at line 1343 of file pl_comp.c.

References Assert, bms_add_member(), PLpgSQL_function::cur_estate, PLpgSQL_execstate::datums, PLpgSQL_function::fn_cxt, PLpgSQL_expr::func, Param::location, makeNode, MemoryContextSwitchTo(), PARAM_EXTERN, Param::paramcollid, Param::paramid, Param::paramkind, PLpgSQL_expr::paramnos, Param::paramtype, Param::paramtypmod, and plpgsql_exec_get_datum_type_info().

Referenced by plpgsql_param_ref(), and resolve_column_ref().

1344 {
1345  PLpgSQL_execstate *estate;
1346  PLpgSQL_datum *datum;
1347  Param *param;
1348  MemoryContext oldcontext;
1349 
1350  /* see comment in resolve_column_ref */
1351  estate = expr->func->cur_estate;
1352  Assert(dno >= 0 && dno < estate->ndatums);
1353  datum = estate->datums[dno];
1354 
1355  /*
1356  * Bitmapset must be allocated in function's permanent memory context
1357  */
1358  oldcontext = MemoryContextSwitchTo(expr->func->fn_cxt);
1359  expr->paramnos = bms_add_member(expr->paramnos, dno);
1360  MemoryContextSwitchTo(oldcontext);
1361 
1362  param = makeNode(Param);
1363  param->paramkind = PARAM_EXTERN;
1364  param->paramid = dno + 1;
1366  datum,
1367  &param->paramtype,
1368  &param->paramtypmod,
1369  &param->paramcollid);
1370  param->location = location;
1371 
1372  return (Node *) param;
1373 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ParamKind paramkind
Definition: primnodes.h:267
Definition: nodes.h:536
PLpgSQL_datum ** datums
Definition: plpgsql.h:1057
Bitmapset * paramnos
Definition: plpgsql.h:222
struct PLpgSQL_execstate * cur_estate
Definition: plpgsql.h:1013
Oid paramcollid
Definition: primnodes.h:271
int location
Definition: primnodes.h:272
MemoryContext fn_cxt
Definition: plpgsql.h:974
void plpgsql_exec_get_datum_type_info(PLpgSQL_execstate *estate, PLpgSQL_datum *datum, Oid *typeId, int32 *typMod, Oid *collation)
Definition: pl_exec.c:5488
struct PLpgSQL_function * func
Definition: plpgsql.h:225
int32 paramtypmod
Definition: primnodes.h:270
#define makeNode(_type_)
Definition: nodes.h:584
#define Assert(condition)
Definition: c.h:804
int paramid
Definition: primnodes.h:268
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
Oid paramtype
Definition: primnodes.h:269

◆ plpgsql_add_initdatums()

int plpgsql_add_initdatums ( int **  varnos)

Definition at line 2394 of file pl_comp.c.

References datums_last, PLpgSQL_datum::dno, i, palloc(), PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_VAR, and plpgsql_nDatums.

2395 {
2396  int i;
2397  int n = 0;
2398 
2399  /*
2400  * The set of dtypes recognized here must match what exec_stmt_block()
2401  * cares about (re)initializing at block entry.
2402  */
2403  for (i = datums_last; i < plpgsql_nDatums; i++)
2404  {
2405  switch (plpgsql_Datums[i]->dtype)
2406  {
2407  case PLPGSQL_DTYPE_VAR:
2408  case PLPGSQL_DTYPE_REC:
2409  n++;
2410  break;
2411 
2412  default:
2413  break;
2414  }
2415  }
2416 
2417  if (varnos != NULL)
2418  {
2419  if (n > 0)
2420  {
2421  *varnos = (int *) palloc(sizeof(int) * n);
2422 
2423  n = 0;
2424  for (i = datums_last; i < plpgsql_nDatums; i++)
2425  {
2426  switch (plpgsql_Datums[i]->dtype)
2427  {
2428  case PLPGSQL_DTYPE_VAR:
2429  case PLPGSQL_DTYPE_REC:
2430  (*varnos)[n++] = plpgsql_Datums[i]->dno;
2431 
2432  default:
2433  break;
2434  }
2435  }
2436  }
2437  else
2438  *varnos = NULL;
2439  }
2440 
2442  return n;
2443 }
int plpgsql_nDatums
Definition: pl_comp.c:45
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:46
void * palloc(Size size)
Definition: mcxt.c:1062
int i
static int datums_last
Definition: pl_comp.c:47

◆ plpgsql_adddatum()

void plpgsql_adddatum ( PLpgSQL_datum newdatum)

Definition at line 2333 of file pl_comp.c.

References datums_alloc, PLpgSQL_datum::dno, plpgsql_nDatums, and repalloc().

Referenced by do_compile(), plpgsql_build_recfield(), plpgsql_build_record(), and plpgsql_build_variable().

2334 {
2336  {
2337  datums_alloc *= 2;
2339  }
2340 
2341  newdatum->dno = plpgsql_nDatums;
2342  plpgsql_Datums[plpgsql_nDatums++] = newdatum;
2343 }
int plpgsql_nDatums
Definition: pl_comp.c:45
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:46
static int datums_alloc
Definition: pl_comp.c:44
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182

◆ plpgsql_build_datatype()

PLpgSQL_type* plpgsql_build_datatype ( Oid  typeOid,
int32  typmod,
Oid  collation,
TypeName origtypname 
)

Definition at line 2091 of file pl_comp.c.

References build_datatype(), elog, ERROR, HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1(), and TYPEOID.

Referenced by do_compile(), exec_stmt_case(), plpgsql_compile_inline(), plpgsql_parse_cwordrowtype(), and plpgsql_parse_wordrowtype().

2093 {
2094  HeapTuple typeTup;
2095  PLpgSQL_type *typ;
2096 
2097  typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
2098  if (!HeapTupleIsValid(typeTup))
2099  elog(ERROR, "cache lookup failed for type %u", typeOid);
2100 
2101  typ = build_datatype(typeTup, typmod, collation, origtypname);
2102 
2103  ReleaseSysCache(typeTup);
2104 
2105  return typ;
2106 }
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:2113
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:232

◆ plpgsql_build_recfield()

PLpgSQL_recfield* plpgsql_build_recfield ( PLpgSQL_rec rec,
const char *  fldname 
)

Definition at line 2044 of file pl_comp.c.

References Assert, PLpgSQL_datum::dno, PLpgSQL_rec::dno, PLpgSQL_recfield::dtype, PLpgSQL_recfield::fieldname, PLpgSQL_rec::firstfield, i, INVALID_TUPLEDESC_IDENTIFIER, PLpgSQL_recfield::nextfield, palloc0(), plpgsql_adddatum(), PLPGSQL_DTYPE_RECFIELD, pstrdup(), PLpgSQL_recfield::recparentno, and PLpgSQL_recfield::rectupledescid.

Referenced by plpgsql_parse_dblword(), and plpgsql_parse_tripword().

2045 {
2046  PLpgSQL_recfield *recfield;
2047  int i;
2048 
2049  /* search for an existing datum referencing this field */
2050  i = rec->firstfield;
2051  while (i >= 0)
2052  {
2054 
2056  fld->recparentno == rec->dno);
2057  if (strcmp(fld->fieldname, fldname) == 0)
2058  return fld;
2059  i = fld->nextfield;
2060  }
2061 
2062  /* nope, so make a new one */
2063  recfield = palloc0(sizeof(PLpgSQL_recfield));
2064  recfield->dtype = PLPGSQL_DTYPE_RECFIELD;
2065  recfield->fieldname = pstrdup(fldname);
2066  recfield->recparentno = rec->dno;
2068 
2069  plpgsql_adddatum((PLpgSQL_datum *) recfield);
2070 
2071  /* now we can link it into the parent's chain */
2072  recfield->nextfield = rec->firstfield;
2073  rec->firstfield = recfield->dno;
2074 
2075  return recfield;
2076 }
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:46
char * pstrdup(const char *in)
Definition: mcxt.c:1299
#define INVALID_TUPLEDESC_IDENTIFIER
Definition: typcache.h:155
void plpgsql_adddatum(PLpgSQL_datum *newdatum)
Definition: pl_comp.c:2333
uint64 rectupledescid
Definition: plpgsql.h:428
void * palloc0(Size size)
Definition: mcxt.c:1093
PLpgSQL_datum_type dtype
Definition: plpgsql.h:421
#define Assert(condition)
Definition: c.h:804
int i
char * fieldname
Definition: plpgsql.h:425
int firstfield
Definition: plpgsql.h:408

◆ plpgsql_build_record()

PLpgSQL_rec* plpgsql_build_record ( const char *  refname,
int  lineno,
PLpgSQL_type dtype,
Oid  rectypeid,
bool  add2namespace 
)

Definition at line 1950 of file pl_comp.c.

References PLpgSQL_rec::datatype, PLpgSQL_datum::dno, PLpgSQL_rec::dtype, PLpgSQL_rec::erh, PLpgSQL_rec::firstfield, PLpgSQL_rec::lineno, palloc0(), plpgsql_adddatum(), PLPGSQL_DTYPE_REC, plpgsql_ns_additem(), PLPGSQL_NSTYPE_REC, pstrdup(), PLpgSQL_rec::rectypeid, and PLpgSQL_rec::refname.

Referenced by do_compile(), and plpgsql_build_variable().

1953 {
1954  PLpgSQL_rec *rec;
1955 
1956  rec = palloc0(sizeof(PLpgSQL_rec));
1957  rec->dtype = PLPGSQL_DTYPE_REC;
1958  rec->refname = pstrdup(refname);
1959  rec->lineno = lineno;
1960  /* other fields are left as 0, might be changed by caller */
1961  rec->datatype = dtype;
1962  rec->rectypeid = rectypeid;
1963  rec->firstfield = -1;
1964  rec->erh = NULL;
1966  if (add2namespace)
1968 
1969  return rec;
1970 }
PLpgSQL_datum_type dtype
Definition: plpgsql.h:390
PLpgSQL_type * datatype
Definition: plpgsql.h:405
char * pstrdup(const char *in)
Definition: mcxt.c:1299
void plpgsql_ns_additem(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
Definition: pl_funcs.c:92
ExpandedRecordHeader * erh
Definition: plpgsql.h:413
char * refname
Definition: plpgsql.h:392
void plpgsql_adddatum(PLpgSQL_datum *newdatum)
Definition: pl_comp.c:2333
void * palloc0(Size size)
Definition: mcxt.c:1093
Oid rectypeid
Definition: plpgsql.h:406
int lineno
Definition: plpgsql.h:393
int firstfield
Definition: plpgsql.h:408

◆ plpgsql_build_variable()

PLpgSQL_variable* plpgsql_build_variable ( const char *  refname,
int  lineno,
PLpgSQL_type dtype,
bool  add2namespace 
)

Definition at line 1887 of file pl_comp.c.

References PLpgSQL_var::datatype, PLpgSQL_datum::dno, PLpgSQL_var::dtype, elog, ereport, errcode(), errmsg(), ERROR, format_type_be(), PLpgSQL_var::freeval, PLpgSQL_var::isnull, PLpgSQL_var::lineno, palloc0(), plpgsql_adddatum(), plpgsql_build_record(), PLPGSQL_DTYPE_VAR, plpgsql_ns_additem(), PLPGSQL_NSTYPE_VAR, PLPGSQL_TTYPE_PSEUDO, PLPGSQL_TTYPE_REC, PLPGSQL_TTYPE_SCALAR, pstrdup(), PLpgSQL_var::refname, PLpgSQL_type::ttype, PLpgSQL_type::typoid, and PLpgSQL_var::value.

Referenced by do_compile(), and plpgsql_compile_inline().

1889 {
1890  PLpgSQL_variable *result;
1891 
1892  switch (dtype->ttype)
1893  {
1894  case PLPGSQL_TTYPE_SCALAR:
1895  {
1896  /* Ordinary scalar datatype */
1897  PLpgSQL_var *var;
1898 
1899  var = palloc0(sizeof(PLpgSQL_var));
1900  var->dtype = PLPGSQL_DTYPE_VAR;
1901  var->refname = pstrdup(refname);
1902  var->lineno = lineno;
1903  var->datatype = dtype;
1904  /* other fields are left as 0, might be changed by caller */
1905 
1906  /* preset to NULL */
1907  var->value = 0;
1908  var->isnull = true;
1909  var->freeval = false;
1910 
1912  if (add2namespace)
1914  var->dno,
1915  refname);
1916  result = (PLpgSQL_variable *) var;
1917  break;
1918  }
1919  case PLPGSQL_TTYPE_REC:
1920  {
1921  /* Composite type -- build a record variable */
1922  PLpgSQL_rec *rec;
1923 
1924  rec = plpgsql_build_record(refname, lineno,
1925  dtype, dtype->typoid,
1926  add2namespace);
1927  result = (PLpgSQL_variable *) rec;
1928  break;
1929  }
1930  case PLPGSQL_TTYPE_PSEUDO:
1931  ereport(ERROR,
1932  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1933  errmsg("variable \"%s\" has pseudo-type %s",
1934  refname, format_type_be(dtype->typoid))));
1935  result = NULL; /* keep compiler quiet */
1936  break;
1937  default:
1938  elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
1939  result = NULL; /* keep compiler quiet */
1940  break;
1941  }
1942 
1943  return result;
1944 }
char * refname
Definition: plpgsql.h:312
PLpgSQL_rec * plpgsql_build_record(const char *refname, int lineno, PLpgSQL_type *dtype, Oid rectypeid, bool add2namespace)
Definition: pl_comp.c:1950
PLpgSQL_datum_type dtype
Definition: plpgsql.h:310
char * pstrdup(const char *in)
Definition: mcxt.c:1299
PLpgSQL_type * datatype
Definition: plpgsql.h:319
void plpgsql_ns_additem(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
Definition: pl_funcs.c:92
PLpgSQL_type_type ttype
Definition: plpgsql.h:201
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
void plpgsql_adddatum(PLpgSQL_datum *newdatum)
Definition: pl_comp.c:2333
#define ERROR
Definition: elog.h:46
bool freeval
Definition: plpgsql.h:334
void * palloc0(Size size)
Definition: mcxt.c:1093
Datum value
Definition: plpgsql.h:332
#define ereport(elevel,...)
Definition: elog.h:157
int lineno
Definition: plpgsql.h:313
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
bool isnull
Definition: plpgsql.h:333
Oid typoid
Definition: plpgsql.h:200

◆ plpgsql_compile()

PLpgSQL_function* plpgsql_compile ( FunctionCallInfo  fcinfo,
bool  forValidator 
)

Definition at line 136 of file pl_comp.c.

References compute_function_hashkey(), delete_function(), do_compile(), elog, ERROR, FunctionCallInfoBaseData::flinfo, FmgrInfo::fn_extra, FmgrInfo::fn_oid, PLpgSQL_function::fn_tid, PLpgSQL_function::fn_xmin, plpgsql_hashent::function, GETSTRUCT, HeapTupleHeaderGetRawXmin, HeapTupleIsValid, ItemPointerEquals(), ObjectIdGetDatum, plpgsql_HashTableLookup(), PROCOID, ReleaseSysCache(), SearchSysCache1(), HeapTupleData::t_data, HeapTupleData::t_self, and PLpgSQL_function::use_count.

Referenced by plpgsql_call_handler(), and plpgsql_validator().

137 {
138  Oid funcOid = fcinfo->flinfo->fn_oid;
139  HeapTuple procTup;
140  Form_pg_proc procStruct;
141  PLpgSQL_function *function;
142  PLpgSQL_func_hashkey hashkey;
143  bool function_valid = false;
144  bool hashkey_valid = false;
145 
146  /*
147  * Lookup the pg_proc tuple by Oid; we'll need it in any case
148  */
149  procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
150  if (!HeapTupleIsValid(procTup))
151  elog(ERROR, "cache lookup failed for function %u", funcOid);
152  procStruct = (Form_pg_proc) GETSTRUCT(procTup);
153 
154  /*
155  * See if there's already a cache entry for the current FmgrInfo. If not,
156  * try to find one in the hash table.
157  */
158  function = (PLpgSQL_function *) fcinfo->flinfo->fn_extra;
159 
160 recheck:
161  if (!function)
162  {
163  /* Compute hashkey using function signature and actual arg types */
164  compute_function_hashkey(fcinfo, procStruct, &hashkey, forValidator);
165  hashkey_valid = true;
166 
167  /* And do the lookup */
168  function = plpgsql_HashTableLookup(&hashkey);
169  }
170 
171  if (function)
172  {
173  /* We have a compiled function, but is it still valid? */
174  if (function->fn_xmin == HeapTupleHeaderGetRawXmin(procTup->t_data) &&
175  ItemPointerEquals(&function->fn_tid, &procTup->t_self))
176  function_valid = true;
177  else
178  {
179  /*
180  * Nope, so remove it from hashtable and try to drop associated
181  * storage (if not done already).
182  */
183  delete_function(function);
184 
185  /*
186  * If the function isn't in active use then we can overwrite the
187  * func struct with new data, allowing any other existing fn_extra
188  * pointers to make use of the new definition on their next use.
189  * If it is in use then just leave it alone and make a new one.
190  * (The active invocations will run to completion using the
191  * previous definition, and then the cache entry will just be
192  * leaked; doesn't seem worth adding code to clean it up, given
193  * what a corner case this is.)
194  *
195  * If we found the function struct via fn_extra then it's possible
196  * a replacement has already been made, so go back and recheck the
197  * hashtable.
198  */
199  if (function->use_count != 0)
200  {
201  function = NULL;
202  if (!hashkey_valid)
203  goto recheck;
204  }
205  }
206  }
207 
208  /*
209  * If the function wasn't found or was out-of-date, we have to compile it
210  */
211  if (!function_valid)
212  {
213  /*
214  * Calculate hashkey if we didn't already; we'll need it to store the
215  * completed function.
216  */
217  if (!hashkey_valid)
218  compute_function_hashkey(fcinfo, procStruct, &hashkey,
219  forValidator);
220 
221  /*
222  * Do the hard part.
223  */
224  function = do_compile(fcinfo, procTup, function,
225  &hashkey, forValidator);
226  }
227 
228  ReleaseSysCache(procTup);
229 
230  /*
231  * Save pointer in FmgrInfo to avoid search on subsequent calls
232  */
233  fcinfo->flinfo->fn_extra = (void *) function;
234 
235  /*
236  * Finally return the compiled function
237  */
238  return function;
239 }
static PLpgSQL_function * do_compile(FunctionCallInfo fcinfo, HeapTuple procTup, PLpgSQL_function *function, PLpgSQL_func_hashkey *hashkey, bool forValidator)
Definition: pl_comp.c:264
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
static void compute_function_hashkey(FunctionCallInfo fcinfo, Form_pg_proc procStruct, PLpgSQL_func_hashkey *hashkey, bool forValidator)
Definition: pl_comp.c:2452
unsigned int Oid
Definition: postgres_ext.h:31
HeapTupleHeader t_data
Definition: htup.h:68
static void delete_function(PLpgSQL_function *func)
Definition: pl_comp.c:2577
static PLpgSQL_function * plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key)
Definition: pl_comp.c:2605
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
FmgrInfo * flinfo
Definition: fmgr.h:87
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
Oid fn_oid
Definition: fmgr.h:59
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:308
void * fn_extra
Definition: fmgr.h:64
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
Definition: itemptr.c:29
on_exit_nicely_callback function
#define elog(elevel,...)
Definition: elog.h:232

◆ plpgsql_compile_error_callback()

static void plpgsql_compile_error_callback ( void *  arg)
static

Definition at line 984 of file pl_comp.c.

References errcontext, function_parse_error_transpose(), plpgsql_error_funcname, and plpgsql_latest_lineno().

Referenced by do_compile(), and plpgsql_compile_inline().

985 {
986  if (arg)
987  {
988  /*
989  * Try to convert syntax error position to reference text of original
990  * CREATE FUNCTION or DO command.
991  */
992  if (function_parse_error_transpose((const char *) arg))
993  return;
994 
995  /*
996  * Done if a syntax error position was reported; otherwise we have to
997  * fall back to a "near line N" report.
998  */
999  }
1000 
1002  errcontext("compilation of PL/pgSQL function \"%s\" near line %d",
1004 }
int plpgsql_latest_lineno(void)
Definition: pl_scanner.c:572
char * plpgsql_error_funcname
Definition: pl_comp.c:49
bool function_parse_error_transpose(const char *prosrc)
Definition: pg_proc.c:1011
#define errcontext
Definition: elog.h:204
void * arg

◆ plpgsql_compile_inline()

PLpgSQL_function* plpgsql_compile_inline ( char *  proc_source)

Definition at line 847 of file pl_comp.c.

References add_dummy_return(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, ErrorContextCallback::arg, ErrorContextCallback::callback, check_function_bodies, CurrentMemoryContext, PLpgSQL_variable::dno, elog, ERROR, error_context_stack, PLpgSQL_function::fn_rettype, plpgsql_hashent::function, InvalidOid, MemoryContextSwitchTo(), palloc0(), plpgsql_build_datatype(), plpgsql_build_variable(), plpgsql_check_syntax, plpgsql_compile_error_callback(), plpgsql_DumpExecTree, plpgsql_error_funcname, plpgsql_finish_datums(), PLPGSQL_LABEL_BLOCK, PLPGSQL_NOT_TRIGGER, plpgsql_ns_init(), plpgsql_ns_push(), plpgsql_parse_result, plpgsql_print_strict_params, plpgsql_scanner_finish(), plpgsql_scanner_init(), plpgsql_start_datums(), plpgsql_variable_conflict, plpgsql_yyparse(), ErrorContextCallback::previous, and pstrdup().

Referenced by plpgsql_inline_handler().

848 {
849  char *func_name = "inline_code_block";
850  PLpgSQL_function *function;
851  ErrorContextCallback plerrcontext;
852  PLpgSQL_variable *var;
853  int parse_rc;
854  MemoryContext func_cxt;
855 
856  /*
857  * Setup the scanner input and error info. We assume that this function
858  * cannot be invoked recursively, so there's no need to save and restore
859  * the static variables used here.
860  */
861  plpgsql_scanner_init(proc_source);
862 
863  plpgsql_error_funcname = func_name;
864 
865  /*
866  * Setup error traceback support for ereport()
867  */
869  plerrcontext.arg = proc_source;
870  plerrcontext.previous = error_context_stack;
871  error_context_stack = &plerrcontext;
872 
873  /* Do extra syntax checking if check_function_bodies is on */
875 
876  /* Function struct does not live past current statement */
877  function = (PLpgSQL_function *) palloc0(sizeof(PLpgSQL_function));
878 
879  plpgsql_curr_compile = function;
880 
881  /*
882  * All the rest of the compile-time storage (e.g. parse tree) is kept in
883  * its own memory context, so it can be reclaimed easily.
884  */
886  "PL/pgSQL inline code context",
889 
890  function->fn_signature = pstrdup(func_name);
891  function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
892  function->fn_input_collation = InvalidOid;
893  function->fn_cxt = func_cxt;
894  function->out_param_varno = -1; /* set up for no OUT param */
895  function->resolve_option = plpgsql_variable_conflict;
896  function->print_strict_params = plpgsql_print_strict_params;
897 
898  /*
899  * don't do extra validation for inline code as we don't want to add spam
900  * at runtime
901  */
902  function->extra_warnings = 0;
903  function->extra_errors = 0;
904 
905  function->nstatements = 0;
906  function->requires_procedure_resowner = false;
907 
908  plpgsql_ns_init();
910  plpgsql_DumpExecTree = false;
912 
913  /* Set up as though in a function returning VOID */
914  function->fn_rettype = VOIDOID;
915  function->fn_retset = false;
916  function->fn_retistuple = false;
917  function->fn_retisdomain = false;
918  function->fn_prokind = PROKIND_FUNCTION;
919  /* a bit of hardwired knowledge about type VOID here */
920  function->fn_retbyval = true;
921  function->fn_rettyplen = sizeof(int32);
922 
923  /*
924  * Remember if function is STABLE/IMMUTABLE. XXX would it be better to
925  * set this true inside a read-only transaction? Not clear.
926  */
927  function->fn_readonly = false;
928 
929  /*
930  * Create the magic FOUND variable.
931  */
932  var = plpgsql_build_variable("found", 0,
933  plpgsql_build_datatype(BOOLOID,
934  -1,
935  InvalidOid,
936  NULL),
937  true);
938  function->found_varno = var->dno;
939 
940  /*
941  * Now parse the function's text
942  */
943  parse_rc = plpgsql_yyparse();
944  if (parse_rc != 0)
945  elog(ERROR, "plpgsql parser returned %d", parse_rc);
946  function->action = plpgsql_parse_result;
947 
949 
950  /*
951  * If it returns VOID (always true at the moment), we allow control to
952  * fall off the end without an explicit RETURN statement.
953  */
954  if (function->fn_rettype == VOIDOID)
955  add_dummy_return(function);
956 
957  /*
958  * Complete the function's info
959  */
960  function->fn_nargs = 0;
961 
962  plpgsql_finish_datums(function);
963 
964  /*
965  * Pop the error context stack
966  */
967  error_context_stack = plerrcontext.previous;
968  plpgsql_error_funcname = NULL;
969 
970  plpgsql_check_syntax = false;
971 
974  return function;
975 }
int plpgsql_yyparse(void)
#define AllocSetContextCreate
Definition: memutils.h:173
char * pstrdup(const char *in)
Definition: mcxt.c:1299
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool check_function_bodies
Definition: guc.c:586
void(* callback)(void *arg)
Definition: elog.h:247
struct ErrorContextCallback * previous
Definition: elog.h:246
static void plpgsql_start_datums(void)
Definition: pl_comp.c:2316
signed int int32
Definition: c.h:429
ErrorContextCallback * error_context_stack
Definition: elog.c:93
void plpgsql_scanner_finish(void)
Definition: pl_scanner.c:613
bool plpgsql_check_syntax
Definition: pl_comp.c:51
#define ERROR
Definition: elog.h:46
char * plpgsql_error_funcname
Definition: pl_comp.c:49
bool plpgsql_DumpExecTree
Definition: pl_comp.c:50
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:195
static void add_dummy_return(PLpgSQL_function *function)
Definition: pl_comp.c:1036
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
void plpgsql_ns_init(void)
Definition: pl_funcs.c:43
void * palloc0(Size size)
Definition: mcxt.c:1093
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:2091
#define InvalidOid
Definition: postgres_ext.h:36
bool plpgsql_print_strict_params
Definition: pl_handler.c:46
static void plpgsql_compile_error_callback(void *arg)
Definition: pl_comp.c:984
int plpgsql_variable_conflict
Definition: pl_handler.c:44
void plpgsql_ns_push(const char *label, PLpgSQL_label_type label_type)
Definition: pl_funcs.c:54
PLpgSQL_stmt_block * plpgsql_parse_result
Definition: pl_comp.c:42
PLpgSQL_variable * plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype, bool add2namespace)
Definition: pl_comp.c:1887
on_exit_nicely_callback function
void plpgsql_scanner_init(const char *str)
Definition: pl_scanner.c:586
static void plpgsql_finish_datums(PLpgSQL_function *function)
Definition: pl_comp.c:2350
#define elog(elevel,...)
Definition: elog.h:232
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:56
PLpgSQL_function * plpgsql_curr_compile
Definition: pl_comp.c:53

◆ plpgsql_finish_datums()

static void plpgsql_finish_datums ( PLpgSQL_function function)
static

Definition at line 2350 of file pl_comp.c.

References PLpgSQL_function::datums, PLpgSQL_datum::dtype, plpgsql_hashent::function, i, MAXALIGN, palloc(), PLPGSQL_DTYPE_PROMISE, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_VAR, and plpgsql_nDatums.

Referenced by do_compile(), and plpgsql_compile_inline().

2351 {
2352  Size copiable_size = 0;
2353  int i;
2354 
2355  function->ndatums = plpgsql_nDatums;
2356  function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
2357  for (i = 0; i < plpgsql_nDatums; i++)
2358  {
2359  function->datums[i] = plpgsql_Datums[i];
2360 
2361  /* This must agree with copy_plpgsql_datums on what is copiable */
2362  switch (function->datums[i]->dtype)
2363  {
2364  case PLPGSQL_DTYPE_VAR:
2365  case PLPGSQL_DTYPE_PROMISE:
2366  copiable_size += MAXALIGN(sizeof(PLpgSQL_var));
2367  break;
2368  case PLPGSQL_DTYPE_REC:
2369  copiable_size += MAXALIGN(sizeof(PLpgSQL_rec));
2370  break;
2371  default:
2372  break;
2373  }
2374  }
2375  function->copiable_size = copiable_size;
2376 }
int plpgsql_nDatums
Definition: pl_comp.c:45
PLpgSQL_datum ** datums
Definition: plpgsql.h:1002
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:46
PLpgSQL_datum_type dtype
Definition: plpgsql.h:276
size_t Size
Definition: c.h:540
#define MAXALIGN(LEN)
Definition: c.h:757
void * palloc(Size size)
Definition: mcxt.c:1062
int i

◆ plpgsql_HashTableDelete()

static void plpgsql_HashTableDelete ( PLpgSQL_function function)
static

Definition at line 2639 of file pl_comp.c.

References elog, PLpgSQL_function::fn_hashkey, plpgsql_hashent::function, HASH_REMOVE, hash_search(), and WARNING.

Referenced by delete_function().

2640 {
2641  plpgsql_HashEnt *hentry;
2642 
2643  /* do nothing if not in table */
2644  if (function->fn_hashkey == NULL)
2645  return;
2646 
2648  (void *) function->fn_hashkey,
2649  HASH_REMOVE,
2650  NULL);
2651  if (hentry == NULL)
2652  elog(WARNING, "trying to delete function that does not exist");
2653 
2654  /* remove back link, which no longer points to allocated storage */
2655  function->fn_hashkey = NULL;
2656 }
PLpgSQL_func_hashkey * fn_hashkey
Definition: plpgsql.h:973
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:62
#define WARNING
Definition: elog.h:40
#define elog(elevel,...)
Definition: elog.h:232

◆ plpgsql_HashTableInit()

void plpgsql_HashTableInit ( void  )

Definition at line 2589 of file pl_comp.c.

References Assert, HASHCTL::entrysize, FUNCS_PER_USER, HASH_BLOBS, hash_create(), HASH_ELEM, and HASHCTL::keysize.

Referenced by _PG_init().

2590 {
2591  HASHCTL ctl;
2592 
2593  /* don't allow double-initialization */
2594  Assert(plpgsql_HashTable == NULL);
2595 
2596  ctl.keysize = sizeof(PLpgSQL_func_hashkey);
2597  ctl.entrysize = sizeof(plpgsql_HashEnt);
2598  plpgsql_HashTable = hash_create("PLpgSQL function hash",
2600  &ctl,
2601  HASH_ELEM | HASH_BLOBS);
2602 }
#define FUNCS_PER_USER
Definition: pl_comp.c:70
#define HASH_ELEM
Definition: hsearch.h:95
Size entrysize
Definition: hsearch.h:76
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:62
struct plpgsql_hashent plpgsql_HashEnt
struct PLpgSQL_func_hashkey PLpgSQL_func_hashkey
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:349
#define HASH_BLOBS
Definition: hsearch.h:97
Size keysize
Definition: hsearch.h:75
#define Assert(condition)
Definition: c.h:804

◆ plpgsql_HashTableInsert()

static void plpgsql_HashTableInsert ( PLpgSQL_function function,
PLpgSQL_func_hashkey func_key 
)
static

Definition at line 2620 of file pl_comp.c.

References elog, PLpgSQL_function::fn_hashkey, plpgsql_hashent::function, HASH_ENTER, hash_search(), plpgsql_hashent::key, and WARNING.

Referenced by do_compile().

2622 {
2623  plpgsql_HashEnt *hentry;
2624  bool found;
2625 
2627  (void *) func_key,
2628  HASH_ENTER,
2629  &found);
2630  if (found)
2631  elog(WARNING, "trying to insert a function that already exists");
2632 
2633  hentry->function = function;
2634  /* prepare back link from function to hashtable key */
2635  function->fn_hashkey = &hentry->key;
2636 }
PLpgSQL_func_hashkey * fn_hashkey
Definition: plpgsql.h:973
PLpgSQL_func_hashkey key
Definition: pl_comp.c:66
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:62
PLpgSQL_function * function
Definition: pl_comp.c:67
#define WARNING
Definition: elog.h:40
#define elog(elevel,...)
Definition: elog.h:232

◆ plpgsql_HashTableLookup()

static PLpgSQL_function * plpgsql_HashTableLookup ( PLpgSQL_func_hashkey func_key)
static

Definition at line 2605 of file pl_comp.c.

References plpgsql_hashent::function, HASH_FIND, and hash_search().

Referenced by plpgsql_compile().

2606 {
2607  plpgsql_HashEnt *hentry;
2608 
2610  (void *) func_key,
2611  HASH_FIND,
2612  NULL);
2613  if (hentry)
2614  return hentry->function;
2615  else
2616  return NULL;
2617 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:62
PLpgSQL_function * function
Definition: pl_comp.c:67

◆ plpgsql_param_ref()

static Node * plpgsql_param_ref ( ParseState pstate,
ParamRef pref 
)
static

Definition at line 1152 of file pl_comp.c.

References ParamRef::location, make_datum_param(), PLpgSQL_expr::ns, ParamRef::number, ParseState::p_ref_hook_state, plpgsql_ns_lookup(), and snprintf.

Referenced by plpgsql_parser_setup().

1153 {
1154  PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1155  char pname[32];
1156  PLpgSQL_nsitem *nse;
1157 
1158  snprintf(pname, sizeof(pname), "$%d", pref->number);
1159 
1160  nse = plpgsql_ns_lookup(expr->ns, false,
1161  pname, NULL, NULL,
1162  NULL);
1163 
1164  if (nse == NULL)
1165  return NULL; /* name not known to plpgsql */
1166 
1167  return make_datum_param(expr, nse->itemno, pref->location);
1168 }
PLpgSQL_nsitem * plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode, const char *name1, const char *name2, const char *name3, int *names_used)
Definition: pl_funcs.c:130
struct PLpgSQL_nsitem * ns
Definition: plpgsql.h:228
int number
Definition: parsenodes.h:257
int location
Definition: parsenodes.h:258
void * p_ref_hook_state
Definition: parse_node.h:224
#define snprintf
Definition: port.h:216
static Node * make_datum_param(PLpgSQL_expr *expr, int dno, int location)
Definition: pl_comp.c:1343

◆ plpgsql_parse_cwordrowtype()

PLpgSQL_type* plpgsql_parse_cwordrowtype ( List idents)

Definition at line 1839 of file pl_comp.c.

References ereport, errcode(), errmsg(), ERROR, get_rel_type_id(), InvalidOid, linitial, list_length(), lsecond, makeRangeVar(), makeTypeNameFromNameList(), MemoryContextSwitchTo(), NoLock, OidIsValid, plpgsql_build_datatype(), RangeVarGetRelid, and strVal.

1840 {
1841  Oid classOid;
1842  Oid typOid;
1843  RangeVar *relvar;
1844  MemoryContext oldCxt;
1845 
1846  /*
1847  * As above, this is a relation lookup but could be a type lookup if we
1848  * weren't being backwards-compatible about error wording.
1849  */
1850  if (list_length(idents) != 2)
1851  return NULL;
1852 
1853  /* Avoid memory leaks in long-term function context */
1855 
1856  /* Look up relation name. Can't lock it - we might not have privileges. */
1857  relvar = makeRangeVar(strVal(linitial(idents)),
1858  strVal(lsecond(idents)),
1859  -1);
1860  classOid = RangeVarGetRelid(relvar, NoLock, false);
1861 
1862  /* Some relkinds lack type OIDs */
1863  typOid = get_rel_type_id(classOid);
1864  if (!OidIsValid(typOid))
1865  ereport(ERROR,
1866  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1867  errmsg("relation \"%s\" does not have a composite type",
1868  strVal(lsecond(idents)))));
1869 
1870  MemoryContextSwitchTo(oldCxt);
1871 
1872  /* Build and return the row type struct */
1873  return plpgsql_build_datatype(typOid, -1, InvalidOid,
1874  makeTypeNameFromNameList(idents));
1875 }
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:79
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define strVal(v)
Definition: value.h:65
int errcode(int sqlerrcode)
Definition: elog.c:698
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
#define lsecond(l)
Definition: pg_list.h:179
#define linitial(l)
Definition: pg_list.h:174
#define ERROR
Definition: elog.h:46
#define NoLock
Definition: lockdefs.h:34
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:2091
Oid get_rel_type_id(Oid relid)
Definition: lsyscache.c:1950
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
static int list_length(const List *l)
Definition: pg_list.h:149
int errmsg(const char *fmt,...)
Definition: elog.c:909
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:456
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:56
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:422

◆ plpgsql_parse_cwordtype()

PLpgSQL_type* plpgsql_parse_cwordtype ( List idents)

Definition at line 1682 of file pl_comp.c.

References build_datatype(), elog, ERROR, GETSTRUCT, HeapTupleIsValid, PLpgSQL_nsitem::itemno, PLpgSQL_nsitem::itemtype, linitial, list_length(), lsecond, lthird, makeRangeVar(), MemoryContextSwitchTo(), NoLock, ObjectIdGetDatum, OidIsValid, plpgsql_ns_lookup(), plpgsql_ns_top(), PLPGSQL_NSTYPE_VAR, RangeVarGetRelid, ReleaseSysCache(), RelnameGetRelid(), RELOID, SearchSysCache1(), SearchSysCacheAttName(), strVal, and TYPEOID.

1683 {
1684  PLpgSQL_type *dtype = NULL;
1685  PLpgSQL_nsitem *nse;
1686  const char *fldname;
1687  Oid classOid;
1688  HeapTuple classtup = NULL;
1689  HeapTuple attrtup = NULL;
1690  HeapTuple typetup = NULL;
1691  Form_pg_class classStruct;
1692  Form_pg_attribute attrStruct;
1693  MemoryContext oldCxt;
1694 
1695  /* Avoid memory leaks in the long-term function context */
1697 
1698  if (list_length(idents) == 2)
1699  {
1700  /*
1701  * Do a lookup in the current namespace stack. We don't need to check
1702  * number of names matched, because we will only consider scalar
1703  * variables.
1704  */
1705  nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1706  strVal(linitial(idents)),
1707  strVal(lsecond(idents)),
1708  NULL,
1709  NULL);
1710 
1711  if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_VAR)
1712  {
1713  dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1714  goto done;
1715  }
1716 
1717  /*
1718  * First word could also be a table name
1719  */
1720  classOid = RelnameGetRelid(strVal(linitial(idents)));
1721  if (!OidIsValid(classOid))
1722  goto done;
1723  fldname = strVal(lsecond(idents));
1724  }
1725  else if (list_length(idents) == 3)
1726  {
1727  RangeVar *relvar;
1728 
1729  relvar = makeRangeVar(strVal(linitial(idents)),
1730  strVal(lsecond(idents)),
1731  -1);
1732  /* Can't lock relation - we might not have privileges. */
1733  classOid = RangeVarGetRelid(relvar, NoLock, true);
1734  if (!OidIsValid(classOid))
1735  goto done;
1736  fldname = strVal(lthird(idents));
1737  }
1738  else
1739  goto done;
1740 
1741  classtup = SearchSysCache1(RELOID, ObjectIdGetDatum(classOid));
1742  if (!HeapTupleIsValid(classtup))
1743  goto done;
1744  classStruct = (Form_pg_class) GETSTRUCT(classtup);
1745 
1746  /*
1747  * It must be a relation, sequence, view, materialized view, composite
1748  * type, or foreign table
1749  */
1750  if (classStruct->relkind != RELKIND_RELATION &&
1751  classStruct->relkind != RELKIND_SEQUENCE &&
1752  classStruct->relkind != RELKIND_VIEW &&
1753  classStruct->relkind != RELKIND_MATVIEW &&
1754  classStruct->relkind != RELKIND_COMPOSITE_TYPE &&
1755  classStruct->relkind != RELKIND_FOREIGN_TABLE &&
1756  classStruct->relkind != RELKIND_PARTITIONED_TABLE)
1757  goto done;
1758 
1759  /*
1760  * Fetch the named table field and its type
1761  */
1762  attrtup = SearchSysCacheAttName(classOid, fldname);
1763  if (!HeapTupleIsValid(attrtup))
1764  goto done;
1765  attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1766 
1767  typetup = SearchSysCache1(TYPEOID,
1768  ObjectIdGetDatum(attrStruct->atttypid));
1769  if (!HeapTupleIsValid(typetup))
1770  elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1771 
1772  /*
1773  * Found that - build a compiler type struct in the caller's cxt and
1774  * return it. Note that we treat the type as being found-by-OID; no
1775  * attempt to re-look-up the type name will happen during invalidations.
1776  */
1777  MemoryContextSwitchTo(oldCxt);
1778  dtype = build_datatype(typetup,
1779  attrStruct->atttypmod,
1780  attrStruct->attcollation,
1781  NULL);
1783 
1784 done:
1785  if (HeapTupleIsValid(classtup))
1786  ReleaseSysCache(classtup);
1787  if (HeapTupleIsValid(attrtup))
1788  ReleaseSysCache(attrtup);
1789  if (HeapTupleIsValid(typetup))
1790  ReleaseSysCache(typetup);
1791 
1792  MemoryContextSwitchTo(oldCxt);
1793  return dtype;
1794 }
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:46
PLpgSQL_nsitem * plpgsql_ns_top(void)
Definition: pl_funcs.c:81
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
Oid RelnameGetRelid(const char *relname)
Definition: namespace.c:681
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:2113
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:79
PLpgSQL_nsitem * plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode, const char *name1, const char *name2, const char *name3, int *names_used)
Definition: pl_funcs.c:130
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define strVal(v)
Definition: value.h:65
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
#define lsecond(l)
Definition: pg_list.h:179
#define linitial(l)
Definition: pg_list.h:174
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define NoLock
Definition: lockdefs.h:34
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static int list_length(const List *l)
Definition: pg_list.h:149
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1268
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:438
#define elog(elevel,...)
Definition: elog.h:232
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:56
#define lthird(l)
Definition: pg_list.h:184
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:422

◆ plpgsql_parse_dblword()

bool plpgsql_parse_dblword ( char *  word1,
char *  word2,
PLwdatum wdatum,
PLcword cword 
)

Definition at line 1451 of file pl_comp.c.

References PLwdatum::datum, PLwdatum::ident, IDENTIFIER_LOOKUP_DECLARE, PLcword::idents, PLwdatum::idents, PLpgSQL_nsitem::itemno, PLpgSQL_nsitem::itemtype, list_make2, makeString(), plpgsql_build_recfield(), plpgsql_IdentifierLookup, plpgsql_ns_lookup(), plpgsql_ns_top(), PLPGSQL_NSTYPE_REC, PLPGSQL_NSTYPE_VAR, and PLwdatum::quoted.

Referenced by plpgsql_yylex().

1453 {
1454  PLpgSQL_nsitem *ns;
1455  List *idents;
1456  int nnames;
1457 
1458  idents = list_make2(makeString(word1),
1459  makeString(word2));
1460 
1461  /*
1462  * We should do nothing in DECLARE sections. In SQL expressions, we
1463  * really only need to make sure that RECFIELD datums are created when
1464  * needed. In all the cases handled by this function, returning a T_DATUM
1465  * with a two-word idents string is the right thing.
1466  */
1468  {
1469  /*
1470  * Do a lookup in the current namespace stack
1471  */
1472  ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1473  word1, word2, NULL,
1474  &nnames);
1475  if (ns != NULL)
1476  {
1477  switch (ns->itemtype)
1478  {
1479  case PLPGSQL_NSTYPE_VAR:
1480  /* Block-qualified reference to scalar variable. */
1481  wdatum->datum = plpgsql_Datums[ns->itemno];
1482  wdatum->ident = NULL;
1483  wdatum->quoted = false; /* not used */
1484  wdatum->idents = idents;
1485  return true;
1486 
1487  case PLPGSQL_NSTYPE_REC:
1488  if (nnames == 1)
1489  {
1490  /*
1491  * First word is a record name, so second word could
1492  * be a field in this record. We build a RECFIELD
1493  * datum whether it is or not --- any error will be
1494  * detected later.
1495  */
1496  PLpgSQL_rec *rec;
1497  PLpgSQL_recfield *new;
1498 
1499  rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
1500  new = plpgsql_build_recfield(rec, word2);
1501 
1502  wdatum->datum = (PLpgSQL_datum *) new;
1503  }
1504  else
1505  {
1506  /* Block-qualified reference to record variable. */
1507  wdatum->datum = plpgsql_Datums[ns->itemno];
1508  }
1509  wdatum->ident = NULL;
1510  wdatum->quoted = false; /* not used */
1511  wdatum->idents = idents;
1512  return true;
1513 
1514  default:
1515  break;
1516  }
1517  }
1518  }
1519 
1520  /* Nothing found */
1521  cword->idents = idents;
1522  return false;
1523 }
#define list_make2(x1, x2)
Definition: pg_list.h:208
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:46
PLpgSQL_nsitem * plpgsql_ns_top(void)
Definition: pl_funcs.c:81
PLpgSQL_nsitem * plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode, const char *name1, const char *name2, const char *name3, int *names_used)
Definition: pl_funcs.c:130
PLpgSQL_recfield * plpgsql_build_recfield(PLpgSQL_rec *rec, const char *fldname)
Definition: pl_comp.c:2044
String * makeString(char *str)
Definition: value.c:51
List * idents
Definition: plpgsql.h:1153
List * idents
Definition: plpgsql.h:1161
IdentifierLookup plpgsql_IdentifierLookup
Definition: pl_scanner.c:26
PLpgSQL_datum * datum
Definition: plpgsql.h:1158
bool quoted
Definition: plpgsql.h:1160
char * ident
Definition: plpgsql.h:1159
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:438
Definition: pg_list.h:50

◆ plpgsql_parse_err_condition()

PLpgSQL_condition* plpgsql_parse_err_condition ( char *  condname)

Definition at line 2265 of file pl_comp.c.

References ereport, errcode(), errmsg(), ERROR, i, ExceptionLabelMap::label, label, palloc(), and ExceptionLabelMap::sqlerrstate.

2266 {
2267  int i;
2268  PLpgSQL_condition *new;
2269  PLpgSQL_condition *prev;
2270 
2271  /*
2272  * XXX Eventually we will want to look for user-defined exception names
2273  * here.
2274  */
2275 
2276  /*
2277  * OTHERS is represented as code 0 (which would map to '00000', but we
2278  * have no need to represent that as an exception condition).
2279  */
2280  if (strcmp(condname, "others") == 0)
2281  {
2282  new = palloc(sizeof(PLpgSQL_condition));
2283  new->sqlerrstate = 0;
2284  new->condname = condname;
2285  new->next = NULL;
2286  return new;
2287  }
2288 
2289  prev = NULL;
2290  for (i = 0; exception_label_map[i].label != NULL; i++)
2291  {
2292  if (strcmp(condname, exception_label_map[i].label) == 0)
2293  {
2294  new = palloc(sizeof(PLpgSQL_condition));
2295  new->sqlerrstate = exception_label_map[i].sqlerrstate;
2296  new->condname = condname;
2297  new->next = prev;
2298  prev = new;
2299  }
2300  }
2301 
2302  if (!prev)
2303  ereport(ERROR,
2304  (errcode(ERRCODE_UNDEFINED_OBJECT),
2305  errmsg("unrecognized exception condition \"%s\"",
2306  condname)));
2307 
2308  return prev;
2309 }
const char * label
Definition: pl_comp.c:78
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ERROR
Definition: elog.h:46
static char * label
#define ereport(elevel,...)
Definition: elog.h:157
static const ExceptionLabelMap exception_label_map[]
Definition: pl_comp.c:82
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i

◆ plpgsql_parse_tripword()

bool plpgsql_parse_tripword ( char *  word1,
char *  word2,
char *  word3,
PLwdatum wdatum,
PLcword cword 
)

Definition at line 1532 of file pl_comp.c.

References PLwdatum::datum, PLwdatum::ident, IDENTIFIER_LOOKUP_DECLARE, PLcword::idents, PLwdatum::idents, PLpgSQL_nsitem::itemno, PLpgSQL_nsitem::itemtype, list_make2, list_make3, makeString(), plpgsql_build_recfield(), plpgsql_IdentifierLookup, plpgsql_ns_lookup(), plpgsql_ns_top(), PLPGSQL_NSTYPE_REC, and PLwdatum::quoted.

Referenced by plpgsql_yylex().

1534 {
1535  PLpgSQL_nsitem *ns;
1536  List *idents;
1537  int nnames;
1538 
1539  /*
1540  * We should do nothing in DECLARE sections. In SQL expressions, we need
1541  * to make sure that RECFIELD datums are created when needed, and we need
1542  * to be careful about how many names are reported as belonging to the
1543  * T_DATUM: the third word could be a sub-field reference, which we don't
1544  * care about here.
1545  */
1547  {
1548  /*
1549  * Do a lookup in the current namespace stack. Must find a record
1550  * reference, else ignore.
1551  */
1552  ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1553  word1, word2, word3,
1554  &nnames);
1555  if (ns != NULL)
1556  {
1557  switch (ns->itemtype)
1558  {
1559  case PLPGSQL_NSTYPE_REC:
1560  {
1561  PLpgSQL_rec *rec;
1562  PLpgSQL_recfield *new;
1563 
1564  rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
1565  if (nnames == 1)
1566  {
1567  /*
1568  * First word is a record name, so second word
1569  * could be a field in this record (and the third,
1570  * a sub-field). We build a RECFIELD datum
1571  * whether it is or not --- any error will be
1572  * detected later.
1573  */
1574  new = plpgsql_build_recfield(rec, word2);
1575  idents = list_make2(makeString(word1),
1576  makeString(word2));
1577  }
1578  else
1579  {
1580  /* Block-qualified reference to record variable. */
1581  new = plpgsql_build_recfield(rec, word3);
1582  idents = list_make3(makeString(word1),
1583  makeString(word2),
1584  makeString(word3));
1585  }
1586  wdatum->datum = (PLpgSQL_datum *) new;
1587  wdatum->ident = NULL;
1588  wdatum->quoted = false; /* not used */
1589  wdatum->idents = idents;
1590  return true;
1591  }
1592 
1593  default:
1594  break;
1595  }
1596  }
1597  }
1598 
1599  /* Nothing found */
1600  idents = list_make3(makeString(word1),
1601  makeString(word2),
1602  makeString(word3));
1603  cword->idents = idents;
1604  return false;
1605 }
#define list_make2(x1, x2)
Definition: pg_list.h:208
#define list_make3(x1, x2, x3)
Definition: pg_list.h:210
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:46
PLpgSQL_nsitem * plpgsql_ns_top(void)
Definition: pl_funcs.c:81
PLpgSQL_nsitem * plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode, const char *name1, const char *name2, const char *name3, int *names_used)
Definition: pl_funcs.c:130
PLpgSQL_recfield * plpgsql_build_recfield(PLpgSQL_rec *rec, const char *fldname)
Definition: pl_comp.c:2044
String * makeString(char *str)
Definition: value.c:51
List * idents
Definition: plpgsql.h:1153
List * idents
Definition: plpgsql.h:1161
IdentifierLookup plpgsql_IdentifierLookup
Definition: pl_scanner.c:26
PLpgSQL_datum * datum
Definition: plpgsql.h:1158
bool quoted
Definition: plpgsql.h:1160
char * ident
Definition: plpgsql.h:1159
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:438
Definition: pg_list.h:50

◆ plpgsql_parse_word()

bool plpgsql_parse_word ( char *  word1,
const char *  yytxt,
bool  lookup,
PLwdatum wdatum,
PLword word 
)

Definition at line 1396 of file pl_comp.c.

References PLwdatum::datum, elog, ERROR, PLword::ident, PLwdatum::ident, IDENTIFIER_LOOKUP_NORMAL, PLwdatum::idents, PLpgSQL_nsitem::itemno, PLpgSQL_nsitem::itemtype, NIL, plpgsql_IdentifierLookup, plpgsql_ns_lookup(), plpgsql_ns_top(), PLPGSQL_NSTYPE_REC, PLPGSQL_NSTYPE_VAR, PLword::quoted, and PLwdatum::quoted.

Referenced by plpgsql_yylex().

1398 {
1399  PLpgSQL_nsitem *ns;
1400 
1401  /*
1402  * We should not lookup variables in DECLARE sections. In SQL
1403  * expressions, there's no need to do so either --- lookup will happen
1404  * when the expression is compiled.
1405  */
1407  {
1408  /*
1409  * Do a lookup in the current namespace stack
1410  */
1411  ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1412  word1, NULL, NULL,
1413  NULL);
1414 
1415  if (ns != NULL)
1416  {
1417  switch (ns->itemtype)
1418  {
1419  case PLPGSQL_NSTYPE_VAR:
1420  case PLPGSQL_NSTYPE_REC:
1421  wdatum->datum = plpgsql_Datums[ns->itemno];
1422  wdatum->ident = word1;
1423  wdatum->quoted = (yytxt[0] == '"');
1424  wdatum->idents = NIL;
1425  return true;
1426 
1427  default:
1428  /* plpgsql_ns_lookup should never return anything else */
1429  elog(ERROR, "unrecognized plpgsql itemtype: %d",
1430  ns->itemtype);
1431  }
1432  }
1433  }
1434 
1435  /*
1436  * Nothing found - up to now it's a word without any special meaning for
1437  * us.
1438  */
1439  word->ident = word1;
1440  word->quoted = (yytxt[0] == '"');
1441  return false;
1442 }
#define NIL
Definition: pg_list.h:65
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:46
PLpgSQL_nsitem * plpgsql_ns_top(void)
Definition: pl_funcs.c:81
PLpgSQL_nsitem * plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode, const char *name1, const char *name2, const char *name3, int *names_used)
Definition: pl_funcs.c:130
char * ident
Definition: plpgsql.h:1147
#define ERROR
Definition: elog.h:46
Definition: zic.c:301
List * idents
Definition: plpgsql.h:1161
IdentifierLookup plpgsql_IdentifierLookup
Definition: pl_scanner.c:26
bool quoted
Definition: plpgsql.h:1148
PLpgSQL_datum * datum
Definition: plpgsql.h:1158
bool quoted
Definition: plpgsql.h:1160
char * ident
Definition: plpgsql.h:1159
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:438
#define elog(elevel,...)
Definition: elog.h:232

◆ plpgsql_parse_wordrowtype()

PLpgSQL_type* plpgsql_parse_wordrowtype ( char *  ident)

Definition at line 1802 of file pl_comp.c.

References ereport, errcode(), ERRCODE_UNDEFINED_TABLE, errmsg(), ERROR, get_rel_type_id(), InvalidOid, makeTypeName(), OidIsValid, plpgsql_build_datatype(), and RelnameGetRelid().

1803 {
1804  Oid classOid;
1805  Oid typOid;
1806 
1807  /*
1808  * Look up the relation. Note that because relation rowtypes have the
1809  * same names as their relations, this could be handled as a type lookup
1810  * equally well; we use the relation lookup code path only because the
1811  * errors thrown here have traditionally referred to relations not types.
1812  * But we'll make a TypeName in case we have to do re-look-up of the type.
1813  */
1814  classOid = RelnameGetRelid(ident);
1815  if (!OidIsValid(classOid))
1816  ereport(ERROR,
1818  errmsg("relation \"%s\" does not exist", ident)));
1819 
1820  /* Some relkinds lack type OIDs */
1821  typOid = get_rel_type_id(classOid);
1822  if (!OidIsValid(typOid))
1823  ereport(ERROR,
1824  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1825  errmsg("relation \"%s\" does not have a composite type",
1826  ident)));
1827 
1828  /* Build and return the row type struct */
1829  return plpgsql_build_datatype(typOid, -1, InvalidOid,
1830  makeTypeName(ident));
1831 }
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:78
Oid RelnameGetRelid(const char *relname)
Definition: namespace.c:681
int errcode(int sqlerrcode)
Definition: elog.c:698
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
#define ERROR
Definition: elog.h:46
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:2091
Oid get_rel_type_id(Oid relid)
Definition: lsyscache.c:1950
#define InvalidOid
Definition: postgres_ext.h:36
TypeName * makeTypeName(char *typnam)
Definition: makefuncs.c:444
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ plpgsql_parse_wordtype()

PLpgSQL_type* plpgsql_parse_wordtype ( char *  ident)

Definition at line 1616 of file pl_comp.c.

References build_datatype(), PLpgSQL_function::fn_input_collation, GETSTRUCT, InvalidOid, PLpgSQL_nsitem::itemno, PLpgSQL_nsitem::itemtype, LookupTypeName(), makeTypeName(), plpgsql_ns_lookup(), plpgsql_ns_top(), PLPGSQL_NSTYPE_VAR, and ReleaseSysCache().

1617 {
1618  PLpgSQL_type *dtype;
1619  PLpgSQL_nsitem *nse;
1620  TypeName *typeName;
1621  HeapTuple typeTup;
1622 
1623  /*
1624  * Do a lookup in the current namespace stack
1625  */
1626  nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1627  ident, NULL, NULL,
1628  NULL);
1629 
1630  if (nse != NULL)
1631  {
1632  switch (nse->itemtype)
1633  {
1634  case PLPGSQL_NSTYPE_VAR:
1635  return ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1636 
1637  /* XXX perhaps allow REC/ROW here? */
1638 
1639  default:
1640  return NULL;
1641  }
1642  }
1643 
1644  /*
1645  * Word wasn't found in the namespace stack. Try to find a data type with
1646  * that name, but ignore shell types and complex types.
1647  */
1648  typeName = makeTypeName(ident);
1649  typeTup = LookupTypeName(NULL, typeName, NULL, false);
1650  if (typeTup)
1651  {
1652  Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1653 
1654  if (!typeStruct->typisdefined ||
1655  typeStruct->typrelid != InvalidOid)
1656  {
1657  ReleaseSysCache(typeTup);
1658  return NULL;
1659  }
1660 
1661  dtype = build_datatype(typeTup, -1,
1663  typeName);
1664 
1665  ReleaseSysCache(typeTup);
1666  return dtype;
1667  }
1668 
1669  /*
1670  * Nothing found - up to now it's a word without any special meaning for
1671  * us.
1672  */
1673  return NULL;
1674 }
Type LookupTypeName(ParseState *pstate, const TypeName *typeName, int32 *typmod_p, bool missing_ok)
Definition: parse_type.c:38
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:46
PLpgSQL_nsitem * plpgsql_ns_top(void)
Definition: pl_funcs.c:81
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:2113
PLpgSQL_nsitem * plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode, const char *name1, const char *name2, const char *name3, int *names_used)
Definition: pl_funcs.c:130
Oid fn_input_collation
Definition: plpgsql.h:972
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define InvalidOid
Definition: postgres_ext.h:36
TypeName * makeTypeName(char *typnam)
Definition: makefuncs.c:444
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:438
PLpgSQL_function * plpgsql_curr_compile
Definition: pl_comp.c:53

◆ plpgsql_parser_setup()

void plpgsql_parser_setup ( struct ParseState pstate,
PLpgSQL_expr expr 
)

Definition at line 1081 of file pl_comp.c.

References ParseState::p_paramref_hook, ParseState::p_post_columnref_hook, ParseState::p_pre_columnref_hook, ParseState::p_ref_hook_state, plpgsql_param_ref(), plpgsql_post_column_ref(), and plpgsql_pre_column_ref().

Referenced by exec_prepare_plan(), and plpgsql_estate_setup().

1082 {
1086  /* no need to use p_coerce_param_hook */
1087  pstate->p_ref_hook_state = (void *) expr;
1088 }
static Node * plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref)
Definition: pl_comp.c:1094
PostParseColumnRefHook p_post_columnref_hook
Definition: parse_node.h:221
ParseParamRefHook p_paramref_hook
Definition: parse_node.h:222
static Node * plpgsql_param_ref(ParseState *pstate, ParamRef *pref)
Definition: pl_comp.c:1152
void * p_ref_hook_state
Definition: parse_node.h:224
PreParseColumnRefHook p_pre_columnref_hook
Definition: parse_node.h:220
static Node * plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
Definition: pl_comp.c:1108

◆ plpgsql_post_column_ref()

static Node * plpgsql_post_column_ref ( ParseState pstate,
ColumnRef cref,
Node var 
)
static

Definition at line 1108 of file pl_comp.c.

References ereport, errcode(), errdetail(), errmsg(), ERROR, ColumnRef::fields, PLpgSQL_expr::func, ColumnRef::location, NameListToString(), ParseState::p_ref_hook_state, parser_errposition(), PLPGSQL_RESOLVE_COLUMN, PLPGSQL_RESOLVE_VARIABLE, resolve_column_ref(), and PLpgSQL_function::resolve_option.

Referenced by plpgsql_parser_setup().

1109 {
1110  PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1111  Node *myvar;
1112 
1114  return NULL; /* we already found there's no match */
1115 
1116  if (expr->func->resolve_option == PLPGSQL_RESOLVE_COLUMN && var != NULL)
1117  return NULL; /* there's a table column, prefer that */
1118 
1119  /*
1120  * If we find a record/row variable but can't match a field name, throw
1121  * error if there was no core resolution for the ColumnRef either. In
1122  * that situation, the reference is inevitably going to fail, and
1123  * complaining about the record/row variable is likely to be more on-point
1124  * than the core parser's error message. (It's too bad we don't have
1125  * access to transformColumnRef's internal crerr state here, as in case of
1126  * a conflict with a table name this could still be less than the most
1127  * helpful error message possible.)
1128  */
1129  myvar = resolve_column_ref(pstate, expr, cref, (var == NULL));
1130 
1131  if (myvar != NULL && var != NULL)
1132  {
1133  /*
1134  * We could leave it to the core parser to throw this error, but we
1135  * can add a more useful detail message than the core could.
1136  */
1137  ereport(ERROR,
1138  (errcode(ERRCODE_AMBIGUOUS_COLUMN),
1139  errmsg("column reference \"%s\" is ambiguous",
1140  NameListToString(cref->fields)),
1141  errdetail("It could refer to either a PL/pgSQL variable or a table column."),
1142  parser_errposition(pstate, cref->location)));
1143  }
1144 
1145  return myvar;
1146 }
Definition: nodes.h:536
int errcode(int sqlerrcode)
Definition: elog.c:698
PLpgSQL_resolve_option resolve_option
Definition: plpgsql.h:992
int location
Definition: parsenodes.h:248
#define ERROR
Definition: elog.h:46
int errdetail(const char *fmt,...)
Definition: elog.c:1042
char * NameListToString(List *names)
Definition: namespace.c:3147
struct PLpgSQL_function * func
Definition: plpgsql.h:225
#define ereport(elevel,...)
Definition: elog.h:157
void * p_ref_hook_state
Definition: parse_node.h:224
static Node * resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr, ColumnRef *cref, bool error_if_no_field)
Definition: pl_comp.c:1179
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
int errmsg(const char *fmt,...)
Definition: elog.c:909
List * fields
Definition: parsenodes.h:247

◆ plpgsql_pre_column_ref()

static Node * plpgsql_pre_column_ref ( ParseState pstate,
ColumnRef cref 
)
static

Definition at line 1094 of file pl_comp.c.

References PLpgSQL_expr::func, ParseState::p_ref_hook_state, PLPGSQL_RESOLVE_VARIABLE, resolve_column_ref(), and PLpgSQL_function::resolve_option.

Referenced by plpgsql_parser_setup().

1095 {
1096  PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1097 
1099  return resolve_column_ref(pstate, expr, cref, false);
1100  else
1101  return NULL;
1102 }
PLpgSQL_resolve_option resolve_option
Definition: plpgsql.h:992
struct PLpgSQL_function * func
Definition: plpgsql.h:225
void * p_ref_hook_state
Definition: parse_node.h:224
static Node * resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr, ColumnRef *cref, bool error_if_no_field)
Definition: pl_comp.c:1179

◆ plpgsql_recognize_err_condition()

int plpgsql_recognize_err_condition ( const char *  condname,
bool  allow_sqlstate 
)

Definition at line 2229 of file pl_comp.c.

References ereport, errcode(), errmsg(), ERROR, i, ExceptionLabelMap::label, label, MAKE_SQLSTATE, and ExceptionLabelMap::sqlerrstate.

Referenced by exec_stmt_raise().

2230 {
2231  int i;
2232 
2233  if (allow_sqlstate)
2234  {
2235  if (strlen(condname) == 5 &&
2236  strspn(condname, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") == 5)
2237  return MAKE_SQLSTATE(condname[0],
2238  condname[1],
2239  condname[2],
2240  condname[3],
2241  condname[4]);
2242  }
2243 
2244  for (i = 0; exception_label_map[i].label != NULL; i++)
2245  {
2246  if (strcmp(condname, exception_label_map[i].label) == 0)
2248  }
2249 
2250  ereport(ERROR,
2251  (errcode(ERRCODE_UNDEFINED_OBJECT),
2252  errmsg("unrecognized exception condition \"%s\"",
2253  condname)));
2254  return 0; /* keep compiler quiet */
2255 }
const char * label
Definition: pl_comp.c:78
#define MAKE_SQLSTATE(ch1, ch2, ch3, ch4, ch5)
Definition: elog.h:64
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ERROR
Definition: elog.h:46
static char * label
#define ereport(elevel,...)
Definition: elog.h:157
static const ExceptionLabelMap exception_label_map[]
Definition: pl_comp.c:82
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i

◆ plpgsql_resolve_polymorphic_argtypes()

static void plpgsql_resolve_polymorphic_argtypes ( int  numargs,
Oid argtypes,
char *  argmodes,
Node call_expr,
bool  forValidator,
const char *  proname 
)
static

Definition at line 2512 of file pl_comp.c.

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

Referenced by compute_function_hashkey(), and do_compile().

2516 {
2517  int i;
2518 
2519  if (!forValidator)
2520  {
2521  /* normal case, pass to standard routine */
2522  if (!resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
2523  call_expr))
2524  ereport(ERROR,
2525  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2526  errmsg("could not determine actual argument "
2527  "type for polymorphic function \"%s\"",
2528  proname)));
2529  }
2530  else
2531  {
2532  /* special validation case */
2533  for (i = 0; i < numargs; i++)
2534  {
2535  switch (argtypes[i])
2536  {
2537  case ANYELEMENTOID:
2538  case ANYNONARRAYOID:
2539  case ANYENUMOID: /* XXX dubious */
2540  case ANYCOMPATIBLEOID:
2541  case ANYCOMPATIBLENONARRAYOID:
2542  argtypes[i] = INT4OID;
2543  break;
2544  case ANYARRAYOID:
2545  case ANYCOMPATIBLEARRAYOID:
2546  argtypes[i] = INT4ARRAYOID;
2547  break;
2548  case ANYRANGEOID:
2549  case ANYCOMPATIBLERANGEOID:
2550  argtypes[i] = INT4RANGEOID;
2551  break;
2552  case ANYMULTIRANGEOID:
2553  argtypes[i] = INT4MULTIRANGEOID;
2554  break;
2555  default:
2556  break;
2557  }
2558  }
2559  }
2560 }
bool resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, Node *call_expr)
Definition: funcapi.c:953
NameData proname
Definition: pg_proc.h:35
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ERROR
Definition: elog.h:46
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i

◆ plpgsql_start_datums()

static void plpgsql_start_datums ( void  )
static

Definition at line 2316 of file pl_comp.c.

References datums_alloc, datums_last, MemoryContextAlloc(), and plpgsql_nDatums.

Referenced by do_compile(), and plpgsql_compile_inline().

2317 {
2318  datums_alloc = 128;
2319  plpgsql_nDatums = 0;
2320  /* This is short-lived, so needn't allocate in function's cxt */
2322  sizeof(PLpgSQL_datum *) * datums_alloc);
2323  /* datums_last tracks what's been seen by plpgsql_add_initdatums() */
2324  datums_last = 0;
2325 }
int plpgsql_nDatums
Definition: pl_comp.c:45
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:46
static int datums_alloc
Definition: pl_comp.c:44
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:56
static int datums_last
Definition: pl_comp.c:47

◆ resolve_column_ref()

static Node * resolve_column_ref ( ParseState pstate,
PLpgSQL_expr expr,
ColumnRef cref,
bool  error_if_no_field 
)
static

Definition at line 1179 of file pl_comp.c.

References Assert, PLpgSQL_function::cur_estate, PLpgSQL_execstate::datums, PLpgSQL_recfield::dtype, elog, ereport, errcode(), errmsg(), ERROR, PLpgSQL_recfield::fieldname, ColumnRef::fields, PLpgSQL_rec::firstfield, PLpgSQL_expr::func, i, IsA, PLpgSQL_nsitem::itemno, PLpgSQL_nsitem::itemtype, linitial, list_length(), ColumnRef::location, lsecond, lthird, make_datum_param(), PLpgSQL_recfield::nextfield, PLpgSQL_expr::ns, parser_errposition(), PLPGSQL_DTYPE_RECFIELD, plpgsql_ns_lookup(), PLPGSQL_NSTYPE_REC, PLPGSQL_NSTYPE_VAR, PLpgSQL_recfield::recparentno, and strVal.

Referenced by plpgsql_post_column_ref(), and plpgsql_pre_column_ref().

1181 {
1182  PLpgSQL_execstate *estate;
1183  PLpgSQL_nsitem *nse;
1184  const char *name1;
1185  const char *name2 = NULL;
1186  const char *name3 = NULL;
1187  const char *colname = NULL;
1188  int nnames;
1189  int nnames_scalar = 0;
1190  int nnames_wholerow = 0;
1191  int nnames_field = 0;
1192 
1193  /*
1194  * We use the function's current estate to resolve parameter data types.
1195  * This is really pretty bogus because there is no provision for updating
1196  * plans when those types change ...
1197  */
1198  estate = expr->func->cur_estate;
1199 
1200  /*----------
1201  * The allowed syntaxes are:
1202  *
1203  * A Scalar variable reference, or whole-row record reference.
1204  * A.B Qualified scalar or whole-row reference, or field reference.
1205  * A.B.C Qualified record field reference.
1206  * A.* Whole-row record reference.
1207  * A.B.* Qualified whole-row record reference.
1208  *----------
1209  */
1210  switch (list_length(cref->fields))
1211  {
1212  case 1:
1213  {
1214  Node *field1 = (Node *) linitial(cref->fields);
1215 
1216  Assert(IsA(field1, String));
1217  name1 = strVal(field1);
1218  nnames_scalar = 1;
1219  nnames_wholerow = 1;
1220  break;
1221  }
1222  case 2:
1223  {
1224  Node *field1 = (Node *) linitial(cref->fields);
1225  Node *field2 = (Node *) lsecond(cref->fields);
1226 
1227  Assert(IsA(field1, String));
1228  name1 = strVal(field1);
1229 
1230  /* Whole-row reference? */
1231  if (IsA(field2, A_Star))
1232  {
1233  /* Set name2 to prevent matches to scalar variables */
1234  name2 = "*";
1235  nnames_wholerow = 1;
1236  break;
1237  }
1238 
1239  Assert(IsA(field2, String));
1240  name2 = strVal(field2);
1241  colname = name2;
1242  nnames_scalar = 2;
1243  nnames_wholerow = 2;
1244  nnames_field = 1;
1245  break;
1246  }
1247  case 3:
1248  {
1249  Node *field1 = (Node *) linitial(cref->fields);
1250  Node *field2 = (Node *) lsecond(cref->fields);
1251  Node *field3 = (Node *) lthird(cref->fields);
1252 
1253  Assert(IsA(field1, String));
1254  name1 = strVal(field1);
1255  Assert(IsA(field2, String));
1256  name2 = strVal(field2);
1257 
1258  /* Whole-row reference? */
1259  if (IsA(field3, A_Star))
1260  {
1261  /* Set name3 to prevent matches to scalar variables */
1262  name3 = "*";
1263  nnames_wholerow = 2;
1264  break;
1265  }
1266 
1267  Assert(IsA(field3, String));
1268  name3 = strVal(field3);
1269  colname = name3;
1270  nnames_field = 2;
1271  break;
1272  }
1273  default:
1274  /* too many names, ignore */
1275  return NULL;
1276  }
1277 
1278  nse = plpgsql_ns_lookup(expr->ns, false,
1279  name1, name2, name3,
1280  &nnames);
1281 
1282  if (nse == NULL)
1283  return NULL; /* name not known to plpgsql */
1284 
1285  switch (nse->itemtype)
1286  {
1287  case PLPGSQL_NSTYPE_VAR:
1288  if (nnames == nnames_scalar)
1289  return make_datum_param(expr, nse->itemno, cref->location);
1290  break;
1291  case PLPGSQL_NSTYPE_REC:
1292  if (nnames == nnames_wholerow)
1293  return make_datum_param(expr, nse->itemno, cref->location);
1294  if (nnames == nnames_field)
1295  {
1296  /* colname could be a field in this record */
1297  PLpgSQL_rec *rec = (PLpgSQL_rec *) estate->datums[nse->itemno];
1298  int i;
1299 
1300  /* search for a datum referencing this field */
1301  i = rec->firstfield;
1302  while (i >= 0)
1303  {
1304  PLpgSQL_recfield *fld = (PLpgSQL_recfield *) estate->datums[i];
1305 
1307  fld->recparentno == nse->itemno);
1308  if (strcmp(fld->fieldname, colname) == 0)
1309  {
1310  return make_datum_param(expr, i, cref->location);
1311  }
1312  i = fld->nextfield;
1313  }
1314 
1315  /*
1316  * We should not get here, because a RECFIELD datum should
1317  * have been built at parse time for every possible qualified
1318  * reference to fields of this record. But if we do, handle
1319  * it like field-not-found: throw error or return NULL.
1320  */
1321  if (error_if_no_field)
1322  ereport(ERROR,
1323  (errcode(ERRCODE_UNDEFINED_COLUMN),
1324  errmsg("record \"%s\" has no field \"%s\"",
1325  (nnames_field == 1) ? name1 : name2,
1326  colname),
1327  parser_errposition(pstate, cref->location)));
1328  }
1329  break;
1330  default:
1331  elog(ERROR, "unrecognized plpgsql itemtype: %d", nse->itemtype);
1332  }
1333 
1334  /* Name format doesn't match the plpgsql variable type */
1335  return NULL;
1336 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
PLpgSQL_nsitem * plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode, const char *name1, const char *name2, const char *name3, int *names_used)
Definition: pl_funcs.c:130
Definition: nodes.h:536
#define strVal(v)
Definition: value.h:65
int errcode(int sqlerrcode)
Definition: elog.c:698
Definition: value.h:51
#define lsecond(l)
Definition: pg_list.h:179
PLpgSQL_datum ** datums
Definition: plpgsql.h:1057
int location
Definition: parsenodes.h:248
#define linitial(l)
Definition: pg_list.h:174
#define ERROR
Definition: elog.h:46
struct PLpgSQL_execstate * cur_estate
Definition: plpgsql.h:1013
struct PLpgSQL_nsitem * ns
Definition: plpgsql.h:228
PLpgSQL_datum_type dtype
Definition: plpgsql.h:421
struct PLpgSQL_function * func
Definition: plpgsql.h:225
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
static int list_length(const List *l)
Definition: pg_list.h:149
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
int errmsg(const char *fmt,...)
Definition: elog.c:909
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:438
#define elog(elevel,...)
Definition: elog.h:232
int i
#define lthird(l)
Definition: pg_list.h:184
char * fieldname
Definition: plpgsql.h:425
List * fields
Definition: parsenodes.h:247
int firstfield
Definition: plpgsql.h:408
static Node * make_datum_param(PLpgSQL_expr *expr, int dno, int location)
Definition: pl_comp.c:1343

Variable Documentation

◆ datums_alloc

int datums_alloc
static

Definition at line 44 of file pl_comp.c.

Referenced by plpgsql_adddatum(), and plpgsql_start_datums().

◆ datums_last

int datums_last
static

Definition at line 47 of file pl_comp.c.

Referenced by plpgsql_add_initdatums(), and plpgsql_start_datums().

◆ exception_label_map

const ExceptionLabelMap exception_label_map[]
static
Initial value:
= {
{NULL, 0}
}

Definition at line 82 of file pl_comp.c.

◆ plpgsql_check_syntax

bool plpgsql_check_syntax = false

Definition at line 51 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_compile_tmp_cxt

MemoryContext plpgsql_compile_tmp_cxt

Definition at line 56 of file pl_comp.c.

◆ plpgsql_curr_compile

PLpgSQL_function* plpgsql_curr_compile

Definition at line 53 of file pl_comp.c.

◆ plpgsql_Datums

PLpgSQL_datum** plpgsql_Datums

Definition at line 46 of file pl_comp.c.

◆ plpgsql_DumpExecTree

bool plpgsql_DumpExecTree = false

Definition at line 50 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_error_funcname

char* plpgsql_error_funcname

Definition at line 49 of file pl_comp.c.

Referenced by do_compile(), plpgsql_compile_error_callback(), and plpgsql_compile_inline().

◆ plpgsql_HashTable

HTAB* plpgsql_HashTable = NULL
static

Definition at line 62 of file pl_comp.c.

◆ plpgsql_nDatums

int plpgsql_nDatums

◆ plpgsql_parse_result

PLpgSQL_stmt_block* plpgsql_parse_result

Definition at line 42 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().