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

Go to the source code of this file.

Data Structures

struct  plpgsql_hashent
 
struct  ExceptionLabelMap
 

Macros

#define FUNCS_PER_USER   128 /* initial table size */
 

Typedefs

typedef struct plpgsql_hashent plpgsql_HashEnt
 

Functions

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

Variables

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

Macro Definition Documentation

◆ FUNCS_PER_USER

#define FUNCS_PER_USER   128 /* initial table size */

Definition at line 69 of file pl_comp.c.

Referenced by plpgsql_HashTableInit().

Typedef Documentation

◆ plpgsql_HashEnt

Function Documentation

◆ add_dummy_return()

static void add_dummy_return ( PLpgSQL_function function)
static

Definition at line 1029 of file pl_comp.c.

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

Referenced by do_compile(), and plpgsql_compile_inline().

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

◆ add_parameter_name()

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

Definition at line 1004 of file pl_comp.c.

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

Referenced by do_compile().

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

◆ build_datatype()

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

Definition at line 2069 of file pl_comp.c.

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

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

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

◆ build_row_from_vars()

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

Definition at line 1933 of file pl_comp.c.

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

Referenced by do_compile().

1934 {
1935  PLpgSQL_row *row;
1936  int i;
1937 
1938  row = palloc0(sizeof(PLpgSQL_row));
1939  row->dtype = PLPGSQL_DTYPE_ROW;
1940  row->refname = "(unnamed row)";
1941  row->lineno = -1;
1942  row->rowtupdesc = CreateTemplateTupleDesc(numvars);
1943  row->nfields = numvars;
1944  row->fieldnames = palloc(numvars * sizeof(char *));
1945  row->varnos = palloc(numvars * sizeof(int));
1946 
1947  for (i = 0; i < numvars; i++)
1948  {
1949  PLpgSQL_variable *var = vars[i];
1950  Oid typoid;
1951  int32 typmod;
1952  Oid typcoll;
1953 
1954  /* Member vars of a row should never be const */
1955  Assert(!var->isconst);
1956 
1957  switch (var->dtype)
1958  {
1959  case PLPGSQL_DTYPE_VAR:
1960  case PLPGSQL_DTYPE_PROMISE:
1961  typoid = ((PLpgSQL_var *) var)->datatype->typoid;
1962  typmod = ((PLpgSQL_var *) var)->datatype->atttypmod;
1963  typcoll = ((PLpgSQL_var *) var)->datatype->collation;
1964  break;
1965 
1966  case PLPGSQL_DTYPE_REC:
1967  /* shouldn't need to revalidate rectypeid already... */
1968  typoid = ((PLpgSQL_rec *) var)->rectypeid;
1969  typmod = -1; /* don't know typmod, if it's used at all */
1970  typcoll = InvalidOid; /* composite types have no collation */
1971  break;
1972 
1973  default:
1974  elog(ERROR, "unrecognized dtype: %d", var->dtype);
1975  typoid = InvalidOid; /* keep compiler quiet */
1976  typmod = 0;
1977  typcoll = InvalidOid;
1978  break;
1979  }
1980 
1981  row->fieldnames[i] = var->refname;
1982  row->varnos[i] = var->dno;
1983 
1984  TupleDescInitEntry(row->rowtupdesc, i + 1,
1985  var->refname,
1986  typoid, typmod,
1987  0);
1988  TupleDescInitEntryCollation(row->rowtupdesc, i + 1, typcoll);
1989  }
1990 
1991  return row;
1992 }
char * refname
Definition: plpgsql.h:348
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:44
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:347
#define ERROR
Definition: elog.h:43
char ** fieldnames
Definition: plpgsql.h:363
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition: tupdesc.c:769
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:603
int * varnos
Definition: plpgsql.h:364
void * palloc0(Size size)
Definition: mcxt.c:980
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:739
int nfields
Definition: plpgsql.h:362
char * refname
Definition: plpgsql.h:272
PLpgSQL_datum_type dtype
Definition: plpgsql.h:270
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:228
int i
TupleDesc rowtupdesc
Definition: plpgsql.h:360
PLpgSQL_datum_type dtype
Definition: plpgsql.h:346
int lineno
Definition: plpgsql.h:349

◆ compute_function_hashkey()

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

Definition at line 2408 of file pl_comp.c.

References PLpgSQL_func_hashkey::argtypes, 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::isTrigger, MemSet, NameStr, plpgsql_resolve_polymorphic_argtypes(), TriggerData::tg_trigger, Trigger::tgoid, and PLpgSQL_func_hashkey::trigOid.

Referenced by plpgsql_compile().

2412 {
2413  /* Make sure any unused bytes of the struct are zero */
2414  MemSet(hashkey, 0, sizeof(PLpgSQL_func_hashkey));
2415 
2416  /* get function OID */
2417  hashkey->funcOid = fcinfo->flinfo->fn_oid;
2418 
2419  /* get call context */
2420  hashkey->isTrigger = CALLED_AS_TRIGGER(fcinfo);
2421 
2422  /*
2423  * if trigger, get its OID. In validation mode we do not know what
2424  * relation or transition table names are intended to be used, so we leave
2425  * trigOid zero; the hash entry built in this case will never really be
2426  * used.
2427  */
2428  if (hashkey->isTrigger && !forValidator)
2429  {
2430  TriggerData *trigdata = (TriggerData *) fcinfo->context;
2431 
2432  hashkey->trigOid = trigdata->tg_trigger->tgoid;
2433  }
2434 
2435  /* get input collation, if known */
2436  hashkey->inputCollation = fcinfo->fncollation;
2437 
2438  if (procStruct->pronargs > 0)
2439  {
2440  /* get the argument types */
2441  memcpy(hashkey->argtypes, procStruct->proargtypes.values,
2442  procStruct->pronargs * sizeof(Oid));
2443 
2444  /* resolve any polymorphic argument types */
2445  plpgsql_resolve_polymorphic_argtypes(procStruct->pronargs,
2446  hashkey->argtypes,
2447  NULL,
2448  fcinfo->flinfo->fn_expr,
2449  forValidator,
2450  NameStr(procStruct->proname));
2451  }
2452 }
Oid argtypes[FUNC_MAX_ARGS]
Definition: plpgsql.h:965
Oid tgoid
Definition: reltrigger.h:25
#define MemSet(start, val, len)
Definition: c.h:962
fmNodePtr context
Definition: fmgr.h:88
unsigned int Oid
Definition: postgres_ext.h:31
static void plpgsql_resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, Node *call_expr, bool forValidator, const char *proname)
Definition: pl_comp.c:2461
FmgrInfo * flinfo
Definition: fmgr.h:87
Trigger * tg_trigger
Definition: trigger.h:37
Oid fn_oid
Definition: fmgr.h:59
#define CALLED_AS_TRIGGER(fcinfo)
Definition: trigger.h:25
fmNodePtr fn_expr
Definition: fmgr.h:66
#define NameStr(name)
Definition: c.h:616

◆ delete_function()

static void delete_function ( PLpgSQL_function func)
static

Definition at line 2519 of file pl_comp.c.

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

Referenced by plpgsql_compile().

2520 {
2521  /* remove function from hash table (might be done already) */
2523 
2524  /* release the function's storage if safe and not done already */
2525  if (func->use_count == 0)
2527 }
void plpgsql_free_function_memory(PLpgSQL_function *func)
Definition: pl_funcs.c:737
unsigned long use_count
Definition: plpgsql.h:1029
static void plpgsql_HashTableDelete(PLpgSQL_function *function)
Definition: pl_comp.c:2582

◆ do_compile()

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

Definition at line 263 of file pl_comp.c.

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

Referenced by plpgsql_compile().

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

◆ make_datum_param()

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

Definition at line 1334 of file pl_comp.c.

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

Referenced by plpgsql_param_ref(), and resolve_column_ref().

1335 {
1336  PLpgSQL_execstate *estate;
1337  PLpgSQL_datum *datum;
1338  Param *param;
1339  MemoryContext oldcontext;
1340 
1341  /* see comment in resolve_column_ref */
1342  estate = expr->func->cur_estate;
1343  Assert(dno >= 0 && dno < estate->ndatums);
1344  datum = estate->datums[dno];
1345 
1346  /*
1347  * Bitmapset must be allocated in function's permanent memory context
1348  */
1349  oldcontext = MemoryContextSwitchTo(expr->func->fn_cxt);
1350  expr->paramnos = bms_add_member(expr->paramnos, dno);
1351  MemoryContextSwitchTo(oldcontext);
1352 
1353  param = makeNode(Param);
1354  param->paramkind = PARAM_EXTERN;
1355  param->paramid = dno + 1;
1357  datum,
1358  &param->paramtype,
1359  &param->paramtypmod,
1360  &param->paramcollid);
1361  param->location = location;
1362 
1363  return (Node *) param;
1364 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ParamKind paramkind
Definition: primnodes.h:248
Definition: nodes.h:525
PLpgSQL_datum ** datums
Definition: plpgsql.h:1072
Bitmapset * paramnos
Definition: plpgsql.h:223
struct PLpgSQL_execstate * cur_estate
Definition: plpgsql.h:1028
Oid paramcollid
Definition: primnodes.h:252
int location
Definition: primnodes.h:253
MemoryContext fn_cxt
Definition: plpgsql.h:990
void plpgsql_exec_get_datum_type_info(PLpgSQL_execstate *estate, PLpgSQL_datum *datum, Oid *typeId, int32 *typMod, Oid *collation)
Definition: pl_exec.c:5608
struct PLpgSQL_function * func
Definition: plpgsql.h:227
int32 paramtypmod
Definition: primnodes.h:251
#define makeNode(_type_)
Definition: nodes.h:573
#define Assert(condition)
Definition: c.h:739
int paramid
Definition: primnodes.h:249
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
Oid paramtype
Definition: primnodes.h:250

◆ plpgsql_add_initdatums()

int plpgsql_add_initdatums ( int **  varnos)

Definition at line 2350 of file pl_comp.c.

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

2351 {
2352  int i;
2353  int n = 0;
2354 
2355  /*
2356  * The set of dtypes recognized here must match what exec_stmt_block()
2357  * cares about (re)initializing at block entry.
2358  */
2359  for (i = datums_last; i < plpgsql_nDatums; i++)
2360  {
2361  switch (plpgsql_Datums[i]->dtype)
2362  {
2363  case PLPGSQL_DTYPE_VAR:
2364  case PLPGSQL_DTYPE_REC:
2365  n++;
2366  break;
2367 
2368  default:
2369  break;
2370  }
2371  }
2372 
2373  if (varnos != NULL)
2374  {
2375  if (n > 0)
2376  {
2377  *varnos = (int *) palloc(sizeof(int) * n);
2378 
2379  n = 0;
2380  for (i = datums_last; i < plpgsql_nDatums; i++)
2381  {
2382  switch (plpgsql_Datums[i]->dtype)
2383  {
2384  case PLPGSQL_DTYPE_VAR:
2385  case PLPGSQL_DTYPE_REC:
2386  (*varnos)[n++] = plpgsql_Datums[i]->dno;
2387 
2388  default:
2389  break;
2390  }
2391  }
2392  }
2393  else
2394  *varnos = NULL;
2395  }
2396 
2398  return n;
2399 }
int plpgsql_nDatums
Definition: pl_comp.c:44
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:45
void * palloc(Size size)
Definition: mcxt.c:949
int i
static int datums_last
Definition: pl_comp.c:46

◆ plpgsql_adddatum()

void plpgsql_adddatum ( PLpgSQL_datum newdatum)

Definition at line 2289 of file pl_comp.c.

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

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

2290 {
2292  {
2293  datums_alloc *= 2;
2295  }
2296 
2297  newdatum->dno = plpgsql_nDatums;
2298  plpgsql_Datums[plpgsql_nDatums++] = newdatum;
2299 }
int plpgsql_nDatums
Definition: pl_comp.c:44
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:45
static int datums_alloc
Definition: pl_comp.c:43
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069

◆ plpgsql_build_datatype()

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

Definition at line 2047 of file pl_comp.c.

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

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

2049 {
2050  HeapTuple typeTup;
2051  PLpgSQL_type *typ;
2052 
2053  typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
2054  if (!HeapTupleIsValid(typeTup))
2055  elog(ERROR, "cache lookup failed for type %u", typeOid);
2056 
2057  typ = build_datatype(typeTup, typmod, collation, origtypname);
2058 
2059  ReleaseSysCache(typeTup);
2060 
2061  return typ;
2062 }
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:2069
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:228

◆ plpgsql_build_recfield()

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

Definition at line 2000 of file pl_comp.c.

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

Referenced by plpgsql_parse_dblword(), and plpgsql_parse_tripword().

2001 {
2002  PLpgSQL_recfield *recfield;
2003  int i;
2004 
2005  /* search for an existing datum referencing this field */
2006  i = rec->firstfield;
2007  while (i >= 0)
2008  {
2010 
2012  fld->recparentno == rec->dno);
2013  if (strcmp(fld->fieldname, fldname) == 0)
2014  return fld;
2015  i = fld->nextfield;
2016  }
2017 
2018  /* nope, so make a new one */
2019  recfield = palloc0(sizeof(PLpgSQL_recfield));
2020  recfield->dtype = PLPGSQL_DTYPE_RECFIELD;
2021  recfield->fieldname = pstrdup(fldname);
2022  recfield->recparentno = rec->dno;
2024 
2025  plpgsql_adddatum((PLpgSQL_datum *) recfield);
2026 
2027  /* now we can link it into the parent's chain */
2028  recfield->nextfield = rec->firstfield;
2029  rec->firstfield = recfield->dno;
2030 
2031  return recfield;
2032 }
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:45
char * pstrdup(const char *in)
Definition: mcxt.c:1186
#define INVALID_TUPLEDESC_IDENTIFIER
Definition: typcache.h:146
void plpgsql_adddatum(PLpgSQL_datum *newdatum)
Definition: pl_comp.c:2289
uint64 rectupledescid
Definition: plpgsql.h:410
void * palloc0(Size size)
Definition: mcxt.c:980
PLpgSQL_datum_type dtype
Definition: plpgsql.h:403
#define Assert(condition)
Definition: c.h:739
int i
char * fieldname
Definition: plpgsql.h:407
int firstfield
Definition: plpgsql.h:390

◆ plpgsql_build_record()

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

Definition at line 1906 of file pl_comp.c.

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

Referenced by do_compile(), and plpgsql_build_variable().

1909 {
1910  PLpgSQL_rec *rec;
1911 
1912  rec = palloc0(sizeof(PLpgSQL_rec));
1913  rec->dtype = PLPGSQL_DTYPE_REC;
1914  rec->refname = pstrdup(refname);
1915  rec->lineno = lineno;
1916  /* other fields are left as 0, might be changed by caller */
1917  rec->datatype = dtype;
1918  rec->rectypeid = rectypeid;
1919  rec->firstfield = -1;
1920  rec->erh = NULL;
1922  if (add2namespace)
1924 
1925  return rec;
1926 }
PLpgSQL_datum_type dtype
Definition: plpgsql.h:372
PLpgSQL_type * datatype
Definition: plpgsql.h:387
char * pstrdup(const char *in)
Definition: mcxt.c:1186
void plpgsql_ns_additem(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
Definition: pl_funcs.c:92
ExpandedRecordHeader * erh
Definition: plpgsql.h:395
char * refname
Definition: plpgsql.h:374
void plpgsql_adddatum(PLpgSQL_datum *newdatum)
Definition: pl_comp.c:2289
void * palloc0(Size size)
Definition: mcxt.c:980
Oid rectypeid
Definition: plpgsql.h:388
int lineno
Definition: plpgsql.h:375
int firstfield
Definition: plpgsql.h:390

◆ plpgsql_build_variable()

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

Definition at line 1843 of file pl_comp.c.

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

Referenced by do_compile(), and plpgsql_compile_inline().

1845 {
1846  PLpgSQL_variable *result;
1847 
1848  switch (dtype->ttype)
1849  {
1850  case PLPGSQL_TTYPE_SCALAR:
1851  {
1852  /* Ordinary scalar datatype */
1853  PLpgSQL_var *var;
1854 
1855  var = palloc0(sizeof(PLpgSQL_var));
1856  var->dtype = PLPGSQL_DTYPE_VAR;
1857  var->refname = pstrdup(refname);
1858  var->lineno = lineno;
1859  var->datatype = dtype;
1860  /* other fields are left as 0, might be changed by caller */
1861 
1862  /* preset to NULL */
1863  var->value = 0;
1864  var->isnull = true;
1865  var->freeval = false;
1866 
1868  if (add2namespace)
1870  var->dno,
1871  refname);
1872  result = (PLpgSQL_variable *) var;
1873  break;
1874  }
1875  case PLPGSQL_TTYPE_REC:
1876  {
1877  /* Composite type -- build a record variable */
1878  PLpgSQL_rec *rec;
1879 
1880  rec = plpgsql_build_record(refname, lineno,
1881  dtype, dtype->typoid,
1882  add2namespace);
1883  result = (PLpgSQL_variable *) rec;
1884  break;
1885  }
1886  case PLPGSQL_TTYPE_PSEUDO:
1887  ereport(ERROR,
1888  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1889  errmsg("variable \"%s\" has pseudo-type %s",
1890  refname, format_type_be(dtype->typoid))));
1891  result = NULL; /* keep compiler quiet */
1892  break;
1893  default:
1894  elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
1895  result = NULL; /* keep compiler quiet */
1896  break;
1897  }
1898 
1899  return result;
1900 }
char * refname
Definition: plpgsql.h:294
PLpgSQL_rec * plpgsql_build_record(const char *refname, int lineno, PLpgSQL_type *dtype, Oid rectypeid, bool add2namespace)
Definition: pl_comp.c:1906
PLpgSQL_datum_type dtype
Definition: plpgsql.h:292
char * pstrdup(const char *in)
Definition: mcxt.c:1186
PLpgSQL_type * datatype
Definition: plpgsql.h:301
void plpgsql_ns_additem(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
Definition: pl_funcs.c:92
PLpgSQL_type_type ttype
Definition: plpgsql.h:203
int errcode(int sqlerrcode)
Definition: elog.c:608
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
void plpgsql_adddatum(PLpgSQL_datum *newdatum)
Definition: pl_comp.c:2289
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
bool freeval
Definition: plpgsql.h:316
void * palloc0(Size size)
Definition: mcxt.c:980
Datum value
Definition: plpgsql.h:314
int lineno
Definition: plpgsql.h:295
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
bool isnull
Definition: plpgsql.h:315
Oid typoid
Definition: plpgsql.h:202

◆ plpgsql_compile()

PLpgSQL_function* plpgsql_compile ( FunctionCallInfo  fcinfo,
bool  forValidator 
)

Definition at line 135 of file pl_comp.c.

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

Referenced by plpgsql_call_handler(), and plpgsql_validator().

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

◆ plpgsql_compile_error_callback()

static void plpgsql_compile_error_callback ( void *  arg)
static

Definition at line 977 of file pl_comp.c.

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

Referenced by do_compile(), and plpgsql_compile_inline().

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

◆ plpgsql_compile_inline()

PLpgSQL_function* plpgsql_compile_inline ( char *  proc_source)

Definition at line 841 of file pl_comp.c.

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

Referenced by plpgsql_inline_handler().

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

◆ plpgsql_finish_datums()

static void plpgsql_finish_datums ( PLpgSQL_function function)
static

Definition at line 2306 of file pl_comp.c.

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

Referenced by do_compile(), and plpgsql_compile_inline().

2307 {
2308  Size copiable_size = 0;
2309  int i;
2310 
2311  function->ndatums = plpgsql_nDatums;
2312  function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
2313  for (i = 0; i < plpgsql_nDatums; i++)
2314  {
2315  function->datums[i] = plpgsql_Datums[i];
2316 
2317  /* This must agree with copy_plpgsql_datums on what is copiable */
2318  switch (function->datums[i]->dtype)
2319  {
2320  case PLPGSQL_DTYPE_VAR:
2321  case PLPGSQL_DTYPE_PROMISE:
2322  copiable_size += MAXALIGN(sizeof(PLpgSQL_var));
2323  break;
2324  case PLPGSQL_DTYPE_REC:
2325  copiable_size += MAXALIGN(sizeof(PLpgSQL_rec));
2326  break;
2327  default:
2328  break;
2329  }
2330  }
2331  function->copiable_size = copiable_size;
2332 }
int plpgsql_nDatums
Definition: pl_comp.c:44
PLpgSQL_datum ** datums
Definition: plpgsql.h:1021
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:45
PLpgSQL_datum_type dtype
Definition: plpgsql.h:258
size_t Size
Definition: c.h:467
#define MAXALIGN(LEN)
Definition: c.h:692
void * palloc(Size size)
Definition: mcxt.c:949
int i

◆ plpgsql_HashTableDelete()

static void plpgsql_HashTableDelete ( PLpgSQL_function function)
static

Definition at line 2582 of file pl_comp.c.

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

Referenced by delete_function().

2583 {
2584  plpgsql_HashEnt *hentry;
2585 
2586  /* do nothing if not in table */
2587  if (function->fn_hashkey == NULL)
2588  return;
2589 
2591  (void *) function->fn_hashkey,
2592  HASH_REMOVE,
2593  NULL);
2594  if (hentry == NULL)
2595  elog(WARNING, "trying to delete function that does not exist");
2596 
2597  /* remove back link, which no longer points to allocated storage */
2598  function->fn_hashkey = NULL;
2599 }
PLpgSQL_func_hashkey * fn_hashkey
Definition: plpgsql.h:989
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:61
#define WARNING
Definition: elog.h:40
#define elog(elevel,...)
Definition: elog.h:228

◆ plpgsql_HashTableInit()

void plpgsql_HashTableInit ( void  )

Definition at line 2531 of file pl_comp.c.

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

Referenced by _PG_init().

2532 {
2533  HASHCTL ctl;
2534 
2535  /* don't allow double-initialization */
2536  Assert(plpgsql_HashTable == NULL);
2537 
2538  memset(&ctl, 0, sizeof(ctl));
2539  ctl.keysize = sizeof(PLpgSQL_func_hashkey);
2540  ctl.entrysize = sizeof(plpgsql_HashEnt);
2541  plpgsql_HashTable = hash_create("PLpgSQL function hash",
2543  &ctl,
2544  HASH_ELEM | HASH_BLOBS);
2545 }
#define FUNCS_PER_USER
Definition: pl_comp.c:69
#define HASH_ELEM
Definition: hsearch.h:87
Size entrysize
Definition: hsearch.h:73
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:61
struct plpgsql_hashent plpgsql_HashEnt
struct PLpgSQL_func_hashkey PLpgSQL_func_hashkey
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
Size keysize
Definition: hsearch.h:72
#define Assert(condition)
Definition: c.h:739

◆ plpgsql_HashTableInsert()

static void plpgsql_HashTableInsert ( PLpgSQL_function function,
PLpgSQL_func_hashkey func_key 
)
static

Definition at line 2563 of file pl_comp.c.

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

Referenced by do_compile().

2565 {
2566  plpgsql_HashEnt *hentry;
2567  bool found;
2568 
2570  (void *) func_key,
2571  HASH_ENTER,
2572  &found);
2573  if (found)
2574  elog(WARNING, "trying to insert a function that already exists");
2575 
2576  hentry->function = function;
2577  /* prepare back link from function to hashtable key */
2578  function->fn_hashkey = &hentry->key;
2579 }
PLpgSQL_func_hashkey * fn_hashkey
Definition: plpgsql.h:989
PLpgSQL_func_hashkey key
Definition: pl_comp.c:65
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:61
PLpgSQL_function * function
Definition: pl_comp.c:66
#define WARNING
Definition: elog.h:40
#define elog(elevel,...)
Definition: elog.h:228

◆ plpgsql_HashTableLookup()

static PLpgSQL_function * plpgsql_HashTableLookup ( PLpgSQL_func_hashkey func_key)
static

Definition at line 2548 of file pl_comp.c.

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

Referenced by plpgsql_compile().

2549 {
2550  plpgsql_HashEnt *hentry;
2551 
2553  (void *) func_key,
2554  HASH_FIND,
2555  NULL);
2556  if (hentry)
2557  return hentry->function;
2558  else
2559  return NULL;
2560 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:61
PLpgSQL_function * function
Definition: pl_comp.c:66

◆ plpgsql_param_ref()

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

Definition at line 1143 of file pl_comp.c.

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

Referenced by plpgsql_parser_setup().

1144 {
1145  PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1146  char pname[32];
1147  PLpgSQL_nsitem *nse;
1148 
1149  snprintf(pname, sizeof(pname), "$%d", pref->number);
1150 
1151  nse = plpgsql_ns_lookup(expr->ns, false,
1152  pname, NULL, NULL,
1153  NULL);
1154 
1155  if (nse == NULL)
1156  return NULL; /* name not known to plpgsql */
1157 
1158  return make_datum_param(expr, nse->itemno, pref->location);
1159 }
PLpgSQL_nsitem * plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode, const char *name1, const char *name2, const char *name3, int *names_used)
Definition: pl_funcs.c:130
struct PLpgSQL_nsitem * ns
Definition: plpgsql.h:230
int number
Definition: parsenodes.h:245
int location
Definition: parsenodes.h:246
void * p_ref_hook_state
Definition: parse_node.h:219
#define snprintf
Definition: port.h:192
static Node * make_datum_param(PLpgSQL_expr *expr, int dno, int location)
Definition: pl_comp.c:1334

◆ plpgsql_parse_cwordrowtype()

PLpgSQL_type* plpgsql_parse_cwordrowtype ( List idents)

Definition at line 1804 of file pl_comp.c.

References get_rel_type_id(), InvalidOid, linitial, list_length(), lsecond, makeRangeVar(), makeTypeNameFromNameList(), MemoryContextSwitchTo(), NoLock, plpgsql_build_datatype(), RangeVarGetRelid, and strVal.

1805 {
1806  Oid classOid;
1807  RangeVar *relvar;
1808  MemoryContext oldCxt;
1809 
1810  /*
1811  * As above, this is a relation lookup but could be a type lookup if we
1812  * weren't being backwards-compatible about error wording.
1813  */
1814  if (list_length(idents) != 2)
1815  return NULL;
1816 
1817  /* Avoid memory leaks in long-term function context */
1819 
1820  /* Look up relation name. Can't lock it - we might not have privileges. */
1821  relvar = makeRangeVar(strVal(linitial(idents)),
1822  strVal(lsecond(idents)),
1823  -1);
1824  classOid = RangeVarGetRelid(relvar, NoLock, false);
1825 
1826  MemoryContextSwitchTo(oldCxt);
1827 
1828  /* Build and return the row type struct */
1829  return plpgsql_build_datatype(get_rel_type_id(classOid), -1, InvalidOid,
1830  makeTypeNameFromNameList(idents));
1831 }
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:63
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define strVal(v)
Definition: value.h:54
unsigned int Oid
Definition: postgres_ext.h:31
#define lsecond(l)
Definition: pg_list.h:200
#define linitial(l)
Definition: pg_list.h:195
#define NoLock
Definition: lockdefs.h:34
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:2047
Oid get_rel_type_id(Oid relid)
Definition: lsyscache.c:1781
#define InvalidOid
Definition: postgres_ext.h:36
static int list_length(const List *l)
Definition: pg_list.h:169
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:454
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:55
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:420

◆ plpgsql_parse_cwordtype()

PLpgSQL_type* plpgsql_parse_cwordtype ( List idents)

Definition at line 1656 of file pl_comp.c.

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

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

◆ plpgsql_parse_dblword()

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

Definition at line 1442 of file pl_comp.c.

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

Referenced by plpgsql_yylex().

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

◆ plpgsql_parse_err_condition()

PLpgSQL_condition* plpgsql_parse_err_condition ( char *  condname)

Definition at line 2221 of file pl_comp.c.

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

2222 {
2223  int i;
2224  PLpgSQL_condition *new;
2225  PLpgSQL_condition *prev;
2226 
2227  /*
2228  * XXX Eventually we will want to look for user-defined exception names
2229  * here.
2230  */
2231 
2232  /*
2233  * OTHERS is represented as code 0 (which would map to '00000', but we
2234  * have no need to represent that as an exception condition).
2235  */
2236  if (strcmp(condname, "others") == 0)
2237  {
2238  new = palloc(sizeof(PLpgSQL_condition));
2239  new->sqlerrstate = 0;
2240  new->condname = condname;
2241  new->next = NULL;
2242  return new;
2243  }
2244 
2245  prev = NULL;
2246  for (i = 0; exception_label_map[i].label != NULL; i++)
2247  {
2248  if (strcmp(condname, exception_label_map[i].label) == 0)
2249  {
2250  new = palloc(sizeof(PLpgSQL_condition));
2251  new->sqlerrstate = exception_label_map[i].sqlerrstate;
2252  new->condname = condname;
2253  new->next = prev;
2254  prev = new;
2255  }
2256  }
2257 
2258  if (!prev)
2259  ereport(ERROR,
2260  (errcode(ERRCODE_UNDEFINED_OBJECT),
2261  errmsg("unrecognized exception condition \"%s\"",
2262  condname)));
2263 
2264  return prev;
2265 }
const char * label
Definition: pl_comp.c:77
int errcode(int sqlerrcode)
Definition: elog.c:608
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
static char * label
static const ExceptionLabelMap exception_label_map[]
Definition: pl_comp.c:81
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:822
int i

◆ plpgsql_parse_tripword()

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

Definition at line 1522 of file pl_comp.c.

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

Referenced by plpgsql_yylex().

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

◆ plpgsql_parse_word()

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

Definition at line 1387 of file pl_comp.c.

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

Referenced by plpgsql_yylex().

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

◆ plpgsql_parse_wordrowtype()

PLpgSQL_type* plpgsql_parse_wordrowtype ( char *  ident)

Definition at line 1776 of file pl_comp.c.

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

1777 {
1778  Oid classOid;
1779 
1780  /*
1781  * Look up the relation. Note that because relation rowtypes have the
1782  * same names as their relations, this could be handled as a type lookup
1783  * equally well; we use the relation lookup code path only because the
1784  * errors thrown here have traditionally referred to relations not types.
1785  * But we'll make a TypeName in case we have to do re-look-up of the type.
1786  */
1787  classOid = RelnameGetRelid(ident);
1788  if (!OidIsValid(classOid))
1789  ereport(ERROR,
1791  errmsg("relation \"%s\" does not exist", ident)));
1792 
1793  /* Build and return the row type struct */
1794  return plpgsql_build_datatype(get_rel_type_id(classOid), -1, InvalidOid,
1795  makeTypeName(ident));
1796 }
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:74
Oid RelnameGetRelid(const char *relname)
Definition: namespace.c:672
int errcode(int sqlerrcode)
Definition: elog.c:608
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:645
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:2047
Oid get_rel_type_id(Oid relid)
Definition: lsyscache.c:1781
#define InvalidOid
Definition: postgres_ext.h:36
TypeName * makeTypeName(char *typnam)
Definition: makefuncs.c:442
int errmsg(const char *fmt,...)
Definition: elog.c:822

◆ plpgsql_parse_wordtype()

PLpgSQL_type* plpgsql_parse_wordtype ( char *  ident)

Definition at line 1590 of file pl_comp.c.

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

1591 {
1592  PLpgSQL_type *dtype;
1593  PLpgSQL_nsitem *nse;
1594  TypeName *typeName;
1595  HeapTuple typeTup;
1596 
1597  /*
1598  * Do a lookup in the current namespace stack
1599  */
1600  nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1601  ident, NULL, NULL,
1602  NULL);
1603 
1604  if (nse != NULL)
1605  {
1606  switch (nse->itemtype)
1607  {
1608  case PLPGSQL_NSTYPE_VAR:
1609  return ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1610 
1611  /* XXX perhaps allow REC/ROW here? */
1612 
1613  default:
1614  return NULL;
1615  }
1616  }
1617 
1618  /*
1619  * Word wasn't found in the namespace stack. Try to find a data type with
1620  * that name, but ignore shell types and complex types.
1621  */
1622  typeName = makeTypeName(ident);
1623  typeTup = LookupTypeName(NULL, typeName, NULL, false);
1624  if (typeTup)
1625  {
1626  Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1627 
1628  if (!typeStruct->typisdefined ||
1629  typeStruct->typrelid != InvalidOid)
1630  {
1631  ReleaseSysCache(typeTup);
1632  return NULL;
1633  }
1634 
1635  dtype = build_datatype(typeTup, -1,
1637  typeName);
1638 
1639  ReleaseSysCache(typeTup);
1640  return dtype;
1641  }
1642 
1643  /*
1644  * Nothing found - up to now it's a word without any special meaning for
1645  * us.
1646  */
1647  return NULL;
1648 }
Type LookupTypeName(ParseState *pstate, const TypeName *typeName, int32 *typmod_p, bool missing_ok)
Definition: parse_type.c:38
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:45
PLpgSQL_nsitem * plpgsql_ns_top(void)
Definition: pl_funcs.c:81
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:2069
PLpgSQL_nsitem * plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode, const char *name1, const char *name2, const char *name3, int *names_used)
Definition: pl_funcs.c:130
Oid fn_input_collation
Definition: plpgsql.h:988
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define InvalidOid
Definition: postgres_ext.h:36
TypeName * makeTypeName(char *typnam)
Definition: makefuncs.c:442
FormData_pg_type * Form_pg_type
Definition: pg_type.h:250
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:444
PLpgSQL_function * plpgsql_curr_compile
Definition: pl_comp.c:52

◆ plpgsql_parser_setup()

void plpgsql_parser_setup ( struct ParseState pstate,
PLpgSQL_expr expr 
)

Definition at line 1072 of file pl_comp.c.

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

Referenced by exec_prepare_plan(), and plpgsql_estate_setup().

1073 {
1077  /* no need to use p_coerce_param_hook */
1078  pstate->p_ref_hook_state = (void *) expr;
1079 }
static Node * plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref)
Definition: pl_comp.c:1085
PostParseColumnRefHook p_post_columnref_hook
Definition: parse_node.h:216
ParseParamRefHook p_paramref_hook
Definition: parse_node.h:217
static Node * plpgsql_param_ref(ParseState *pstate, ParamRef *pref)
Definition: pl_comp.c:1143
void * p_ref_hook_state
Definition: parse_node.h:219
PreParseColumnRefHook p_pre_columnref_hook
Definition: parse_node.h:215
static Node * plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
Definition: pl_comp.c:1099

◆ plpgsql_post_column_ref()

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

Definition at line 1099 of file pl_comp.c.

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

Referenced by plpgsql_parser_setup().

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

◆ plpgsql_pre_column_ref()

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

Definition at line 1085 of file pl_comp.c.

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

Referenced by plpgsql_parser_setup().

1086 {
1087  PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1088 
1090  return resolve_column_ref(pstate, expr, cref, false);
1091  else
1092  return NULL;
1093 }
PLpgSQL_resolve_option resolve_option
Definition: plpgsql.h:1008
struct PLpgSQL_function * func
Definition: plpgsql.h:227
void * p_ref_hook_state
Definition: parse_node.h:219
static Node * resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr, ColumnRef *cref, bool error_if_no_field)
Definition: pl_comp.c:1170

◆ plpgsql_recognize_err_condition()

int plpgsql_recognize_err_condition ( const char *  condname,
bool  allow_sqlstate 
)

Definition at line 2185 of file pl_comp.c.

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

Referenced by exec_stmt_raise().

2186 {
2187  int i;
2188 
2189  if (allow_sqlstate)
2190  {
2191  if (strlen(condname) == 5 &&
2192  strspn(condname, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") == 5)
2193  return MAKE_SQLSTATE(condname[0],
2194  condname[1],
2195  condname[2],
2196  condname[3],
2197  condname[4]);
2198  }
2199 
2200  for (i = 0; exception_label_map[i].label != NULL; i++)
2201  {
2202  if (strcmp(condname, exception_label_map[i].label) == 0)
2204  }
2205 
2206  ereport(ERROR,
2207  (errcode(ERRCODE_UNDEFINED_OBJECT),
2208  errmsg("unrecognized exception condition \"%s\"",
2209  condname)));
2210  return 0; /* keep compiler quiet */
2211 }
const char * label
Definition: pl_comp.c:77
#define MAKE_SQLSTATE(ch1, ch2, ch3, ch4, ch5)
Definition: elog.h:62
int errcode(int sqlerrcode)
Definition: elog.c:608
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
static char * label
static const ExceptionLabelMap exception_label_map[]
Definition: pl_comp.c:81
int errmsg(const char *fmt,...)
Definition: elog.c:822
int i

◆ plpgsql_resolve_polymorphic_argtypes()

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

Definition at line 2461 of file pl_comp.c.

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

Referenced by compute_function_hashkey(), and do_compile().

2465 {
2466  int i;
2467 
2468  if (!forValidator)
2469  {
2470  /* normal case, pass to standard routine */
2471  if (!resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
2472  call_expr))
2473  ereport(ERROR,
2474  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2475  errmsg("could not determine actual argument "
2476  "type for polymorphic function \"%s\"",
2477  proname)));
2478  }
2479  else
2480  {
2481  /* special validation case */
2482  for (i = 0; i < numargs; i++)
2483  {
2484  switch (argtypes[i])
2485  {
2486  case ANYELEMENTOID:
2487  case ANYNONARRAYOID:
2488  case ANYENUMOID: /* XXX dubious */
2489  argtypes[i] = INT4OID;
2490  break;
2491  case ANYARRAYOID:
2492  argtypes[i] = INT4ARRAYOID;
2493  break;
2494  case ANYRANGEOID:
2495  argtypes[i] = INT4RANGEOID;
2496  break;
2497  default:
2498  break;
2499  }
2500  }
2501  }
2502 }
bool resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, Node *call_expr)
Definition: funcapi.c:661
NameData proname
Definition: pg_proc.h:35
int errcode(int sqlerrcode)
Definition: elog.c:608
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
int errmsg(const char *fmt,...)
Definition: elog.c:822
int i

◆ plpgsql_start_datums()

static void plpgsql_start_datums ( void  )
static

Definition at line 2272 of file pl_comp.c.

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

Referenced by do_compile(), and plpgsql_compile_inline().

2273 {
2274  datums_alloc = 128;
2275  plpgsql_nDatums = 0;
2276  /* This is short-lived, so needn't allocate in function's cxt */
2278  sizeof(PLpgSQL_datum *) * datums_alloc);
2279  /* datums_last tracks what's been seen by plpgsql_add_initdatums() */
2280  datums_last = 0;
2281 }
int plpgsql_nDatums
Definition: pl_comp.c:44
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:45
static int datums_alloc
Definition: pl_comp.c:43
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:55
static int datums_last
Definition: pl_comp.c:46

◆ resolve_column_ref()

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

Definition at line 1170 of file pl_comp.c.

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

Referenced by plpgsql_post_column_ref(), and plpgsql_pre_column_ref().

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

Variable Documentation

◆ datums_alloc

int datums_alloc
static

Definition at line 43 of file pl_comp.c.

Referenced by plpgsql_adddatum(), and plpgsql_start_datums().

◆ datums_last

int datums_last
static

Definition at line 46 of file pl_comp.c.

Referenced by plpgsql_add_initdatums(), and plpgsql_start_datums().

◆ exception_label_map

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

Definition at line 81 of file pl_comp.c.

◆ plpgsql_check_syntax

bool plpgsql_check_syntax = false

Definition at line 50 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_compile_tmp_cxt

MemoryContext plpgsql_compile_tmp_cxt

Definition at line 55 of file pl_comp.c.

◆ plpgsql_curr_compile

PLpgSQL_function* plpgsql_curr_compile

Definition at line 52 of file pl_comp.c.

◆ plpgsql_Datums

PLpgSQL_datum** plpgsql_Datums

Definition at line 45 of file pl_comp.c.

◆ plpgsql_DumpExecTree

bool plpgsql_DumpExecTree = false

Definition at line 49 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_error_funcname

char* plpgsql_error_funcname

Definition at line 48 of file pl_comp.c.

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

◆ plpgsql_HashTable

HTAB* plpgsql_HashTable = NULL
static

Definition at line 61 of file pl_comp.c.

◆ plpgsql_nDatums

int plpgsql_nDatums

◆ plpgsql_parse_result

PLpgSQL_stmt_block* plpgsql_parse_result

Definition at line 41 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().