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

Go to the source code of this file.

Data Structures

struct  plpgsql_hashent
 
struct  ExceptionLabelMap
 

Macros

#define FUNCS_PER_USER   128 /* initial table size */
 

Typedefs

typedef struct plpgsql_hashent plpgsql_HashEnt
 

Functions

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

Variables

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

Macro Definition Documentation

◆ FUNCS_PER_USER

#define FUNCS_PER_USER   128 /* initial table size */

Definition at line 70 of file pl_comp.c.

Typedef Documentation

◆ plpgsql_HashEnt

Function Documentation

◆ add_dummy_return()

static void add_dummy_return ( PLpgSQL_function function)
static

Definition at line 1032 of file pl_comp.c.

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

References function, lappend(), list_make1, llast, NIL, palloc0(), PLPGSQL_STMT_BLOCK, and PLPGSQL_STMT_RETURN.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ add_parameter_name()

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

Definition at line 1007 of file pl_comp.c.

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

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

Referenced by do_compile().

◆ build_datatype()

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

Definition at line 2066 of file pl_comp.c.

2068 {
2069  Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
2070  PLpgSQL_type *typ;
2071 
2072  if (!typeStruct->typisdefined)
2073  ereport(ERROR,
2074  (errcode(ERRCODE_UNDEFINED_OBJECT),
2075  errmsg("type \"%s\" is only a shell",
2076  NameStr(typeStruct->typname))));
2077 
2078  typ = (PLpgSQL_type *) palloc(sizeof(PLpgSQL_type));
2079 
2080  typ->typname = pstrdup(NameStr(typeStruct->typname));
2081  typ->typoid = typeStruct->oid;
2082  switch (typeStruct->typtype)
2083  {
2084  case TYPTYPE_BASE:
2085  case TYPTYPE_ENUM:
2086  case TYPTYPE_RANGE:
2087  case TYPTYPE_MULTIRANGE:
2088  typ->ttype = PLPGSQL_TTYPE_SCALAR;
2089  break;
2090  case TYPTYPE_COMPOSITE:
2091  typ->ttype = PLPGSQL_TTYPE_REC;
2092  break;
2093  case TYPTYPE_DOMAIN:
2094  if (type_is_rowtype(typeStruct->typbasetype))
2095  typ->ttype = PLPGSQL_TTYPE_REC;
2096  else
2097  typ->ttype = PLPGSQL_TTYPE_SCALAR;
2098  break;
2099  case TYPTYPE_PSEUDO:
2100  if (typ->typoid == RECORDOID)
2101  typ->ttype = PLPGSQL_TTYPE_REC;
2102  else
2103  typ->ttype = PLPGSQL_TTYPE_PSEUDO;
2104  break;
2105  default:
2106  elog(ERROR, "unrecognized typtype: %d",
2107  (int) typeStruct->typtype);
2108  break;
2109  }
2110  typ->typlen = typeStruct->typlen;
2111  typ->typbyval = typeStruct->typbyval;
2112  typ->typtype = typeStruct->typtype;
2113  typ->collation = typeStruct->typcollation;
2114  if (OidIsValid(collation) && OidIsValid(typ->collation))
2115  typ->collation = collation;
2116  /* Detect if type is true array, or domain thereof */
2117  /* NB: this is only used to decide whether to apply expand_array */
2118  if (typeStruct->typtype == TYPTYPE_BASE)
2119  {
2120  /*
2121  * This test should include what get_element_type() checks. We also
2122  * disallow non-toastable array types (i.e. oidvector and int2vector).
2123  */
2124  typ->typisarray = (IsTrueArrayType(typeStruct) &&
2125  typeStruct->typstorage != TYPSTORAGE_PLAIN);
2126  }
2127  else if (typeStruct->typtype == TYPTYPE_DOMAIN)
2128  {
2129  /* we can short-circuit looking up base types if it's not varlena */
2130  typ->typisarray = (typeStruct->typlen == -1 &&
2131  typeStruct->typstorage != TYPSTORAGE_PLAIN &&
2132  OidIsValid(get_base_element_type(typeStruct->typbasetype)));
2133  }
2134  else
2135  typ->typisarray = false;
2136  typ->atttypmod = typmod;
2137 
2138  /*
2139  * If it's a named composite type (or domain over one), find the typcache
2140  * entry and record the current tupdesc ID, so we can detect changes
2141  * (including drops). We don't currently support on-the-fly replacement
2142  * of non-composite types, else we might want to do this for them too.
2143  */
2144  if (typ->ttype == PLPGSQL_TTYPE_REC && typ->typoid != RECORDOID)
2145  {
2146  TypeCacheEntry *typentry;
2147 
2148  typentry = lookup_type_cache(typ->typoid,
2151  if (typentry->typtype == TYPTYPE_DOMAIN)
2152  typentry = lookup_type_cache(typentry->domainBaseType,
2154  if (typentry->tupDesc == NULL)
2155  ereport(ERROR,
2156  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2157  errmsg("type %s is not composite",
2158  format_type_be(typ->typoid))));
2159 
2160  typ->origtypname = origtypname;
2161  typ->tcache = typentry;
2162  typ->tupdesc_id = typentry->tupDesc_identifier;
2163  }
2164  else
2165  {
2166  typ->origtypname = NULL;
2167  typ->tcache = NULL;
2168  typ->tupdesc_id = 0;
2169  }
2170 
2171  return typ;
2172 }
#define NameStr(name)
Definition: c.h:746
#define OidIsValid(objectId)
Definition: c.h:775
#define elog(elevel,...)
Definition: elog.h:224
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2655
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2832
char * pstrdup(const char *in)
Definition: mcxt.c:1695
void * palloc(Size size)
Definition: mcxt.c:1316
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
@ PLPGSQL_TTYPE_PSEUDO
Definition: plpgsql.h:96
@ PLPGSQL_TTYPE_REC
Definition: plpgsql.h:95
@ PLPGSQL_TTYPE_SCALAR
Definition: plpgsql.h:94
char typtype
Definition: plpgsql.h:205
TypeName * origtypname
Definition: plpgsql.h:210
bool typisarray
Definition: plpgsql.h:207
TypeCacheEntry * tcache
Definition: plpgsql.h:211
uint64 tupdesc_id
Definition: plpgsql.h:212
Oid collation
Definition: plpgsql.h:206
PLpgSQL_type_type ttype
Definition: plpgsql.h:202
Oid typoid
Definition: plpgsql.h:201
char * typname
Definition: plpgsql.h:200
int16 typlen
Definition: plpgsql.h:203
int32 atttypmod
Definition: plpgsql.h:208
bool typbyval
Definition: plpgsql.h:204
uint64 tupDesc_identifier
Definition: typcache.h:90
char typtype
Definition: typcache.h:43
TupleDesc tupDesc
Definition: typcache.h:89
Oid domainBaseType
Definition: typcache.h:114
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:346
#define TYPECACHE_TUPDESC
Definition: typcache.h:145
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:149

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(), and plpgsql_parse_cwordtype().

◆ build_row_from_vars()

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

Definition at line 1930 of file pl_comp.c.

1931 {
1932  PLpgSQL_row *row;
1933  int i;
1934 
1935  row = palloc0(sizeof(PLpgSQL_row));
1936  row->dtype = PLPGSQL_DTYPE_ROW;
1937  row->refname = "(unnamed row)";
1938  row->lineno = -1;
1939  row->rowtupdesc = CreateTemplateTupleDesc(numvars);
1940  row->nfields = numvars;
1941  row->fieldnames = palloc(numvars * sizeof(char *));
1942  row->varnos = palloc(numvars * sizeof(int));
1943 
1944  for (i = 0; i < numvars; i++)
1945  {
1946  PLpgSQL_variable *var = vars[i];
1947  Oid typoid;
1948  int32 typmod;
1949  Oid typcoll;
1950 
1951  /* Member vars of a row should never be const */
1952  Assert(!var->isconst);
1953 
1954  switch (var->dtype)
1955  {
1956  case PLPGSQL_DTYPE_VAR:
1957  case PLPGSQL_DTYPE_PROMISE:
1958  typoid = ((PLpgSQL_var *) var)->datatype->typoid;
1959  typmod = ((PLpgSQL_var *) var)->datatype->atttypmod;
1960  typcoll = ((PLpgSQL_var *) var)->datatype->collation;
1961  break;
1962 
1963  case PLPGSQL_DTYPE_REC:
1964  /* shouldn't need to revalidate rectypeid already... */
1965  typoid = ((PLpgSQL_rec *) var)->rectypeid;
1966  typmod = -1; /* don't know typmod, if it's used at all */
1967  typcoll = InvalidOid; /* composite types have no collation */
1968  break;
1969 
1970  default:
1971  elog(ERROR, "unrecognized dtype: %d", var->dtype);
1972  typoid = InvalidOid; /* keep compiler quiet */
1973  typmod = 0;
1974  typcoll = InvalidOid;
1975  break;
1976  }
1977 
1978  row->fieldnames[i] = var->refname;
1979  row->varnos[i] = var->dno;
1980 
1981  TupleDescInitEntry(row->rowtupdesc, i + 1,
1982  var->refname,
1983  typoid, typmod,
1984  0);
1985  TupleDescInitEntryCollation(row->rowtupdesc, i + 1, typcoll);
1986  }
1987 
1988  return row;
1989 }
signed int int32
Definition: c.h:494
#define Assert(condition)
Definition: c.h:858
int i
Definition: isn.c:73
@ PLPGSQL_DTYPE_ROW
Definition: plpgsql.h:64
@ PLPGSQL_DTYPE_PROMISE
Definition: plpgsql.h:67
@ PLPGSQL_DTYPE_REC
Definition: plpgsql.h:65
@ PLPGSQL_DTYPE_VAR
Definition: plpgsql.h:63
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
TupleDesc rowtupdesc
Definition: plpgsql.h:379
int lineno
Definition: plpgsql.h:368
PLpgSQL_datum_type dtype
Definition: plpgsql.h:365
int * varnos
Definition: plpgsql.h:383
char * refname
Definition: plpgsql.h:367
char ** fieldnames
Definition: plpgsql.h:382
int nfields
Definition: plpgsql.h:381
PLpgSQL_datum_type dtype
Definition: plpgsql.h:289
char * refname
Definition: plpgsql.h:291
Definition: regcomp.c:281
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:67
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition: tupdesc.c:833
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:651

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().

◆ compute_function_hashkey()

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

Definition at line 2432 of file pl_comp.c.

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

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().

◆ delete_function()

static void delete_function ( PLpgSQL_function func)
static

Definition at line 2583 of file pl_comp.c.

2584 {
2585  /* remove function from hash table (might be done already) */
2587 
2588  /* release the function's storage if safe and not done already */
2589  if (func->use_count == 0)
2591 }
static void plpgsql_HashTableDelete(PLpgSQL_function *function)
Definition: pl_comp.c:2645
void plpgsql_free_function_memory(PLpgSQL_function *func)
Definition: pl_funcs.c:727
unsigned long use_count
Definition: plpgsql.h:1015

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

Referenced by plpgsql_compile().

◆ do_compile()

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

Definition at line 264 of file pl_comp.c.

269 {
270  Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
271  bool is_dml_trigger = CALLED_AS_TRIGGER(fcinfo);
272  bool is_event_trigger = CALLED_AS_EVENT_TRIGGER(fcinfo);
273  Datum prosrcdatum;
274  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 = SysCacheGetAttrNotNull(PROCOID, procTup, Anum_pg_proc_prosrc);
299  proc_source = TextDatumGetCString(prosrcdatum);
300  plpgsql_scanner_init(proc_source);
301 
302  plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname));
303 
304  /*
305  * Setup error traceback support for ereport()
306  */
308  plerrcontext.arg = forValidator ? proc_source : NULL;
309  plerrcontext.previous = error_context_stack;
310  error_context_stack = &plerrcontext;
311 
312  /*
313  * Do extra syntax checks when validating the function definition. We skip
314  * this when actually compiling functions for execution, for performance
315  * reasons.
316  */
317  plpgsql_check_syntax = forValidator;
318 
319  /*
320  * Create the new function struct, if not done already. The function
321  * structs are never thrown away, so keep them in TopMemoryContext.
322  */
323  if (function == NULL)
324  {
325  function = (PLpgSQL_function *)
327  }
328  else
329  {
330  /* re-using a previously existing struct, so clear it out */
331  memset(function, 0, sizeof(PLpgSQL_function));
332  }
333  plpgsql_curr_compile = function;
334 
335  /*
336  * All the permanent output of compilation (e.g. parse tree) is kept in a
337  * per-function memory context, so it can be reclaimed easily.
338  */
340  "PL/pgSQL function",
343 
344  function->fn_signature = format_procedure(fcinfo->flinfo->fn_oid);
345  MemoryContextSetIdentifier(func_cxt, function->fn_signature);
346  function->fn_oid = fcinfo->flinfo->fn_oid;
347  function->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data);
348  function->fn_tid = procTup->t_self;
349  function->fn_input_collation = fcinfo->fncollation;
350  function->fn_cxt = func_cxt;
351  function->out_param_varno = -1; /* set up for no OUT param */
352  function->resolve_option = plpgsql_variable_conflict;
353  function->print_strict_params = plpgsql_print_strict_params;
354  /* only promote extra warnings and errors at CREATE FUNCTION time */
355  function->extra_warnings = forValidator ? plpgsql_extra_warnings : 0;
356  function->extra_errors = forValidator ? plpgsql_extra_errors : 0;
357 
358  if (is_dml_trigger)
359  function->fn_is_trigger = PLPGSQL_DML_TRIGGER;
360  else if (is_event_trigger)
361  function->fn_is_trigger = PLPGSQL_EVENT_TRIGGER;
362  else
363  function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
364 
365  function->fn_prokind = procStruct->prokind;
366 
367  function->nstatements = 0;
368  function->requires_procedure_resowner = false;
369 
370  /*
371  * Initialize the compiler, particularly the namespace stack. The
372  * outermost namespace contains function parameters and other special
373  * variables (such as FOUND), and is named after the function itself.
374  */
375  plpgsql_ns_init();
376  plpgsql_ns_push(NameStr(procStruct->proname), PLPGSQL_LABEL_BLOCK);
377  plpgsql_DumpExecTree = false;
379 
380  switch (function->fn_is_trigger)
381  {
382  case PLPGSQL_NOT_TRIGGER:
383 
384  /*
385  * Fetch info about the procedure's parameters. Allocations aren't
386  * needed permanently, so make them in tmp cxt.
387  *
388  * We also need to resolve any polymorphic input or output
389  * argument types. In validation mode we won't be able to, so we
390  * arbitrarily assume we are dealing with integers.
391  */
393 
394  numargs = get_func_arg_info(procTup,
395  &argtypes, &argnames, &argmodes);
396 
397  plpgsql_resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
398  fcinfo->flinfo->fn_expr,
399  forValidator,
401 
402  in_arg_varnos = (int *) palloc(numargs * sizeof(int));
403  out_arg_variables = (PLpgSQL_variable **) palloc(numargs * sizeof(PLpgSQL_variable *));
404 
405  MemoryContextSwitchTo(func_cxt);
406 
407  /*
408  * Create the variables for the procedure's parameters.
409  */
410  for (i = 0; i < numargs; i++)
411  {
412  char buf[32];
413  Oid argtypeid = argtypes[i];
414  char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
415  PLpgSQL_type *argdtype;
416  PLpgSQL_variable *argvariable;
417  PLpgSQL_nsitem_type argitemtype;
418 
419  /* Create $n name for variable */
420  snprintf(buf, sizeof(buf), "$%d", i + 1);
421 
422  /* Create datatype info */
423  argdtype = plpgsql_build_datatype(argtypeid,
424  -1,
425  function->fn_input_collation,
426  NULL);
427 
428  /* Disallow pseudotype argument */
429  /* (note we already replaced polymorphic types) */
430  /* (build_variable would do this, but wrong message) */
431  if (argdtype->ttype == PLPGSQL_TTYPE_PSEUDO)
432  ereport(ERROR,
433  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
434  errmsg("PL/pgSQL functions cannot accept type %s",
435  format_type_be(argtypeid))));
436 
437  /*
438  * Build variable and add to datum list. If there's a name
439  * for the argument, use that as refname, else use $n name.
440  */
441  argvariable = plpgsql_build_variable((argnames &&
442  argnames[i][0] != '\0') ?
443  argnames[i] : buf,
444  0, argdtype, false);
445 
446  if (argvariable->dtype == PLPGSQL_DTYPE_VAR)
447  {
448  argitemtype = PLPGSQL_NSTYPE_VAR;
449  }
450  else
451  {
452  Assert(argvariable->dtype == PLPGSQL_DTYPE_REC);
453  argitemtype = PLPGSQL_NSTYPE_REC;
454  }
455 
456  /* Remember arguments in appropriate arrays */
457  if (argmode == PROARGMODE_IN ||
458  argmode == PROARGMODE_INOUT ||
459  argmode == PROARGMODE_VARIADIC)
460  in_arg_varnos[num_in_args++] = argvariable->dno;
461  if (argmode == PROARGMODE_OUT ||
462  argmode == PROARGMODE_INOUT ||
463  argmode == PROARGMODE_TABLE)
464  out_arg_variables[num_out_args++] = argvariable;
465 
466  /* Add to namespace under the $n name */
467  add_parameter_name(argitemtype, argvariable->dno, buf);
468 
469  /* If there's a name for the argument, make an alias */
470  if (argnames && argnames[i][0] != '\0')
471  add_parameter_name(argitemtype, argvariable->dno,
472  argnames[i]);
473  }
474 
475  /*
476  * If there's just one OUT parameter, out_param_varno points
477  * directly to it. If there's more than one, build a row that
478  * holds all of them. Procedures return a row even for one OUT
479  * parameter.
480  */
481  if (num_out_args > 1 ||
482  (num_out_args == 1 && function->fn_prokind == PROKIND_PROCEDURE))
483  {
484  PLpgSQL_row *row = build_row_from_vars(out_arg_variables,
485  num_out_args);
486 
488  function->out_param_varno = row->dno;
489  }
490  else if (num_out_args == 1)
491  function->out_param_varno = out_arg_variables[0]->dno;
492 
493  /*
494  * Check for a polymorphic returntype. If found, use the actual
495  * returntype type from the caller's FuncExpr node, if we have
496  * one. (In validation mode we arbitrarily assume we are dealing
497  * with integers.)
498  *
499  * Note: errcode is FEATURE_NOT_SUPPORTED because it should always
500  * work; if it doesn't we're in some context that fails to make
501  * the info available.
502  */
503  rettypeid = procStruct->prorettype;
504  if (IsPolymorphicType(rettypeid))
505  {
506  if (forValidator)
507  {
508  if (rettypeid == ANYARRAYOID ||
509  rettypeid == ANYCOMPATIBLEARRAYOID)
510  rettypeid = INT4ARRAYOID;
511  else if (rettypeid == ANYRANGEOID ||
512  rettypeid == ANYCOMPATIBLERANGEOID)
513  rettypeid = INT4RANGEOID;
514  else if (rettypeid == ANYMULTIRANGEOID)
515  rettypeid = INT4MULTIRANGEOID;
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 == EVENT_TRIGGEROID)
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 }
#define TextDatumGetCString(d)
Definition: builtins.h:98
ErrorContextCallback * error_context_stack
Definition: elog.c:94
int errhint(const char *fmt,...)
Definition: elog.c:1319
Oid get_fn_expr_rettype(FmgrInfo *flinfo)
Definition: fmgr.c:1888
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
Definition: funcapi.c:1379
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:304
void pfree(void *pointer)
Definition: mcxt.c:1520
MemoryContext TopMemoryContext
Definition: mcxt.c:149
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1214
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
Definition: mcxt.c:612
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
static char * buf
Definition: pg_test_fsync.c:73
static void add_dummy_return(PLpgSQL_function *function)
Definition: pl_comp.c:1032
static PLpgSQL_row * build_row_from_vars(PLpgSQL_variable **vars, int numvars)
Definition: pl_comp.c:1930
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:56
PLpgSQL_rec * plpgsql_build_record(const char *refname, int lineno, PLpgSQL_type *dtype, Oid rectypeid, bool add2namespace)
Definition: pl_comp.c:1903
static void plpgsql_HashTableInsert(PLpgSQL_function *function, PLpgSQL_func_hashkey *func_key)
Definition: pl_comp.c:2626
static void plpgsql_compile_error_callback(void *arg)
Definition: pl_comp.c:980
PLpgSQL_variable * plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype, bool add2namespace)
Definition: pl_comp.c:1840
static void plpgsql_start_datums(void)
Definition: pl_comp.c:2296
char * plpgsql_error_funcname
Definition: pl_comp.c:49
PLpgSQL_stmt_block * plpgsql_parse_result
Definition: pl_comp.c:42
bool plpgsql_check_syntax
Definition: pl_comp.c:51
static void plpgsql_finish_datums(PLpgSQL_function *function)
Definition: pl_comp.c:2330
PLpgSQL_function * plpgsql_curr_compile
Definition: pl_comp.c:53
void plpgsql_adddatum(PLpgSQL_datum *newdatum)
Definition: pl_comp.c:2313
bool plpgsql_DumpExecTree
Definition: pl_comp.c:50
static void add_parameter_name(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
Definition: pl_comp.c:1007
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:2066
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:2044
void plpgsql_ns_init(void)
Definition: pl_funcs.c:43
void plpgsql_dumptree(PLpgSQL_function *func)
Definition: pl_funcs.c:1600
void plpgsql_ns_push(const char *label, PLpgSQL_label_type label_type)
Definition: pl_funcs.c:54
int plpgsql_variable_conflict
Definition: pl_handler.c:44
int plpgsql_extra_warnings
Definition: pl_handler.c:52
bool plpgsql_print_strict_params
Definition: pl_handler.c:46
int plpgsql_extra_errors
Definition: pl_handler.c:53
void plpgsql_scanner_finish(void)
Definition: pl_scanner.c:630
void plpgsql_scanner_init(const char *str)
Definition: pl_scanner.c:603
@ PLPGSQL_DML_TRIGGER
Definition: plpgsql.h:958
@ PLPGSQL_NOT_TRIGGER
Definition: plpgsql.h:960
@ PLPGSQL_EVENT_TRIGGER
Definition: plpgsql.h:959
@ PLPGSQL_PROMISE_TG_RELID
Definition: plpgsql.h:80
@ PLPGSQL_PROMISE_TG_WHEN
Definition: plpgsql.h:77
@ PLPGSQL_PROMISE_TG_ARGV
Definition: plpgsql.h:84
@ PLPGSQL_PROMISE_TG_TABLE_SCHEMA
Definition: plpgsql.h:82
@ PLPGSQL_PROMISE_TG_EVENT
Definition: plpgsql.h:85
@ PLPGSQL_PROMISE_TG_TABLE_NAME
Definition: plpgsql.h:81
@ PLPGSQL_PROMISE_TG_TAG
Definition: plpgsql.h:86
@ PLPGSQL_PROMISE_TG_OP
Definition: plpgsql.h:79
@ PLPGSQL_PROMISE_TG_LEVEL
Definition: plpgsql.h:78
@ PLPGSQL_PROMISE_TG_NARGS
Definition: plpgsql.h:83
@ PLPGSQL_PROMISE_TG_NAME
Definition: plpgsql.h:76
int plpgsql_yyparse(void)
@ PLPGSQL_LABEL_BLOCK
Definition: plpgsql.h:53
PLpgSQL_nsitem_type
Definition: plpgsql.h:42
@ PLPGSQL_NSTYPE_VAR
Definition: plpgsql.h:44
@ PLPGSQL_NSTYPE_REC
Definition: plpgsql.h:45
#define snprintf
Definition: port.h:238
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
MemoryContextSwitchTo(old_ctx)
char * format_procedure(Oid procedure_oid)
Definition: regproc.c:299
struct ErrorContextCallback * previous
Definition: elog.h:295
void(* callback)(void *arg)
Definition: elog.h:296
ItemPointerData t_self
Definition: htup.h:65
HeapTupleHeader t_data
Definition: htup.h:68
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:266
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:218
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:510

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_variable::dno, PLpgSQL_row::dno, PLpgSQL_rec::dno, PLpgSQL_variable::dtype, elog, ereport, errcode(), errhint(), errmsg(), ERROR, error_context_stack, FunctionCallInfoBaseData::flinfo, FmgrInfo::fn_expr, FmgrInfo::fn_oid, FunctionCallInfoBaseData::fncollation, format_procedure(), format_type_be(), 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_compile_tmp_cxt, plpgsql_curr_compile, 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, pstrdup(), ReleaseSysCache(), SearchSysCache1(), snprintf, SysCacheGetAttrNotNull(), HeapTupleData::t_data, HeapTupleData::t_self, TextDatumGetCString, TopMemoryContext, PLpgSQL_type::ttype, and type_is_rowtype().

Referenced by plpgsql_compile().

◆ make_datum_param()

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

Definition at line 1333 of file pl_comp.c.

1334 {
1335  PLpgSQL_execstate *estate;
1336  PLpgSQL_datum *datum;
1337  Param *param;
1338  MemoryContext oldcontext;
1339 
1340  /* see comment in resolve_column_ref */
1341  estate = expr->func->cur_estate;
1342  Assert(dno >= 0 && dno < estate->ndatums);
1343  datum = estate->datums[dno];
1344 
1345  /*
1346  * Bitmapset must be allocated in function's permanent memory context
1347  */
1348  oldcontext = MemoryContextSwitchTo(expr->func->fn_cxt);
1349  expr->paramnos = bms_add_member(expr->paramnos, dno);
1350  MemoryContextSwitchTo(oldcontext);
1351 
1352  param = makeNode(Param);
1353  param->paramkind = PARAM_EXTERN;
1354  param->paramid = dno + 1;
1356  datum,
1357  &param->paramtype,
1358  &param->paramtypmod,
1359  &param->paramcollid);
1360  param->location = location;
1361 
1362  return (Node *) param;
1363 }
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
#define makeNode(_type_)
Definition: nodes.h:155
void plpgsql_exec_get_datum_type_info(PLpgSQL_execstate *estate, PLpgSQL_datum *datum, Oid *typeId, int32 *typMod, Oid *collation)
Definition: pl_exec.c:5543
@ PARAM_EXTERN
Definition: primnodes.h:367
Definition: nodes.h:129
PLpgSQL_datum ** datums
Definition: plpgsql.h:1058
struct PLpgSQL_function * func
Definition: plpgsql.h:226
Bitmapset * paramnos
Definition: plpgsql.h:223
MemoryContext fn_cxt
Definition: plpgsql.h:975
struct PLpgSQL_execstate * cur_estate
Definition: plpgsql.h:1014
ParseLoc location
Definition: primnodes.h:384
int paramid
Definition: primnodes.h:377
Oid paramtype
Definition: primnodes.h:378
ParamKind paramkind
Definition: primnodes.h:376

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::paramid, Param::paramkind, PLpgSQL_expr::paramnos, Param::paramtype, and plpgsql_exec_get_datum_type_info().

Referenced by plpgsql_param_ref(), and resolve_column_ref().

◆ plpgsql_add_initdatums()

int plpgsql_add_initdatums ( int **  varnos)

Definition at line 2374 of file pl_comp.c.

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

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

◆ plpgsql_adddatum()

void plpgsql_adddatum ( PLpgSQL_datum newdatum)

Definition at line 2313 of file pl_comp.c.

2314 {
2316  {
2317  datums_alloc *= 2;
2319  }
2320 
2321  newdatum->dno = plpgsql_nDatums;
2322  plpgsql_Datums[plpgsql_nDatums++] = newdatum;
2323 }
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1540
static int datums_alloc
Definition: pl_comp.c:44

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

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

◆ plpgsql_build_datatype()

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

Definition at line 2044 of file pl_comp.c.

2046 {
2047  HeapTuple typeTup;
2048  PLpgSQL_type *typ;
2049 
2050  typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
2051  if (!HeapTupleIsValid(typeTup))
2052  elog(ERROR, "cache lookup failed for type %u", typeOid);
2053 
2054  typ = build_datatype(typeTup, typmod, collation, origtypname);
2055 
2056  ReleaseSysCache(typeTup);
2057 
2058  return typ;
2059 }

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

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

◆ plpgsql_build_datatype_arrayof()

PLpgSQL_type* plpgsql_build_datatype_arrayof ( PLpgSQL_type dtype)

Definition at line 2178 of file pl_comp.c.

2179 {
2180  Oid array_typeid;
2181 
2182  /*
2183  * If it's already an array type, use it as-is: Postgres doesn't do nested
2184  * arrays.
2185  */
2186  if (dtype->typisarray)
2187  return dtype;
2188 
2189  array_typeid = get_array_type(dtype->typoid);
2190  if (!OidIsValid(array_typeid))
2191  ereport(ERROR,
2192  (errcode(ERRCODE_UNDEFINED_OBJECT),
2193  errmsg("could not find array type for data type %s",
2194  format_type_be(dtype->typoid))));
2195 
2196  /* Note we inherit typmod and collation, if any, from the element type */
2197  return plpgsql_build_datatype(array_typeid, dtype->atttypmod,
2198  dtype->collation, NULL);
2199 }
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2787

References PLpgSQL_type::atttypmod, PLpgSQL_type::collation, ereport, errcode(), errmsg(), ERROR, format_type_be(), get_array_type(), OidIsValid, plpgsql_build_datatype(), PLpgSQL_type::typisarray, and PLpgSQL_type::typoid.

◆ plpgsql_build_recfield()

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

Definition at line 1997 of file pl_comp.c.

1998 {
1999  PLpgSQL_recfield *recfield;
2000  int i;
2001 
2002  /* search for an existing datum referencing this field */
2003  i = rec->firstfield;
2004  while (i >= 0)
2005  {
2007 
2009  fld->recparentno == rec->dno);
2010  if (strcmp(fld->fieldname, fldname) == 0)
2011  return fld;
2012  i = fld->nextfield;
2013  }
2014 
2015  /* nope, so make a new one */
2016  recfield = palloc0(sizeof(PLpgSQL_recfield));
2017  recfield->dtype = PLPGSQL_DTYPE_RECFIELD;
2018  recfield->fieldname = pstrdup(fldname);
2019  recfield->recparentno = rec->dno;
2021 
2022  plpgsql_adddatum((PLpgSQL_datum *) recfield);
2023 
2024  /* now we can link it into the parent's chain */
2025  recfield->nextfield = rec->firstfield;
2026  rec->firstfield = recfield->dno;
2027 
2028  return recfield;
2029 }
@ PLPGSQL_DTYPE_RECFIELD
Definition: plpgsql.h:66
int firstfield
Definition: plpgsql.h:409
uint64 rectupledescid
Definition: plpgsql.h:429
PLpgSQL_datum_type dtype
Definition: plpgsql.h:422
char * fieldname
Definition: plpgsql.h:426
#define INVALID_TUPLEDESC_IDENTIFIER
Definition: typcache.h:156

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

Referenced by plpgsql_parse_dblword(), and plpgsql_parse_tripword().

◆ plpgsql_build_record()

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

Definition at line 1903 of file pl_comp.c.

1906 {
1907  PLpgSQL_rec *rec;
1908 
1909  rec = palloc0(sizeof(PLpgSQL_rec));
1910  rec->dtype = PLPGSQL_DTYPE_REC;
1911  rec->refname = pstrdup(refname);
1912  rec->lineno = lineno;
1913  /* other fields are left as 0, might be changed by caller */
1914  rec->datatype = dtype;
1915  rec->rectypeid = rectypeid;
1916  rec->firstfield = -1;
1917  rec->erh = NULL;
1919  if (add2namespace)
1921 
1922  return rec;
1923 }
ExpandedRecordHeader * erh
Definition: plpgsql.h:414
PLpgSQL_type * datatype
Definition: plpgsql.h:406
PLpgSQL_datum_type dtype
Definition: plpgsql.h:391
Oid rectypeid
Definition: plpgsql.h:407
int lineno
Definition: plpgsql.h:394
char * refname
Definition: plpgsql.h:393

References PLpgSQL_rec::datatype, PLpgSQL_rec::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().

◆ plpgsql_build_variable()

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

Definition at line 1840 of file pl_comp.c.

1842 {
1843  PLpgSQL_variable *result;
1844 
1845  switch (dtype->ttype)
1846  {
1847  case PLPGSQL_TTYPE_SCALAR:
1848  {
1849  /* Ordinary scalar datatype */
1850  PLpgSQL_var *var;
1851 
1852  var = palloc0(sizeof(PLpgSQL_var));
1853  var->dtype = PLPGSQL_DTYPE_VAR;
1854  var->refname = pstrdup(refname);
1855  var->lineno = lineno;
1856  var->datatype = dtype;
1857  /* other fields are left as 0, might be changed by caller */
1858 
1859  /* preset to NULL */
1860  var->value = 0;
1861  var->isnull = true;
1862  var->freeval = false;
1863 
1865  if (add2namespace)
1867  var->dno,
1868  refname);
1869  result = (PLpgSQL_variable *) var;
1870  break;
1871  }
1872  case PLPGSQL_TTYPE_REC:
1873  {
1874  /* Composite type -- build a record variable */
1875  PLpgSQL_rec *rec;
1876 
1877  rec = plpgsql_build_record(refname, lineno,
1878  dtype, dtype->typoid,
1879  add2namespace);
1880  result = (PLpgSQL_variable *) rec;
1881  break;
1882  }
1883  case PLPGSQL_TTYPE_PSEUDO:
1884  ereport(ERROR,
1885  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1886  errmsg("variable \"%s\" has pseudo-type %s",
1887  refname, format_type_be(dtype->typoid))));
1888  result = NULL; /* keep compiler quiet */
1889  break;
1890  default:
1891  elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
1892  result = NULL; /* keep compiler quiet */
1893  break;
1894  }
1895 
1896  return result;
1897 }
int lineno
Definition: plpgsql.h:314
PLpgSQL_datum_type dtype
Definition: plpgsql.h:311
bool freeval
Definition: plpgsql.h:335
bool isnull
Definition: plpgsql.h:334
PLpgSQL_type * datatype
Definition: plpgsql.h:320
char * refname
Definition: plpgsql.h:313
Datum value
Definition: plpgsql.h:333

References PLpgSQL_var::datatype, PLpgSQL_var::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().

◆ plpgsql_compile()

PLpgSQL_function* plpgsql_compile ( FunctionCallInfo  fcinfo,
bool  forValidator 
)

Definition at line 136 of file pl_comp.c.

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

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

Referenced by plpgsql_call_handler(), and plpgsql_validator().

◆ plpgsql_compile_error_callback()

static void plpgsql_compile_error_callback ( void *  arg)
static

Definition at line 980 of file pl_comp.c.

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

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

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_compile_inline()

PLpgSQL_function* plpgsql_compile_inline ( char *  proc_source)

Definition at line 843 of file pl_comp.c.

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  function->requires_procedure_resowner = false;
903 
904  plpgsql_ns_init();
906  plpgsql_DumpExecTree = false;
908 
909  /* Set up as though in a function returning VOID */
910  function->fn_rettype = VOIDOID;
911  function->fn_retset = false;
912  function->fn_retistuple = false;
913  function->fn_retisdomain = false;
914  function->fn_prokind = PROKIND_FUNCTION;
915  /* a bit of hardwired knowledge about type VOID here */
916  function->fn_retbyval = true;
917  function->fn_rettyplen = sizeof(int32);
918 
919  /*
920  * Remember if function is STABLE/IMMUTABLE. XXX would it be better to
921  * set this true inside a read-only transaction? Not clear.
922  */
923  function->fn_readonly = false;
924 
925  /*
926  * Create the magic FOUND variable.
927  */
928  var = plpgsql_build_variable("found", 0,
929  plpgsql_build_datatype(BOOLOID,
930  -1,
931  InvalidOid,
932  NULL),
933  true);
934  function->found_varno = var->dno;
935 
936  /*
937  * Now parse the function's text
938  */
939  parse_rc = plpgsql_yyparse();
940  if (parse_rc != 0)
941  elog(ERROR, "plpgsql parser returned %d", parse_rc);
942  function->action = plpgsql_parse_result;
943 
945 
946  /*
947  * If it returns VOID (always true at the moment), we allow control to
948  * fall off the end without an explicit RETURN statement.
949  */
950  if (function->fn_rettype == VOIDOID)
951  add_dummy_return(function);
952 
953  /*
954  * Complete the function's info
955  */
956  function->fn_nargs = 0;
957 
958  plpgsql_finish_datums(function);
959 
960  /*
961  * Pop the error context stack
962  */
963  error_context_stack = plerrcontext.previous;
964  plpgsql_error_funcname = NULL;
965 
966  plpgsql_check_syntax = false;
967 
970  return function;
971 }
bool check_function_bodies
Definition: guc_tables.c:514
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143

References add_dummy_return(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, ErrorContextCallback::arg, ErrorContextCallback::callback, check_function_bodies, CurrentMemoryContext, PLpgSQL_variable::dno, elog, ERROR, error_context_stack, function, InvalidOid, MemoryContextSwitchTo(), palloc0(), plpgsql_build_datatype(), plpgsql_build_variable(), plpgsql_check_syntax, plpgsql_compile_error_callback(), plpgsql_compile_tmp_cxt, plpgsql_curr_compile, 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().

◆ plpgsql_finish_datums()

static void plpgsql_finish_datums ( PLpgSQL_function function)
static

Definition at line 2330 of file pl_comp.c.

2331 {
2332  Size copiable_size = 0;
2333  int i;
2334 
2335  function->ndatums = plpgsql_nDatums;
2336  function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
2337  for (i = 0; i < plpgsql_nDatums; i++)
2338  {
2339  function->datums[i] = plpgsql_Datums[i];
2340 
2341  /* This must agree with copy_plpgsql_datums on what is copiable */
2342  switch (function->datums[i]->dtype)
2343  {
2344  case PLPGSQL_DTYPE_VAR:
2345  case PLPGSQL_DTYPE_PROMISE:
2346  copiable_size += MAXALIGN(sizeof(PLpgSQL_var));
2347  break;
2348  case PLPGSQL_DTYPE_REC:
2349  copiable_size += MAXALIGN(sizeof(PLpgSQL_rec));
2350  break;
2351  default:
2352  break;
2353  }
2354  }
2355  function->copiable_size = copiable_size;
2356 }
#define MAXALIGN(LEN)
Definition: c.h:811
size_t Size
Definition: c.h:605

References function, i, MAXALIGN, palloc(), plpgsql_Datums, PLPGSQL_DTYPE_PROMISE, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_VAR, and plpgsql_nDatums.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_HashTableDelete()

static void plpgsql_HashTableDelete ( PLpgSQL_function function)
static

Definition at line 2645 of file pl_comp.c.

2646 {
2647  plpgsql_HashEnt *hentry;
2648 
2649  /* do nothing if not in table */
2650  if (function->fn_hashkey == NULL)
2651  return;
2652 
2654  function->fn_hashkey,
2655  HASH_REMOVE,
2656  NULL);
2657  if (hentry == NULL)
2658  elog(WARNING, "trying to delete function that does not exist");
2659 
2660  /* remove back link, which no longer points to allocated storage */
2661  function->fn_hashkey = NULL;
2662 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
#define WARNING
Definition: elog.h:36
@ HASH_REMOVE
Definition: hsearch.h:115
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:62

References elog, function, HASH_REMOVE, hash_search(), plpgsql_HashTable, and WARNING.

Referenced by delete_function().

◆ plpgsql_HashTableInit()

void plpgsql_HashTableInit ( void  )

Definition at line 2595 of file pl_comp.c.

2596 {
2597  HASHCTL ctl;
2598 
2599  /* don't allow double-initialization */
2600  Assert(plpgsql_HashTable == NULL);
2601 
2602  ctl.keysize = sizeof(PLpgSQL_func_hashkey);
2603  ctl.entrysize = sizeof(plpgsql_HashEnt);
2604  plpgsql_HashTable = hash_create("PLpgSQL function hash",
2606  &ctl,
2607  HASH_ELEM | HASH_BLOBS);
2608 }
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
#define FUNCS_PER_USER
Definition: pl_comp.c:70
struct plpgsql_hashent plpgsql_HashEnt
struct PLpgSQL_func_hashkey PLpgSQL_func_hashkey
tree ctl
Definition: radixtree.h:1847

References Assert, ctl, FUNCS_PER_USER, HASH_BLOBS, hash_create(), HASH_ELEM, and plpgsql_HashTable.

Referenced by _PG_init().

◆ plpgsql_HashTableInsert()

static void plpgsql_HashTableInsert ( PLpgSQL_function function,
PLpgSQL_func_hashkey func_key 
)
static

Definition at line 2626 of file pl_comp.c.

2628 {
2629  plpgsql_HashEnt *hentry;
2630  bool found;
2631 
2633  func_key,
2634  HASH_ENTER,
2635  &found);
2636  if (found)
2637  elog(WARNING, "trying to insert a function that already exists");
2638 
2639  hentry->function = function;
2640  /* prepare back link from function to hashtable key */
2641  function->fn_hashkey = &hentry->key;
2642 }
@ HASH_ENTER
Definition: hsearch.h:114
PLpgSQL_func_hashkey * fn_hashkey
Definition: plpgsql.h:974
PLpgSQL_function * function
Definition: pl_comp.c:67
PLpgSQL_func_hashkey key
Definition: pl_comp.c:66

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

Referenced by do_compile().

◆ plpgsql_HashTableLookup()

static PLpgSQL_function * plpgsql_HashTableLookup ( PLpgSQL_func_hashkey func_key)
static

Definition at line 2611 of file pl_comp.c.

2612 {
2613  plpgsql_HashEnt *hentry;
2614 
2616  func_key,
2617  HASH_FIND,
2618  NULL);
2619  if (hentry)
2620  return hentry->function;
2621  else
2622  return NULL;
2623 }
@ HASH_FIND
Definition: hsearch.h:113

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

Referenced by plpgsql_compile().

◆ plpgsql_param_ref()

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

Definition at line 1148 of file pl_comp.c.

1149 {
1150  PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1151  char pname[32];
1152  PLpgSQL_nsitem *nse;
1153 
1154  snprintf(pname, sizeof(pname), "$%d", pref->number);
1155 
1156  nse = plpgsql_ns_lookup(expr->ns, false,
1157  pname, NULL, NULL,
1158  NULL);
1159 
1160  if (nse == NULL)
1161  return NULL; /* name not known to plpgsql */
1162 
1163  return make_datum_param(expr, nse->itemno, pref->location);
1164 }
static Node * make_datum_param(PLpgSQL_expr *expr, int dno, int location)
Definition: pl_comp.c:1333
struct PLpgSQL_nsitem * ns
Definition: plpgsql.h:229
ParseLoc location
Definition: parsenodes.h:305
int number
Definition: parsenodes.h:304
void * p_ref_hook_state
Definition: parse_node.h:239

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().

◆ plpgsql_parse_cwordrowtype()

PLpgSQL_type* plpgsql_parse_cwordrowtype ( List idents)

Definition at line 1796 of file pl_comp.c.

1797 {
1798  Oid classOid;
1799  Oid typOid;
1800  RangeVar *relvar;
1801  MemoryContext oldCxt;
1802 
1803  /*
1804  * As above, this is a relation lookup but could be a type lookup if we
1805  * weren't being backwards-compatible about error wording.
1806  */
1807 
1808  /* Avoid memory leaks in long-term function context */
1810 
1811  /* Look up relation name. Can't lock it - we might not have privileges. */
1812  relvar = makeRangeVarFromNameList(idents);
1813  classOid = RangeVarGetRelid(relvar, NoLock, false);
1814 
1815  /* Some relkinds lack type OIDs */
1816  typOid = get_rel_type_id(classOid);
1817  if (!OidIsValid(typOid))
1818  ereport(ERROR,
1819  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1820  errmsg("relation \"%s\" does not have a composite type",
1821  relvar->relname)));
1822 
1823  MemoryContextSwitchTo(oldCxt);
1824 
1825  /* Build and return the row type struct */
1826  return plpgsql_build_datatype(typOid, -1, InvalidOid,
1827  makeTypeNameFromNameList(idents));
1828 }
#define NoLock
Definition: lockdefs.h:34
Oid get_rel_type_id(Oid relid)
Definition: lsyscache.c:1979
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:458
RangeVar * makeRangeVarFromNameList(const List *names)
Definition: namespace.c:3539
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:80
char * relname
Definition: primnodes.h:82

References ereport, errcode(), errmsg(), ERROR, get_rel_type_id(), InvalidOid, makeRangeVarFromNameList(), makeTypeNameFromNameList(), MemoryContextSwitchTo(), NoLock, OidIsValid, plpgsql_build_datatype(), plpgsql_compile_tmp_cxt, RangeVarGetRelid, and RangeVar::relname.

◆ plpgsql_parse_cwordtype()

PLpgSQL_type* plpgsql_parse_cwordtype ( List idents)

Definition at line 1647 of file pl_comp.c.

1648 {
1649  PLpgSQL_type *dtype = NULL;
1650  PLpgSQL_nsitem *nse;
1651  int nnames;
1652  RangeVar *relvar = NULL;
1653  const char *fldname = NULL;
1654  Oid classOid;
1655  HeapTuple attrtup = NULL;
1656  HeapTuple typetup = NULL;
1657  Form_pg_attribute attrStruct;
1658  MemoryContext oldCxt;
1659 
1660  /* Avoid memory leaks in the long-term function context */
1662 
1663  if (list_length(idents) == 2)
1664  {
1665  /*
1666  * Do a lookup in the current namespace stack
1667  */
1668  nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1669  strVal(linitial(idents)),
1670  strVal(lsecond(idents)),
1671  NULL,
1672  &nnames);
1673 
1674  if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_VAR)
1675  {
1676  /* Block-qualified reference to scalar variable. */
1677  dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1678  goto done;
1679  }
1680  else if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_REC &&
1681  nnames == 2)
1682  {
1683  /* Block-qualified reference to record variable. */
1684  dtype = ((PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]))->datatype;
1685  goto done;
1686  }
1687 
1688  /*
1689  * First word could also be a table name
1690  */
1691  relvar = makeRangeVar(NULL,
1692  strVal(linitial(idents)),
1693  -1);
1694  fldname = strVal(lsecond(idents));
1695  }
1696  else
1697  {
1698  /*
1699  * We could check for a block-qualified reference to a field of a
1700  * record variable, but %TYPE is documented as applying to variables,
1701  * not fields of variables. Things would get rather ambiguous if we
1702  * allowed either interpretation.
1703  */
1704  List *rvnames;
1705 
1706  Assert(list_length(idents) > 2);
1707  rvnames = list_delete_last(list_copy(idents));
1708  relvar = makeRangeVarFromNameList(rvnames);
1709  fldname = strVal(llast(idents));
1710  }
1711 
1712  /* Look up relation name. Can't lock it - we might not have privileges. */
1713  classOid = RangeVarGetRelid(relvar, NoLock, false);
1714 
1715  /*
1716  * Fetch the named table field and its type
1717  */
1718  attrtup = SearchSysCacheAttName(classOid, fldname);
1719  if (!HeapTupleIsValid(attrtup))
1720  ereport(ERROR,
1721  (errcode(ERRCODE_UNDEFINED_COLUMN),
1722  errmsg("column \"%s\" of relation \"%s\" does not exist",
1723  fldname, relvar->relname)));
1724  attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1725 
1726  typetup = SearchSysCache1(TYPEOID,
1727  ObjectIdGetDatum(attrStruct->atttypid));
1728  if (!HeapTupleIsValid(typetup))
1729  elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1730 
1731  /*
1732  * Found that - build a compiler type struct in the caller's cxt and
1733  * return it. Note that we treat the type as being found-by-OID; no
1734  * attempt to re-look-up the type name will happen during invalidations.
1735  */
1736  MemoryContextSwitchTo(oldCxt);
1737  dtype = build_datatype(typetup,
1738  attrStruct->atttypmod,
1739  attrStruct->attcollation,
1740  NULL);
1742 
1743 done:
1744  if (HeapTupleIsValid(attrtup))
1745  ReleaseSysCache(attrtup);
1746  if (HeapTupleIsValid(typetup))
1747  ReleaseSysCache(typetup);
1748 
1749  MemoryContextSwitchTo(oldCxt);
1750  return dtype;
1751 }
List * list_copy(const List *oldlist)
Definition: list.c:1573
List * list_delete_last(List *list)
Definition: list.c:957
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:424
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
Definition: pg_list.h:54
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:439
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:359
#define strVal(v)
Definition: value.h:82

References Assert, build_datatype(), elog, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, PLpgSQL_nsitem::itemno, PLpgSQL_nsitem::itemtype, linitial, list_copy(), list_delete_last(), list_length(), llast, lsecond, makeRangeVar(), makeRangeVarFromNameList(), MemoryContextSwitchTo(), NoLock, ObjectIdGetDatum(), plpgsql_compile_tmp_cxt, plpgsql_Datums, plpgsql_ns_lookup(), plpgsql_ns_top(), PLPGSQL_NSTYPE_REC, PLPGSQL_NSTYPE_VAR, RangeVarGetRelid, ReleaseSysCache(), RangeVar::relname, SearchSysCache1(), SearchSysCacheAttName(), and strVal.

◆ plpgsql_parse_dblword()

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

Definition at line 1441 of file pl_comp.c.

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

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_Datums, plpgsql_IdentifierLookup, plpgsql_ns_lookup(), plpgsql_ns_top(), PLPGSQL_NSTYPE_REC, PLPGSQL_NSTYPE_VAR, and PLwdatum::quoted.

Referenced by plpgsql_yylex().

◆ plpgsql_parse_err_condition()

PLpgSQL_condition* plpgsql_parse_err_condition ( char *  condname)

Definition at line 2245 of file pl_comp.c.

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

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

◆ plpgsql_parse_tripword()

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

Definition at line 1522 of file pl_comp.c.

1524 {
1525  PLpgSQL_nsitem *ns;
1526  List *idents;
1527  int nnames;
1528 
1529  /*
1530  * We should do nothing in DECLARE sections. In SQL expressions, we need
1531  * to make sure that RECFIELD datums are created when needed, and we need
1532  * to be careful about how many names are reported as belonging to the
1533  * T_DATUM: the third word could be a sub-field reference, which we don't
1534  * care about here.
1535  */
1537  {
1538  /*
1539  * Do a lookup in the current namespace stack. Must find a record
1540  * reference, else ignore.
1541  */
1542  ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1543  word1, word2, word3,
1544  &nnames);
1545  if (ns != NULL)
1546  {
1547  switch (ns->itemtype)
1548  {
1549  case PLPGSQL_NSTYPE_REC:
1550  {
1551  PLpgSQL_rec *rec;
1552  PLpgSQL_recfield *new;
1553 
1554  rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
1555  if (nnames == 1)
1556  {
1557  /*
1558  * First word is a record name, so second word
1559  * could be a field in this record (and the third,
1560  * a sub-field). We build a RECFIELD datum
1561  * whether it is or not --- any error will be
1562  * detected later.
1563  */
1564  new = plpgsql_build_recfield(rec, word2);
1565  idents = list_make2(makeString(word1),
1566  makeString(word2));
1567  }
1568  else
1569  {
1570  /* Block-qualified reference to record variable. */
1571  new = plpgsql_build_recfield(rec, word3);
1572  idents = list_make3(makeString(word1),
1573  makeString(word2),
1574  makeString(word3));
1575  }
1576  wdatum->datum = (PLpgSQL_datum *) new;
1577  wdatum->ident = NULL;
1578  wdatum->quoted = false; /* not used */
1579  wdatum->idents = idents;
1580  return true;
1581  }
1582 
1583  default:
1584  break;
1585  }
1586  }
1587  }
1588 
1589  /* Nothing found */
1590  idents = list_make3(makeString(word1),
1591  makeString(word2),
1592  makeString(word3));
1593  cword->idents = idents;
1594  return false;
1595 }
#define list_make3(x1, x2, x3)
Definition: pg_list.h:216

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

Referenced by plpgsql_yylex().

◆ plpgsql_parse_word()

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

Definition at line 1386 of file pl_comp.c.

1388 {
1389  PLpgSQL_nsitem *ns;
1390 
1391  /*
1392  * We should not lookup variables in DECLARE sections. In SQL
1393  * expressions, there's no need to do so either --- lookup will happen
1394  * when the expression is compiled.
1395  */
1397  {
1398  /*
1399  * Do a lookup in the current namespace stack
1400  */
1401  ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1402  word1, NULL, NULL,
1403  NULL);
1404 
1405  if (ns != NULL)
1406  {
1407  switch (ns->itemtype)
1408  {
1409  case PLPGSQL_NSTYPE_VAR:
1410  case PLPGSQL_NSTYPE_REC:
1411  wdatum->datum = plpgsql_Datums[ns->itemno];
1412  wdatum->ident = word1;
1413  wdatum->quoted = (yytxt[0] == '"');
1414  wdatum->idents = NIL;
1415  return true;
1416 
1417  default:
1418  /* plpgsql_ns_lookup should never return anything else */
1419  elog(ERROR, "unrecognized plpgsql itemtype: %d",
1420  ns->itemtype);
1421  }
1422  }
1423  }
1424 
1425  /*
1426  * Nothing found - up to now it's a word without any special meaning for
1427  * us.
1428  */
1429  word->ident = word1;
1430  word->quoted = (yytxt[0] == '"');
1431  return false;
1432 }
@ IDENTIFIER_LOOKUP_NORMAL
Definition: plpgsql.h:1189
static void word(struct vars *v, int dir, struct state *lp, struct state *rp)
Definition: regcomp.c:1474
Definition: zic.c:304

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

Referenced by plpgsql_yylex().

◆ plpgsql_parse_wordrowtype()

PLpgSQL_type* plpgsql_parse_wordrowtype ( char *  ident)

Definition at line 1759 of file pl_comp.c.

1760 {
1761  Oid classOid;
1762  Oid typOid;
1763 
1764  /*
1765  * Look up the relation. Note that because relation rowtypes have the
1766  * same names as their relations, this could be handled as a type lookup
1767  * equally well; we use the relation lookup code path only because the
1768  * errors thrown here have traditionally referred to relations not types.
1769  * But we'll make a TypeName in case we have to do re-look-up of the type.
1770  */
1771  classOid = RelnameGetRelid(ident);
1772  if (!OidIsValid(classOid))
1773  ereport(ERROR,
1775  errmsg("relation \"%s\" does not exist", ident)));
1776 
1777  /* Some relkinds lack type OIDs */
1778  typOid = get_rel_type_id(classOid);
1779  if (!OidIsValid(typOid))
1780  ereport(ERROR,
1781  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1782  errmsg("relation \"%s\" does not have a composite type",
1783  ident)));
1784 
1785  /* Build and return the row type struct */
1786  return plpgsql_build_datatype(typOid, -1, InvalidOid,
1787  makeTypeName(ident));
1788 }
#define ident
Definition: indent_codes.h:47
TypeName * makeTypeName(char *typnam)
Definition: makefuncs.c:446
Oid RelnameGetRelid(const char *relname)
Definition: namespace.c:870
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:78

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

◆ plpgsql_parse_wordtype()

PLpgSQL_type* plpgsql_parse_wordtype ( char *  ident)

Definition at line 1606 of file pl_comp.c.

1607 {
1608  PLpgSQL_nsitem *nse;
1609 
1610  /*
1611  * Do a lookup in the current namespace stack
1612  */
1613  nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1614  ident, NULL, NULL,
1615  NULL);
1616 
1617  if (nse != NULL)
1618  {
1619  switch (nse->itemtype)
1620  {
1621  case PLPGSQL_NSTYPE_VAR:
1622  return ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1623  case PLPGSQL_NSTYPE_REC:
1624  return ((PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]))->datatype;
1625  default:
1626  break;
1627  }
1628  }
1629 
1630  /* No match, complain */
1631  ereport(ERROR,
1632  (errcode(ERRCODE_UNDEFINED_OBJECT),
1633  errmsg("variable \"%s\" does not exist", ident)));
1634  return NULL; /* keep compiler quiet */
1635 }

References ereport, errcode(), errmsg(), ERROR, ident, PLpgSQL_nsitem::itemno, PLpgSQL_nsitem::itemtype, plpgsql_Datums, plpgsql_ns_lookup(), plpgsql_ns_top(), PLPGSQL_NSTYPE_REC, and PLPGSQL_NSTYPE_VAR.

◆ plpgsql_parser_setup()

void plpgsql_parser_setup ( struct ParseState pstate,
PLpgSQL_expr expr 
)

Definition at line 1077 of file pl_comp.c.

1078 {
1082  /* no need to use p_coerce_param_hook */
1083  pstate->p_ref_hook_state = (void *) expr;
1084 }
static Node * plpgsql_param_ref(ParseState *pstate, ParamRef *pref)
Definition: pl_comp.c:1148
static Node * plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref)
Definition: pl_comp.c:1090
static Node * plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
Definition: pl_comp.c:1104
ParseParamRefHook p_paramref_hook
Definition: parse_node.h:237
PreParseColumnRefHook p_pre_columnref_hook
Definition: parse_node.h:235
PostParseColumnRefHook p_post_columnref_hook
Definition: parse_node.h:236

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().

◆ plpgsql_post_column_ref()

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

Definition at line 1104 of file pl_comp.c.

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

References ereport, errcode(), errdetail(), errmsg(), ERROR, ColumnRef::fields, PLpgSQL_expr::func, if(), 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().

◆ plpgsql_pre_column_ref()

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

Definition at line 1090 of file pl_comp.c.

1091 {
1092  PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1093 
1095  return resolve_column_ref(pstate, expr, cref, false);
1096  else
1097  return NULL;
1098 }

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

Referenced by plpgsql_parser_setup().

◆ plpgsql_recognize_err_condition()

int plpgsql_recognize_err_condition ( const char *  condname,
bool  allow_sqlstate 
)

Definition at line 2209 of file pl_comp.c.

2210 {
2211  int i;
2212 
2213  if (allow_sqlstate)
2214  {
2215  if (strlen(condname) == 5 &&
2216  strspn(condname, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") == 5)
2217  return MAKE_SQLSTATE(condname[0],
2218  condname[1],
2219  condname[2],
2220  condname[3],
2221  condname[4]);
2222  }
2223 
2224  for (i = 0; exception_label_map[i].label != NULL; i++)
2225  {
2226  if (strcmp(condname, exception_label_map[i].label) == 0)
2228  }
2229 
2230  ereport(ERROR,
2231  (errcode(ERRCODE_UNDEFINED_OBJECT),
2232  errmsg("unrecognized exception condition \"%s\"",
2233  condname)));
2234  return 0; /* keep compiler quiet */
2235 }
#define MAKE_SQLSTATE(ch1, ch2, ch3, ch4, ch5)
Definition: elog.h:56

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

Referenced by exec_stmt_raise().

◆ 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 2498 of file pl_comp.c.

2502 {
2503  int i;
2504 
2505  if (!forValidator)
2506  {
2507  int inargno;
2508 
2509  /* normal case, pass to standard routine */
2510  if (!resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
2511  call_expr))
2512  ereport(ERROR,
2513  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2514  errmsg("could not determine actual argument "
2515  "type for polymorphic function \"%s\"",
2516  proname)));
2517  /* also, treat RECORD inputs (but not outputs) as polymorphic */
2518  inargno = 0;
2519  for (i = 0; i < numargs; i++)
2520  {
2521  char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
2522 
2523  if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE)
2524  continue;
2525  if (argtypes[i] == RECORDOID || argtypes[i] == RECORDARRAYOID)
2526  {
2527  Oid resolvedtype = get_call_expr_argtype(call_expr,
2528  inargno);
2529 
2530  if (OidIsValid(resolvedtype))
2531  argtypes[i] = resolvedtype;
2532  }
2533  inargno++;
2534  }
2535  }
2536  else
2537  {
2538  /* special validation case (no need to do anything for RECORD) */
2539  for (i = 0; i < numargs; i++)
2540  {
2541  switch (argtypes[i])
2542  {
2543  case ANYELEMENTOID:
2544  case ANYNONARRAYOID:
2545  case ANYENUMOID: /* XXX dubious */
2546  case ANYCOMPATIBLEOID:
2547  case ANYCOMPATIBLENONARRAYOID:
2548  argtypes[i] = INT4OID;
2549  break;
2550  case ANYARRAYOID:
2551  case ANYCOMPATIBLEARRAYOID:
2552  argtypes[i] = INT4ARRAYOID;
2553  break;
2554  case ANYRANGEOID:
2555  case ANYCOMPATIBLERANGEOID:
2556  argtypes[i] = INT4RANGEOID;
2557  break;
2558  case ANYMULTIRANGEOID:
2559  argtypes[i] = INT4MULTIRANGEOID;
2560  break;
2561  default:
2562  break;
2563  }
2564  }
2565  }
2566 }
Oid get_call_expr_argtype(Node *expr, int argnum)
Definition: fmgr.c:1929
bool resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, Node *call_expr)
Definition: funcapi.c:1064
NameData proname
Definition: pg_proc.h:35

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

Referenced by compute_function_hashkey(), and do_compile().

◆ plpgsql_start_datums()

static void plpgsql_start_datums ( void  )
static

Definition at line 2296 of file pl_comp.c.

2297 {
2298  datums_alloc = 128;
2299  plpgsql_nDatums = 0;
2300  /* This is short-lived, so needn't allocate in function's cxt */
2302  sizeof(PLpgSQL_datum *) * datums_alloc);
2303  /* datums_last tracks what's been seen by plpgsql_add_initdatums() */
2304  datums_last = 0;
2305 }
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1180

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

Referenced by do_compile(), and plpgsql_compile_inline().

◆ resolve_column_ref()

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

Definition at line 1175 of file pl_comp.c.

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

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, strVal, and while().

Referenced by plpgsql_post_column_ref(), and plpgsql_pre_column_ref().

Variable Documentation

◆ datums_alloc

int datums_alloc
static

Definition at line 44 of file pl_comp.c.

Referenced by plpgsql_adddatum(), and plpgsql_start_datums().

◆ datums_last

int datums_last
static

Definition at line 47 of file pl_comp.c.

Referenced by plpgsql_add_initdatums(), and plpgsql_start_datums().

◆ exception_label_map

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

Definition at line 82 of file pl_comp.c.

Referenced by plpgsql_parse_err_condition(), and plpgsql_recognize_err_condition().

◆ plpgsql_check_syntax

bool plpgsql_check_syntax = false

Definition at line 51 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_compile_tmp_cxt

◆ plpgsql_curr_compile

PLpgSQL_function* plpgsql_curr_compile

Definition at line 53 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_Datums

◆ plpgsql_DumpExecTree

bool plpgsql_DumpExecTree = false

Definition at line 50 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_error_funcname

char* plpgsql_error_funcname

Definition at line 49 of file pl_comp.c.

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

◆ plpgsql_HashTable

HTAB* plpgsql_HashTable = NULL
static

◆ plpgsql_nDatums

int plpgsql_nDatums

◆ plpgsql_parse_result

PLpgSQL_stmt_block* plpgsql_parse_result

Definition at line 42 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().