PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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_node.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/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 69 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 1031 of file pl_comp.c.

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

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

2067 {
2068  Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
2069  PLpgSQL_type *typ;
2070 
2071  if (!typeStruct->typisdefined)
2072  ereport(ERROR,
2073  (errcode(ERRCODE_UNDEFINED_OBJECT),
2074  errmsg("type \"%s\" is only a shell",
2075  NameStr(typeStruct->typname))));
2076 
2077  typ = (PLpgSQL_type *) palloc(sizeof(PLpgSQL_type));
2078 
2079  typ->typname = pstrdup(NameStr(typeStruct->typname));
2080  typ->typoid = typeStruct->oid;
2081  switch (typeStruct->typtype)
2082  {
2083  case TYPTYPE_BASE:
2084  case TYPTYPE_ENUM:
2085  case TYPTYPE_RANGE:
2086  case TYPTYPE_MULTIRANGE:
2087  typ->ttype = PLPGSQL_TTYPE_SCALAR;
2088  break;
2089  case TYPTYPE_COMPOSITE:
2090  typ->ttype = PLPGSQL_TTYPE_REC;
2091  break;
2092  case TYPTYPE_DOMAIN:
2093  if (type_is_rowtype(typeStruct->typbasetype))
2094  typ->ttype = PLPGSQL_TTYPE_REC;
2095  else
2096  typ->ttype = PLPGSQL_TTYPE_SCALAR;
2097  break;
2098  case TYPTYPE_PSEUDO:
2099  if (typ->typoid == RECORDOID)
2100  typ->ttype = PLPGSQL_TTYPE_REC;
2101  else
2102  typ->ttype = PLPGSQL_TTYPE_PSEUDO;
2103  break;
2104  default:
2105  elog(ERROR, "unrecognized typtype: %d",
2106  (int) typeStruct->typtype);
2107  break;
2108  }
2109  typ->typlen = typeStruct->typlen;
2110  typ->typbyval = typeStruct->typbyval;
2111  typ->typtype = typeStruct->typtype;
2112  typ->collation = typeStruct->typcollation;
2113  if (OidIsValid(collation) && OidIsValid(typ->collation))
2114  typ->collation = collation;
2115  /* Detect if type is true array, or domain thereof */
2116  /* NB: this is only used to decide whether to apply expand_array */
2117  if (typeStruct->typtype == TYPTYPE_BASE)
2118  {
2119  /*
2120  * This test should include what get_element_type() checks. We also
2121  * disallow non-toastable array types (i.e. oidvector and int2vector).
2122  */
2123  typ->typisarray = (IsTrueArrayType(typeStruct) &&
2124  typeStruct->typstorage != TYPSTORAGE_PLAIN);
2125  }
2126  else if (typeStruct->typtype == TYPTYPE_DOMAIN)
2127  {
2128  /* we can short-circuit looking up base types if it's not varlena */
2129  typ->typisarray = (typeStruct->typlen == -1 &&
2130  typeStruct->typstorage != TYPSTORAGE_PLAIN &&
2131  OidIsValid(get_base_element_type(typeStruct->typbasetype)));
2132  }
2133  else
2134  typ->typisarray = false;
2135  typ->atttypmod = typmod;
2136 
2137  /*
2138  * If it's a named composite type (or domain over one), find the typcache
2139  * entry and record the current tupdesc ID, so we can detect changes
2140  * (including drops). We don't currently support on-the-fly replacement
2141  * of non-composite types, else we might want to do this for them too.
2142  */
2143  if (typ->ttype == PLPGSQL_TTYPE_REC && typ->typoid != RECORDOID)
2144  {
2145  TypeCacheEntry *typentry;
2146 
2147  typentry = lookup_type_cache(typ->typoid,
2150  if (typentry->typtype == TYPTYPE_DOMAIN)
2151  typentry = lookup_type_cache(typentry->domainBaseType,
2153  if (typentry->tupDesc == NULL)
2154  ereport(ERROR,
2155  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2156  errmsg("type %s is not composite",
2157  format_type_be(typ->typoid))));
2158 
2159  typ->origtypname = origtypname;
2160  typ->tcache = typentry;
2161  typ->tupdesc_id = typentry->tupDesc_identifier;
2162  }
2163  else
2164  {
2165  typ->origtypname = NULL;
2166  typ->tcache = NULL;
2167  typ->tupdesc_id = 0;
2168  }
2169 
2170  return typ;
2171 }
#define NameStr(name)
Definition: c.h:751
#define OidIsValid(objectId)
Definition: c.h:780
#define elog(elevel,...)
Definition: elog.h:225
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:1696
void * palloc(Size size)
Definition: mcxt.c:1317
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:386
#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 1929 of file pl_comp.c.

1930 {
1931  PLpgSQL_row *row;
1932  int i;
1933 
1934  row = palloc0(sizeof(PLpgSQL_row));
1935  row->dtype = PLPGSQL_DTYPE_ROW;
1936  row->refname = "(unnamed row)";
1937  row->lineno = -1;
1938  row->rowtupdesc = CreateTemplateTupleDesc(numvars);
1939  row->nfields = numvars;
1940  row->fieldnames = palloc(numvars * sizeof(char *));
1941  row->varnos = palloc(numvars * sizeof(int));
1942 
1943  for (i = 0; i < numvars; i++)
1944  {
1945  PLpgSQL_variable *var = vars[i];
1946  Oid typoid;
1947  int32 typmod;
1948  Oid typcoll;
1949 
1950  /* Member vars of a row should never be const */
1951  Assert(!var->isconst);
1952 
1953  switch (var->dtype)
1954  {
1955  case PLPGSQL_DTYPE_VAR:
1956  case PLPGSQL_DTYPE_PROMISE:
1957  typoid = ((PLpgSQL_var *) var)->datatype->typoid;
1958  typmod = ((PLpgSQL_var *) var)->datatype->atttypmod;
1959  typcoll = ((PLpgSQL_var *) var)->datatype->collation;
1960  break;
1961 
1962  case PLPGSQL_DTYPE_REC:
1963  /* shouldn't need to revalidate rectypeid already... */
1964  typoid = ((PLpgSQL_rec *) var)->rectypeid;
1965  typmod = -1; /* don't know typmod, if it's used at all */
1966  typcoll = InvalidOid; /* composite types have no collation */
1967  break;
1968 
1969  default:
1970  elog(ERROR, "unrecognized dtype: %d", var->dtype);
1971  typoid = InvalidOid; /* keep compiler quiet */
1972  typmod = 0;
1973  typcoll = InvalidOid;
1974  break;
1975  }
1976 
1977  row->fieldnames[i] = var->refname;
1978  row->varnos[i] = var->dno;
1979 
1980  TupleDescInitEntry(row->rowtupdesc, i + 1,
1981  var->refname,
1982  typoid, typmod,
1983  0);
1984  TupleDescInitEntryCollation(row->rowtupdesc, i + 1, typcoll);
1985  }
1986 
1987  return row;
1988 }
signed int int32
Definition: c.h:508
#define Assert(condition)
Definition: c.h:863
int i
Definition: isn.c:72
@ 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:282
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 2431 of file pl_comp.c.

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

2583 {
2584  /* remove function from hash table (might be done already) */
2586 
2587  /* release the function's storage if safe and not done already */
2588  if (func->use_count == 0)
2590 }
static void plpgsql_HashTableDelete(PLpgSQL_function *function)
Definition: pl_comp.c:2644
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 263 of file pl_comp.c.

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

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

1333 {
1334  PLpgSQL_execstate *estate;
1335  PLpgSQL_datum *datum;
1336  Param *param;
1337  MemoryContext oldcontext;
1338 
1339  /* see comment in resolve_column_ref */
1340  estate = expr->func->cur_estate;
1341  Assert(dno >= 0 && dno < estate->ndatums);
1342  datum = estate->datums[dno];
1343 
1344  /*
1345  * Bitmapset must be allocated in function's permanent memory context
1346  */
1347  oldcontext = MemoryContextSwitchTo(expr->func->fn_cxt);
1348  expr->paramnos = bms_add_member(expr->paramnos, dno);
1349  MemoryContextSwitchTo(oldcontext);
1350 
1351  param = makeNode(Param);
1352  param->paramkind = PARAM_EXTERN;
1353  param->paramid = dno + 1;
1355  datum,
1356  &param->paramtype,
1357  &param->paramtypmod,
1358  &param->paramcollid);
1359  param->location = location;
1360 
1361  return (Node *) param;
1362 }
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:5542
@ 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 2373 of file pl_comp.c.

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

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

2313 {
2315  {
2316  datums_alloc *= 2;
2318  }
2319 
2320  newdatum->dno = plpgsql_nDatums;
2321  plpgsql_Datums[plpgsql_nDatums++] = newdatum;
2322 }
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541
static int datums_alloc
Definition: pl_comp.c:43

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

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

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

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

1997 {
1998  PLpgSQL_recfield *recfield;
1999  int i;
2000 
2001  /* search for an existing datum referencing this field */
2002  i = rec->firstfield;
2003  while (i >= 0)
2004  {
2006 
2008  fld->recparentno == rec->dno);
2009  if (strcmp(fld->fieldname, fldname) == 0)
2010  return fld;
2011  i = fld->nextfield;
2012  }
2013 
2014  /* nope, so make a new one */
2015  recfield = palloc0(sizeof(PLpgSQL_recfield));
2016  recfield->dtype = PLPGSQL_DTYPE_RECFIELD;
2017  recfield->fieldname = pstrdup(fldname);
2018  recfield->recparentno = rec->dno;
2020 
2021  plpgsql_adddatum((PLpgSQL_datum *) recfield);
2022 
2023  /* now we can link it into the parent's chain */
2024  recfield->nextfield = rec->firstfield;
2025  rec->firstfield = recfield->dno;
2026 
2027  return recfield;
2028 }
@ 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 1902 of file pl_comp.c.

1905 {
1906  PLpgSQL_rec *rec;
1907 
1908  rec = palloc0(sizeof(PLpgSQL_rec));
1909  rec->dtype = PLPGSQL_DTYPE_REC;
1910  rec->refname = pstrdup(refname);
1911  rec->lineno = lineno;
1912  /* other fields are left as 0, might be changed by caller */
1913  rec->datatype = dtype;
1914  rec->rectypeid = rectypeid;
1915  rec->firstfield = -1;
1916  rec->erh = NULL;
1918  if (add2namespace)
1920 
1921  return rec;
1922 }
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 1839 of file pl_comp.c.

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

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

980 {
981  if (arg)
982  {
983  /*
984  * Try to convert syntax error position to reference text of original
985  * CREATE FUNCTION or DO command.
986  */
987  if (function_parse_error_transpose((const char *) arg))
988  return;
989 
990  /*
991  * Done if a syntax error position was reported; otherwise we have to
992  * fall back to a "near line N" report.
993  */
994  }
995 
997  errcontext("compilation of PL/pgSQL function \"%s\" near line %d",
999 }
#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 842 of file pl_comp.c.

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

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

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

2645 {
2646  plpgsql_HashEnt *hentry;
2647 
2648  /* do nothing if not in table */
2649  if (function->fn_hashkey == NULL)
2650  return;
2651 
2653  function->fn_hashkey,
2654  HASH_REMOVE,
2655  NULL);
2656  if (hentry == NULL)
2657  elog(WARNING, "trying to delete function that does not exist");
2658 
2659  /* remove back link, which no longer points to allocated storage */
2660  function->fn_hashkey = NULL;
2661 }
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:61

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

Referenced by delete_function().

◆ plpgsql_HashTableInit()

void plpgsql_HashTableInit ( void  )

Definition at line 2594 of file pl_comp.c.

2595 {
2596  HASHCTL ctl;
2597 
2598  /* don't allow double-initialization */
2599  Assert(plpgsql_HashTable == NULL);
2600 
2601  ctl.keysize = sizeof(PLpgSQL_func_hashkey);
2602  ctl.entrysize = sizeof(plpgsql_HashEnt);
2603  plpgsql_HashTable = hash_create("PLpgSQL function hash",
2605  &ctl,
2606  HASH_ELEM | HASH_BLOBS);
2607 }
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:69
struct plpgsql_hashent plpgsql_HashEnt
struct PLpgSQL_func_hashkey PLpgSQL_func_hashkey
tree ctl
Definition: radixtree.h:1853

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

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

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

2611 {
2612  plpgsql_HashEnt *hentry;
2613 
2615  func_key,
2616  HASH_FIND,
2617  NULL);
2618  if (hentry)
2619  return hentry->function;
2620  else
2621  return NULL;
2622 }
@ 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 1147 of file pl_comp.c.

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

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

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

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

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

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

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

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

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

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

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

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

1077 {
1081  /* no need to use p_coerce_param_hook */
1082  pstate->p_ref_hook_state = (void *) expr;
1083 }
static Node * plpgsql_param_ref(ParseState *pstate, ParamRef *pref)
Definition: pl_comp.c:1147
static Node * plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref)
Definition: pl_comp.c:1089
static Node * plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
Definition: pl_comp.c:1103
ParseParamRefHook p_paramref_hook
Definition: parse_node.h:256
PreParseColumnRefHook p_pre_columnref_hook
Definition: parse_node.h:254
PostParseColumnRefHook p_post_columnref_hook
Definition: parse_node.h:255

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

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

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

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

2209 {
2210  int i;
2211 
2212  if (allow_sqlstate)
2213  {
2214  if (strlen(condname) == 5 &&
2215  strspn(condname, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") == 5)
2216  return MAKE_SQLSTATE(condname[0],
2217  condname[1],
2218  condname[2],
2219  condname[3],
2220  condname[4]);
2221  }
2222 
2223  for (i = 0; exception_label_map[i].label != NULL; i++)
2224  {
2225  if (strcmp(condname, exception_label_map[i].label) == 0)
2227  }
2228 
2229  ereport(ERROR,
2230  (errcode(ERRCODE_UNDEFINED_OBJECT),
2231  errmsg("unrecognized exception condition \"%s\"",
2232  condname)));
2233  return 0; /* keep compiler quiet */
2234 }
#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 2497 of file pl_comp.c.

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

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

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

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

Referenced by plpgsql_adddatum(), and plpgsql_start_datums().

◆ datums_last

int datums_last
static

Definition at line 46 of file pl_comp.c.

Referenced by plpgsql_add_initdatums(), and plpgsql_start_datums().

◆ exception_label_map

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

Definition at line 81 of file pl_comp.c.

Referenced by plpgsql_parse_err_condition(), and plpgsql_recognize_err_condition().

◆ plpgsql_check_syntax

bool plpgsql_check_syntax = false

Definition at line 50 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_compile_tmp_cxt

◆ plpgsql_curr_compile

PLpgSQL_function* plpgsql_curr_compile

Definition at line 52 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_Datums

◆ plpgsql_DumpExecTree

bool plpgsql_DumpExecTree = false

Definition at line 49 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_error_funcname

char* plpgsql_error_funcname

Definition at line 48 of file pl_comp.c.

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

◆ plpgsql_HashTable

HTAB* plpgsql_HashTable = NULL
static

◆ plpgsql_nDatums

int plpgsql_nDatums

◆ plpgsql_parse_result

PLpgSQL_stmt_block* plpgsql_parse_result

Definition at line 41 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().