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/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 69 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 1031 of file pl_comp.c.

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

Referenced by do_compile(), and plpgsql_compile_inline().

1032 {
1033  /*
1034  * If the outer block has an EXCEPTION clause, we need to make a new outer
1035  * block, since the added RETURN shouldn't act like it is inside the
1036  * EXCEPTION clause.
1037  */
1038  if (function->action->exceptions != NULL)
1039  {
1040  PLpgSQL_stmt_block *new;
1041 
1042  new = palloc0(sizeof(PLpgSQL_stmt_block));
1043  new->cmd_type = PLPGSQL_STMT_BLOCK;
1044  new->stmtid = ++function->nstatements;
1045  new->body = list_make1(function->action);
1046 
1047  function->action = new;
1048  }
1049  if (function->action->body == NIL ||
1050  ((PLpgSQL_stmt *) llast(function->action->body))->cmd_type != PLPGSQL_STMT_RETURN)
1051  {
1052  PLpgSQL_stmt_return *new;
1053 
1054  new = palloc0(sizeof(PLpgSQL_stmt_return));
1055  new->cmd_type = PLPGSQL_STMT_RETURN;
1056  new->stmtid = ++function->nstatements;
1057  new->expr = NULL;
1058  new->retvarno = function->out_param_varno;
1059 
1060  function->action->body = lappend(function->action->body, new);
1061  }
1062 }
#define NIL
Definition: pg_list.h:65
PLpgSQL_stmt_block * action
Definition: plpgsql.h:1035
#define llast(l)
Definition: pg_list.h:215
#define list_make1(x1)
Definition: pg_list.h:227
List * lappend(List *list, void *datum)
Definition: list.c:321
void * palloc0(Size size)
Definition: mcxt.c:980
PLpgSQL_exception_block * exceptions
Definition: plpgsql.h:522

◆ add_parameter_name()

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

Definition at line 1006 of file pl_comp.c.

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

Referenced by do_compile().

1007 {
1008  /*
1009  * Before adding the name, check for duplicates. We need this even though
1010  * functioncmds.c has a similar check, because that code explicitly
1011  * doesn't complain about conflicting IN and OUT parameter names. In
1012  * plpgsql, such names are in the same namespace, so there is no way to
1013  * disambiguate.
1014  */
1015  if (plpgsql_ns_lookup(plpgsql_ns_top(), true,
1016  name, NULL, NULL,
1017  NULL) != NULL)
1018  ereport(ERROR,
1019  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1020  errmsg("parameter name \"%s\" used more than once",
1021  name)));
1022 
1023  /* OK, add the name */
1024  plpgsql_ns_additem(itemtype, itemno, name);
1025 }
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:610
#define ERROR
Definition: elog.h:43
#define ereport(elevel,...)
Definition: elog.h:144
const char * name
Definition: encode.c:561
int errmsg(const char *fmt,...)
Definition: elog.c:824

◆ build_datatype()

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

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

2091 {
2092  Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
2093  PLpgSQL_type *typ;
2094 
2095  if (!typeStruct->typisdefined)
2096  ereport(ERROR,
2097  (errcode(ERRCODE_UNDEFINED_OBJECT),
2098  errmsg("type \"%s\" is only a shell",
2099  NameStr(typeStruct->typname))));
2100 
2101  typ = (PLpgSQL_type *) palloc(sizeof(PLpgSQL_type));
2102 
2103  typ->typname = pstrdup(NameStr(typeStruct->typname));
2104  typ->typoid = typeStruct->oid;
2105  switch (typeStruct->typtype)
2106  {
2107  case TYPTYPE_BASE:
2108  case TYPTYPE_ENUM:
2109  case TYPTYPE_RANGE:
2110  typ->ttype = PLPGSQL_TTYPE_SCALAR;
2111  break;
2112  case TYPTYPE_COMPOSITE:
2113  typ->ttype = PLPGSQL_TTYPE_REC;
2114  break;
2115  case TYPTYPE_DOMAIN:
2116  if (type_is_rowtype(typeStruct->typbasetype))
2117  typ->ttype = PLPGSQL_TTYPE_REC;
2118  else
2119  typ->ttype = PLPGSQL_TTYPE_SCALAR;
2120  break;
2121  case TYPTYPE_PSEUDO:
2122  if (typ->typoid == RECORDOID)
2123  typ->ttype = PLPGSQL_TTYPE_REC;
2124  else
2125  typ->ttype = PLPGSQL_TTYPE_PSEUDO;
2126  break;
2127  default:
2128  elog(ERROR, "unrecognized typtype: %d",
2129  (int) typeStruct->typtype);
2130  break;
2131  }
2132  typ->typlen = typeStruct->typlen;
2133  typ->typbyval = typeStruct->typbyval;
2134  typ->typtype = typeStruct->typtype;
2135  typ->collation = typeStruct->typcollation;
2136  if (OidIsValid(collation) && OidIsValid(typ->collation))
2137  typ->collation = collation;
2138  /* Detect if type is true array, or domain thereof */
2139  /* NB: this is only used to decide whether to apply expand_array */
2140  if (typeStruct->typtype == TYPTYPE_BASE)
2141  {
2142  /*
2143  * This test should include what get_element_type() checks. We also
2144  * disallow non-toastable array types (i.e. oidvector and int2vector).
2145  */
2146  typ->typisarray = (typeStruct->typlen == -1 &&
2147  OidIsValid(typeStruct->typelem) &&
2148  typeStruct->typstorage != TYPSTORAGE_PLAIN);
2149  }
2150  else if (typeStruct->typtype == TYPTYPE_DOMAIN)
2151  {
2152  /* we can short-circuit looking up base types if it's not varlena */
2153  typ->typisarray = (typeStruct->typlen == -1 &&
2154  typeStruct->typstorage != TYPSTORAGE_PLAIN &&
2155  OidIsValid(get_base_element_type(typeStruct->typbasetype)));
2156  }
2157  else
2158  typ->typisarray = false;
2159  typ->atttypmod = typmod;
2160 
2161  /*
2162  * If it's a named composite type (or domain over one), find the typcache
2163  * entry and record the current tupdesc ID, so we can detect changes
2164  * (including drops). We don't currently support on-the-fly replacement
2165  * of non-composite types, else we might want to do this for them too.
2166  */
2167  if (typ->ttype == PLPGSQL_TTYPE_REC && typ->typoid != RECORDOID)
2168  {
2169  TypeCacheEntry *typentry;
2170 
2171  typentry = lookup_type_cache(typ->typoid,
2174  if (typentry->typtype == TYPTYPE_DOMAIN)
2175  typentry = lookup_type_cache(typentry->domainBaseType,
2177  if (typentry->tupDesc == NULL)
2178  ereport(ERROR,
2179  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2180  errmsg("type %s is not composite",
2181  format_type_be(typ->typoid))));
2182 
2183  typ->origtypname = origtypname;
2184  typ->tcache = typentry;
2185  typ->tupdesc_id = typentry->tupDesc_identifier;
2186  }
2187  else
2188  {
2189  typ->origtypname = NULL;
2190  typ->tcache = NULL;
2191  typ->tupdesc_id = 0;
2192  }
2193 
2194  return typ;
2195 }
TypeCacheEntry * tcache
Definition: plpgsql.h:212
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
TypeName * origtypname
Definition: plpgsql.h:211
char * pstrdup(const char *in)
Definition: mcxt.c:1186
PLpgSQL_type_type ttype
Definition: plpgsql.h:203
int errcode(int sqlerrcode)
Definition: elog.c:610
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
uint64 tupdesc_id
Definition: plpgsql.h:213
#define OidIsValid(objectId)
Definition: c.h:651
Oid domainBaseType
Definition: typcache.h:107
#define ERROR
Definition: elog.h:43
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2543
bool typbyval
Definition: plpgsql.h:205
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:142
Oid collation
Definition: plpgsql.h:207
bool typisarray
Definition: plpgsql.h:208
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:331
#define ereport(elevel,...)
Definition: elog.h:144
char typtype
Definition: typcache.h:43
FormData_pg_type * Form_pg_type
Definition: pg_type.h:255
char * typname
Definition: plpgsql.h:201
uint64 tupDesc_identifier
Definition: typcache.h:89
char typtype
Definition: plpgsql.h:206
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2709
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:824
int32 atttypmod
Definition: plpgsql.h:209
#define elog(elevel,...)
Definition: elog.h:214
#define NameStr(name)
Definition: c.h:622
int16 typlen
Definition: plpgsql.h:204
TupleDesc tupDesc
Definition: typcache.h:88
#define TYPECACHE_TUPDESC
Definition: typcache.h:138
Oid typoid
Definition: plpgsql.h:202

◆ build_row_from_vars()

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

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

1954 {
1955  PLpgSQL_row *row;
1956  int i;
1957 
1958  row = palloc0(sizeof(PLpgSQL_row));
1959  row->dtype = PLPGSQL_DTYPE_ROW;
1960  row->refname = "(unnamed row)";
1961  row->lineno = -1;
1962  row->rowtupdesc = CreateTemplateTupleDesc(numvars);
1963  row->nfields = numvars;
1964  row->fieldnames = palloc(numvars * sizeof(char *));
1965  row->varnos = palloc(numvars * sizeof(int));
1966 
1967  for (i = 0; i < numvars; i++)
1968  {
1969  PLpgSQL_variable *var = vars[i];
1970  Oid typoid;
1971  int32 typmod;
1972  Oid typcoll;
1973 
1974  /* Member vars of a row should never be const */
1975  Assert(!var->isconst);
1976 
1977  switch (var->dtype)
1978  {
1979  case PLPGSQL_DTYPE_VAR:
1980  case PLPGSQL_DTYPE_PROMISE:
1981  typoid = ((PLpgSQL_var *) var)->datatype->typoid;
1982  typmod = ((PLpgSQL_var *) var)->datatype->atttypmod;
1983  typcoll = ((PLpgSQL_var *) var)->datatype->collation;
1984  break;
1985 
1986  case PLPGSQL_DTYPE_REC:
1987  /* shouldn't need to revalidate rectypeid already... */
1988  typoid = ((PLpgSQL_rec *) var)->rectypeid;
1989  typmod = -1; /* don't know typmod, if it's used at all */
1990  typcoll = InvalidOid; /* composite types have no collation */
1991  break;
1992 
1993  default:
1994  elog(ERROR, "unrecognized dtype: %d", var->dtype);
1995  typoid = InvalidOid; /* keep compiler quiet */
1996  typmod = 0;
1997  typcoll = InvalidOid;
1998  break;
1999  }
2000 
2001  row->fieldnames[i] = var->refname;
2002  row->varnos[i] = var->dno;
2003 
2004  TupleDescInitEntry(row->rowtupdesc, i + 1,
2005  var->refname,
2006  typoid, typmod,
2007  0);
2008  TupleDescInitEntryCollation(row->rowtupdesc, i + 1, typcoll);
2009  }
2010 
2011  return row;
2012 }
char * refname
Definition: plpgsql.h:357
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:44
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:362
#define ERROR
Definition: elog.h:43
char ** fieldnames
Definition: plpgsql.h:372
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition: tupdesc.c:769
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:603
int * varnos
Definition: plpgsql.h:373
void * palloc0(Size size)
Definition: mcxt.c:980
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:745
int nfields
Definition: plpgsql.h:371
char * refname
Definition: plpgsql.h:281
PLpgSQL_datum_type dtype
Definition: plpgsql.h:279
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:214
int i
TupleDesc rowtupdesc
Definition: plpgsql.h:369
PLpgSQL_datum_type dtype
Definition: plpgsql.h:355
int lineno
Definition: plpgsql.h:358

◆ compute_function_hashkey()

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

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

2432 {
2433  /* Make sure any unused bytes of the struct are zero */
2434  MemSet(hashkey, 0, sizeof(PLpgSQL_func_hashkey));
2435 
2436  /* get function OID */
2437  hashkey->funcOid = fcinfo->flinfo->fn_oid;
2438 
2439  /* get call context */
2440  hashkey->isTrigger = CALLED_AS_TRIGGER(fcinfo);
2441  hashkey->isEventTrigger = CALLED_AS_EVENT_TRIGGER(fcinfo);
2442 
2443  /*
2444  * If DML trigger, include trigger's OID in the hash, so that each trigger
2445  * usage gets a different hash entry, allowing for e.g. different relation
2446  * rowtypes or transition table names. In validation mode we do not know
2447  * what relation or transition table names are intended to be used, so we
2448  * leave trigOid zero; the hash entry built in this case will never be
2449  * used for any actual calls.
2450  *
2451  * We don't currently need to distinguish different event trigger usages
2452  * in the same way, since the special parameter variables don't vary in
2453  * type in that case.
2454  */
2455  if (hashkey->isTrigger && !forValidator)
2456  {
2457  TriggerData *trigdata = (TriggerData *) fcinfo->context;
2458 
2459  hashkey->trigOid = trigdata->tg_trigger->tgoid;
2460  }
2461 
2462  /* get input collation, if known */
2463  hashkey->inputCollation = fcinfo->fncollation;
2464 
2465  if (procStruct->pronargs > 0)
2466  {
2467  /* get the argument types */
2468  memcpy(hashkey->argtypes, procStruct->proargtypes.values,
2469  procStruct->pronargs * sizeof(Oid));
2470 
2471  /* resolve any polymorphic argument types */
2472  plpgsql_resolve_polymorphic_argtypes(procStruct->pronargs,
2473  hashkey->argtypes,
2474  NULL,
2475  fcinfo->flinfo->fn_expr,
2476  forValidator,
2477  NameStr(procStruct->proname));
2478  }
2479 }
Oid argtypes[FUNC_MAX_ARGS]
Definition: plpgsql.h:975
#define CALLED_AS_EVENT_TRIGGER(fcinfo)
Definition: event_trigger.h:40
Oid tgoid
Definition: reltrigger.h:25
#define MemSet(start, val, len)
Definition: c.h:978
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:2488
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:622

◆ delete_function()

static void delete_function ( PLpgSQL_function func)
static

Definition at line 2550 of file pl_comp.c.

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

Referenced by plpgsql_compile().

2551 {
2552  /* remove function from hash table (might be done already) */
2554 
2555  /* release the function's storage if safe and not done already */
2556  if (func->use_count == 0)
2558 }
void plpgsql_free_function_memory(PLpgSQL_function *func)
Definition: pl_funcs.c:737
unsigned long use_count
Definition: plpgsql.h:1039
static void plpgsql_HashTableDelete(PLpgSQL_function *function)
Definition: pl_comp.c:2613

◆ do_compile()

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

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

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

1337 {
1338  PLpgSQL_execstate *estate;
1339  PLpgSQL_datum *datum;
1340  Param *param;
1341  MemoryContext oldcontext;
1342 
1343  /* see comment in resolve_column_ref */
1344  estate = expr->func->cur_estate;
1345  Assert(dno >= 0 && dno < estate->ndatums);
1346  datum = estate->datums[dno];
1347 
1348  /*
1349  * Bitmapset must be allocated in function's permanent memory context
1350  */
1351  oldcontext = MemoryContextSwitchTo(expr->func->fn_cxt);
1352  expr->paramnos = bms_add_member(expr->paramnos, dno);
1353  MemoryContextSwitchTo(oldcontext);
1354 
1355  param = makeNode(Param);
1356  param->paramkind = PARAM_EXTERN;
1357  param->paramid = dno + 1;
1359  datum,
1360  &param->paramtype,
1361  &param->paramtypmod,
1362  &param->paramcollid);
1363  param->location = location;
1364 
1365  return (Node *) param;
1366 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ParamKind paramkind
Definition: primnodes.h:262
Definition: nodes.h:529
PLpgSQL_datum ** datums
Definition: plpgsql.h:1082
Bitmapset * paramnos
Definition: plpgsql.h:223
struct PLpgSQL_execstate * cur_estate
Definition: plpgsql.h:1038
Oid paramcollid
Definition: primnodes.h:266
int location
Definition: primnodes.h:267
MemoryContext fn_cxt
Definition: plpgsql.h:1000
void plpgsql_exec_get_datum_type_info(PLpgSQL_execstate *estate, PLpgSQL_datum *datum, Oid *typeId, int32 *typMod, Oid *collation)
Definition: pl_exec.c:5692
struct PLpgSQL_function * func
Definition: plpgsql.h:227
int32 paramtypmod
Definition: primnodes.h:265
#define makeNode(_type_)
Definition: nodes.h:577
#define Assert(condition)
Definition: c.h:745
int paramid
Definition: primnodes.h:263
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
Oid paramtype
Definition: primnodes.h:264

◆ plpgsql_add_initdatums()

int plpgsql_add_initdatums ( int **  varnos)

Definition at line 2370 of file pl_comp.c.

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

2371 {
2372  int i;
2373  int n = 0;
2374 
2375  /*
2376  * The set of dtypes recognized here must match what exec_stmt_block()
2377  * cares about (re)initializing at block entry.
2378  */
2379  for (i = datums_last; i < plpgsql_nDatums; i++)
2380  {
2381  switch (plpgsql_Datums[i]->dtype)
2382  {
2383  case PLPGSQL_DTYPE_VAR:
2384  case PLPGSQL_DTYPE_REC:
2385  n++;
2386  break;
2387 
2388  default:
2389  break;
2390  }
2391  }
2392 
2393  if (varnos != NULL)
2394  {
2395  if (n > 0)
2396  {
2397  *varnos = (int *) palloc(sizeof(int) * n);
2398 
2399  n = 0;
2400  for (i = datums_last; i < plpgsql_nDatums; i++)
2401  {
2402  switch (plpgsql_Datums[i]->dtype)
2403  {
2404  case PLPGSQL_DTYPE_VAR:
2405  case PLPGSQL_DTYPE_REC:
2406  (*varnos)[n++] = plpgsql_Datums[i]->dno;
2407 
2408  default:
2409  break;
2410  }
2411  }
2412  }
2413  else
2414  *varnos = NULL;
2415  }
2416 
2418  return n;
2419 }
int plpgsql_nDatums
Definition: pl_comp.c:44
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:45
void * palloc(Size size)
Definition: mcxt.c:949
int i
static int datums_last
Definition: pl_comp.c:46

◆ plpgsql_adddatum()

void plpgsql_adddatum ( PLpgSQL_datum newdatum)

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

2310 {
2312  {
2313  datums_alloc *= 2;
2315  }
2316 
2317  newdatum->dno = plpgsql_nDatums;
2318  plpgsql_Datums[plpgsql_nDatums++] = newdatum;
2319 }
int plpgsql_nDatums
Definition: pl_comp.c:44
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:45
static int datums_alloc
Definition: pl_comp.c:43
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069

◆ plpgsql_build_datatype()

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

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

2069 {
2070  HeapTuple typeTup;
2071  PLpgSQL_type *typ;
2072 
2073  typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
2074  if (!HeapTupleIsValid(typeTup))
2075  elog(ERROR, "cache lookup failed for type %u", typeOid);
2076 
2077  typ = build_datatype(typeTup, typmod, collation, origtypname);
2078 
2079  ReleaseSysCache(typeTup);
2080 
2081  return typ;
2082 }
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:2089
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:214

◆ plpgsql_build_recfield()

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

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

2021 {
2022  PLpgSQL_recfield *recfield;
2023  int i;
2024 
2025  /* search for an existing datum referencing this field */
2026  i = rec->firstfield;
2027  while (i >= 0)
2028  {
2030 
2032  fld->recparentno == rec->dno);
2033  if (strcmp(fld->fieldname, fldname) == 0)
2034  return fld;
2035  i = fld->nextfield;
2036  }
2037 
2038  /* nope, so make a new one */
2039  recfield = palloc0(sizeof(PLpgSQL_recfield));
2040  recfield->dtype = PLPGSQL_DTYPE_RECFIELD;
2041  recfield->fieldname = pstrdup(fldname);
2042  recfield->recparentno = rec->dno;
2044 
2045  plpgsql_adddatum((PLpgSQL_datum *) recfield);
2046 
2047  /* now we can link it into the parent's chain */
2048  recfield->nextfield = rec->firstfield;
2049  rec->firstfield = recfield->dno;
2050 
2051  return recfield;
2052 }
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:45
char * pstrdup(const char *in)
Definition: mcxt.c:1186
#define INVALID_TUPLEDESC_IDENTIFIER
Definition: typcache.h:148
void plpgsql_adddatum(PLpgSQL_datum *newdatum)
Definition: pl_comp.c:2309
uint64 rectupledescid
Definition: plpgsql.h:419
void * palloc0(Size size)
Definition: mcxt.c:980
PLpgSQL_datum_type dtype
Definition: plpgsql.h:412
#define Assert(condition)
Definition: c.h:745
int i
char * fieldname
Definition: plpgsql.h:416
int firstfield
Definition: plpgsql.h:399

◆ plpgsql_build_record()

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

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

1929 {
1930  PLpgSQL_rec *rec;
1931 
1932  rec = palloc0(sizeof(PLpgSQL_rec));
1933  rec->dtype = PLPGSQL_DTYPE_REC;
1934  rec->refname = pstrdup(refname);
1935  rec->lineno = lineno;
1936  /* other fields are left as 0, might be changed by caller */
1937  rec->datatype = dtype;
1938  rec->rectypeid = rectypeid;
1939  rec->firstfield = -1;
1940  rec->erh = NULL;
1942  if (add2namespace)
1944 
1945  return rec;
1946 }
PLpgSQL_datum_type dtype
Definition: plpgsql.h:381
PLpgSQL_type * datatype
Definition: plpgsql.h:396
char * pstrdup(const char *in)
Definition: mcxt.c:1186
void plpgsql_ns_additem(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
Definition: pl_funcs.c:92
ExpandedRecordHeader * erh
Definition: plpgsql.h:404
char * refname
Definition: plpgsql.h:383
void plpgsql_adddatum(PLpgSQL_datum *newdatum)
Definition: pl_comp.c:2309
void * palloc0(Size size)
Definition: mcxt.c:980
Oid rectypeid
Definition: plpgsql.h:397
int lineno
Definition: plpgsql.h:384
int firstfield
Definition: plpgsql.h:399

◆ plpgsql_build_variable()

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

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

1865 {
1866  PLpgSQL_variable *result;
1867 
1868  switch (dtype->ttype)
1869  {
1870  case PLPGSQL_TTYPE_SCALAR:
1871  {
1872  /* Ordinary scalar datatype */
1873  PLpgSQL_var *var;
1874 
1875  var = palloc0(sizeof(PLpgSQL_var));
1876  var->dtype = PLPGSQL_DTYPE_VAR;
1877  var->refname = pstrdup(refname);
1878  var->lineno = lineno;
1879  var->datatype = dtype;
1880  /* other fields are left as 0, might be changed by caller */
1881 
1882  /* preset to NULL */
1883  var->value = 0;
1884  var->isnull = true;
1885  var->freeval = false;
1886 
1888  if (add2namespace)
1890  var->dno,
1891  refname);
1892  result = (PLpgSQL_variable *) var;
1893  break;
1894  }
1895  case PLPGSQL_TTYPE_REC:
1896  {
1897  /* Composite type -- build a record variable */
1898  PLpgSQL_rec *rec;
1899 
1900  rec = plpgsql_build_record(refname, lineno,
1901  dtype, dtype->typoid,
1902  add2namespace);
1903  result = (PLpgSQL_variable *) rec;
1904  break;
1905  }
1906  case PLPGSQL_TTYPE_PSEUDO:
1907  ereport(ERROR,
1908  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1909  errmsg("variable \"%s\" has pseudo-type %s",
1910  refname, format_type_be(dtype->typoid))));
1911  result = NULL; /* keep compiler quiet */
1912  break;
1913  default:
1914  elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
1915  result = NULL; /* keep compiler quiet */
1916  break;
1917  }
1918 
1919  return result;
1920 }
char * refname
Definition: plpgsql.h:303
PLpgSQL_rec * plpgsql_build_record(const char *refname, int lineno, PLpgSQL_type *dtype, Oid rectypeid, bool add2namespace)
Definition: pl_comp.c:1926
PLpgSQL_datum_type dtype
Definition: plpgsql.h:301
char * pstrdup(const char *in)
Definition: mcxt.c:1186
PLpgSQL_type * datatype
Definition: plpgsql.h:310
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:203
int errcode(int sqlerrcode)
Definition: elog.c:610
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
void plpgsql_adddatum(PLpgSQL_datum *newdatum)
Definition: pl_comp.c:2309
#define ERROR
Definition: elog.h:43
bool freeval
Definition: plpgsql.h:325
void * palloc0(Size size)
Definition: mcxt.c:980
Datum value
Definition: plpgsql.h:323
#define ereport(elevel,...)
Definition: elog.h:144
int lineno
Definition: plpgsql.h:304
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214
bool isnull
Definition: plpgsql.h:324
Oid typoid
Definition: plpgsql.h:202

◆ plpgsql_compile()

PLpgSQL_function* plpgsql_compile ( FunctionCallInfo  fcinfo,
bool  forValidator 
)

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

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

◆ plpgsql_compile_error_callback()

static void plpgsql_compile_error_callback ( void *  arg)
static

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

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

◆ plpgsql_compile_inline()

PLpgSQL_function* plpgsql_compile_inline ( char *  proc_source)

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

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

◆ plpgsql_finish_datums()

static void plpgsql_finish_datums ( PLpgSQL_function function)
static

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

2327 {
2328  Size copiable_size = 0;
2329  int i;
2330 
2331  function->ndatums = plpgsql_nDatums;
2332  function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
2333  for (i = 0; i < plpgsql_nDatums; i++)
2334  {
2335  function->datums[i] = plpgsql_Datums[i];
2336 
2337  /* This must agree with copy_plpgsql_datums on what is copiable */
2338  switch (function->datums[i]->dtype)
2339  {
2340  case PLPGSQL_DTYPE_VAR:
2341  case PLPGSQL_DTYPE_PROMISE:
2342  copiable_size += MAXALIGN(sizeof(PLpgSQL_var));
2343  break;
2344  case PLPGSQL_DTYPE_REC:
2345  copiable_size += MAXALIGN(sizeof(PLpgSQL_rec));
2346  break;
2347  default:
2348  break;
2349  }
2350  }
2351  function->copiable_size = copiable_size;
2352 }
int plpgsql_nDatums
Definition: pl_comp.c:44
PLpgSQL_datum ** datums
Definition: plpgsql.h:1031
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:45
PLpgSQL_datum_type dtype
Definition: plpgsql.h:267
size_t Size
Definition: c.h:473
#define MAXALIGN(LEN)
Definition: c.h:698
void * palloc(Size size)
Definition: mcxt.c:949
int i

◆ plpgsql_HashTableDelete()

static void plpgsql_HashTableDelete ( PLpgSQL_function function)
static

Definition at line 2613 of file pl_comp.c.

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

Referenced by delete_function().

2614 {
2615  plpgsql_HashEnt *hentry;
2616 
2617  /* do nothing if not in table */
2618  if (function->fn_hashkey == NULL)
2619  return;
2620 
2622  (void *) function->fn_hashkey,
2623  HASH_REMOVE,
2624  NULL);
2625  if (hentry == NULL)
2626  elog(WARNING, "trying to delete function that does not exist");
2627 
2628  /* remove back link, which no longer points to allocated storage */
2629  function->fn_hashkey = NULL;
2630 }
PLpgSQL_func_hashkey * fn_hashkey
Definition: plpgsql.h:999
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:927
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:61
#define WARNING
Definition: elog.h:40
#define elog(elevel,...)
Definition: elog.h:214

◆ plpgsql_HashTableInit()

void plpgsql_HashTableInit ( void  )

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

2563 {
2564  HASHCTL ctl;
2565 
2566  /* don't allow double-initialization */
2567  Assert(plpgsql_HashTable == NULL);
2568 
2569  memset(&ctl, 0, sizeof(ctl));
2570  ctl.keysize = sizeof(PLpgSQL_func_hashkey);
2571  ctl.entrysize = sizeof(plpgsql_HashEnt);
2572  plpgsql_HashTable = hash_create("PLpgSQL function hash",
2574  &ctl,
2575  HASH_ELEM | HASH_BLOBS);
2576 }
#define FUNCS_PER_USER
Definition: pl_comp.c:69
#define HASH_ELEM
Definition: hsearch.h:87
Size entrysize
Definition: hsearch.h:73
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:61
struct plpgsql_hashent plpgsql_HashEnt
struct PLpgSQL_func_hashkey PLpgSQL_func_hashkey
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:328
Size keysize
Definition: hsearch.h:72
#define Assert(condition)
Definition: c.h:745

◆ plpgsql_HashTableInsert()

static void plpgsql_HashTableInsert ( PLpgSQL_function function,
PLpgSQL_func_hashkey func_key 
)
static

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

2596 {
2597  plpgsql_HashEnt *hentry;
2598  bool found;
2599 
2601  (void *) func_key,
2602  HASH_ENTER,
2603  &found);
2604  if (found)
2605  elog(WARNING, "trying to insert a function that already exists");
2606 
2607  hentry->function = function;
2608  /* prepare back link from function to hashtable key */
2609  function->fn_hashkey = &hentry->key;
2610 }
PLpgSQL_func_hashkey * fn_hashkey
Definition: plpgsql.h:999
PLpgSQL_func_hashkey key
Definition: pl_comp.c:65
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:927
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:61
PLpgSQL_function * function
Definition: pl_comp.c:66
#define WARNING
Definition: elog.h:40
#define elog(elevel,...)
Definition: elog.h:214

◆ plpgsql_HashTableLookup()

static PLpgSQL_function * plpgsql_HashTableLookup ( PLpgSQL_func_hashkey func_key)
static

Definition at line 2579 of file pl_comp.c.

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

Referenced by plpgsql_compile().

2580 {
2581  plpgsql_HashEnt *hentry;
2582 
2584  (void *) func_key,
2585  HASH_FIND,
2586  NULL);
2587  if (hentry)
2588  return hentry->function;
2589  else
2590  return NULL;
2591 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:927
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:61
PLpgSQL_function * function
Definition: pl_comp.c:66

◆ plpgsql_param_ref()

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

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

1146 {
1147  PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1148  char pname[32];
1149  PLpgSQL_nsitem *nse;
1150 
1151  snprintf(pname, sizeof(pname), "$%d", pref->number);
1152 
1153  nse = plpgsql_ns_lookup(expr->ns, false,
1154  pname, NULL, NULL,
1155  NULL);
1156 
1157  if (nse == NULL)
1158  return NULL; /* name not known to plpgsql */
1159 
1160  return make_datum_param(expr, nse->itemno, pref->location);
1161 }
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:230
int number
Definition: parsenodes.h:246
int location
Definition: parsenodes.h:247
void * p_ref_hook_state
Definition: parse_node.h:222
#define snprintf
Definition: port.h:193
static Node * make_datum_param(PLpgSQL_expr *expr, int dno, int location)
Definition: pl_comp.c:1336

◆ plpgsql_parse_cwordrowtype()

PLpgSQL_type* plpgsql_parse_cwordrowtype ( List idents)

Definition at line 1815 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.

1816 {
1817  Oid classOid;
1818  Oid typOid;
1819  RangeVar *relvar;
1820  MemoryContext oldCxt;
1821 
1822  /*
1823  * As above, this is a relation lookup but could be a type lookup if we
1824  * weren't being backwards-compatible about error wording.
1825  */
1826  if (list_length(idents) != 2)
1827  return NULL;
1828 
1829  /* Avoid memory leaks in long-term function context */
1831 
1832  /* Look up relation name. Can't lock it - we might not have privileges. */
1833  relvar = makeRangeVar(strVal(linitial(idents)),
1834  strVal(lsecond(idents)),
1835  -1);
1836  classOid = RangeVarGetRelid(relvar, NoLock, false);
1837 
1838  /* Some relkinds lack type OIDs */
1839  typOid = get_rel_type_id(classOid);
1840  if (!OidIsValid(typOid))
1841  ereport(ERROR,
1842  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1843  errmsg("relation \"%s\" does not have a composite type",
1844  strVal(lsecond(idents)))));
1845 
1846  MemoryContextSwitchTo(oldCxt);
1847 
1848  /* Build and return the row type struct */
1849  return plpgsql_build_datatype(typOid, -1, InvalidOid,
1850  makeTypeNameFromNameList(idents));
1851 }
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:78
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:610
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:651
#define lsecond(l)
Definition: pg_list.h:200
#define linitial(l)
Definition: pg_list.h:195
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:2067
Oid get_rel_type_id(Oid relid)
Definition: lsyscache.c:1891
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:144
static int list_length(const List *l)
Definition: pg_list.h:169
int errmsg(const char *fmt,...)
Definition: elog.c:824
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:456
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:55
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 1658 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.

1659 {
1660  PLpgSQL_type *dtype = NULL;
1661  PLpgSQL_nsitem *nse;
1662  const char *fldname;
1663  Oid classOid;
1664  HeapTuple classtup = NULL;
1665  HeapTuple attrtup = NULL;
1666  HeapTuple typetup = NULL;
1667  Form_pg_class classStruct;
1668  Form_pg_attribute attrStruct;
1669  MemoryContext oldCxt;
1670 
1671  /* Avoid memory leaks in the long-term function context */
1673 
1674  if (list_length(idents) == 2)
1675  {
1676  /*
1677  * Do a lookup in the current namespace stack. We don't need to check
1678  * number of names matched, because we will only consider scalar
1679  * variables.
1680  */
1681  nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1682  strVal(linitial(idents)),
1683  strVal(lsecond(idents)),
1684  NULL,
1685  NULL);
1686 
1687  if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_VAR)
1688  {
1689  dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1690  goto done;
1691  }
1692 
1693  /*
1694  * First word could also be a table name
1695  */
1696  classOid = RelnameGetRelid(strVal(linitial(idents)));
1697  if (!OidIsValid(classOid))
1698  goto done;
1699  fldname = strVal(lsecond(idents));
1700  }
1701  else if (list_length(idents) == 3)
1702  {
1703  RangeVar *relvar;
1704 
1705  relvar = makeRangeVar(strVal(linitial(idents)),
1706  strVal(lsecond(idents)),
1707  -1);
1708  /* Can't lock relation - we might not have privileges. */
1709  classOid = RangeVarGetRelid(relvar, NoLock, true);
1710  if (!OidIsValid(classOid))
1711  goto done;
1712  fldname = strVal(lthird(idents));
1713  }
1714  else
1715  goto done;
1716 
1717  classtup = SearchSysCache1(RELOID, ObjectIdGetDatum(classOid));
1718  if (!HeapTupleIsValid(classtup))
1719  goto done;
1720  classStruct = (Form_pg_class) GETSTRUCT(classtup);
1721 
1722  /*
1723  * It must be a relation, sequence, view, materialized view, composite
1724  * type, or foreign table
1725  */
1726  if (classStruct->relkind != RELKIND_RELATION &&
1727  classStruct->relkind != RELKIND_SEQUENCE &&
1728  classStruct->relkind != RELKIND_VIEW &&
1729  classStruct->relkind != RELKIND_MATVIEW &&
1730  classStruct->relkind != RELKIND_COMPOSITE_TYPE &&
1731  classStruct->relkind != RELKIND_FOREIGN_TABLE &&
1732  classStruct->relkind != RELKIND_PARTITIONED_TABLE)
1733  goto done;
1734 
1735  /*
1736  * Fetch the named table field and its type
1737  */
1738  attrtup = SearchSysCacheAttName(classOid, fldname);
1739  if (!HeapTupleIsValid(attrtup))
1740  goto done;
1741  attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1742 
1743  typetup = SearchSysCache1(TYPEOID,
1744  ObjectIdGetDatum(attrStruct->atttypid));
1745  if (!HeapTupleIsValid(typetup))
1746  elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1747 
1748  /*
1749  * Found that - build a compiler type struct in the caller's cxt and
1750  * return it. Note that we treat the type as being found-by-OID; no
1751  * attempt to re-look-up the type name will happen during invalidations.
1752  */
1753  MemoryContextSwitchTo(oldCxt);
1754  dtype = build_datatype(typetup,
1755  attrStruct->atttypmod,
1756  attrStruct->attcollation,
1757  NULL);
1759 
1760 done:
1761  if (HeapTupleIsValid(classtup))
1762  ReleaseSysCache(classtup);
1763  if (HeapTupleIsValid(attrtup))
1764  ReleaseSysCache(attrtup);
1765  if (HeapTupleIsValid(typetup))
1766  ReleaseSysCache(typetup);
1767 
1768  MemoryContextSwitchTo(oldCxt);
1769  return dtype;
1770 }
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:45
PLpgSQL_nsitem * plpgsql_ns_top(void)
Definition: pl_funcs.c:81
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Oid RelnameGetRelid(const char *relname)
Definition: namespace.c:680
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:2089
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:78
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:54
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:651
#define lsecond(l)
Definition: pg_list.h:200
#define linitial(l)
Definition: pg_list.h:195
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static int list_length(const List *l)
Definition: pg_list.h:169
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1257
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:453
#define elog(elevel,...)
Definition: elog.h:214
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:55
#define lthird(l)
Definition: pg_list.h:205
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 1444 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().

1446 {
1447  PLpgSQL_nsitem *ns;
1448  List *idents;
1449  int nnames;
1450 
1451  idents = list_make2(makeString(word1),
1452  makeString(word2));
1453 
1454  /*
1455  * We should do nothing in DECLARE sections. In SQL expressions, we
1456  * really only need to make sure that RECFIELD datums are created when
1457  * needed.
1458  */
1460  {
1461  /*
1462  * Do a lookup in the current namespace stack
1463  */
1464  ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1465  word1, word2, NULL,
1466  &nnames);
1467  if (ns != NULL)
1468  {
1469  switch (ns->itemtype)
1470  {
1471  case PLPGSQL_NSTYPE_VAR:
1472  /* Block-qualified reference to scalar variable. */
1473  wdatum->datum = plpgsql_Datums[ns->itemno];
1474  wdatum->ident = NULL;
1475  wdatum->quoted = false; /* not used */
1476  wdatum->idents = idents;
1477  return true;
1478 
1479  case PLPGSQL_NSTYPE_REC:
1480  if (nnames == 1)
1481  {
1482  /*
1483  * First word is a record name, so second word could
1484  * be a field in this record. We build a RECFIELD
1485  * datum whether it is or not --- any error will be
1486  * detected later.
1487  */
1488  PLpgSQL_rec *rec;
1489  PLpgSQL_recfield *new;
1490 
1491  rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
1492  new = plpgsql_build_recfield(rec, word2);
1493 
1494  wdatum->datum = (PLpgSQL_datum *) new;
1495  }
1496  else
1497  {
1498  /* Block-qualified reference to record variable. */
1499  wdatum->datum = plpgsql_Datums[ns->itemno];
1500  }
1501  wdatum->ident = NULL;
1502  wdatum->quoted = false; /* not used */
1503  wdatum->idents = idents;
1504  return true;
1505 
1506  default:
1507  break;
1508  }
1509  }
1510  }
1511 
1512  /* Nothing found */
1513  cword->idents = idents;
1514  return false;
1515 }
#define list_make2(x1, x2)
Definition: pg_list.h:229
Value * makeString(char *str)
Definition: value.c:53
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:45
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:2020
List * idents
Definition: plpgsql.h:1175
List * idents
Definition: plpgsql.h:1183
IdentifierLookup plpgsql_IdentifierLookup
Definition: pl_scanner.c:26
PLpgSQL_datum * datum
Definition: plpgsql.h:1180
bool quoted
Definition: plpgsql.h:1182
char * ident
Definition: plpgsql.h:1181
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:453
Definition: pg_list.h:50

◆ plpgsql_parse_err_condition()

PLpgSQL_condition* plpgsql_parse_err_condition ( char *  condname)

Definition at line 2241 of file pl_comp.c.

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

2242 {
2243  int i;
2244  PLpgSQL_condition *new;
2245  PLpgSQL_condition *prev;
2246 
2247  /*
2248  * XXX Eventually we will want to look for user-defined exception names
2249  * here.
2250  */
2251 
2252  /*
2253  * OTHERS is represented as code 0 (which would map to '00000', but we
2254  * have no need to represent that as an exception condition).
2255  */
2256  if (strcmp(condname, "others") == 0)
2257  {
2258  new = palloc(sizeof(PLpgSQL_condition));
2259  new->sqlerrstate = 0;
2260  new->condname = condname;
2261  new->next = NULL;
2262  return new;
2263  }
2264 
2265  prev = NULL;
2266  for (i = 0; exception_label_map[i].label != NULL; i++)
2267  {
2268  if (strcmp(condname, exception_label_map[i].label) == 0)
2269  {
2270  new = palloc(sizeof(PLpgSQL_condition));
2271  new->sqlerrstate = exception_label_map[i].sqlerrstate;
2272  new->condname = condname;
2273  new->next = prev;
2274  prev = new;
2275  }
2276  }
2277 
2278  if (!prev)
2279  ereport(ERROR,
2280  (errcode(ERRCODE_UNDEFINED_OBJECT),
2281  errmsg("unrecognized exception condition \"%s\"",
2282  condname)));
2283 
2284  return prev;
2285 }
const char * label
Definition: pl_comp.c:77
int errcode(int sqlerrcode)
Definition: elog.c:610
#define ERROR
Definition: elog.h:43
static char * label
#define ereport(elevel,...)
Definition: elog.h:144
static const ExceptionLabelMap exception_label_map[]
Definition: pl_comp.c:81
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:824
int i

◆ plpgsql_parse_tripword()

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

Definition at line 1524 of file pl_comp.c.

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

Referenced by plpgsql_yylex().

1526 {
1527  PLpgSQL_nsitem *ns;
1528  List *idents;
1529  int nnames;
1530 
1531  idents = list_make3(makeString(word1),
1532  makeString(word2),
1533  makeString(word3));
1534 
1535  /*
1536  * We should do nothing in DECLARE sections. In SQL expressions, we
1537  * really only need to make sure that RECFIELD datums are created when
1538  * needed.
1539  */
1541  {
1542  /*
1543  * Do a lookup in the current namespace stack. Must find a qualified
1544  * reference, else ignore.
1545  */
1546  ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1547  word1, word2, word3,
1548  &nnames);
1549  if (ns != NULL && nnames == 2)
1550  {
1551  switch (ns->itemtype)
1552  {
1553  case PLPGSQL_NSTYPE_REC:
1554  {
1555  /*
1556  * words 1/2 are a record name, so third word could be
1557  * a field in this record.
1558  */
1559  PLpgSQL_rec *rec;
1560  PLpgSQL_recfield *new;
1561 
1562  rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
1563  new = plpgsql_build_recfield(rec, word3);
1564 
1565  wdatum->datum = (PLpgSQL_datum *) new;
1566  wdatum->ident = NULL;
1567  wdatum->quoted = false; /* not used */
1568  wdatum->idents = idents;
1569  return true;
1570  }
1571 
1572  default:
1573  break;
1574  }
1575  }
1576  }
1577 
1578  /* Nothing found */
1579  cword->idents = idents;
1580  return false;
1581 }
Value * makeString(char *str)
Definition: value.c:53
#define list_make3(x1, x2, x3)
Definition: pg_list.h:231
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:45
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:2020
List * idents
Definition: plpgsql.h:1175
List * idents
Definition: plpgsql.h:1183
IdentifierLookup plpgsql_IdentifierLookup
Definition: pl_scanner.c:26
PLpgSQL_datum * datum
Definition: plpgsql.h:1180
bool quoted
Definition: plpgsql.h:1182
char * ident
Definition: plpgsql.h:1181
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:453
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 1389 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().

1391 {
1392  PLpgSQL_nsitem *ns;
1393 
1394  /*
1395  * We should not lookup variables in DECLARE sections. In SQL
1396  * expressions, there's no need to do so either --- lookup will happen
1397  * when the expression is compiled.
1398  */
1400  {
1401  /*
1402  * Do a lookup in the current namespace stack
1403  */
1404  ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1405  word1, NULL, NULL,
1406  NULL);
1407 
1408  if (ns != NULL)
1409  {
1410  switch (ns->itemtype)
1411  {
1412  case PLPGSQL_NSTYPE_VAR:
1413  case PLPGSQL_NSTYPE_REC:
1414  wdatum->datum = plpgsql_Datums[ns->itemno];
1415  wdatum->ident = word1;
1416  wdatum->quoted = (yytxt[0] == '"');
1417  wdatum->idents = NIL;
1418  return true;
1419 
1420  default:
1421  /* plpgsql_ns_lookup should never return anything else */
1422  elog(ERROR, "unrecognized plpgsql itemtype: %d",
1423  ns->itemtype);
1424  }
1425  }
1426  }
1427 
1428  /*
1429  * Nothing found - up to now it's a word without any special meaning for
1430  * us.
1431  */
1432  word->ident = word1;
1433  word->quoted = (yytxt[0] == '"');
1434  return false;
1435 }
#define NIL
Definition: pg_list.h:65
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:45
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:1169
#define ERROR
Definition: elog.h:43
Definition: zic.c:303
List * idents
Definition: plpgsql.h:1183
IdentifierLookup plpgsql_IdentifierLookup
Definition: pl_scanner.c:26
bool quoted
Definition: plpgsql.h:1170
PLpgSQL_datum * datum
Definition: plpgsql.h:1180
bool quoted
Definition: plpgsql.h:1182
char * ident
Definition: plpgsql.h:1181
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:453
#define elog(elevel,...)
Definition: elog.h:214

◆ plpgsql_parse_wordrowtype()

PLpgSQL_type* plpgsql_parse_wordrowtype ( char *  ident)

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

1779 {
1780  Oid classOid;
1781  Oid typOid;
1782 
1783  /*
1784  * Look up the relation. Note that because relation rowtypes have the
1785  * same names as their relations, this could be handled as a type lookup
1786  * equally well; we use the relation lookup code path only because the
1787  * errors thrown here have traditionally referred to relations not types.
1788  * But we'll make a TypeName in case we have to do re-look-up of the type.
1789  */
1790  classOid = RelnameGetRelid(ident);
1791  if (!OidIsValid(classOid))
1792  ereport(ERROR,
1794  errmsg("relation \"%s\" does not exist", ident)));
1795 
1796  /* Some relkinds lack type OIDs */
1797  typOid = get_rel_type_id(classOid);
1798  if (!OidIsValid(typOid))
1799  ereport(ERROR,
1800  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1801  errmsg("relation \"%s\" does not have a composite type",
1802  ident)));
1803 
1804  /* Build and return the row type struct */
1805  return plpgsql_build_datatype(typOid, -1, InvalidOid,
1806  makeTypeName(ident));
1807 }
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:73
Oid RelnameGetRelid(const char *relname)
Definition: namespace.c:680
int errcode(int sqlerrcode)
Definition: elog.c:610
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:651
#define ERROR
Definition: elog.h:43
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:2067
Oid get_rel_type_id(Oid relid)
Definition: lsyscache.c:1891
#define InvalidOid
Definition: postgres_ext.h:36
TypeName * makeTypeName(char *typnam)
Definition: makefuncs.c:444
#define ereport(elevel,...)
Definition: elog.h:144
int errmsg(const char *fmt,...)
Definition: elog.c:824

◆ plpgsql_parse_wordtype()

PLpgSQL_type* plpgsql_parse_wordtype ( char *  ident)

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

1593 {
1594  PLpgSQL_type *dtype;
1595  PLpgSQL_nsitem *nse;
1596  TypeName *typeName;
1597  HeapTuple typeTup;
1598 
1599  /*
1600  * Do a lookup in the current namespace stack
1601  */
1602  nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1603  ident, NULL, NULL,
1604  NULL);
1605 
1606  if (nse != NULL)
1607  {
1608  switch (nse->itemtype)
1609  {
1610  case PLPGSQL_NSTYPE_VAR:
1611  return ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1612 
1613  /* XXX perhaps allow REC/ROW here? */
1614 
1615  default:
1616  return NULL;
1617  }
1618  }
1619 
1620  /*
1621  * Word wasn't found in the namespace stack. Try to find a data type with
1622  * that name, but ignore shell types and complex types.
1623  */
1624  typeName = makeTypeName(ident);
1625  typeTup = LookupTypeName(NULL, typeName, NULL, false);
1626  if (typeTup)
1627  {
1628  Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1629 
1630  if (!typeStruct->typisdefined ||
1631  typeStruct->typrelid != InvalidOid)
1632  {
1633  ReleaseSysCache(typeTup);
1634  return NULL;
1635  }
1636 
1637  dtype = build_datatype(typeTup, -1,
1639  typeName);
1640 
1641  ReleaseSysCache(typeTup);
1642  return dtype;
1643  }
1644 
1645  /*
1646  * Nothing found - up to now it's a word without any special meaning for
1647  * us.
1648  */
1649  return NULL;
1650 }
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:45
PLpgSQL_nsitem * plpgsql_ns_top(void)
Definition: pl_funcs.c:81
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:2089
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:998
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#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:255
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:453
PLpgSQL_function * plpgsql_curr_compile
Definition: pl_comp.c:52

◆ plpgsql_parser_setup()

void plpgsql_parser_setup ( struct ParseState pstate,
PLpgSQL_expr expr 
)

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

1075 {
1079  /* no need to use p_coerce_param_hook */
1080  pstate->p_ref_hook_state = (void *) expr;
1081 }
static Node * plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref)
Definition: pl_comp.c:1087
PostParseColumnRefHook p_post_columnref_hook
Definition: parse_node.h:219
ParseParamRefHook p_paramref_hook
Definition: parse_node.h:220
static Node * plpgsql_param_ref(ParseState *pstate, ParamRef *pref)
Definition: pl_comp.c:1145
void * p_ref_hook_state
Definition: parse_node.h:222
PreParseColumnRefHook p_pre_columnref_hook
Definition: parse_node.h:218
static Node * plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
Definition: pl_comp.c:1101

◆ plpgsql_post_column_ref()

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

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

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

◆ plpgsql_pre_column_ref()

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

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

1088 {
1089  PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1090 
1092  return resolve_column_ref(pstate, expr, cref, false);
1093  else
1094  return NULL;
1095 }
PLpgSQL_resolve_option resolve_option
Definition: plpgsql.h:1018
struct PLpgSQL_function * func
Definition: plpgsql.h:227
void * p_ref_hook_state
Definition: parse_node.h:222
static Node * resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr, ColumnRef *cref, bool error_if_no_field)
Definition: pl_comp.c:1172

◆ plpgsql_recognize_err_condition()

int plpgsql_recognize_err_condition ( const char *  condname,
bool  allow_sqlstate 
)

Definition at line 2205 of file pl_comp.c.

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

Referenced by exec_stmt_raise().

2206 {
2207  int i;
2208 
2209  if (allow_sqlstate)
2210  {
2211  if (strlen(condname) == 5 &&
2212  strspn(condname, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") == 5)
2213  return MAKE_SQLSTATE(condname[0],
2214  condname[1],
2215  condname[2],
2216  condname[3],
2217  condname[4]);
2218  }
2219 
2220  for (i = 0; exception_label_map[i].label != NULL; i++)
2221  {
2222  if (strcmp(condname, exception_label_map[i].label) == 0)
2224  }
2225 
2226  ereport(ERROR,
2227  (errcode(ERRCODE_UNDEFINED_OBJECT),
2228  errmsg("unrecognized exception condition \"%s\"",
2229  condname)));
2230  return 0; /* keep compiler quiet */
2231 }
const char * label
Definition: pl_comp.c:77
#define MAKE_SQLSTATE(ch1, ch2, ch3, ch4, ch5)
Definition: elog.h:62
int errcode(int sqlerrcode)
Definition: elog.c:610
#define ERROR
Definition: elog.h:43
static char * label
#define ereport(elevel,...)
Definition: elog.h:144
static const ExceptionLabelMap exception_label_map[]
Definition: pl_comp.c:81
int errmsg(const char *fmt,...)
Definition: elog.c:824
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 2488 of file pl_comp.c.

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

Referenced by compute_function_hashkey(), and do_compile().

2492 {
2493  int i;
2494 
2495  if (!forValidator)
2496  {
2497  /* normal case, pass to standard routine */
2498  if (!resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
2499  call_expr))
2500  ereport(ERROR,
2501  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2502  errmsg("could not determine actual argument "
2503  "type for polymorphic function \"%s\"",
2504  proname)));
2505  }
2506  else
2507  {
2508  /* special validation case */
2509  for (i = 0; i < numargs; i++)
2510  {
2511  switch (argtypes[i])
2512  {
2513  case ANYELEMENTOID:
2514  case ANYNONARRAYOID:
2515  case ANYENUMOID: /* XXX dubious */
2516  case ANYCOMPATIBLEOID:
2517  case ANYCOMPATIBLENONARRAYOID:
2518  argtypes[i] = INT4OID;
2519  break;
2520  case ANYARRAYOID:
2521  case ANYCOMPATIBLEARRAYOID:
2522  argtypes[i] = INT4ARRAYOID;
2523  break;
2524  case ANYRANGEOID:
2525  case ANYCOMPATIBLERANGEOID:
2526  argtypes[i] = INT4RANGEOID;
2527  break;
2528  default:
2529  break;
2530  }
2531  }
2532  }
2533 }
bool resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, Node *call_expr)
Definition: funcapi.c:830
NameData proname
Definition: pg_proc.h:35
int errcode(int sqlerrcode)
Definition: elog.c:610
#define ERROR
Definition: elog.h:43
#define ereport(elevel,...)
Definition: elog.h:144
int errmsg(const char *fmt,...)
Definition: elog.c:824
int i

◆ plpgsql_start_datums()

static void plpgsql_start_datums ( void  )
static

Definition at line 2292 of file pl_comp.c.

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

Referenced by do_compile(), and plpgsql_compile_inline().

2293 {
2294  datums_alloc = 128;
2295  plpgsql_nDatums = 0;
2296  /* This is short-lived, so needn't allocate in function's cxt */
2298  sizeof(PLpgSQL_datum *) * datums_alloc);
2299  /* datums_last tracks what's been seen by plpgsql_add_initdatums() */
2300  datums_last = 0;
2301 }
int plpgsql_nDatums
Definition: pl_comp.c:44
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:45
static int datums_alloc
Definition: pl_comp.c:43
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:55
static int datums_last
Definition: pl_comp.c:46

◆ resolve_column_ref()

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

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

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

Variable Documentation

◆ datums_alloc

int datums_alloc
static

Definition at line 43 of file pl_comp.c.

Referenced by plpgsql_adddatum(), and plpgsql_start_datums().

◆ datums_last

int datums_last
static

Definition at line 46 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 81 of file pl_comp.c.

◆ plpgsql_check_syntax

bool plpgsql_check_syntax = false

Definition at line 50 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 55 of file pl_comp.c.

◆ plpgsql_curr_compile

PLpgSQL_function* plpgsql_curr_compile

Definition at line 52 of file pl_comp.c.

◆ plpgsql_Datums

PLpgSQL_datum** plpgsql_Datums

Definition at line 45 of file pl_comp.c.

◆ plpgsql_DumpExecTree

bool plpgsql_DumpExecTree = false

Definition at line 49 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_error_funcname

char* plpgsql_error_funcname

Definition at line 48 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 61 of file pl_comp.c.

◆ plpgsql_nDatums

int plpgsql_nDatums

◆ plpgsql_parse_result

PLpgSQL_stmt_block* plpgsql_parse_result

Definition at line 41 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().