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_proc_fn.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "nodes/makefuncs.h"
#include "parser/parse_type.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 "plpgsql.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_class (Oid classOid)
 
static PLpgSQL_rowbuild_row_from_vars (PLpgSQL_variable **vars, int numvars)
 
static PLpgSQL_typebuild_datatype (HeapTuple typeTup, int32 typmod, Oid collation)
 
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, 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, bool add2namespace)
 
PLpgSQL_typeplpgsql_build_datatype (Oid typeOid, int32 typmod, Oid collation)
 
int plpgsql_recognize_err_condition (const char *condname, bool allow_sqlstate)
 
PLpgSQL_conditionplpgsql_parse_err_condition (char *condname)
 
void plpgsql_adddatum (PLpgSQL_datum *new)
 
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 71 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 986 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().

987 {
988  /*
989  * If the outer block has an EXCEPTION clause, we need to make a new outer
990  * block, since the added RETURN shouldn't act like it is inside the
991  * EXCEPTION clause.
992  */
993  if (function->action->exceptions != NULL)
994  {
995  PLpgSQL_stmt_block *new;
996 
997  new = palloc0(sizeof(PLpgSQL_stmt_block));
998  new->cmd_type = PLPGSQL_STMT_BLOCK;
999  new->body = list_make1(function->action);
1000 
1001  function->action = new;
1002  }
1003  if (function->action->body == NIL ||
1004  ((PLpgSQL_stmt *) llast(function->action->body))->cmd_type != PLPGSQL_STMT_RETURN)
1005  {
1006  PLpgSQL_stmt_return *new;
1007 
1008  new = palloc0(sizeof(PLpgSQL_stmt_return));
1009  new->cmd_type = PLPGSQL_STMT_RETURN;
1010  new->expr = NULL;
1011  new->retvarno = function->out_param_varno;
1012 
1013  function->action->body = lappend(function->action->body, new);
1014  }
1015 }
#define NIL
Definition: pg_list.h:69
PLpgSQL_stmt_block * action
Definition: plpgsql.h:863
#define llast(l)
Definition: pg_list.h:131
#define list_make1(x1)
Definition: pg_list.h:139
List * lappend(List *list, void *datum)
Definition: list.c:128
void * palloc0(Size size)
Definition: mcxt.c:864
PLpgSQL_exception_block * exceptions
Definition: plpgsql.h:412

◆ add_parameter_name()

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

Definition at line 961 of file pl_comp.c.

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

Referenced by do_compile().

962 {
963  /*
964  * Before adding the name, check for duplicates. We need this even though
965  * functioncmds.c has a similar check, because that code explicitly
966  * doesn't complain about conflicting IN and OUT parameter names. In
967  * plpgsql, such names are in the same namespace, so there is no way to
968  * disambiguate.
969  */
970  if (plpgsql_ns_lookup(plpgsql_ns_top(), true,
971  name, NULL, NULL,
972  NULL) != NULL)
973  ereport(ERROR,
974  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
975  errmsg("parameter name \"%s\" used more than once",
976  name)));
977 
978  /* OK, add the name */
979  plpgsql_ns_additem(itemtype, itemno, name);
980 }
PLpgSQL_nsitem * plpgsql_ns_top(void)
Definition: pl_funcs.c:83
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:132
void plpgsql_ns_additem(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
Definition: pl_funcs.c:94
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
const char * name
Definition: encode.c:521
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ build_datatype()

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

Definition at line 2156 of file pl_comp.c.

References Assert, PLpgSQL_type::atttypmod, PLpgSQL_type::collation, elog, ereport, errcode(), errmsg(), ERROR, get_base_element_type(), GETSTRUCT, HeapTupleGetOid, NameStr, OidIsValid, palloc(), PLPGSQL_TTYPE_PSEUDO, PLPGSQL_TTYPE_REC, PLPGSQL_TTYPE_ROW, PLPGSQL_TTYPE_SCALAR, pstrdup(), RECORDOID, PLpgSQL_type::ttype, PLpgSQL_type::typbyval, PLpgSQL_type::typisarray, PLpgSQL_type::typlen, PLpgSQL_type::typname, PLpgSQL_type::typoid, PLpgSQL_type::typrelid, PLpgSQL_type::typtype, TYPTYPE_BASE, TYPTYPE_COMPOSITE, TYPTYPE_DOMAIN, TYPTYPE_ENUM, TYPTYPE_PSEUDO, and TYPTYPE_RANGE.

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

2157 {
2158  Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
2159  PLpgSQL_type *typ;
2160 
2161  if (!typeStruct->typisdefined)
2162  ereport(ERROR,
2163  (errcode(ERRCODE_UNDEFINED_OBJECT),
2164  errmsg("type \"%s\" is only a shell",
2165  NameStr(typeStruct->typname))));
2166 
2167  typ = (PLpgSQL_type *) palloc(sizeof(PLpgSQL_type));
2168 
2169  typ->typname = pstrdup(NameStr(typeStruct->typname));
2170  typ->typoid = HeapTupleGetOid(typeTup);
2171  switch (typeStruct->typtype)
2172  {
2173  case TYPTYPE_BASE:
2174  case TYPTYPE_DOMAIN:
2175  case TYPTYPE_ENUM:
2176  case TYPTYPE_RANGE:
2177  typ->ttype = PLPGSQL_TTYPE_SCALAR;
2178  break;
2179  case TYPTYPE_COMPOSITE:
2180  Assert(OidIsValid(typeStruct->typrelid));
2181  typ->ttype = PLPGSQL_TTYPE_ROW;
2182  break;
2183  case TYPTYPE_PSEUDO:
2184  if (typ->typoid == RECORDOID)
2185  typ->ttype = PLPGSQL_TTYPE_REC;
2186  else
2187  typ->ttype = PLPGSQL_TTYPE_PSEUDO;
2188  break;
2189  default:
2190  elog(ERROR, "unrecognized typtype: %d",
2191  (int) typeStruct->typtype);
2192  break;
2193  }
2194  typ->typlen = typeStruct->typlen;
2195  typ->typbyval = typeStruct->typbyval;
2196  typ->typtype = typeStruct->typtype;
2197  typ->typrelid = typeStruct->typrelid;
2198  typ->collation = typeStruct->typcollation;
2199  if (OidIsValid(collation) && OidIsValid(typ->collation))
2200  typ->collation = collation;
2201  /* Detect if type is true array, or domain thereof */
2202  /* NB: this is only used to decide whether to apply expand_array */
2203  if (typeStruct->typtype == TYPTYPE_BASE)
2204  {
2205  /*
2206  * This test should include what get_element_type() checks. We also
2207  * disallow non-toastable array types (i.e. oidvector and int2vector).
2208  */
2209  typ->typisarray = (typeStruct->typlen == -1 &&
2210  OidIsValid(typeStruct->typelem) &&
2211  typeStruct->typstorage != 'p');
2212  }
2213  else if (typeStruct->typtype == TYPTYPE_DOMAIN)
2214  {
2215  /* we can short-circuit looking up base types if it's not varlena */
2216  typ->typisarray = (typeStruct->typlen == -1 &&
2217  typeStruct->typstorage != 'p' &&
2218  OidIsValid(get_base_element_type(typeStruct->typbasetype)));
2219  }
2220  else
2221  typ->typisarray = false;
2222  typ->atttypmod = typmod;
2223 
2224  return typ;
2225 }
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define TYPTYPE_BASE
Definition: pg_type.h:720
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
char * pstrdup(const char *in)
Definition: mcxt.c:1063
PLpgSQL_type_type ttype
Definition: plpgsql.h:180
int errcode(int sqlerrcode)
Definition: elog.c:575
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
#define OidIsValid(objectId)
Definition: c.h:586
#define ERROR
Definition: elog.h:43
#define RECORDOID
Definition: pg_type.h:680
#define ereport(elevel, rest)
Definition: elog.h:122
Oid typrelid
Definition: plpgsql.h:184
bool typbyval
Definition: plpgsql.h:182
#define TYPTYPE_RANGE
Definition: pg_type.h:725
Oid collation
Definition: plpgsql.h:185
bool typisarray
Definition: plpgsql.h:186
#define Assert(condition)
Definition: c.h:680
char * typname
Definition: plpgsql.h:178
#define TYPTYPE_PSEUDO
Definition: pg_type.h:724
char typtype
Definition: plpgsql.h:183
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2590
void * palloc(Size size)
Definition: mcxt.c:835
int errmsg(const char *fmt,...)
Definition: elog.c:797
int32 atttypmod
Definition: plpgsql.h:187
#define NameStr(name)
Definition: c.h:557
#define TYPTYPE_ENUM
Definition: pg_type.h:723
#define elog
Definition: elog.h:219
int16 typlen
Definition: plpgsql.h:181
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
Oid typoid
Definition: plpgsql.h:179

◆ build_row_from_class()

static PLpgSQL_row * build_row_from_class ( Oid  classOid)
static

Definition at line 1976 of file pl_comp.c.

References AccessShareLock, CreateTupleDescCopy(), PLpgSQL_row::dtype, ereport, errcode(), errmsg(), ERROR, PLpgSQL_row::fieldnames, i, NAMEDATALEN, NameStr, PLpgSQL_row::nfields, palloc(), palloc0(), plpgsql_build_datatype(), plpgsql_build_variable(), PLPGSQL_DTYPE_ROW, relation_close(), relation_open(), RelationGetDescr, RelationGetForm, RelationGetRelationName, RELKIND_COMPOSITE_TYPE, RELKIND_FOREIGN_TABLE, RELKIND_MATVIEW, RELKIND_PARTITIONED_TABLE, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW, PLpgSQL_row::rowtupdesc, snprintf(), TupleDescAttr, and PLpgSQL_row::varnos.

Referenced by plpgsql_build_variable().

1977 {
1978  PLpgSQL_row *row;
1979  Relation rel;
1980  Form_pg_class classStruct;
1981  const char *relname;
1982  int i;
1983 
1984  /*
1985  * Open the relation to get info.
1986  */
1987  rel = relation_open(classOid, AccessShareLock);
1988  classStruct = RelationGetForm(rel);
1989  relname = RelationGetRelationName(rel);
1990 
1991  /*
1992  * Accept relation, sequence, view, materialized view, composite type, or
1993  * foreign table.
1994  */
1995  if (classStruct->relkind != RELKIND_RELATION &&
1996  classStruct->relkind != RELKIND_SEQUENCE &&
1997  classStruct->relkind != RELKIND_VIEW &&
1998  classStruct->relkind != RELKIND_MATVIEW &&
1999  classStruct->relkind != RELKIND_COMPOSITE_TYPE &&
2000  classStruct->relkind != RELKIND_FOREIGN_TABLE &&
2001  classStruct->relkind != RELKIND_PARTITIONED_TABLE)
2002  ereport(ERROR,
2003  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2004  errmsg("relation \"%s\" is not a table", relname)));
2005 
2006  /*
2007  * Create a row datum entry and all the required variables that it will
2008  * point to.
2009  */
2010  row = palloc0(sizeof(PLpgSQL_row));
2011  row->dtype = PLPGSQL_DTYPE_ROW;
2013  row->nfields = classStruct->relnatts;
2014  row->fieldnames = palloc(sizeof(char *) * row->nfields);
2015  row->varnos = palloc(sizeof(int) * row->nfields);
2016 
2017  for (i = 0; i < row->nfields; i++)
2018  {
2019  Form_pg_attribute attrStruct;
2020 
2021  /*
2022  * Get the attribute and check for dropped column
2023  */
2024  attrStruct = TupleDescAttr(row->rowtupdesc, i);
2025 
2026  if (!attrStruct->attisdropped)
2027  {
2028  char *attname;
2029  char refname[(NAMEDATALEN * 2) + 100];
2030  PLpgSQL_variable *var;
2031 
2032  attname = NameStr(attrStruct->attname);
2033  snprintf(refname, sizeof(refname), "%s.%s", relname, attname);
2034 
2035  /*
2036  * Create the internal variable for the field
2037  *
2038  * We know if the table definitions contain a default value or if
2039  * the field is declared in the table as NOT NULL. But it's
2040  * possible to create a table field as NOT NULL without a default
2041  * value and that would lead to problems later when initializing
2042  * the variables due to entering a block at execution time. Thus
2043  * we ignore this information for now.
2044  */
2045  var = plpgsql_build_variable(refname, 0,
2046  plpgsql_build_datatype(attrStruct->atttypid,
2047  attrStruct->atttypmod,
2048  attrStruct->attcollation),
2049  false);
2050 
2051  /* Add the variable to the row */
2052  row->fieldnames[i] = attname;
2053  row->varnos[i] = var->dno;
2054  }
2055  else
2056  {
2057  /* Leave a hole in the row structure for the dropped col */
2058  row->fieldnames[i] = NULL;
2059  row->varnos[i] = -1;
2060  }
2061  }
2062 
2064 
2065  return row;
2066 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:102
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation)
Definition: pl_comp.c:2136
#define RelationGetDescr(relation)
Definition: rel.h:437
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
#define RelationGetForm(relation)
Definition: rel.h:419
#define RELKIND_MATVIEW
Definition: pg_class.h:165
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
#define NAMEDATALEN
#define ERROR
Definition: elog.h:43
char ** fieldnames
Definition: plpgsql.h:293
#define RelationGetRelationName(relation)
Definition: rel.h:445
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
#define ereport(elevel, rest)
Definition: elog.h:122
int * varnos
Definition: plpgsql.h:294
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
void * palloc0(Size size)
Definition: mcxt.c:864
int nfields
Definition: plpgsql.h:292
PLpgSQL_variable * plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype, bool add2namespace)
Definition: pl_comp.c:1873
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
void * palloc(Size size)
Definition: mcxt.c:835
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RELKIND_VIEW
Definition: pg_class.h:164
int i
TupleDesc rowtupdesc
Definition: plpgsql.h:285
#define NameStr(name)
Definition: c.h:557
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
#define RELKIND_RELATION
Definition: pg_class.h:160
#define RELKIND_SEQUENCE
Definition: pg_class.h:162
PLpgSQL_datum_type dtype
Definition: plpgsql.h:279

◆ build_row_from_vars()

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

Definition at line 2072 of file pl_comp.c.

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

Referenced by do_compile().

2073 {
2074  PLpgSQL_row *row;
2075  int i;
2076 
2077  row = palloc0(sizeof(PLpgSQL_row));
2078  row->dtype = PLPGSQL_DTYPE_ROW;
2079  row->rowtupdesc = CreateTemplateTupleDesc(numvars, false);
2080  row->nfields = numvars;
2081  row->fieldnames = palloc(numvars * sizeof(char *));
2082  row->varnos = palloc(numvars * sizeof(int));
2083 
2084  for (i = 0; i < numvars; i++)
2085  {
2086  PLpgSQL_variable *var = vars[i];
2087  Oid typoid = RECORDOID;
2088  int32 typmod = -1;
2089  Oid typcoll = InvalidOid;
2090 
2091  switch (var->dtype)
2092  {
2093  case PLPGSQL_DTYPE_VAR:
2094  typoid = ((PLpgSQL_var *) var)->datatype->typoid;
2095  typmod = ((PLpgSQL_var *) var)->datatype->atttypmod;
2096  typcoll = ((PLpgSQL_var *) var)->datatype->collation;
2097  break;
2098 
2099  case PLPGSQL_DTYPE_REC:
2100  break;
2101 
2102  case PLPGSQL_DTYPE_ROW:
2103  if (((PLpgSQL_row *) var)->rowtupdesc)
2104  {
2105  typoid = ((PLpgSQL_row *) var)->rowtupdesc->tdtypeid;
2106  typmod = ((PLpgSQL_row *) var)->rowtupdesc->tdtypmod;
2107  /* composite types have no collation */
2108  }
2109  break;
2110 
2111  default:
2112  elog(ERROR, "unrecognized dtype: %d", var->dtype);
2113  }
2114 
2115  row->fieldnames[i] = var->refname;
2116  row->varnos[i] = var->dno;
2117 
2118  TupleDescInitEntry(row->rowtupdesc, i + 1,
2119  var->refname,
2120  typoid, typmod,
2121  0);
2122  TupleDescInitEntryCollation(row->rowtupdesc, i + 1, typcoll);
2123  }
2124 
2125  return row;
2126 }
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:294
#define ERROR
Definition: elog.h:43
char ** fieldnames
Definition: plpgsql.h:293
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition: tupdesc.c:664
#define RECORDOID
Definition: pg_type.h:680
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:505
int * varnos
Definition: plpgsql.h:294
void * palloc0(Size size)
Definition: mcxt.c:864
#define InvalidOid
Definition: postgres_ext.h:36
int nfields
Definition: plpgsql.h:292
char * refname
Definition: plpgsql.h:212
PLpgSQL_datum_type dtype
Definition: plpgsql.h:210
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:43
void * palloc(Size size)
Definition: mcxt.c:835
int i
TupleDesc rowtupdesc
Definition: plpgsql.h:285
#define elog
Definition: elog.h:219
PLpgSQL_datum_type dtype
Definition: plpgsql.h:279

◆ compute_function_hashkey()

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

Definition at line 2458 of file pl_comp.c.

References PLpgSQL_func_hashkey::argtypes, CALLED_AS_TRIGGER, FunctionCallInfoData::context, FunctionCallInfoData::flinfo, FmgrInfo::fn_expr, FmgrInfo::fn_oid, FunctionCallInfoData::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().

2462 {
2463  /* Make sure any unused bytes of the struct are zero */
2464  MemSet(hashkey, 0, sizeof(PLpgSQL_func_hashkey));
2465 
2466  /* get function OID */
2467  hashkey->funcOid = fcinfo->flinfo->fn_oid;
2468 
2469  /* get call context */
2470  hashkey->isTrigger = CALLED_AS_TRIGGER(fcinfo);
2471 
2472  /*
2473  * if trigger, get its OID. In validation mode we do not know what
2474  * relation or transition table names are intended to be used, so we leave
2475  * trigOid zero; the hash entry built in this case will never really be
2476  * used.
2477  */
2478  if (hashkey->isTrigger && !forValidator)
2479  {
2480  TriggerData *trigdata = (TriggerData *) fcinfo->context;
2481 
2482  hashkey->trigOid = trigdata->tg_trigger->tgoid;
2483  }
2484 
2485  /* get input collation, if known */
2486  hashkey->inputCollation = fcinfo->fncollation;
2487 
2488  if (procStruct->pronargs > 0)
2489  {
2490  /* get the argument types */
2491  memcpy(hashkey->argtypes, procStruct->proargtypes.values,
2492  procStruct->pronargs * sizeof(Oid));
2493 
2494  /* resolve any polymorphic argument types */
2495  plpgsql_resolve_polymorphic_argtypes(procStruct->pronargs,
2496  hashkey->argtypes,
2497  NULL,
2498  fcinfo->flinfo->fn_expr,
2499  forValidator,
2500  NameStr(procStruct->proname));
2501  }
2502 }
Oid argtypes[FUNC_MAX_ARGS]
Definition: plpgsql.h:794
fmNodePtr context
Definition: fmgr.h:80
Oid tgoid
Definition: reltrigger.h:25
#define MemSet(start, val, len)
Definition: c.h:863
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:2511
FmgrInfo * flinfo
Definition: fmgr.h:79
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:557

◆ delete_function()

static void delete_function ( PLpgSQL_function func)
static

Definition at line 2569 of file pl_comp.c.

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

Referenced by plpgsql_compile().

2570 {
2571  /* remove function from hash table (might be done already) */
2573 
2574  /* release the function's storage if safe and not done already */
2575  if (func->use_count == 0)
2577 }
void plpgsql_free_function_memory(PLpgSQL_function *func)
Definition: pl_funcs.c:695
unsigned long use_count
Definition: plpgsql.h:867
static void plpgsql_HashTableDelete(PLpgSQL_function *function)
Definition: pl_comp.c:2632

◆ do_compile()

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

Definition at line 265 of file pl_comp.c.

References add_dummy_return(), add_parameter_name(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Anum_pg_proc_prosrc, ANYARRAYOID, ANYRANGEOID, ErrorContextCallback::arg, Assert, BOOLOID, 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, EVTTRIGGEROID, FunctionCallInfoData::flinfo, PLpgSQL_function::fn_argvarnos, FmgrInfo::fn_expr, PLpgSQL_function::fn_input_collation, PLpgSQL_function::fn_is_trigger, FmgrInfo::fn_oid, PLpgSQL_function::fn_retset, PLpgSQL_function::fn_rettype, FunctionCallInfoData::fncollation, format_procedure(), format_type_be(), plpgsql_hashent::function, get_fn_expr_rettype(), get_func_arg_info(), GETSTRUCT, HeapTupleHeaderGetRawXmin, HeapTupleIsValid, i, INT4ARRAYOID, INT4OID, INT4RANGEOID, InvalidOid, IsPolymorphicType, MemoryContextAllocZero(), MemoryContextSwitchTo(), NAMEOID, NameStr, ObjectIdGetDatum, OidIsValid, OIDOID, 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_ROW, 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_ROW, PLPGSQL_NSTYPE_VAR, plpgsql_parse_result, plpgsql_print_strict_params, plpgsql_resolve_polymorphic_argtypes(), plpgsql_scanner_finish(), plpgsql_scanner_init(), plpgsql_start_datums(), PLPGSQL_TTYPE_ROW, PLPGSQL_TTYPE_SCALAR, plpgsql_variable_conflict, plpgsql_yyparse(), ErrorContextCallback::previous, PROARGMODE_IN, PROARGMODE_INOUT, PROARGMODE_OUT, PROARGMODE_TABLE, PROARGMODE_VARIADIC, PROCOID, PROVOLATILE_VOLATILE, pstrdup(), RECORDOID, ReleaseSysCache(), SearchSysCache1(), snprintf(), SysCacheGetAttr(), HeapTupleData::t_data, HeapTupleData::t_self, TEXTARRAYOID, TextDatumGetCString, TEXTOID, TopMemoryContext, TRIGGEROID, PLpgSQL_type::ttype, TYPEOID, TYPTYPE_PSEUDO, and VOIDOID.

Referenced by plpgsql_compile().

270 {
271  Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
272  bool is_dml_trigger = CALLED_AS_TRIGGER(fcinfo);
273  bool is_event_trigger = CALLED_AS_EVENT_TRIGGER(fcinfo);
274  Datum prosrcdatum;
275  bool isnull;
276  char *proc_source;
277  HeapTuple typeTup;
278  PLpgSQL_variable *var;
279  PLpgSQL_rec *rec;
280  int i;
281  ErrorContextCallback plerrcontext;
282  int parse_rc;
283  Oid rettypeid;
284  int numargs;
285  int num_in_args = 0;
286  int num_out_args = 0;
287  Oid *argtypes;
288  char **argnames;
289  char *argmodes;
290  int *in_arg_varnos = NULL;
291  PLpgSQL_variable **out_arg_variables;
292  MemoryContext func_cxt;
293 
294  /*
295  * Setup the scanner input and error info. We assume that this function
296  * cannot be invoked recursively, so there's no need to save and restore
297  * the static variables used here.
298  */
299  prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
300  Anum_pg_proc_prosrc, &isnull);
301  if (isnull)
302  elog(ERROR, "null prosrc");
303  proc_source = TextDatumGetCString(prosrcdatum);
304  plpgsql_scanner_init(proc_source);
305 
306  plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname));
307 
308  /*
309  * Setup error traceback support for ereport()
310  */
312  plerrcontext.arg = forValidator ? proc_source : NULL;
313  plerrcontext.previous = error_context_stack;
314  error_context_stack = &plerrcontext;
315 
316  /*
317  * Do extra syntax checks when validating the function definition. We skip
318  * this when actually compiling functions for execution, for performance
319  * reasons.
320  */
321  plpgsql_check_syntax = forValidator;
322 
323  /*
324  * Create the new function struct, if not done already. The function
325  * structs are never thrown away, so keep them in TopMemoryContext.
326  */
327  if (function == NULL)
328  {
329  function = (PLpgSQL_function *)
331  }
332  else
333  {
334  /* re-using a previously existing struct, so clear it out */
335  memset(function, 0, sizeof(PLpgSQL_function));
336  }
337  plpgsql_curr_compile = function;
338 
339  /*
340  * All the permanent output of compilation (e.g. parse tree) is kept in a
341  * per-function memory context, so it can be reclaimed easily.
342  */
344  "PL/pgSQL function context",
347 
348  function->fn_signature = format_procedure(fcinfo->flinfo->fn_oid);
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  /*
369  * Initialize the compiler, particularly the namespace stack. The
370  * outermost namespace contains function parameters and other special
371  * variables (such as FOUND), and is named after the function itself.
372  */
373  plpgsql_ns_init();
374  plpgsql_ns_push(NameStr(procStruct->proname), PLPGSQL_LABEL_BLOCK);
375  plpgsql_DumpExecTree = false;
377 
378  switch (function->fn_is_trigger)
379  {
380  case PLPGSQL_NOT_TRIGGER:
381 
382  /*
383  * Fetch info about the procedure's parameters. Allocations aren't
384  * needed permanently, so make them in tmp cxt.
385  *
386  * We also need to resolve any polymorphic input or output
387  * argument types. In validation mode we won't be able to, so we
388  * arbitrarily assume we are dealing with integers.
389  */
391 
392  numargs = get_func_arg_info(procTup,
393  &argtypes, &argnames, &argmodes);
394 
395  plpgsql_resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
396  fcinfo->flinfo->fn_expr,
397  forValidator,
399 
400  in_arg_varnos = (int *) palloc(numargs * sizeof(int));
401  out_arg_variables = (PLpgSQL_variable **) palloc(numargs * sizeof(PLpgSQL_variable *));
402 
403  MemoryContextSwitchTo(func_cxt);
404 
405  /*
406  * Create the variables for the procedure's parameters.
407  */
408  for (i = 0; i < numargs; i++)
409  {
410  char buf[32];
411  Oid argtypeid = argtypes[i];
412  char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
413  PLpgSQL_type *argdtype;
414  PLpgSQL_variable *argvariable;
415  PLpgSQL_nsitem_type argitemtype;
416 
417  /* Create $n name for variable */
418  snprintf(buf, sizeof(buf), "$%d", i + 1);
419 
420  /* Create datatype info */
421  argdtype = plpgsql_build_datatype(argtypeid,
422  -1,
423  function->fn_input_collation);
424 
425  /* Disallow pseudotype argument */
426  /* (note we already replaced polymorphic types) */
427  /* (build_variable would do this, but wrong message) */
428  if (argdtype->ttype != PLPGSQL_TTYPE_SCALAR &&
429  argdtype->ttype != PLPGSQL_TTYPE_ROW)
430  ereport(ERROR,
431  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
432  errmsg("PL/pgSQL functions cannot accept type %s",
433  format_type_be(argtypeid))));
434 
435  /*
436  * Build variable and add to datum list. If there's a name
437  * for the argument, use that as refname, else use $n name.
438  */
439  argvariable = plpgsql_build_variable((argnames &&
440  argnames[i][0] != '\0') ?
441  argnames[i] : buf,
442  0, argdtype, false);
443 
444  if (argvariable->dtype == PLPGSQL_DTYPE_VAR)
445  {
446  argitemtype = PLPGSQL_NSTYPE_VAR;
447  }
448  else
449  {
450  Assert(argvariable->dtype == PLPGSQL_DTYPE_ROW);
451  argitemtype = PLPGSQL_NSTYPE_ROW;
452  }
453 
454  /* Remember arguments in appropriate arrays */
455  if (argmode == PROARGMODE_IN ||
456  argmode == PROARGMODE_INOUT ||
457  argmode == PROARGMODE_VARIADIC)
458  in_arg_varnos[num_in_args++] = argvariable->dno;
459  if (argmode == PROARGMODE_OUT ||
460  argmode == PROARGMODE_INOUT ||
461  argmode == PROARGMODE_TABLE)
462  out_arg_variables[num_out_args++] = argvariable;
463 
464  /* Add to namespace under the $n name */
465  add_parameter_name(argitemtype, argvariable->dno, buf);
466 
467  /* If there's a name for the argument, make an alias */
468  if (argnames && argnames[i][0] != '\0')
469  add_parameter_name(argitemtype, argvariable->dno,
470  argnames[i]);
471  }
472 
473  /*
474  * If there's just one OUT parameter, out_param_varno points
475  * directly to it. If there's more than one, build a row that
476  * holds all of them.
477  */
478  if (num_out_args == 1)
479  function->out_param_varno = out_arg_variables[0]->dno;
480  else if (num_out_args > 1)
481  {
482  PLpgSQL_row *row = build_row_from_vars(out_arg_variables,
483  num_out_args);
484 
486  function->out_param_varno = row->dno;
487  }
488 
489  /*
490  * Check for a polymorphic returntype. If found, use the actual
491  * returntype type from the caller's FuncExpr node, if we have
492  * one. (In validation mode we arbitrarily assume we are dealing
493  * with integers.)
494  *
495  * Note: errcode is FEATURE_NOT_SUPPORTED because it should always
496  * work; if it doesn't we're in some context that fails to make
497  * the info available.
498  */
499  rettypeid = procStruct->prorettype;
500  if (IsPolymorphicType(rettypeid))
501  {
502  if (forValidator)
503  {
504  if (rettypeid == ANYARRAYOID)
505  rettypeid = INT4ARRAYOID;
506  else if (rettypeid == ANYRANGEOID)
507  rettypeid = INT4RANGEOID;
508  else /* ANYELEMENT or ANYNONARRAY */
509  rettypeid = INT4OID;
510  /* XXX what could we use for ANYENUM? */
511  }
512  else
513  {
514  rettypeid = get_fn_expr_rettype(fcinfo->flinfo);
515  if (!OidIsValid(rettypeid))
516  ereport(ERROR,
517  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
518  errmsg("could not determine actual return type "
519  "for polymorphic function \"%s\"",
521  }
522  }
523 
524  /*
525  * Normal function has a defined returntype
526  */
527  function->fn_rettype = rettypeid;
528  function->fn_retset = procStruct->proretset;
529 
530  /*
531  * Lookup the function's return type
532  */
533  if (rettypeid)
534  {
535  Form_pg_type typeStruct;
536 
537  typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(rettypeid));
538  if (!HeapTupleIsValid(typeTup))
539  elog(ERROR, "cache lookup failed for type %u", rettypeid);
540  typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
541 
542  /* Disallow pseudotype result, except VOID or RECORD */
543  /* (note we already replaced polymorphic types) */
544  if (typeStruct->typtype == TYPTYPE_PSEUDO)
545  {
546  if (rettypeid == VOIDOID ||
547  rettypeid == RECORDOID)
548  /* okay */ ;
549  else if (rettypeid == TRIGGEROID || rettypeid == EVTTRIGGEROID)
550  ereport(ERROR,
551  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
552  errmsg("trigger functions can only be called as triggers")));
553  else
554  ereport(ERROR,
555  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
556  errmsg("PL/pgSQL functions cannot return type %s",
557  format_type_be(rettypeid))));
558  }
559 
560  if (typeStruct->typrelid != InvalidOid ||
561  rettypeid == RECORDOID)
562  function->fn_retistuple = true;
563  else
564  {
565  function->fn_retbyval = typeStruct->typbyval;
566  function->fn_rettyplen = typeStruct->typlen;
567 
568  /*
569  * install $0 reference, but only for polymorphic return
570  * types, and not when the return is specified through an
571  * output parameter.
572  */
573  if (IsPolymorphicType(procStruct->prorettype) &&
574  num_out_args == 0)
575  {
576  (void) plpgsql_build_variable("$0", 0,
577  build_datatype(typeTup,
578  -1,
579  function->fn_input_collation),
580  true);
581  }
582  }
583  ReleaseSysCache(typeTup);
584  }
585  break;
586 
587  case PLPGSQL_DML_TRIGGER:
588  /* Trigger procedure's return type is unknown yet */
589  function->fn_rettype = InvalidOid;
590  function->fn_retbyval = false;
591  function->fn_retistuple = true;
592  function->fn_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, true);
603  function->new_varno = rec->dno;
604 
605  /* Add the record for referencing OLD ROW */
606  rec = plpgsql_build_record("old", 0, true);
607  function->old_varno = rec->dno;
608 
609  /* Add the variable tg_name */
610  var = plpgsql_build_variable("tg_name", 0,
612  -1,
613  InvalidOid),
614  true);
615  function->tg_name_varno = var->dno;
616 
617  /* Add the variable tg_when */
618  var = plpgsql_build_variable("tg_when", 0,
620  -1,
621  function->fn_input_collation),
622  true);
623  function->tg_when_varno = var->dno;
624 
625  /* Add the variable tg_level */
626  var = plpgsql_build_variable("tg_level", 0,
628  -1,
629  function->fn_input_collation),
630  true);
631  function->tg_level_varno = var->dno;
632 
633  /* Add the variable tg_op */
634  var = plpgsql_build_variable("tg_op", 0,
636  -1,
637  function->fn_input_collation),
638  true);
639  function->tg_op_varno = var->dno;
640 
641  /* Add the variable tg_relid */
642  var = plpgsql_build_variable("tg_relid", 0,
644  -1,
645  InvalidOid),
646  true);
647  function->tg_relid_varno = var->dno;
648 
649  /* Add the variable tg_relname */
650  var = plpgsql_build_variable("tg_relname", 0,
652  -1,
653  InvalidOid),
654  true);
655  function->tg_relname_varno = var->dno;
656 
657  /* tg_table_name is now preferred to tg_relname */
658  var = plpgsql_build_variable("tg_table_name", 0,
660  -1,
661  InvalidOid),
662  true);
663  function->tg_table_name_varno = var->dno;
664 
665  /* add the variable tg_table_schema */
666  var = plpgsql_build_variable("tg_table_schema", 0,
668  -1,
669  InvalidOid),
670  true);
671  function->tg_table_schema_varno = var->dno;
672 
673  /* Add the variable tg_nargs */
674  var = plpgsql_build_variable("tg_nargs", 0,
676  -1,
677  InvalidOid),
678  true);
679  function->tg_nargs_varno = var->dno;
680 
681  /* Add the variable tg_argv */
682  var = plpgsql_build_variable("tg_argv", 0,
684  -1,
685  function->fn_input_collation),
686  true);
687  function->tg_argv_varno = var->dno;
688 
689  break;
690 
692  function->fn_rettype = VOIDOID;
693  function->fn_retbyval = false;
694  function->fn_retistuple = true;
695  function->fn_retset = false;
696 
697  /* shouldn't be any declared arguments */
698  if (procStruct->pronargs != 0)
699  ereport(ERROR,
700  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
701  errmsg("event trigger functions cannot have declared arguments")));
702 
703  /* Add the variable tg_event */
704  var = plpgsql_build_variable("tg_event", 0,
706  -1,
707  function->fn_input_collation),
708  true);
709  function->tg_event_varno = var->dno;
710 
711  /* Add the variable tg_tag */
712  var = plpgsql_build_variable("tg_tag", 0,
714  -1,
715  function->fn_input_collation),
716  true);
717  function->tg_tag_varno = var->dno;
718 
719  break;
720 
721  default:
722  elog(ERROR, "unrecognized function typecode: %d",
723  (int) function->fn_is_trigger);
724  break;
725  }
726 
727  /* Remember if function is STABLE/IMMUTABLE */
728  function->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
729 
730  /*
731  * Create the magic FOUND variable.
732  */
733  var = plpgsql_build_variable("found", 0,
735  -1,
736  InvalidOid),
737  true);
738  function->found_varno = var->dno;
739 
740  /*
741  * Now parse the function's text
742  */
743  parse_rc = plpgsql_yyparse();
744  if (parse_rc != 0)
745  elog(ERROR, "plpgsql parser returned %d", parse_rc);
746  function->action = plpgsql_parse_result;
747 
749  pfree(proc_source);
750 
751  /*
752  * If it has OUT parameters or returns VOID or returns a set, we allow
753  * control to fall off the end without an explicit RETURN statement. The
754  * easiest way to implement this is to add a RETURN statement to the end
755  * of the statement list during parsing.
756  */
757  if (num_out_args > 0 || function->fn_rettype == VOIDOID ||
758  function->fn_retset)
759  add_dummy_return(function);
760 
761  /*
762  * Complete the function's info
763  */
764  function->fn_nargs = procStruct->pronargs;
765  for (i = 0; i < function->fn_nargs; i++)
766  function->fn_argvarnos[i] = in_arg_varnos[i];
767 
768  plpgsql_finish_datums(function);
769 
770  /* Debug dump for completed functions */
772  plpgsql_dumptree(function);
773 
774  /*
775  * add it to the hash table
776  */
777  plpgsql_HashTableInsert(function, hashkey);
778 
779  /*
780  * Pop the error context stack
781  */
782  error_context_stack = plerrcontext.previous;
783  plpgsql_error_funcname = NULL;
784 
785  plpgsql_check_syntax = false;
786 
789  return function;
790 }
int plpgsql_yyparse(void)
int fn_argvarnos[FUNC_MAX_ARGS]
Definition: plpgsql.h:829
#define CALLED_AS_EVENT_TRIGGER(fcinfo)
Definition: event_trigger.h:40
#define NAMEOID
Definition: pg_type.h:300
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation)
Definition: pl_comp.c:2136
#define OIDOID
Definition: pg_type.h:328
#define TEXTOID
Definition: pg_type.h:324
char * pstrdup(const char *in)
Definition: mcxt.c:1063
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
Definition: funcapi.c:846
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define Anum_pg_proc_prosrc
Definition: pg_proc.h:115
PLpgSQL_type_type ttype
Definition: plpgsql.h:180
#define INT4OID
Definition: pg_type.h:316
PLpgSQL_rec * plpgsql_build_record(const char *refname, int lineno, bool add2namespace)
Definition: pl_comp.c:1953
int plpgsql_extra_errors
Definition: pl_handler.c:55
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
#define PROARGMODE_VARIADIC
Definition: pg_proc.h:5558
void plpgsql_dumptree(PLpgSQL_function *func)
Definition: pl_funcs.c:1524
unsigned int Oid
Definition: postgres_ext.h:31
void(* callback)(void *arg)
Definition: elog.h:239
struct ErrorContextCallback * previous
Definition: elog.h:238
#define OidIsValid(objectId)
Definition: c.h:586
static void plpgsql_resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, Node *call_expr, bool forValidator, const char *proname)
Definition: pl_comp.c:2511
static void plpgsql_HashTableInsert(PLpgSQL_function *function, PLpgSQL_func_hashkey *func_key)
Definition: pl_comp.c:2613
static void plpgsql_start_datums(void)
Definition: pl_comp.c:2322
#define PROARGMODE_INOUT
Definition: pg_proc.h:5557
#define PROARGMODE_OUT
Definition: pg_proc.h:5556
HeapTupleHeader t_data
Definition: htup.h:67
ErrorContextCallback * error_context_stack
Definition: elog.c:88
void plpgsql_scanner_finish(void)
Definition: pl_scanner.c:729
FmgrInfo * flinfo
Definition: fmgr.h:79
void pfree(void *pointer)
Definition: mcxt.c:936
#define VOIDOID
Definition: pg_type.h:690
#define TEXTARRAYOID
Definition: pg_type.h:470
bool plpgsql_check_syntax
Definition: pl_comp.c:52
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
char * plpgsql_error_funcname
Definition: pl_comp.c:50
#define IsPolymorphicType(typid)
Definition: pg_type.h:745
bool plpgsql_DumpExecTree
Definition: pl_comp.c:51
#define ANYRANGEOID
Definition: pg_type.h:714
static void add_parameter_name(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
Definition: pl_comp.c:961
#define TRIGGEROID
Definition: pg_type.h:692
#define PROARGMODE_TABLE
Definition: pg_proc.h:5559
ItemPointerData t_self
Definition: htup.h:65
int plpgsql_extra_warnings
Definition: pl_handler.c:54
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
#define INT4RANGEOID
Definition: pg_type.h:648
static void add_dummy_return(PLpgSQL_function *function)
Definition: pl_comp.c:986
static char * buf
Definition: pg_test_fsync.c:67
#define RECORDOID
Definition: pg_type.h:680
void plpgsql_ns_init(void)
Definition: pl_funcs.c:45
#define ereport(elevel, rest)
Definition: elog.h:122
#define PROARGMODE_IN
Definition: pg_proc.h:5555
MemoryContext TopMemoryContext
Definition: mcxt.c:43
#define PROVOLATILE_VOLATILE
Definition: pg_proc.h:5539
Oid fn_input_collation
Definition: plpgsql.h:817
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:165
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
#define TextDatumGetCString(d)
Definition: builtins.h:92
#define ANYARRAYOID
Definition: pg_type.h:688
uintptr_t Datum
Definition: postgres.h:372
Oid get_fn_expr_rettype(FmgrInfo *flinfo)
Definition: fmgr.c:1882
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:728
#define InvalidOid
Definition: postgres_ext.h:36
Oid fn_oid
Definition: fmgr.h:59
PLpgSQL_trigtype fn_is_trigger
Definition: plpgsql.h:816
bool plpgsql_print_strict_params
Definition: pl_handler.c:48
char * format_procedure(Oid procedure_oid)
Definition: regproc.c:323
static void plpgsql_compile_error_callback(void *arg)
Definition: pl_comp.c:934
int plpgsql_variable_conflict
Definition: pl_handler.c:46
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define EVTTRIGGEROID
Definition: pg_type.h:694
#define CALLED_AS_TRIGGER(fcinfo)
Definition: trigger.h:25
#define Assert(condition)
Definition: c.h:680
fmNodePtr fn_expr
Definition: fmgr.h:66
void plpgsql_ns_push(const char *label, PLpgSQL_label_type label_type)
Definition: pl_funcs.c:56
PLpgSQL_stmt_block * plpgsql_parse_result
Definition: pl_comp.c:43
PLpgSQL_variable * plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype, bool add2namespace)
Definition: pl_comp.c:1873
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:307
PLpgSQL_datum_type dtype
Definition: plpgsql.h:210
#define BOOLOID
Definition: pg_type.h:288
#define TYPTYPE_PSEUDO
Definition: pg_type.h:724
void plpgsql_scanner_init(const char *str)
Definition: pl_scanner.c:702
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation)
Definition: pl_comp.c:2156
void * palloc(Size size)
Definition: mcxt.c:835
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void plpgsql_finish_datums(PLpgSQL_function *function)
Definition: pl_comp.c:2359
void plpgsql_adddatum(PLpgSQL_datum *new)
Definition: pl_comp.c:2339
int i
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:57
#define NameStr(name)
Definition: c.h:557
#define elog
Definition: elog.h:219
#define INT4ARRAYOID
Definition: pg_type.h:467
static PLpgSQL_row * build_row_from_vars(PLpgSQL_variable **vars, int numvars)
Definition: pl_comp.c:2072
PLpgSQL_function * plpgsql_curr_compile
Definition: pl_comp.c:54
PLpgSQL_nsitem_type
Definition: plpgsql.h:38

◆ make_datum_param()

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

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

1315 {
1316  PLpgSQL_execstate *estate;
1317  PLpgSQL_datum *datum;
1318  Param *param;
1319  MemoryContext oldcontext;
1320 
1321  /* see comment in resolve_column_ref */
1322  estate = expr->func->cur_estate;
1323  Assert(dno >= 0 && dno < estate->ndatums);
1324  datum = estate->datums[dno];
1325 
1326  /*
1327  * Bitmapset must be allocated in function's permanent memory context
1328  */
1329  oldcontext = MemoryContextSwitchTo(expr->func->fn_cxt);
1330  expr->paramnos = bms_add_member(expr->paramnos, dno);
1331  MemoryContextSwitchTo(oldcontext);
1332 
1333  param = makeNode(Param);
1334  param->paramkind = PARAM_EXTERN;
1335  param->paramid = dno + 1;
1337  datum,
1338  &param->paramtype,
1339  &param->paramtypmod,
1340  &param->paramcollid);
1341  param->location = location;
1342 
1343  return (Node *) param;
1344 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ParamKind paramkind
Definition: primnodes.h:244
Definition: nodes.h:512
PLpgSQL_datum ** datums
Definition: plpgsql.h:900
Bitmapset * paramnos
Definition: plpgsql.h:225
struct PLpgSQL_execstate * cur_estate
Definition: plpgsql.h:866
Oid paramcollid
Definition: primnodes.h:248
int location
Definition: primnodes.h:249
MemoryContext fn_cxt
Definition: plpgsql.h:819
void plpgsql_exec_get_datum_type_info(PLpgSQL_execstate *estate, PLpgSQL_datum *datum, Oid *typeid, int32 *typmod, Oid *collation)
Definition: pl_exec.c:5012
struct PLpgSQL_function * func
Definition: plpgsql.h:229
int32 paramtypmod
Definition: primnodes.h:247
#define makeNode(_type_)
Definition: nodes.h:560
#define Assert(condition)
Definition: c.h:680
int paramid
Definition: primnodes.h:245
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:698
Oid paramtype
Definition: primnodes.h:246

◆ plpgsql_add_initdatums()

int plpgsql_add_initdatums ( int **  varnos)

Definition at line 2400 of file pl_comp.c.

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

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

◆ plpgsql_adddatum()

void plpgsql_adddatum ( PLpgSQL_datum new)

Definition at line 2339 of file pl_comp.c.

References datums_alloc, plpgsql_nDatums, and repalloc().

Referenced by do_compile(), plpgsql_build_record(), plpgsql_build_variable(), plpgsql_parse_dblword(), and plpgsql_parse_tripword().

2340 {
2342  {
2343  datums_alloc *= 2;
2345  }
2346 
2347  new->dno = plpgsql_nDatums;
2349 }
int plpgsql_nDatums
Definition: pl_comp.c:46
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:47
static int datums_alloc
Definition: pl_comp.c:45
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:949

◆ plpgsql_build_datatype()

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

Definition at line 2136 of file pl_comp.c.

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

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

2137 {
2138  HeapTuple typeTup;
2139  PLpgSQL_type *typ;
2140 
2141  typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
2142  if (!HeapTupleIsValid(typeTup))
2143  elog(ERROR, "cache lookup failed for type %u", typeOid);
2144 
2145  typ = build_datatype(typeTup, typmod, collation);
2146 
2147  ReleaseSysCache(typeTup);
2148 
2149  return typ;
2150 }
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation)
Definition: pl_comp.c:2156
#define elog
Definition: elog.h:219

◆ plpgsql_build_record()

PLpgSQL_rec* plpgsql_build_record ( const char *  refname,
int  lineno,
bool  add2namespace 
)

Definition at line 1953 of file pl_comp.c.

References PLpgSQL_datum::dno, PLpgSQL_rec::dtype, PLpgSQL_rec::freetup, PLpgSQL_rec::freetupdesc, PLpgSQL_rec::lineno, palloc0(), plpgsql_adddatum(), PLPGSQL_DTYPE_REC, plpgsql_ns_additem(), PLPGSQL_NSTYPE_REC, pstrdup(), PLpgSQL_rec::refname, PLpgSQL_rec::tup, and PLpgSQL_rec::tupdesc.

Referenced by do_compile(), and plpgsql_build_variable().

1954 {
1955  PLpgSQL_rec *rec;
1956 
1957  rec = palloc0(sizeof(PLpgSQL_rec));
1958  rec->dtype = PLPGSQL_DTYPE_REC;
1959  rec->refname = pstrdup(refname);
1960  rec->lineno = lineno;
1961  rec->tup = NULL;
1962  rec->tupdesc = NULL;
1963  rec->freetup = false;
1964  rec->freetupdesc = false;
1966  if (add2namespace)
1968 
1969  return rec;
1970 }
PLpgSQL_datum_type dtype
Definition: plpgsql.h:302
TupleDesc tupdesc
Definition: plpgsql.h:308
char * pstrdup(const char *in)
Definition: mcxt.c:1063
bool freetup
Definition: plpgsql.h:309
void plpgsql_ns_additem(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
Definition: pl_funcs.c:94
char * refname
Definition: plpgsql.h:304
void * palloc0(Size size)
Definition: mcxt.c:864
bool freetupdesc
Definition: plpgsql.h:310
HeapTuple tup
Definition: plpgsql.h:307
void plpgsql_adddatum(PLpgSQL_datum *new)
Definition: pl_comp.c:2339
int lineno
Definition: plpgsql.h:305

◆ plpgsql_build_variable()

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

Definition at line 1873 of file pl_comp.c.

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

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

1875 {
1876  PLpgSQL_variable *result;
1877 
1878  switch (dtype->ttype)
1879  {
1880  case PLPGSQL_TTYPE_SCALAR:
1881  {
1882  /* Ordinary scalar datatype */
1883  PLpgSQL_var *var;
1884 
1885  var = palloc0(sizeof(PLpgSQL_var));
1886  var->dtype = PLPGSQL_DTYPE_VAR;
1887  var->refname = pstrdup(refname);
1888  var->lineno = lineno;
1889  var->datatype = dtype;
1890  /* other fields might be filled by caller */
1891 
1892  /* preset to NULL */
1893  var->value = 0;
1894  var->isnull = true;
1895  var->freeval = false;
1896 
1898  if (add2namespace)
1900  var->dno,
1901  refname);
1902  result = (PLpgSQL_variable *) var;
1903  break;
1904  }
1905  case PLPGSQL_TTYPE_ROW:
1906  {
1907  /* Composite type -- build a row variable */
1908  PLpgSQL_row *row;
1909 
1910  row = build_row_from_class(dtype->typrelid);
1911 
1912  row->dtype = PLPGSQL_DTYPE_ROW;
1913  row->refname = pstrdup(refname);
1914  row->lineno = lineno;
1915 
1917  if (add2namespace)
1919  row->dno,
1920  refname);
1921  result = (PLpgSQL_variable *) row;
1922  break;
1923  }
1924  case PLPGSQL_TTYPE_REC:
1925  {
1926  /* "record" type -- build a record variable */
1927  PLpgSQL_rec *rec;
1928 
1929  rec = plpgsql_build_record(refname, lineno, add2namespace);
1930  result = (PLpgSQL_variable *) rec;
1931  break;
1932  }
1933  case PLPGSQL_TTYPE_PSEUDO:
1934  ereport(ERROR,
1935  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1936  errmsg("variable \"%s\" has pseudo-type %s",
1937  refname, format_type_be(dtype->typoid))));
1938  result = NULL; /* keep compiler quiet */
1939  break;
1940  default:
1941  elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
1942  result = NULL; /* keep compiler quiet */
1943  break;
1944  }
1945 
1946  return result;
1947 }
char * refname
Definition: plpgsql.h:281
char * refname
Definition: plpgsql.h:258
static PLpgSQL_row * build_row_from_class(Oid classOid)
Definition: pl_comp.c:1976
PLpgSQL_datum_type dtype
Definition: plpgsql.h:256
char * pstrdup(const char *in)
Definition: mcxt.c:1063
PLpgSQL_type * datatype
Definition: plpgsql.h:261
void plpgsql_ns_additem(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
Definition: pl_funcs.c:94
PLpgSQL_type_type ttype
Definition: plpgsql.h:180
PLpgSQL_rec * plpgsql_build_record(const char *refname, int lineno, bool add2namespace)
Definition: pl_comp.c:1953
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
bool freeval
Definition: plpgsql.h:271
Oid typrelid
Definition: plpgsql.h:184
void * palloc0(Size size)
Definition: mcxt.c:864
Datum value
Definition: plpgsql.h:269
int lineno
Definition: plpgsql.h:259
int errmsg(const char *fmt,...)
Definition: elog.c:797
void plpgsql_adddatum(PLpgSQL_datum *new)
Definition: pl_comp.c:2339
#define elog
Definition: elog.h:219
PLpgSQL_datum_type dtype
Definition: plpgsql.h:279
int lineno
Definition: plpgsql.h:282
bool isnull
Definition: plpgsql.h:270
Oid typoid
Definition: plpgsql.h:179

◆ plpgsql_compile()

PLpgSQL_function* plpgsql_compile ( FunctionCallInfo  fcinfo,
bool  forValidator 
)

Definition at line 137 of file pl_comp.c.

References compute_function_hashkey(), delete_function(), do_compile(), elog, ERROR, FunctionCallInfoData::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().

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

◆ plpgsql_compile_error_callback()

static void plpgsql_compile_error_callback ( void *  arg)
static

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

935 {
936  if (arg)
937  {
938  /*
939  * Try to convert syntax error position to reference text of original
940  * CREATE FUNCTION or DO command.
941  */
942  if (function_parse_error_transpose((const char *) arg))
943  return;
944 
945  /*
946  * Done if a syntax error position was reported; otherwise we have to
947  * fall back to a "near line N" report.
948  */
949  }
950 
952  errcontext("compilation of PL/pgSQL function \"%s\" near line %d",
954 }
int plpgsql_latest_lineno(void)
Definition: pl_scanner.c:688
char * plpgsql_error_funcname
Definition: pl_comp.c:50
bool function_parse_error_transpose(const char *prosrc)
Definition: pg_proc.c:985
#define errcontext
Definition: elog.h:164
void * arg

◆ plpgsql_compile_inline()

PLpgSQL_function* plpgsql_compile_inline ( char *  proc_source)

Definition at line 803 of file pl_comp.c.

References add_dummy_return(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, ErrorContextCallback::arg, BOOLOID, 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, pstrdup(), and VOIDOID.

Referenced by plpgsql_inline_handler().

804 {
805  char *func_name = "inline_code_block";
806  PLpgSQL_function *function;
807  ErrorContextCallback plerrcontext;
808  PLpgSQL_variable *var;
809  int parse_rc;
810  MemoryContext func_cxt;
811 
812  /*
813  * Setup the scanner input and error info. We assume that this function
814  * cannot be invoked recursively, so there's no need to save and restore
815  * the static variables used here.
816  */
817  plpgsql_scanner_init(proc_source);
818 
819  plpgsql_error_funcname = func_name;
820 
821  /*
822  * Setup error traceback support for ereport()
823  */
825  plerrcontext.arg = proc_source;
826  plerrcontext.previous = error_context_stack;
827  error_context_stack = &plerrcontext;
828 
829  /* Do extra syntax checking if check_function_bodies is on */
831 
832  /* Function struct does not live past current statement */
833  function = (PLpgSQL_function *) palloc0(sizeof(PLpgSQL_function));
834 
835  plpgsql_curr_compile = function;
836 
837  /*
838  * All the rest of the compile-time storage (e.g. parse tree) is kept in
839  * its own memory context, so it can be reclaimed easily.
840  */
842  "PL/pgSQL inline code context",
845 
846  function->fn_signature = pstrdup(func_name);
847  function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
848  function->fn_input_collation = InvalidOid;
849  function->fn_cxt = func_cxt;
850  function->out_param_varno = -1; /* set up for no OUT param */
851  function->resolve_option = plpgsql_variable_conflict;
852  function->print_strict_params = plpgsql_print_strict_params;
853 
854  /*
855  * don't do extra validation for inline code as we don't want to add spam
856  * at runtime
857  */
858  function->extra_warnings = 0;
859  function->extra_errors = 0;
860 
861  plpgsql_ns_init();
863  plpgsql_DumpExecTree = false;
865 
866  /* Set up as though in a function returning VOID */
867  function->fn_rettype = VOIDOID;
868  function->fn_retset = false;
869  function->fn_retistuple = false;
870  /* a bit of hardwired knowledge about type VOID here */
871  function->fn_retbyval = true;
872  function->fn_rettyplen = sizeof(int32);
873 
874  /*
875  * Remember if function is STABLE/IMMUTABLE. XXX would it be better to
876  * set this true inside a read-only transaction? Not clear.
877  */
878  function->fn_readonly = false;
879 
880  /*
881  * Create the magic FOUND variable.
882  */
883  var = plpgsql_build_variable("found", 0,
885  -1,
886  InvalidOid),
887  true);
888  function->found_varno = var->dno;
889 
890  /*
891  * Now parse the function's text
892  */
893  parse_rc = plpgsql_yyparse();
894  if (parse_rc != 0)
895  elog(ERROR, "plpgsql parser returned %d", parse_rc);
896  function->action = plpgsql_parse_result;
897 
899 
900  /*
901  * If it returns VOID (always true at the moment), we allow control to
902  * fall off the end without an explicit RETURN statement.
903  */
904  if (function->fn_rettype == VOIDOID)
905  add_dummy_return(function);
906 
907  /*
908  * Complete the function's info
909  */
910  function->fn_nargs = 0;
911 
912  plpgsql_finish_datums(function);
913 
914  /*
915  * Pop the error context stack
916  */
917  error_context_stack = plerrcontext.previous;
918  plpgsql_error_funcname = NULL;
919 
920  plpgsql_check_syntax = false;
921 
924  return function;
925 }
int plpgsql_yyparse(void)
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation)
Definition: pl_comp.c:2136
char * pstrdup(const char *in)
Definition: mcxt.c:1063
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool check_function_bodies
Definition: guc.c:447
void(* callback)(void *arg)
Definition: elog.h:239
struct ErrorContextCallback * previous
Definition: elog.h:238
static void plpgsql_start_datums(void)
Definition: pl_comp.c:2322
signed int int32
Definition: c.h:294
ErrorContextCallback * error_context_stack
Definition: elog.c:88
void plpgsql_scanner_finish(void)
Definition: pl_scanner.c:729
#define VOIDOID
Definition: pg_type.h:690
bool plpgsql_check_syntax
Definition: pl_comp.c:52
#define ERROR
Definition: elog.h:43
char * plpgsql_error_funcname
Definition: pl_comp.c:50
bool plpgsql_DumpExecTree
Definition: pl_comp.c:51
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
static void add_dummy_return(PLpgSQL_function *function)
Definition: pl_comp.c:986
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
void plpgsql_ns_init(void)
Definition: pl_funcs.c:45
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:165
void * palloc0(Size size)
Definition: mcxt.c:864
#define InvalidOid
Definition: postgres_ext.h:36
bool plpgsql_print_strict_params
Definition: pl_handler.c:48
static void plpgsql_compile_error_callback(void *arg)
Definition: pl_comp.c:934
int plpgsql_variable_conflict
Definition: pl_handler.c:46
void plpgsql_ns_push(const char *label, PLpgSQL_label_type label_type)
Definition: pl_funcs.c:56
PLpgSQL_stmt_block * plpgsql_parse_result
Definition: pl_comp.c:43
PLpgSQL_variable * plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype, bool add2namespace)
Definition: pl_comp.c:1873
#define BOOLOID
Definition: pg_type.h:288
on_exit_nicely_callback function
void plpgsql_scanner_init(const char *str)
Definition: pl_scanner.c:702
static void plpgsql_finish_datums(PLpgSQL_function *function)
Definition: pl_comp.c:2359
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:57
#define elog
Definition: elog.h:219
PLpgSQL_function * plpgsql_curr_compile
Definition: pl_comp.c:54

◆ plpgsql_finish_datums()

static void plpgsql_finish_datums ( PLpgSQL_function function)
static

Definition at line 2359 of file pl_comp.c.

References bms_add_member(), PLpgSQL_function::datums, PLpgSQL_datum::dtype, plpgsql_hashent::function, i, palloc(), PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_RECFIELD, PLPGSQL_DTYPE_ROW, and plpgsql_nDatums.

Referenced by do_compile(), and plpgsql_compile_inline().

2360 {
2361  Bitmapset *resettable_datums = NULL;
2362  int i;
2363 
2364  function->ndatums = plpgsql_nDatums;
2365  function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
2366  for (i = 0; i < plpgsql_nDatums; i++)
2367  {
2368  function->datums[i] = plpgsql_Datums[i];
2369  switch (function->datums[i]->dtype)
2370  {
2371  case PLPGSQL_DTYPE_ROW:
2372  case PLPGSQL_DTYPE_REC:
2374  resettable_datums = bms_add_member(resettable_datums, i);
2375  break;
2376 
2377  default:
2378  break;
2379  }
2380  }
2381  function->resettable_datums = resettable_datums;
2382 }
int plpgsql_nDatums
Definition: pl_comp.c:46
PLpgSQL_datum ** datums
Definition: plpgsql.h:859
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:47
PLpgSQL_datum_type dtype
Definition: plpgsql.h:198
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:698
void * palloc(Size size)
Definition: mcxt.c:835
int i

◆ plpgsql_HashTableDelete()

static void plpgsql_HashTableDelete ( PLpgSQL_function function)
static

Definition at line 2632 of file pl_comp.c.

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

Referenced by delete_function().

2633 {
2634  plpgsql_HashEnt *hentry;
2635 
2636  /* do nothing if not in table */
2637  if (function->fn_hashkey == NULL)
2638  return;
2639 
2641  (void *) function->fn_hashkey,
2642  HASH_REMOVE,
2643  NULL);
2644  if (hentry == NULL)
2645  elog(WARNING, "trying to delete function that does not exist");
2646 
2647  /* remove back link, which no longer points to allocated storage */
2648  function->fn_hashkey = NULL;
2649 }
PLpgSQL_func_hashkey * fn_hashkey
Definition: plpgsql.h:818
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:904
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:63
#define WARNING
Definition: elog.h:40
#define elog
Definition: elog.h:219

◆ plpgsql_HashTableInit()

void plpgsql_HashTableInit ( void  )

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

2582 {
2583  HASHCTL ctl;
2584 
2585  /* don't allow double-initialization */
2586  Assert(plpgsql_HashTable == NULL);
2587 
2588  memset(&ctl, 0, sizeof(ctl));
2589  ctl.keysize = sizeof(PLpgSQL_func_hashkey);
2590  ctl.entrysize = sizeof(plpgsql_HashEnt);
2591  plpgsql_HashTable = hash_create("PLpgSQL function cache",
2593  &ctl,
2594  HASH_ELEM | HASH_BLOBS);
2595 }
#define FUNCS_PER_USER
Definition: pl_comp.c:71
#define HASH_ELEM
Definition: hsearch.h:87
Size entrysize
Definition: hsearch.h:73
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:63
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:680

◆ plpgsql_HashTableInsert()

static void plpgsql_HashTableInsert ( PLpgSQL_function function,
PLpgSQL_func_hashkey func_key 
)
static

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

2615 {
2616  plpgsql_HashEnt *hentry;
2617  bool found;
2618 
2620  (void *) func_key,
2621  HASH_ENTER,
2622  &found);
2623  if (found)
2624  elog(WARNING, "trying to insert a function that already exists");
2625 
2626  hentry->function = function;
2627  /* prepare back link from function to hashtable key */
2628  function->fn_hashkey = &hentry->key;
2629 }
PLpgSQL_func_hashkey * fn_hashkey
Definition: plpgsql.h:818
PLpgSQL_func_hashkey key
Definition: pl_comp.c:67
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:904
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:63
PLpgSQL_function * function
Definition: pl_comp.c:68
#define WARNING
Definition: elog.h:40
#define elog
Definition: elog.h:219

◆ plpgsql_HashTableLookup()

static PLpgSQL_function * plpgsql_HashTableLookup ( PLpgSQL_func_hashkey func_key)
static

Definition at line 2598 of file pl_comp.c.

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

Referenced by plpgsql_compile().

2599 {
2600  plpgsql_HashEnt *hentry;
2601 
2603  (void *) func_key,
2604  HASH_FIND,
2605  NULL);
2606  if (hentry)
2607  return hentry->function;
2608  else
2609  return NULL;
2610 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:904
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:63
PLpgSQL_function * function
Definition: pl_comp.c:68

◆ plpgsql_param_ref()

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

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

1099 {
1100  PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1101  char pname[32];
1102  PLpgSQL_nsitem *nse;
1103 
1104  snprintf(pname, sizeof(pname), "$%d", pref->number);
1105 
1106  nse = plpgsql_ns_lookup(expr->ns, false,
1107  pname, NULL, NULL,
1108  NULL);
1109 
1110  if (nse == NULL)
1111  return NULL; /* name not known to plpgsql */
1112 
1113  return make_datum_param(expr, nse->itemno, pref->location);
1114 }
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:132
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
struct PLpgSQL_nsitem * ns
Definition: plpgsql.h:232
int number
Definition: parsenodes.h:244
int location
Definition: parsenodes.h:245
void * p_ref_hook_state
Definition: parse_node.h:215
static Node * make_datum_param(PLpgSQL_expr *expr, int dno, int location)
Definition: pl_comp.c:1314

◆ plpgsql_parse_cwordrowtype()

PLpgSQL_type* plpgsql_parse_cwordrowtype ( List idents)

Definition at line 1839 of file pl_comp.c.

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

1840 {
1841  Oid classOid;
1842  RangeVar *relvar;
1843  MemoryContext oldCxt;
1844 
1845  if (list_length(idents) != 2)
1846  return NULL;
1847 
1848  /* Avoid memory leaks in long-term function context */
1850 
1851  /* Look up relation name. Can't lock it - we might not have privileges. */
1852  relvar = makeRangeVar(strVal(linitial(idents)),
1853  strVal(lsecond(idents)),
1854  -1);
1855  classOid = RangeVarGetRelid(relvar, NoLock, false);
1856 
1857  MemoryContextSwitchTo(oldCxt);
1858 
1859  /* Build and return the row type struct */
1860  return plpgsql_build_datatype(get_rel_type_id(classOid), -1, InvalidOid);
1861 }
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation)
Definition: pl_comp.c:2136
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:53
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:116
#define linitial(l)
Definition: pg_list.h:111
#define NoLock
Definition: lockdefs.h:34
Oid get_rel_type_id(Oid relid)
Definition: lsyscache.c:1796
#define InvalidOid
Definition: postgres_ext.h:36
static int list_length(const List *l)
Definition: pg_list.h:89
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:57
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:421

◆ plpgsql_parse_cwordtype()

PLpgSQL_type* plpgsql_parse_cwordtype ( List idents)

Definition at line 1700 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(), RELKIND_COMPOSITE_TYPE, RELKIND_FOREIGN_TABLE, RELKIND_MATVIEW, RELKIND_PARTITIONED_TABLE, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW, RelnameGetRelid(), RELOID, SearchSysCache1(), SearchSysCacheAttName(), strVal, and TYPEOID.

1701 {
1702  PLpgSQL_type *dtype = NULL;
1703  PLpgSQL_nsitem *nse;
1704  const char *fldname;
1705  Oid classOid;
1706  HeapTuple classtup = NULL;
1707  HeapTuple attrtup = NULL;
1708  HeapTuple typetup = NULL;
1709  Form_pg_class classStruct;
1710  Form_pg_attribute attrStruct;
1711  MemoryContext oldCxt;
1712 
1713  /* Avoid memory leaks in the long-term function context */
1715 
1716  if (list_length(idents) == 2)
1717  {
1718  /*
1719  * Do a lookup in the current namespace stack. We don't need to check
1720  * number of names matched, because we will only consider scalar
1721  * variables.
1722  */
1723  nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1724  strVal(linitial(idents)),
1725  strVal(lsecond(idents)),
1726  NULL,
1727  NULL);
1728 
1729  if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_VAR)
1730  {
1731  dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1732  goto done;
1733  }
1734 
1735  /*
1736  * First word could also be a table name
1737  */
1738  classOid = RelnameGetRelid(strVal(linitial(idents)));
1739  if (!OidIsValid(classOid))
1740  goto done;
1741  fldname = strVal(lsecond(idents));
1742  }
1743  else if (list_length(idents) == 3)
1744  {
1745  RangeVar *relvar;
1746 
1747  relvar = makeRangeVar(strVal(linitial(idents)),
1748  strVal(lsecond(idents)),
1749  -1);
1750  /* Can't lock relation - we might not have privileges. */
1751  classOid = RangeVarGetRelid(relvar, NoLock, true);
1752  if (!OidIsValid(classOid))
1753  goto done;
1754  fldname = strVal(lthird(idents));
1755  }
1756  else
1757  goto done;
1758 
1759  classtup = SearchSysCache1(RELOID, ObjectIdGetDatum(classOid));
1760  if (!HeapTupleIsValid(classtup))
1761  goto done;
1762  classStruct = (Form_pg_class) GETSTRUCT(classtup);
1763 
1764  /*
1765  * It must be a relation, sequence, view, materialized view, composite
1766  * type, or foreign table
1767  */
1768  if (classStruct->relkind != RELKIND_RELATION &&
1769  classStruct->relkind != RELKIND_SEQUENCE &&
1770  classStruct->relkind != RELKIND_VIEW &&
1771  classStruct->relkind != RELKIND_MATVIEW &&
1772  classStruct->relkind != RELKIND_COMPOSITE_TYPE &&
1773  classStruct->relkind != RELKIND_FOREIGN_TABLE &&
1774  classStruct->relkind != RELKIND_PARTITIONED_TABLE)
1775  goto done;
1776 
1777  /*
1778  * Fetch the named table field and its type
1779  */
1780  attrtup = SearchSysCacheAttName(classOid, fldname);
1781  if (!HeapTupleIsValid(attrtup))
1782  goto done;
1783  attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1784 
1785  typetup = SearchSysCache1(TYPEOID,
1786  ObjectIdGetDatum(attrStruct->atttypid));
1787  if (!HeapTupleIsValid(typetup))
1788  elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1789 
1790  /*
1791  * Found that - build a compiler type struct in the caller's cxt and
1792  * return it
1793  */
1794  MemoryContextSwitchTo(oldCxt);
1795  dtype = build_datatype(typetup,
1796  attrStruct->atttypmod,
1797  attrStruct->attcollation);
1799 
1800 done:
1801  if (HeapTupleIsValid(classtup))
1802  ReleaseSysCache(classtup);
1803  if (HeapTupleIsValid(attrtup))
1804  ReleaseSysCache(attrtup);
1805  if (HeapTupleIsValid(typetup))
1806  ReleaseSysCache(typetup);
1807 
1808  MemoryContextSwitchTo(oldCxt);
1809  return dtype;
1810 }
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:47
PLpgSQL_nsitem * plpgsql_ns_top(void)
Definition: pl_funcs.c:83
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
Oid RelnameGetRelid(const char *relname)
Definition: namespace.c:654
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:53
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:132
#define RELKIND_MATVIEW
Definition: pg_class.h:165
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:586
#define lsecond(l)
Definition: pg_list.h:116
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
#define linitial(l)
Definition: pg_list.h:111
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
static int list_length(const List *l)
Definition: pg_list.h:89
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1248
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation)
Definition: pl_comp.c:2156
#define RELKIND_VIEW
Definition: pg_class.h:164
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:351
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:57
#define lthird(l)
Definition: pg_list.h:121
#define elog
Definition: elog.h:219
#define RELKIND_RELATION
Definition: pg_class.h:160
#define RELKIND_SEQUENCE
Definition: pg_class.h:162
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:421

◆ plpgsql_parse_dblword()

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

Definition at line 1420 of file pl_comp.c.

References PLwdatum::datum, PLpgSQL_row::fieldnames, i, PLwdatum::ident, IDENTIFIER_LOOKUP_DECLARE, PLcword::idents, PLwdatum::idents, PLpgSQL_nsitem::itemno, PLpgSQL_nsitem::itemtype, list_make2, makeString(), PLpgSQL_row::nfields, palloc(), plpgsql_adddatum(), PLPGSQL_DTYPE_RECFIELD, plpgsql_IdentifierLookup, plpgsql_ns_lookup(), plpgsql_ns_top(), PLPGSQL_NSTYPE_REC, PLPGSQL_NSTYPE_ROW, PLPGSQL_NSTYPE_VAR, pstrdup(), PLwdatum::quoted, and PLpgSQL_row::varnos.

Referenced by plpgsql_yylex().

1422 {
1423  PLpgSQL_nsitem *ns;
1424  List *idents;
1425  int nnames;
1426 
1427  idents = list_make2(makeString(word1),
1428  makeString(word2));
1429 
1430  /*
1431  * We should do nothing in DECLARE sections. In SQL expressions, we
1432  * really only need to make sure that RECFIELD datums are created when
1433  * needed.
1434  */
1436  {
1437  /*
1438  * Do a lookup in the current namespace stack
1439  */
1440  ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1441  word1, word2, NULL,
1442  &nnames);
1443  if (ns != NULL)
1444  {
1445  switch (ns->itemtype)
1446  {
1447  case PLPGSQL_NSTYPE_VAR:
1448  /* Block-qualified reference to scalar variable. */
1449  wdatum->datum = plpgsql_Datums[ns->itemno];
1450  wdatum->ident = NULL;
1451  wdatum->quoted = false; /* not used */
1452  wdatum->idents = idents;
1453  return true;
1454 
1455  case PLPGSQL_NSTYPE_REC:
1456  if (nnames == 1)
1457  {
1458  /*
1459  * First word is a record name, so second word could
1460  * be a field in this record. We build a RECFIELD
1461  * datum whether it is or not --- any error will be
1462  * detected later.
1463  */
1464  PLpgSQL_recfield *new;
1465 
1466  new = palloc(sizeof(PLpgSQL_recfield));
1467  new->dtype = PLPGSQL_DTYPE_RECFIELD;
1468  new->fieldname = pstrdup(word2);
1469  new->recparentno = ns->itemno;
1470 
1472 
1473  wdatum->datum = (PLpgSQL_datum *) new;
1474  }
1475  else
1476  {
1477  /* Block-qualified reference to record variable. */
1478  wdatum->datum = plpgsql_Datums[ns->itemno];
1479  }
1480  wdatum->ident = NULL;
1481  wdatum->quoted = false; /* not used */
1482  wdatum->idents = idents;
1483  return true;
1484 
1485  case PLPGSQL_NSTYPE_ROW:
1486  if (nnames == 1)
1487  {
1488  /*
1489  * First word is a row name, so second word could be a
1490  * field in this row. Again, no error now if it
1491  * isn't.
1492  */
1493  PLpgSQL_row *row;
1494  int i;
1495 
1496  row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
1497  for (i = 0; i < row->nfields; i++)
1498  {
1499  if (row->fieldnames[i] &&
1500  strcmp(row->fieldnames[i], word2) == 0)
1501  {
1502  wdatum->datum = plpgsql_Datums[row->varnos[i]];
1503  wdatum->ident = NULL;
1504  wdatum->quoted = false; /* not used */
1505  wdatum->idents = idents;
1506  return true;
1507  }
1508  }
1509  /* fall through to return CWORD */
1510  }
1511  else
1512  {
1513  /* Block-qualified reference to row variable. */
1514  wdatum->datum = plpgsql_Datums[ns->itemno];
1515  wdatum->ident = NULL;
1516  wdatum->quoted = false; /* not used */
1517  wdatum->idents = idents;
1518  return true;
1519  }
1520  break;
1521 
1522  default:
1523  break;
1524  }
1525  }
1526  }
1527 
1528  /* Nothing found */
1529  cword->idents = idents;
1530  return false;
1531 }
#define list_make2(x1, x2)
Definition: pg_list.h:140
Value * makeString(char *str)
Definition: value.c:53
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:47
PLpgSQL_nsitem * plpgsql_ns_top(void)
Definition: pl_funcs.c:83
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:132
char * pstrdup(const char *in)
Definition: mcxt.c:1063
char ** fieldnames
Definition: plpgsql.h:293
List * idents
Definition: plpgsql.h:987
List * idents
Definition: plpgsql.h:995
int * varnos
Definition: plpgsql.h:294
IdentifierLookup plpgsql_IdentifierLookup
Definition: pl_scanner.c:29
int nfields
Definition: plpgsql.h:292
PLpgSQL_datum * datum
Definition: plpgsql.h:992
bool quoted
Definition: plpgsql.h:994
char * ident
Definition: plpgsql.h:993
void * palloc(Size size)
Definition: mcxt.c:835
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:351
void plpgsql_adddatum(PLpgSQL_datum *new)
Definition: pl_comp.c:2339
int i
Definition: pg_list.h:45

◆ plpgsql_parse_err_condition()

PLpgSQL_condition* plpgsql_parse_err_condition ( char *  condname)

Definition at line 2271 of file pl_comp.c.

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

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

◆ plpgsql_parse_tripword()

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

Definition at line 1540 of file pl_comp.c.

References PLwdatum::datum, PLpgSQL_row::fieldnames, i, PLwdatum::ident, IDENTIFIER_LOOKUP_DECLARE, PLcword::idents, PLwdatum::idents, PLpgSQL_nsitem::itemno, PLpgSQL_nsitem::itemtype, list_make3, makeString(), PLpgSQL_row::nfields, palloc(), plpgsql_adddatum(), PLPGSQL_DTYPE_RECFIELD, plpgsql_IdentifierLookup, plpgsql_ns_lookup(), plpgsql_ns_top(), PLPGSQL_NSTYPE_REC, PLPGSQL_NSTYPE_ROW, pstrdup(), PLwdatum::quoted, and PLpgSQL_row::varnos.

Referenced by plpgsql_yylex().

1542 {
1543  PLpgSQL_nsitem *ns;
1544  List *idents;
1545  int nnames;
1546 
1547  idents = list_make3(makeString(word1),
1548  makeString(word2),
1549  makeString(word3));
1550 
1551  /*
1552  * We should do nothing in DECLARE sections. In SQL expressions, we
1553  * really only need to make sure that RECFIELD datums are created when
1554  * needed.
1555  */
1557  {
1558  /*
1559  * Do a lookup in the current namespace stack. Must find a qualified
1560  * reference, else ignore.
1561  */
1562  ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1563  word1, word2, word3,
1564  &nnames);
1565  if (ns != NULL && nnames == 2)
1566  {
1567  switch (ns->itemtype)
1568  {
1569  case PLPGSQL_NSTYPE_REC:
1570  {
1571  /*
1572  * words 1/2 are a record name, so third word could be
1573  * a field in this record.
1574  */
1575  PLpgSQL_recfield *new;
1576 
1577  new = palloc(sizeof(PLpgSQL_recfield));
1578  new->dtype = PLPGSQL_DTYPE_RECFIELD;
1579  new->fieldname = pstrdup(word3);
1580  new->recparentno = ns->itemno;
1581 
1583 
1584  wdatum->datum = (PLpgSQL_datum *) new;
1585  wdatum->ident = NULL;
1586  wdatum->quoted = false; /* not used */
1587  wdatum->idents = idents;
1588  return true;
1589  }
1590 
1591  case PLPGSQL_NSTYPE_ROW:
1592  {
1593  /*
1594  * words 1/2 are a row name, so third word could be a
1595  * field in this row.
1596  */
1597  PLpgSQL_row *row;
1598  int i;
1599 
1600  row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
1601  for (i = 0; i < row->nfields; i++)
1602  {
1603  if (row->fieldnames[i] &&
1604  strcmp(row->fieldnames[i], word3) == 0)
1605  {
1606  wdatum->datum = plpgsql_Datums[row->varnos[i]];
1607  wdatum->ident = NULL;
1608  wdatum->quoted = false; /* not used */
1609  wdatum->idents = idents;
1610  return true;
1611  }
1612  }
1613  /* fall through to return CWORD */
1614  break;
1615  }
1616 
1617  default:
1618  break;
1619  }
1620  }
1621  }
1622 
1623  /* Nothing found */
1624  cword->idents = idents;
1625  return false;
1626 }
Value * makeString(char *str)
Definition: value.c:53
#define list_make3(x1, x2, x3)
Definition: pg_list.h:141
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:47
PLpgSQL_nsitem * plpgsql_ns_top(void)
Definition: pl_funcs.c:83
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:132
char * pstrdup(const char *in)
Definition: mcxt.c:1063
char ** fieldnames
Definition: plpgsql.h:293
List * idents
Definition: plpgsql.h:987
List * idents
Definition: plpgsql.h:995
int * varnos
Definition: plpgsql.h:294
IdentifierLookup plpgsql_IdentifierLookup
Definition: pl_scanner.c:29
int nfields
Definition: plpgsql.h:292
PLpgSQL_datum * datum
Definition: plpgsql.h:992
bool quoted
Definition: plpgsql.h:994
char * ident
Definition: plpgsql.h:993
void * palloc(Size size)
Definition: mcxt.c:835
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:351
void plpgsql_adddatum(PLpgSQL_datum *new)
Definition: pl_comp.c:2339
int i
Definition: pg_list.h:45

◆ plpgsql_parse_word()

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

Definition at line 1364 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_ROW, PLPGSQL_NSTYPE_VAR, PLword::quoted, and PLwdatum::quoted.

Referenced by plpgsql_yylex().

1366 {
1367  PLpgSQL_nsitem *ns;
1368 
1369  /*
1370  * We should do nothing in DECLARE sections. In SQL expressions, there's
1371  * no need to do anything either --- lookup will happen when the
1372  * expression is compiled.
1373  */
1375  {
1376  /*
1377  * Do a lookup in the current namespace stack
1378  */
1379  ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1380  word1, NULL, NULL,
1381  NULL);
1382 
1383  if (ns != NULL)
1384  {
1385  switch (ns->itemtype)
1386  {
1387  case PLPGSQL_NSTYPE_VAR:
1388  case PLPGSQL_NSTYPE_ROW:
1389  case PLPGSQL_NSTYPE_REC:
1390  wdatum->datum = plpgsql_Datums[ns->itemno];
1391  wdatum->ident = word1;
1392  wdatum->quoted = (yytxt[0] == '"');
1393  wdatum->idents = NIL;
1394  return true;
1395 
1396  default:
1397  /* plpgsql_ns_lookup should never return anything else */
1398  elog(ERROR, "unrecognized plpgsql itemtype: %d",
1399  ns->itemtype);
1400  }
1401  }
1402  }
1403 
1404  /*
1405  * Nothing found - up to now it's a word without any special meaning for
1406  * us.
1407  */
1408  word->ident = word1;
1409  word->quoted = (yytxt[0] == '"');
1410  return false;
1411 }
#define NIL
Definition: pg_list.h:69
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:47
PLpgSQL_nsitem * plpgsql_ns_top(void)
Definition: pl_funcs.c:83
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:132
char * ident
Definition: plpgsql.h:981
#define ERROR
Definition: elog.h:43
List * idents
Definition: plpgsql.h:995
IdentifierLookup plpgsql_IdentifierLookup
Definition: pl_scanner.c:29
bool quoted
Definition: plpgsql.h:982
PLpgSQL_datum * datum
Definition: plpgsql.h:992
bool quoted
Definition: plpgsql.h:994
char * ident
Definition: plpgsql.h:993
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:351
#define elog
Definition: elog.h:219

◆ plpgsql_parse_wordrowtype()

PLpgSQL_type* plpgsql_parse_wordrowtype ( char *  ident)

Definition at line 1818 of file pl_comp.c.

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

1819 {
1820  Oid classOid;
1821 
1822  /* Lookup the relation */
1823  classOid = RelnameGetRelid(ident);
1824  if (!OidIsValid(classOid))
1825  ereport(ERROR,
1827  errmsg("relation \"%s\" does not exist", ident)));
1828 
1829  /* Build and return the row type struct */
1830  return plpgsql_build_datatype(get_rel_type_id(classOid), -1, InvalidOid);
1831 }
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation)
Definition: pl_comp.c:2136
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:61
Oid RelnameGetRelid(const char *relname)
Definition: namespace.c:654
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:586
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
Oid get_rel_type_id(Oid relid)
Definition: lsyscache.c:1796
#define InvalidOid
Definition: postgres_ext.h:36
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ plpgsql_parse_wordtype()

PLpgSQL_type* plpgsql_parse_wordtype ( char *  ident)

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

1638 {
1639  PLpgSQL_type *dtype;
1640  PLpgSQL_nsitem *nse;
1641  HeapTuple typeTup;
1642 
1643  /*
1644  * Do a lookup in the current namespace stack
1645  */
1646  nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1647  ident, NULL, NULL,
1648  NULL);
1649 
1650  if (nse != NULL)
1651  {
1652  switch (nse->itemtype)
1653  {
1654  case PLPGSQL_NSTYPE_VAR:
1655  return ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1656 
1657  /* XXX perhaps allow REC/ROW here? */
1658 
1659  default:
1660  return NULL;
1661  }
1662  }
1663 
1664  /*
1665  * Word wasn't found in the namespace stack. Try to find a data type with
1666  * that name, but ignore shell types and complex types.
1667  */
1668  typeTup = LookupTypeName(NULL, makeTypeName(ident), NULL, false);
1669  if (typeTup)
1670  {
1671  Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1672 
1673  if (!typeStruct->typisdefined ||
1674  typeStruct->typrelid != InvalidOid)
1675  {
1676  ReleaseSysCache(typeTup);
1677  return NULL;
1678  }
1679 
1680  dtype = build_datatype(typeTup, -1,
1682 
1683  ReleaseSysCache(typeTup);
1684  return dtype;
1685  }
1686 
1687  /*
1688  * Nothing found - up to now it's a word without any special meaning for
1689  * us.
1690  */
1691  return NULL;
1692 }
Type LookupTypeName(ParseState *pstate, const TypeName *typeName, int32 *typmod_p, bool missing_ok)
Definition: parse_type.c:57
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:47
PLpgSQL_nsitem * plpgsql_ns_top(void)
Definition: pl_funcs.c:83
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
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:132
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
Oid fn_input_collation
Definition: plpgsql.h:817
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define InvalidOid
Definition: postgres_ext.h:36
TypeName * makeTypeName(char *typnam)
Definition: makefuncs.c:443
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation)
Definition: pl_comp.c:2156
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:351
PLpgSQL_function * plpgsql_curr_compile
Definition: pl_comp.c:54

◆ plpgsql_parser_setup()

void plpgsql_parser_setup ( struct ParseState pstate,
PLpgSQL_expr expr 
)

Definition at line 1027 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(), plpgsql_estate_setup(), and setup_unshared_param_list().

1028 {
1032  /* no need to use p_coerce_param_hook */
1033  pstate->p_ref_hook_state = (void *) expr;
1034 }
static Node * plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref)
Definition: pl_comp.c:1040
PostParseColumnRefHook p_post_columnref_hook
Definition: parse_node.h:212
ParseParamRefHook p_paramref_hook
Definition: parse_node.h:213
static Node * plpgsql_param_ref(ParseState *pstate, ParamRef *pref)
Definition: pl_comp.c:1098
void * p_ref_hook_state
Definition: parse_node.h:215
PreParseColumnRefHook p_pre_columnref_hook
Definition: parse_node.h:211
static Node * plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
Definition: pl_comp.c:1054

◆ plpgsql_post_column_ref()

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

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

1055 {
1056  PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1057  Node *myvar;
1058 
1060  return NULL; /* we already found there's no match */
1061 
1062  if (expr->func->resolve_option == PLPGSQL_RESOLVE_COLUMN && var != NULL)
1063  return NULL; /* there's a table column, prefer that */
1064 
1065  /*
1066  * If we find a record/row variable but can't match a field name, throw
1067  * error if there was no core resolution for the ColumnRef either. In
1068  * that situation, the reference is inevitably going to fail, and
1069  * complaining about the record/row variable is likely to be more on-point
1070  * than the core parser's error message. (It's too bad we don't have
1071  * access to transformColumnRef's internal crerr state here, as in case of
1072  * a conflict with a table name this could still be less than the most
1073  * helpful error message possible.)
1074  */
1075  myvar = resolve_column_ref(pstate, expr, cref, (var == NULL));
1076 
1077  if (myvar != NULL && var != NULL)
1078  {
1079  /*
1080  * We could leave it to the core parser to throw this error, but we
1081  * can add a more useful detail message than the core could.
1082  */
1083  ereport(ERROR,
1084  (errcode(ERRCODE_AMBIGUOUS_COLUMN),
1085  errmsg("column reference \"%s\" is ambiguous",
1086  NameListToString(cref->fields)),
1087  errdetail("It could refer to either a PL/pgSQL variable or a table column."),
1088  parser_errposition(pstate, cref->location)));
1089  }
1090 
1091  return myvar;
1092 }
Definition: nodes.h:512
int errcode(int sqlerrcode)
Definition: elog.c:575
PLpgSQL_resolve_option resolve_option
Definition: plpgsql.h:849
int location
Definition: parsenodes.h:235
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
char * NameListToString(List *names)
Definition: namespace.c:3063
struct PLpgSQL_function * func
Definition: plpgsql.h:229
void * p_ref_hook_state
Definition: parse_node.h:215
static Node * resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr, ColumnRef *cref, bool error_if_no_field)
Definition: pl_comp.c:1125
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
int errmsg(const char *fmt,...)
Definition: elog.c:797
List * fields
Definition: parsenodes.h:234

◆ plpgsql_pre_column_ref()

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

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

1041 {
1042  PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1043 
1045  return resolve_column_ref(pstate, expr, cref, false);
1046  else
1047  return NULL;
1048 }
PLpgSQL_resolve_option resolve_option
Definition: plpgsql.h:849
struct PLpgSQL_function * func
Definition: plpgsql.h:229
void * p_ref_hook_state
Definition: parse_node.h:215
static Node * resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr, ColumnRef *cref, bool error_if_no_field)
Definition: pl_comp.c:1125

◆ plpgsql_recognize_err_condition()

int plpgsql_recognize_err_condition ( const char *  condname,
bool  allow_sqlstate 
)

Definition at line 2235 of file pl_comp.c.

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

Referenced by exec_stmt_raise().

2236 {
2237  int i;
2238 
2239  if (allow_sqlstate)
2240  {
2241  if (strlen(condname) == 5 &&
2242  strspn(condname, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") == 5)
2243  return MAKE_SQLSTATE(condname[0],
2244  condname[1],
2245  condname[2],
2246  condname[3],
2247  condname[4]);
2248  }
2249 
2250  for (i = 0; exception_label_map[i].label != NULL; i++)
2251  {
2252  if (strcmp(condname, exception_label_map[i].label) == 0)
2254  }
2255 
2256  ereport(ERROR,
2257  (errcode(ERRCODE_UNDEFINED_OBJECT),
2258  errmsg("unrecognized exception condition \"%s\"",
2259  condname)));
2260  return 0; /* keep compiler quiet */
2261 }
const char * label
Definition: pl_comp.c:79
#define MAKE_SQLSTATE(ch1, ch2, ch3, ch4, ch5)
Definition: elog.h:62
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
static char * label
Definition: pg_basebackup.c:82
static const ExceptionLabelMap exception_label_map[]
Definition: pl_comp.c:83
int errmsg(const char *fmt,...)
Definition: elog.c:797
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 2511 of file pl_comp.c.

References ANYARRAYOID, ANYELEMENTOID, ANYENUMOID, ANYNONARRAYOID, ANYRANGEOID, ereport, errcode(), errmsg(), ERROR, i, INT4ARRAYOID, INT4OID, INT4RANGEOID, and resolve_polymorphic_argtypes().

Referenced by compute_function_hashkey(), and do_compile().

2515 {
2516  int i;
2517 
2518  if (!forValidator)
2519  {
2520  /* normal case, pass to standard routine */
2521  if (!resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
2522  call_expr))
2523  ereport(ERROR,
2524  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2525  errmsg("could not determine actual argument "
2526  "type for polymorphic function \"%s\"",
2527  proname)));
2528  }
2529  else
2530  {
2531  /* special validation case */
2532  for (i = 0; i < numargs; i++)
2533  {
2534  switch (argtypes[i])
2535  {
2536  case ANYELEMENTOID:
2537  case ANYNONARRAYOID:
2538  case ANYENUMOID: /* XXX dubious */
2539  argtypes[i] = INT4OID;
2540  break;
2541  case ANYARRAYOID:
2542  argtypes[i] = INT4ARRAYOID;
2543  break;
2544  case ANYRANGEOID:
2545  argtypes[i] = INT4RANGEOID;
2546  break;
2547  default:
2548  break;
2549  }
2550  }
2551  }
2552 }
bool resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, Node *call_expr)
Definition: funcapi.c:644
#define ANYNONARRAYOID
Definition: pg_type.h:704
#define ANYELEMENTOID
Definition: pg_type.h:702
#define INT4OID
Definition: pg_type.h:316
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
#define ANYRANGEOID
Definition: pg_type.h:714
#define INT4RANGEOID
Definition: pg_type.h:648
#define ANYENUMOID
Definition: pg_type.h:706
#define ereport(elevel, rest)
Definition: elog.h:122
#define ANYARRAYOID
Definition: pg_type.h:688
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define INT4ARRAYOID
Definition: pg_type.h:467

◆ plpgsql_start_datums()

static void plpgsql_start_datums ( void  )
static

Definition at line 2322 of file pl_comp.c.

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

Referenced by do_compile(), and plpgsql_compile_inline().

2323 {
2324  datums_alloc = 128;
2325  plpgsql_nDatums = 0;
2326  /* This is short-lived, so needn't allocate in function's cxt */
2328  sizeof(PLpgSQL_datum *) * datums_alloc);
2329  /* datums_last tracks what's been seen by plpgsql_add_initdatums() */
2330  datums_last = 0;
2331 }
int plpgsql_nDatums
Definition: pl_comp.c:46
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:47
static int datums_alloc
Definition: pl_comp.c:45
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:693
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:57
static int datums_last
Definition: pl_comp.c:48

◆ resolve_column_ref()

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

Definition at line 1125 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, PLpgSQL_row::fieldnames, ColumnRef::fields, PLpgSQL_expr::func, i, IsA, PLpgSQL_nsitem::itemno, PLpgSQL_nsitem::itemtype, linitial, list_length(), ColumnRef::location, lsecond, lthird, make_datum_param(), PLpgSQL_execstate::ndatums, PLpgSQL_row::nfields, PLpgSQL_expr::ns, parser_errposition(), PLPGSQL_DTYPE_RECFIELD, plpgsql_ns_lookup(), PLPGSQL_NSTYPE_REC, PLPGSQL_NSTYPE_ROW, PLPGSQL_NSTYPE_VAR, PLpgSQL_recfield::recparentno, strVal, and PLpgSQL_row::varnos.

Referenced by plpgsql_post_column_ref(), and plpgsql_pre_column_ref().

1127 {
1128  PLpgSQL_execstate *estate;
1129  PLpgSQL_nsitem *nse;
1130  const char *name1;
1131  const char *name2 = NULL;
1132  const char *name3 = NULL;
1133  const char *colname = NULL;
1134  int nnames;
1135  int nnames_scalar = 0;
1136  int nnames_wholerow = 0;
1137  int nnames_field = 0;
1138 
1139  /*
1140  * We use the function's current estate to resolve parameter data types.
1141  * This is really pretty bogus because there is no provision for updating
1142  * plans when those types change ...
1143  */
1144  estate = expr->func->cur_estate;
1145 
1146  /*----------
1147  * The allowed syntaxes are:
1148  *
1149  * A Scalar variable reference, or whole-row record reference.
1150  * A.B Qualified scalar or whole-row reference, or field reference.
1151  * A.B.C Qualified record field reference.
1152  * A.* Whole-row record reference.
1153  * A.B.* Qualified whole-row record reference.
1154  *----------
1155  */
1156  switch (list_length(cref->fields))
1157  {
1158  case 1:
1159  {
1160  Node *field1 = (Node *) linitial(cref->fields);
1161 
1162  Assert(IsA(field1, String));
1163  name1 = strVal(field1);
1164  nnames_scalar = 1;
1165  nnames_wholerow = 1;
1166  break;
1167  }
1168  case 2:
1169  {
1170  Node *field1 = (Node *) linitial(cref->fields);
1171  Node *field2 = (Node *) lsecond(cref->fields);
1172 
1173  Assert(IsA(field1, String));
1174  name1 = strVal(field1);
1175 
1176  /* Whole-row reference? */
1177  if (IsA(field2, A_Star))
1178  {
1179  /* Set name2 to prevent matches to scalar variables */
1180  name2 = "*";
1181  nnames_wholerow = 1;
1182  break;
1183  }
1184 
1185  Assert(IsA(field2, String));
1186  name2 = strVal(field2);
1187  colname = name2;
1188  nnames_scalar = 2;
1189  nnames_wholerow = 2;
1190  nnames_field = 1;
1191  break;
1192  }
1193  case 3:
1194  {
1195  Node *field1 = (Node *) linitial(cref->fields);
1196  Node *field2 = (Node *) lsecond(cref->fields);
1197  Node *field3 = (Node *) lthird(cref->fields);
1198 
1199  Assert(IsA(field1, String));
1200  name1 = strVal(field1);
1201  Assert(IsA(field2, String));
1202  name2 = strVal(field2);
1203 
1204  /* Whole-row reference? */
1205  if (IsA(field3, A_Star))
1206  {
1207  /* Set name3 to prevent matches to scalar variables */
1208  name3 = "*";
1209  nnames_wholerow = 2;
1210  break;
1211  }
1212 
1213  Assert(IsA(field3, String));
1214  name3 = strVal(field3);
1215  colname = name3;
1216  nnames_field = 2;
1217  break;
1218  }
1219  default:
1220  /* too many names, ignore */
1221  return NULL;
1222  }
1223 
1224  nse = plpgsql_ns_lookup(expr->ns, false,
1225  name1, name2, name3,
1226  &nnames);
1227 
1228  if (nse == NULL)
1229  return NULL; /* name not known to plpgsql */
1230 
1231  switch (nse->itemtype)
1232  {
1233  case PLPGSQL_NSTYPE_VAR:
1234  if (nnames == nnames_scalar)
1235  return make_datum_param(expr, nse->itemno, cref->location);
1236  break;
1237  case PLPGSQL_NSTYPE_REC:
1238  if (nnames == nnames_wholerow)
1239  return make_datum_param(expr, nse->itemno, cref->location);
1240  if (nnames == nnames_field)
1241  {
1242  /* colname could be a field in this record */
1243  int i;
1244 
1245  /* search for a datum referencing this field */
1246  for (i = 0; i < estate->ndatums; i++)
1247  {
1248  PLpgSQL_recfield *fld = (PLpgSQL_recfield *) estate->datums[i];
1249 
1250  if (fld->dtype == PLPGSQL_DTYPE_RECFIELD &&
1251  fld->recparentno == nse->itemno &&
1252  strcmp(fld->fieldname, colname) == 0)
1253  {
1254  return make_datum_param(expr, i, cref->location);
1255  }
1256  }
1257 
1258  /*
1259  * We should not get here, because a RECFIELD datum should
1260  * have been built at parse time for every possible qualified
1261  * reference to fields of this record. But if we do, handle
1262  * it like field-not-found: throw error or return NULL.
1263  */
1264  if (error_if_no_field)
1265  ereport(ERROR,
1266  (errcode(ERRCODE_UNDEFINED_COLUMN),
1267  errmsg("record \"%s\" has no field \"%s\"",
1268  (nnames_field == 1) ? name1 : name2,
1269  colname),
1270  parser_errposition(pstate, cref->location)));
1271  }
1272  break;
1273  case PLPGSQL_NSTYPE_ROW:
1274  if (nnames == nnames_wholerow)
1275  return make_datum_param(expr, nse->itemno, cref->location);
1276  if (nnames == nnames_field)
1277  {
1278  /* colname could be a field in this row */
1279  PLpgSQL_row *row = (PLpgSQL_row *) estate->datums[nse->itemno];
1280  int i;
1281 
1282  for (i = 0; i < row->nfields; i++)
1283  {
1284  if (row->fieldnames[i] &&
1285  strcmp(row->fieldnames[i], colname) == 0)
1286  {
1287  return make_datum_param(expr, row->varnos[i],
1288  cref->location);
1289  }
1290  }
1291  /* Not found, so throw error or return NULL */
1292  if (error_if_no_field)
1293  ereport(ERROR,
1294  (errcode(ERRCODE_UNDEFINED_COLUMN),
1295  errmsg("record \"%s\" has no field \"%s\"",
1296  (nnames_field == 1) ? name1 : name2,
1297  colname),
1298  parser_errposition(pstate, cref->location)));
1299  }
1300  break;
1301  default:
1302  elog(ERROR, "unrecognized plpgsql itemtype: %d", nse->itemtype);
1303  }
1304 
1305  /* Name format doesn't match the plpgsql variable type */
1306  return NULL;
1307 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:563
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:132
Definition: nodes.h:512
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
#define lsecond(l)
Definition: pg_list.h:116
PLpgSQL_datum ** datums
Definition: plpgsql.h:900
int location
Definition: parsenodes.h:235
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
char ** fieldnames
Definition: plpgsql.h:293
struct PLpgSQL_execstate * cur_estate
Definition: plpgsql.h:866
struct PLpgSQL_nsitem * ns
Definition: plpgsql.h:232
#define ereport(elevel, rest)
Definition: elog.h:122
int * varnos
Definition: plpgsql.h:294
PLpgSQL_datum_type dtype
Definition: plpgsql.h:318
struct PLpgSQL_function * func
Definition: plpgsql.h:229
#define Assert(condition)
Definition: c.h:680
int nfields
Definition: plpgsql.h:292
static int list_length(const List *l)
Definition: pg_list.h:89
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
int errmsg(const char *fmt,...)
Definition: elog.c:797
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:351
int i
#define lthird(l)
Definition: pg_list.h:121
#define elog
Definition: elog.h:219
char * fieldname
Definition: plpgsql.h:320
List * fields
Definition: parsenodes.h:234
static Node * make_datum_param(PLpgSQL_expr *expr, int dno, int location)
Definition: pl_comp.c:1314

Variable Documentation

◆ datums_alloc

int datums_alloc
static

Definition at line 45 of file pl_comp.c.

Referenced by plpgsql_adddatum(), and plpgsql_start_datums().

◆ datums_last

int datums_last
static

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

◆ plpgsql_check_syntax

bool plpgsql_check_syntax = false

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

◆ plpgsql_curr_compile

PLpgSQL_function* plpgsql_curr_compile

Definition at line 54 of file pl_comp.c.

◆ plpgsql_Datums

PLpgSQL_datum** plpgsql_Datums

Definition at line 47 of file pl_comp.c.

◆ plpgsql_DumpExecTree

bool plpgsql_DumpExecTree = false

Definition at line 51 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_error_funcname

char* plpgsql_error_funcname

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

◆ plpgsql_nDatums

int plpgsql_nDatums

◆ plpgsql_parse_result

PLpgSQL_stmt_block* plpgsql_parse_result

Definition at line 43 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().