PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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

#define FUNCS_PER_USER   128 /* initial table size */

Definition at line 71 of file pl_comp.c.

Referenced by plpgsql_HashTableInit().

Typedef Documentation

Function Documentation

static void add_dummy_return ( PLpgSQL_function function)
static

Definition at line 977 of file pl_comp.c.

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

Referenced by do_compile(), and plpgsql_compile_inline().

978 {
979  /*
980  * If the outer block has an EXCEPTION clause, we need to make a new outer
981  * block, since the added RETURN shouldn't act like it is inside the
982  * EXCEPTION clause.
983  */
984  if (function->action->exceptions != NULL)
985  {
986  PLpgSQL_stmt_block *new;
987 
988  new = palloc0(sizeof(PLpgSQL_stmt_block));
989  new->cmd_type = PLPGSQL_STMT_BLOCK;
990  new->body = list_make1(function->action);
991 
992  function->action = new;
993  }
994  if (function->action->body == NIL ||
995  ((PLpgSQL_stmt *) llast(function->action->body))->cmd_type != PLPGSQL_STMT_RETURN)
996  {
997  PLpgSQL_stmt_return *new;
998 
999  new = palloc0(sizeof(PLpgSQL_stmt_return));
1000  new->cmd_type = PLPGSQL_STMT_RETURN;
1001  new->expr = NULL;
1002  new->retvarno = function->out_param_varno;
1003 
1004  function->action->body = lappend(function->action->body, new);
1005  }
1006 }
#define NIL
Definition: pg_list.h:69
PLpgSQL_stmt_block * action
Definition: plpgsql.h:871
#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:878
#define NULL
Definition: c.h:229
PLpgSQL_exception_block * exceptions
Definition: plpgsql.h:412
static void add_parameter_name ( PLpgSQL_nsitem_type  itemtype,
int  itemno,
const char *  name 
)
static

Definition at line 952 of file pl_comp.c.

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

Referenced by do_compile().

953 {
954  /*
955  * Before adding the name, check for duplicates. We need this even though
956  * functioncmds.c has a similar check, because that code explicitly
957  * doesn't complain about conflicting IN and OUT parameter names. In
958  * plpgsql, such names are in the same namespace, so there is no way to
959  * disambiguate.
960  */
961  if (plpgsql_ns_lookup(plpgsql_ns_top(), true,
962  name, NULL, NULL,
963  NULL) != NULL)
964  ereport(ERROR,
965  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
966  errmsg("parameter name \"%s\" used more than once",
967  name)));
968 
969  /* OK, add the name */
970  plpgsql_ns_additem(itemtype, itemno, name);
971 }
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
#define NULL
Definition: c.h:229
const char * name
Definition: encode.c:521
int errmsg(const char *fmt,...)
Definition: elog.c:797
static PLpgSQL_type * build_datatype ( HeapTuple  typeTup,
int32  typmod,
Oid  collation 
)
static

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

2148 {
2149  Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
2150  PLpgSQL_type *typ;
2151 
2152  if (!typeStruct->typisdefined)
2153  ereport(ERROR,
2154  (errcode(ERRCODE_UNDEFINED_OBJECT),
2155  errmsg("type \"%s\" is only a shell",
2156  NameStr(typeStruct->typname))));
2157 
2158  typ = (PLpgSQL_type *) palloc(sizeof(PLpgSQL_type));
2159 
2160  typ->typname = pstrdup(NameStr(typeStruct->typname));
2161  typ->typoid = HeapTupleGetOid(typeTup);
2162  switch (typeStruct->typtype)
2163  {
2164  case TYPTYPE_BASE:
2165  case TYPTYPE_DOMAIN:
2166  case TYPTYPE_ENUM:
2167  case TYPTYPE_RANGE:
2168  typ->ttype = PLPGSQL_TTYPE_SCALAR;
2169  break;
2170  case TYPTYPE_COMPOSITE:
2171  Assert(OidIsValid(typeStruct->typrelid));
2172  typ->ttype = PLPGSQL_TTYPE_ROW;
2173  break;
2174  case TYPTYPE_PSEUDO:
2175  if (typ->typoid == RECORDOID)
2176  typ->ttype = PLPGSQL_TTYPE_REC;
2177  else
2178  typ->ttype = PLPGSQL_TTYPE_PSEUDO;
2179  break;
2180  default:
2181  elog(ERROR, "unrecognized typtype: %d",
2182  (int) typeStruct->typtype);
2183  break;
2184  }
2185  typ->typlen = typeStruct->typlen;
2186  typ->typbyval = typeStruct->typbyval;
2187  typ->typtype = typeStruct->typtype;
2188  typ->typrelid = typeStruct->typrelid;
2189  typ->collation = typeStruct->typcollation;
2190  if (OidIsValid(collation) && OidIsValid(typ->collation))
2191  typ->collation = collation;
2192  /* Detect if type is true array, or domain thereof */
2193  /* NB: this is only used to decide whether to apply expand_array */
2194  if (typeStruct->typtype == TYPTYPE_BASE)
2195  {
2196  /*
2197  * This test should include what get_element_type() checks. We also
2198  * disallow non-toastable array types (i.e. oidvector and int2vector).
2199  */
2200  typ->typisarray = (typeStruct->typlen == -1 &&
2201  OidIsValid(typeStruct->typelem) &&
2202  typeStruct->typstorage != 'p');
2203  }
2204  else if (typeStruct->typtype == TYPTYPE_DOMAIN)
2205  {
2206  /* we can short-circuit looking up base types if it's not varlena */
2207  typ->typisarray = (typeStruct->typlen == -1 &&
2208  typeStruct->typstorage != 'p' &&
2209  OidIsValid(get_base_element_type(typeStruct->typbasetype)));
2210  }
2211  else
2212  typ->typisarray = false;
2213  typ->atttypmod = typmod;
2214 
2215  return typ;
2216 }
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define TYPTYPE_BASE
Definition: pg_type.h:720
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
char * pstrdup(const char *in)
Definition: mcxt.c:1077
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:538
#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:676
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:2557
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
int32 atttypmod
Definition: plpgsql.h:187
#define NameStr(name)
Definition: c.h:499
#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:695
Oid typoid
Definition: plpgsql.h:179
static PLpgSQL_row * build_row_from_class ( Oid  classOid)
static

Definition at line 1967 of file pl_comp.c.

References AccessShareLock, CreateTupleDescCopy(), PLpgSQL_row::dtype, ereport, errcode(), errmsg(), ERROR, PLpgSQL_row::fieldnames, i, NAMEDATALEN, NameStr, PLpgSQL_row::nfields, NULL, 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().

1968 {
1969  PLpgSQL_row *row;
1970  Relation rel;
1971  Form_pg_class classStruct;
1972  const char *relname;
1973  int i;
1974 
1975  /*
1976  * Open the relation to get info.
1977  */
1978  rel = relation_open(classOid, AccessShareLock);
1979  classStruct = RelationGetForm(rel);
1980  relname = RelationGetRelationName(rel);
1981 
1982  /*
1983  * Accept relation, sequence, view, materialized view, composite type, or
1984  * foreign table.
1985  */
1986  if (classStruct->relkind != RELKIND_RELATION &&
1987  classStruct->relkind != RELKIND_SEQUENCE &&
1988  classStruct->relkind != RELKIND_VIEW &&
1989  classStruct->relkind != RELKIND_MATVIEW &&
1990  classStruct->relkind != RELKIND_COMPOSITE_TYPE &&
1991  classStruct->relkind != RELKIND_FOREIGN_TABLE &&
1992  classStruct->relkind != RELKIND_PARTITIONED_TABLE)
1993  ereport(ERROR,
1994  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1995  errmsg("relation \"%s\" is not a table", relname)));
1996 
1997  /*
1998  * Create a row datum entry and all the required variables that it will
1999  * point to.
2000  */
2001  row = palloc0(sizeof(PLpgSQL_row));
2002  row->dtype = PLPGSQL_DTYPE_ROW;
2004  row->nfields = classStruct->relnatts;
2005  row->fieldnames = palloc(sizeof(char *) * row->nfields);
2006  row->varnos = palloc(sizeof(int) * row->nfields);
2007 
2008  for (i = 0; i < row->nfields; i++)
2009  {
2010  Form_pg_attribute attrStruct;
2011 
2012  /*
2013  * Get the attribute and check for dropped column
2014  */
2015  attrStruct = TupleDescAttr(row->rowtupdesc, i);
2016 
2017  if (!attrStruct->attisdropped)
2018  {
2019  char *attname;
2020  char refname[(NAMEDATALEN * 2) + 100];
2021  PLpgSQL_variable *var;
2022 
2023  attname = NameStr(attrStruct->attname);
2024  snprintf(refname, sizeof(refname), "%s.%s", relname, attname);
2025 
2026  /*
2027  * Create the internal variable for the field
2028  *
2029  * We know if the table definitions contain a default value or if
2030  * the field is declared in the table as NOT NULL. But it's
2031  * possible to create a table field as NOT NULL without a default
2032  * value and that would lead to problems later when initializing
2033  * the variables due to entering a block at execution time. Thus
2034  * we ignore this information for now.
2035  */
2036  var = plpgsql_build_variable(refname, 0,
2037  plpgsql_build_datatype(attrStruct->atttypid,
2038  attrStruct->atttypmod,
2039  attrStruct->attcollation),
2040  false);
2041 
2042  /* Add the variable to the row */
2043  row->fieldnames[i] = attname;
2044  row->varnos[i] = var->dno;
2045  }
2046  else
2047  {
2048  /* Leave a hole in the row structure for the dropped col */
2049  row->fieldnames[i] = NULL;
2050  row->varnos[i] = -1;
2051  }
2052  }
2053 
2055 
2056  return row;
2057 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:100
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation)
Definition: pl_comp.c:2127
#define RelationGetDescr(relation)
Definition: rel.h:428
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
#define RelationGetForm(relation)
Definition: rel.h:410
#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:436
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:878
#define NULL
Definition: c.h:229
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:1864
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
void * palloc(Size size)
Definition: mcxt.c:849
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:499
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
static PLpgSQL_row * build_row_from_vars ( PLpgSQL_variable **  vars,
int  numvars 
)
static

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

2064 {
2065  PLpgSQL_row *row;
2066  int i;
2067 
2068  row = palloc0(sizeof(PLpgSQL_row));
2069  row->dtype = PLPGSQL_DTYPE_ROW;
2070  row->rowtupdesc = CreateTemplateTupleDesc(numvars, false);
2071  row->nfields = numvars;
2072  row->fieldnames = palloc(numvars * sizeof(char *));
2073  row->varnos = palloc(numvars * sizeof(int));
2074 
2075  for (i = 0; i < numvars; i++)
2076  {
2077  PLpgSQL_variable *var = vars[i];
2078  Oid typoid = RECORDOID;
2079  int32 typmod = -1;
2080  Oid typcoll = InvalidOid;
2081 
2082  switch (var->dtype)
2083  {
2084  case PLPGSQL_DTYPE_VAR:
2085  typoid = ((PLpgSQL_var *) var)->datatype->typoid;
2086  typmod = ((PLpgSQL_var *) var)->datatype->atttypmod;
2087  typcoll = ((PLpgSQL_var *) var)->datatype->collation;
2088  break;
2089 
2090  case PLPGSQL_DTYPE_REC:
2091  break;
2092 
2093  case PLPGSQL_DTYPE_ROW:
2094  if (((PLpgSQL_row *) var)->rowtupdesc)
2095  {
2096  typoid = ((PLpgSQL_row *) var)->rowtupdesc->tdtypeid;
2097  typmod = ((PLpgSQL_row *) var)->rowtupdesc->tdtypmod;
2098  /* composite types have no collation */
2099  }
2100  break;
2101 
2102  default:
2103  elog(ERROR, "unrecognized dtype: %d", var->dtype);
2104  }
2105 
2106  row->fieldnames[i] = var->refname;
2107  row->varnos[i] = var->dno;
2108 
2109  TupleDescInitEntry(row->rowtupdesc, i + 1,
2110  var->refname,
2111  typoid, typmod,
2112  0);
2113  TupleDescInitEntryCollation(row->rowtupdesc, i + 1, typcoll);
2114  }
2115 
2116  return row;
2117 }
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:256
#define ERROR
Definition: elog.h:43
char ** fieldnames
Definition: plpgsql.h:293
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition: tupdesc.c:621
#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:462
int * varnos
Definition: plpgsql.h:294
void * palloc0(Size size)
Definition: mcxt.c:878
#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:41
void * palloc(Size size)
Definition: mcxt.c:849
int i
TupleDesc rowtupdesc
Definition: plpgsql.h:285
#define elog
Definition: elog.h:219
PLpgSQL_datum_type dtype
Definition: plpgsql.h:279
static void compute_function_hashkey ( FunctionCallInfo  fcinfo,
Form_pg_proc  procStruct,
PLpgSQL_func_hashkey hashkey,
bool  forValidator 
)
static

Definition at line 2443 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, NULL, plpgsql_resolve_polymorphic_argtypes(), TriggerData::tg_trigger, Trigger::tgoid, and PLpgSQL_func_hashkey::trigOid.

Referenced by plpgsql_compile().

2447 {
2448  /* Make sure any unused bytes of the struct are zero */
2449  MemSet(hashkey, 0, sizeof(PLpgSQL_func_hashkey));
2450 
2451  /* get function OID */
2452  hashkey->funcOid = fcinfo->flinfo->fn_oid;
2453 
2454  /* get call context */
2455  hashkey->isTrigger = CALLED_AS_TRIGGER(fcinfo);
2456 
2457  /*
2458  * if trigger, get its OID. In validation mode we do not know what
2459  * relation or transition table names are intended to be used, so we leave
2460  * trigOid zero; the hash entry built in this case will never really be
2461  * used.
2462  */
2463  if (hashkey->isTrigger && !forValidator)
2464  {
2465  TriggerData *trigdata = (TriggerData *) fcinfo->context;
2466 
2467  hashkey->trigOid = trigdata->tg_trigger->tgoid;
2468  }
2469 
2470  /* get input collation, if known */
2471  hashkey->inputCollation = fcinfo->fncollation;
2472 
2473  if (procStruct->pronargs > 0)
2474  {
2475  /* get the argument types */
2476  memcpy(hashkey->argtypes, procStruct->proargtypes.values,
2477  procStruct->pronargs * sizeof(Oid));
2478 
2479  /* resolve any polymorphic argument types */
2480  plpgsql_resolve_polymorphic_argtypes(procStruct->pronargs,
2481  hashkey->argtypes,
2482  NULL,
2483  fcinfo->flinfo->fn_expr,
2484  forValidator,
2485  NameStr(procStruct->proname));
2486  }
2487 }
Oid argtypes[FUNC_MAX_ARGS]
Definition: plpgsql.h:802
fmNodePtr context
Definition: fmgr.h:80
Oid tgoid
Definition: reltrigger.h:25
#define MemSet(start, val, len)
Definition: c.h:858
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:2496
FmgrInfo * flinfo
Definition: fmgr.h:79
Trigger * tg_trigger
Definition: trigger.h:37
Oid fn_oid
Definition: fmgr.h:59
#define NULL
Definition: c.h:229
#define CALLED_AS_TRIGGER(fcinfo)
Definition: trigger.h:25
fmNodePtr fn_expr
Definition: fmgr.h:66
#define NameStr(name)
Definition: c.h:499
static void delete_function ( PLpgSQL_function func)
static

Definition at line 2554 of file pl_comp.c.

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

Referenced by plpgsql_compile().

2555 {
2556  /* remove function from hash table (might be done already) */
2558 
2559  /* release the function's storage if safe and not done already */
2560  if (func->use_count == 0)
2562 }
void plpgsql_free_function_memory(PLpgSQL_function *func)
Definition: pl_funcs.c:695
unsigned long use_count
Definition: plpgsql.h:875
static void plpgsql_HashTableDelete(PLpgSQL_function *function)
Definition: pl_comp.c:2617
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_variable::dno, PLpgSQL_row::dno, PLpgSQL_rec::dno, PLpgSQL_variable::dtype, elog, ereport, errcode(), errhint(), errmsg(), ERROR, error_context_stack, EVTTRIGGEROID, FunctionCallInfoData::flinfo, FmgrInfo::fn_expr, FmgrInfo::fn_oid, FunctionCallInfoData::fncollation, format_procedure(), format_type_be(), function, get_fn_expr_rettype(), get_func_arg_info(), GETSTRUCT, HeapTupleHeaderGetRawXmin, HeapTupleIsValid, i, INT4ARRAYOID, INT4OID, INT4RANGEOID, InvalidOid, IsPolymorphicType, MemoryContextAllocZero(), MemoryContextSwitchTo(), NAMEOID, NameStr, NULL, 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  Form_pg_type typeStruct;
279  PLpgSQL_variable *var;
280  PLpgSQL_rec *rec;
281  int i;
282  ErrorContextCallback plerrcontext;
283  int parse_rc;
284  Oid rettypeid;
285  int numargs;
286  int num_in_args = 0;
287  int num_out_args = 0;
288  Oid *argtypes;
289  char **argnames;
290  char *argmodes;
291  int *in_arg_varnos = NULL;
292  PLpgSQL_variable **out_arg_variables;
293  MemoryContext func_cxt;
294 
295  /*
296  * Setup the scanner input and error info. We assume that this function
297  * cannot be invoked recursively, so there's no need to save and restore
298  * the static variables used here.
299  */
300  prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
301  Anum_pg_proc_prosrc, &isnull);
302  if (isnull)
303  elog(ERROR, "null prosrc");
304  proc_source = TextDatumGetCString(prosrcdatum);
305  plpgsql_scanner_init(proc_source);
306 
307  plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname));
308 
309  /*
310  * Setup error traceback support for ereport()
311  */
313  plerrcontext.arg = forValidator ? proc_source : NULL;
314  plerrcontext.previous = error_context_stack;
315  error_context_stack = &plerrcontext;
316 
317  /*
318  * Do extra syntax checks when validating the function definition. We skip
319  * this when actually compiling functions for execution, for performance
320  * reasons.
321  */
322  plpgsql_check_syntax = forValidator;
323 
324  /*
325  * Create the new function struct, if not done already. The function
326  * structs are never thrown away, so keep them in TopMemoryContext.
327  */
328  if (function == NULL)
329  {
330  function = (PLpgSQL_function *)
332  }
333  else
334  {
335  /* re-using a previously existing struct, so clear it out */
336  memset(function, 0, sizeof(PLpgSQL_function));
337  }
338  plpgsql_curr_compile = function;
339 
340  /*
341  * All the permanent output of compilation (e.g. parse tree) is kept in a
342  * per-function memory context, so it can be reclaimed easily.
343  */
345  "PL/pgSQL function context",
348 
349  function->fn_signature = format_procedure(fcinfo->flinfo->fn_oid);
350  function->fn_oid = fcinfo->flinfo->fn_oid;
351  function->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data);
352  function->fn_tid = procTup->t_self;
353  function->fn_input_collation = fcinfo->fncollation;
354  function->fn_cxt = func_cxt;
355  function->out_param_varno = -1; /* set up for no OUT param */
356  function->resolve_option = plpgsql_variable_conflict;
357  function->print_strict_params = plpgsql_print_strict_params;
358  /* only promote extra warnings and errors at CREATE FUNCTION time */
359  function->extra_warnings = forValidator ? plpgsql_extra_warnings : 0;
360  function->extra_errors = forValidator ? plpgsql_extra_errors : 0;
361 
362  if (is_dml_trigger)
363  function->fn_is_trigger = PLPGSQL_DML_TRIGGER;
364  else if (is_event_trigger)
365  function->fn_is_trigger = PLPGSQL_EVENT_TRIGGER;
366  else
367  function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
368 
369  /*
370  * Initialize the compiler, particularly the namespace stack. The
371  * outermost namespace contains function parameters and other special
372  * variables (such as FOUND), and is named after the function itself.
373  */
374  plpgsql_ns_init();
375  plpgsql_ns_push(NameStr(procStruct->proname), PLPGSQL_LABEL_BLOCK);
376  plpgsql_DumpExecTree = false;
378 
379  switch (function->fn_is_trigger)
380  {
381  case PLPGSQL_NOT_TRIGGER:
382 
383  /*
384  * Fetch info about the procedure's parameters. Allocations aren't
385  * needed permanently, so make them in tmp cxt.
386  *
387  * We also need to resolve any polymorphic input or output
388  * argument types. In validation mode we won't be able to, so we
389  * arbitrarily assume we are dealing with integers.
390  */
392 
393  numargs = get_func_arg_info(procTup,
394  &argtypes, &argnames, &argmodes);
395 
396  plpgsql_resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
397  fcinfo->flinfo->fn_expr,
398  forValidator,
400 
401  in_arg_varnos = (int *) palloc(numargs * sizeof(int));
402  out_arg_variables = (PLpgSQL_variable **) palloc(numargs * sizeof(PLpgSQL_variable *));
403 
404  MemoryContextSwitchTo(func_cxt);
405 
406  /*
407  * Create the variables for the procedure's parameters.
408  */
409  for (i = 0; i < numargs; i++)
410  {
411  char buf[32];
412  Oid argtypeid = argtypes[i];
413  char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
414  PLpgSQL_type *argdtype;
415  PLpgSQL_variable *argvariable;
416  PLpgSQL_nsitem_type argitemtype;
417 
418  /* Create $n name for variable */
419  snprintf(buf, sizeof(buf), "$%d", i + 1);
420 
421  /* Create datatype info */
422  argdtype = plpgsql_build_datatype(argtypeid,
423  -1,
424  function->fn_input_collation);
425 
426  /* Disallow pseudotype argument */
427  /* (note we already replaced polymorphic types) */
428  /* (build_variable would do this, but wrong message) */
429  if (argdtype->ttype != PLPGSQL_TTYPE_SCALAR &&
430  argdtype->ttype != PLPGSQL_TTYPE_ROW)
431  ereport(ERROR,
432  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
433  errmsg("PL/pgSQL functions cannot accept type %s",
434  format_type_be(argtypeid))));
435 
436  /* Build variable and add to datum list */
437  argvariable = plpgsql_build_variable(buf, 0,
438  argdtype, false);
439 
440  if (argvariable->dtype == PLPGSQL_DTYPE_VAR)
441  {
442  argitemtype = PLPGSQL_NSTYPE_VAR;
443  }
444  else
445  {
446  Assert(argvariable->dtype == PLPGSQL_DTYPE_ROW);
447  argitemtype = PLPGSQL_NSTYPE_ROW;
448  }
449 
450  /* Remember arguments in appropriate arrays */
451  if (argmode == PROARGMODE_IN ||
452  argmode == PROARGMODE_INOUT ||
453  argmode == PROARGMODE_VARIADIC)
454  in_arg_varnos[num_in_args++] = argvariable->dno;
455  if (argmode == PROARGMODE_OUT ||
456  argmode == PROARGMODE_INOUT ||
457  argmode == PROARGMODE_TABLE)
458  out_arg_variables[num_out_args++] = argvariable;
459 
460  /* Add to namespace under the $n name */
461  add_parameter_name(argitemtype, argvariable->dno, buf);
462 
463  /* If there's a name for the argument, make an alias */
464  if (argnames && argnames[i][0] != '\0')
465  add_parameter_name(argitemtype, argvariable->dno,
466  argnames[i]);
467  }
468 
469  /*
470  * If there's just one OUT parameter, out_param_varno points
471  * directly to it. If there's more than one, build a row that
472  * holds all of them.
473  */
474  if (num_out_args == 1)
475  function->out_param_varno = out_arg_variables[0]->dno;
476  else if (num_out_args > 1)
477  {
478  PLpgSQL_row *row = build_row_from_vars(out_arg_variables,
479  num_out_args);
480 
482  function->out_param_varno = row->dno;
483  }
484 
485  /*
486  * Check for a polymorphic returntype. If found, use the actual
487  * returntype type from the caller's FuncExpr node, if we have
488  * one. (In validation mode we arbitrarily assume we are dealing
489  * with integers.)
490  *
491  * Note: errcode is FEATURE_NOT_SUPPORTED because it should always
492  * work; if it doesn't we're in some context that fails to make
493  * the info available.
494  */
495  rettypeid = procStruct->prorettype;
496  if (IsPolymorphicType(rettypeid))
497  {
498  if (forValidator)
499  {
500  if (rettypeid == ANYARRAYOID)
501  rettypeid = INT4ARRAYOID;
502  else if (rettypeid == ANYRANGEOID)
503  rettypeid = INT4RANGEOID;
504  else /* ANYELEMENT or ANYNONARRAY */
505  rettypeid = INT4OID;
506  /* XXX what could we use for ANYENUM? */
507  }
508  else
509  {
510  rettypeid = get_fn_expr_rettype(fcinfo->flinfo);
511  if (!OidIsValid(rettypeid))
512  ereport(ERROR,
513  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
514  errmsg("could not determine actual return type "
515  "for polymorphic function \"%s\"",
517  }
518  }
519 
520  /*
521  * Normal function has a defined returntype
522  */
523  function->fn_rettype = rettypeid;
524  function->fn_retset = procStruct->proretset;
525 
526  /*
527  * Lookup the function's return type
528  */
529  typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(rettypeid));
530  if (!HeapTupleIsValid(typeTup))
531  elog(ERROR, "cache lookup failed for type %u", rettypeid);
532  typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
533 
534  /* Disallow pseudotype result, except VOID or RECORD */
535  /* (note we already replaced polymorphic types) */
536  if (typeStruct->typtype == TYPTYPE_PSEUDO)
537  {
538  if (rettypeid == VOIDOID ||
539  rettypeid == RECORDOID)
540  /* okay */ ;
541  else if (rettypeid == TRIGGEROID || rettypeid == EVTTRIGGEROID)
542  ereport(ERROR,
543  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
544  errmsg("trigger functions can only be called as triggers")));
545  else
546  ereport(ERROR,
547  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
548  errmsg("PL/pgSQL functions cannot return type %s",
549  format_type_be(rettypeid))));
550  }
551 
552  if (typeStruct->typrelid != InvalidOid ||
553  rettypeid == RECORDOID)
554  function->fn_retistuple = true;
555  else
556  {
557  function->fn_retbyval = typeStruct->typbyval;
558  function->fn_rettyplen = typeStruct->typlen;
559 
560  /*
561  * install $0 reference, but only for polymorphic return
562  * types, and not when the return is specified through an
563  * output parameter.
564  */
565  if (IsPolymorphicType(procStruct->prorettype) &&
566  num_out_args == 0)
567  {
568  (void) plpgsql_build_variable("$0", 0,
569  build_datatype(typeTup,
570  -1,
571  function->fn_input_collation),
572  true);
573  }
574  }
575  ReleaseSysCache(typeTup);
576  break;
577 
578  case PLPGSQL_DML_TRIGGER:
579  /* Trigger procedure's return type is unknown yet */
580  function->fn_rettype = InvalidOid;
581  function->fn_retbyval = false;
582  function->fn_retistuple = true;
583  function->fn_retset = false;
584 
585  /* shouldn't be any declared arguments */
586  if (procStruct->pronargs != 0)
587  ereport(ERROR,
588  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
589  errmsg("trigger functions cannot have declared arguments"),
590  errhint("The arguments of the trigger can be accessed through TG_NARGS and TG_ARGV instead.")));
591 
592  /* Add the record for referencing NEW ROW */
593  rec = plpgsql_build_record("new", 0, true);
594  function->new_varno = rec->dno;
595 
596  /* Add the record for referencing OLD ROW */
597  rec = plpgsql_build_record("old", 0, true);
598  function->old_varno = rec->dno;
599 
600  /* Add the variable tg_name */
601  var = plpgsql_build_variable("tg_name", 0,
603  -1,
604  InvalidOid),
605  true);
606  function->tg_name_varno = var->dno;
607 
608  /* Add the variable tg_when */
609  var = plpgsql_build_variable("tg_when", 0,
611  -1,
612  function->fn_input_collation),
613  true);
614  function->tg_when_varno = var->dno;
615 
616  /* Add the variable tg_level */
617  var = plpgsql_build_variable("tg_level", 0,
619  -1,
620  function->fn_input_collation),
621  true);
622  function->tg_level_varno = var->dno;
623 
624  /* Add the variable tg_op */
625  var = plpgsql_build_variable("tg_op", 0,
627  -1,
628  function->fn_input_collation),
629  true);
630  function->tg_op_varno = var->dno;
631 
632  /* Add the variable tg_relid */
633  var = plpgsql_build_variable("tg_relid", 0,
635  -1,
636  InvalidOid),
637  true);
638  function->tg_relid_varno = var->dno;
639 
640  /* Add the variable tg_relname */
641  var = plpgsql_build_variable("tg_relname", 0,
643  -1,
644  InvalidOid),
645  true);
646  function->tg_relname_varno = var->dno;
647 
648  /* tg_table_name is now preferred to tg_relname */
649  var = plpgsql_build_variable("tg_table_name", 0,
651  -1,
652  InvalidOid),
653  true);
654  function->tg_table_name_varno = var->dno;
655 
656  /* add the variable tg_table_schema */
657  var = plpgsql_build_variable("tg_table_schema", 0,
659  -1,
660  InvalidOid),
661  true);
662  function->tg_table_schema_varno = var->dno;
663 
664  /* Add the variable tg_nargs */
665  var = plpgsql_build_variable("tg_nargs", 0,
667  -1,
668  InvalidOid),
669  true);
670  function->tg_nargs_varno = var->dno;
671 
672  /* Add the variable tg_argv */
673  var = plpgsql_build_variable("tg_argv", 0,
675  -1,
676  function->fn_input_collation),
677  true);
678  function->tg_argv_varno = var->dno;
679 
680  break;
681 
683  function->fn_rettype = VOIDOID;
684  function->fn_retbyval = false;
685  function->fn_retistuple = true;
686  function->fn_retset = false;
687 
688  /* shouldn't be any declared arguments */
689  if (procStruct->pronargs != 0)
690  ereport(ERROR,
691  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
692  errmsg("event trigger functions cannot have declared arguments")));
693 
694  /* Add the variable tg_event */
695  var = plpgsql_build_variable("tg_event", 0,
697  -1,
698  function->fn_input_collation),
699  true);
700  function->tg_event_varno = var->dno;
701 
702  /* Add the variable tg_tag */
703  var = plpgsql_build_variable("tg_tag", 0,
705  -1,
706  function->fn_input_collation),
707  true);
708  function->tg_tag_varno = var->dno;
709 
710  break;
711 
712  default:
713  elog(ERROR, "unrecognized function typecode: %d",
714  (int) function->fn_is_trigger);
715  break;
716  }
717 
718  /* Remember if function is STABLE/IMMUTABLE */
719  function->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
720 
721  /*
722  * Create the magic FOUND variable.
723  */
724  var = plpgsql_build_variable("found", 0,
726  -1,
727  InvalidOid),
728  true);
729  function->found_varno = var->dno;
730 
731  /*
732  * Now parse the function's text
733  */
734  parse_rc = plpgsql_yyparse();
735  if (parse_rc != 0)
736  elog(ERROR, "plpgsql parser returned %d", parse_rc);
737  function->action = plpgsql_parse_result;
738 
740  pfree(proc_source);
741 
742  /*
743  * If it has OUT parameters or returns VOID or returns a set, we allow
744  * control to fall off the end without an explicit RETURN statement. The
745  * easiest way to implement this is to add a RETURN statement to the end
746  * of the statement list during parsing.
747  */
748  if (num_out_args > 0 || function->fn_rettype == VOIDOID ||
749  function->fn_retset)
750  add_dummy_return(function);
751 
752  /*
753  * Complete the function's info
754  */
755  function->fn_nargs = procStruct->pronargs;
756  for (i = 0; i < function->fn_nargs; i++)
757  function->fn_argvarnos[i] = in_arg_varnos[i];
758 
759  plpgsql_finish_datums(function);
760 
761  /* Debug dump for completed functions */
763  plpgsql_dumptree(function);
764 
765  /*
766  * add it to the hash table
767  */
768  plpgsql_HashTableInsert(function, hashkey);
769 
770  /*
771  * Pop the error context stack
772  */
773  error_context_stack = plerrcontext.previous;
775 
776  plpgsql_check_syntax = false;
777 
780  return function;
781 }
int plpgsql_yyparse(void)
int fn_argvarnos[FUNC_MAX_ARGS]
Definition: plpgsql.h:837
#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:656
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation)
Definition: pl_comp.c:2127
#define OIDOID
Definition: pg_type.h:328
#define TEXTOID
Definition: pg_type.h:324
char * pstrdup(const char *in)
Definition: mcxt.c:1077
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
Definition: funcapi.c:793
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:1944
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:5507
void plpgsql_dumptree(PLpgSQL_function *func)
Definition: pl_funcs.c:1543
unsigned int Oid
Definition: postgres_ext.h:31
struct ErrorContextCallback * previous
Definition: elog.h:238
#define OidIsValid(objectId)
Definition: c.h:538
static void plpgsql_resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, Node *call_expr, bool forValidator, const char *proname)
Definition: pl_comp.c:2496
static void plpgsql_HashTableInsert(PLpgSQL_function *function, PLpgSQL_func_hashkey *func_key)
Definition: pl_comp.c:2598
static void plpgsql_start_datums(void)
Definition: pl_comp.c:2313
#define PROARGMODE_INOUT
Definition: pg_proc.h:5506
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
#define PROARGMODE_OUT
Definition: pg_proc.h:5505
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:950
#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:952
#define TRIGGEROID
Definition: pg_type.h:692
#define PROARGMODE_TABLE
Definition: pg_proc.h:5508
ItemPointerData t_self
Definition: htup.h:65
int plpgsql_extra_warnings
Definition: pl_handler.c:54
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
#define INT4RANGEOID
Definition: pg_type.h:648
static void add_dummy_return(PLpgSQL_function *function)
Definition: pl_comp.c:977
static char * buf
Definition: pg_test_fsync.c:66
#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:5504
MemoryContext TopMemoryContext
Definition: mcxt.c:43
#define PROVOLATILE_VOLATILE
Definition: pg_proc.h:5488
Oid fn_input_collation
Definition: plpgsql.h:825
#define TextDatumGetCString(d)
Definition: builtins.h:92
#define ANYARRAYOID
Definition: pg_type.h:688
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
uintptr_t Datum
Definition: postgres.h:372
Oid get_fn_expr_rettype(FmgrInfo *flinfo)
Definition: fmgr.c:1887
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1279
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:742
#define InvalidOid
Definition: postgres_ext.h:36
Oid fn_oid
Definition: fmgr.h:59
PLpgSQL_trigtype fn_is_trigger
Definition: plpgsql.h:824
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:925
int plpgsql_variable_conflict
Definition: pl_handler.c:46
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define EVTTRIGGEROID
Definition: pg_type.h:694
#define NULL
Definition: c.h:229
#define CALLED_AS_TRIGGER(fcinfo)
Definition: trigger.h:25
#define Assert(condition)
Definition: c.h:676
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:1864
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:302
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
void(* callback)(void *arg)
Definition: elog.h:239
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation)
Definition: pl_comp.c:2147
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void plpgsql_finish_datums(PLpgSQL_function *function)
Definition: pl_comp.c:2350
void plpgsql_adddatum(PLpgSQL_datum *new)
Definition: pl_comp.c:2330
int i
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:57
#define NameStr(name)
Definition: c.h:499
#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:2063
PLpgSQL_function * plpgsql_curr_compile
Definition: pl_comp.c:54
PLpgSQL_nsitem_type
Definition: plpgsql.h:38
static Node * make_datum_param ( PLpgSQL_expr expr,
int  dno,
int  location 
)
static

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

1306 {
1307  PLpgSQL_execstate *estate;
1308  PLpgSQL_datum *datum;
1309  Param *param;
1310  MemoryContext oldcontext;
1311 
1312  /* see comment in resolve_column_ref */
1313  estate = expr->func->cur_estate;
1314  Assert(dno >= 0 && dno < estate->ndatums);
1315  datum = estate->datums[dno];
1316 
1317  /*
1318  * Bitmapset must be allocated in function's permanent memory context
1319  */
1320  oldcontext = MemoryContextSwitchTo(expr->func->fn_cxt);
1321  expr->paramnos = bms_add_member(expr->paramnos, dno);
1322  MemoryContextSwitchTo(oldcontext);
1323 
1324  param = makeNode(Param);
1325  param->paramkind = PARAM_EXTERN;
1326  param->paramid = dno + 1;
1328  datum,
1329  &param->paramtype,
1330  &param->paramtypmod,
1331  &param->paramcollid);
1332  param->location = location;
1333 
1334  return (Node *) param;
1335 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ParamKind paramkind
Definition: primnodes.h:244
Definition: nodes.h:509
PLpgSQL_datum ** datums
Definition: plpgsql.h:908
Bitmapset * paramnos
Definition: plpgsql.h:225
struct PLpgSQL_execstate * cur_estate
Definition: plpgsql.h:874
Oid paramcollid
Definition: primnodes.h:248
int location
Definition: primnodes.h:249
MemoryContext fn_cxt
Definition: plpgsql.h:827
void plpgsql_exec_get_datum_type_info(PLpgSQL_execstate *estate, PLpgSQL_datum *datum, Oid *typeid, int32 *typmod, Oid *collation)
Definition: pl_exec.c:5026
struct PLpgSQL_function * func
Definition: plpgsql.h:229
int32 paramtypmod
Definition: primnodes.h:247
#define makeNode(_type_)
Definition: nodes.h:557
#define Assert(condition)
Definition: c.h:676
int paramid
Definition: primnodes.h:245
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:698
Oid paramtype
Definition: primnodes.h:246
int plpgsql_add_initdatums ( int **  varnos)

Definition at line 2391 of file pl_comp.c.

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

2392 {
2393  int i;
2394  int n = 0;
2395 
2396  for (i = datums_last; i < plpgsql_nDatums; i++)
2397  {
2398  switch (plpgsql_Datums[i]->dtype)
2399  {
2400  case PLPGSQL_DTYPE_VAR:
2401  n++;
2402  break;
2403 
2404  default:
2405  break;
2406  }
2407  }
2408 
2409  if (varnos != NULL)
2410  {
2411  if (n > 0)
2412  {
2413  *varnos = (int *) palloc(sizeof(int) * n);
2414 
2415  n = 0;
2416  for (i = datums_last; i < plpgsql_nDatums; i++)
2417  {
2418  switch (plpgsql_Datums[i]->dtype)
2419  {
2420  case PLPGSQL_DTYPE_VAR:
2421  (*varnos)[n++] = plpgsql_Datums[i]->dno;
2422 
2423  default:
2424  break;
2425  }
2426  }
2427  }
2428  else
2429  *varnos = NULL;
2430  }
2431 
2433  return n;
2434 }
int plpgsql_nDatums
Definition: pl_comp.c:46
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:47
#define NULL
Definition: c.h:229
void * palloc(Size size)
Definition: mcxt.c:849
int i
static int datums_last
Definition: pl_comp.c:48
void plpgsql_adddatum ( PLpgSQL_datum new)

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

2331 {
2333  {
2334  datums_alloc *= 2;
2336  }
2337 
2338  new->dno = plpgsql_nDatums;
2340 }
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:963
PLpgSQL_type* plpgsql_build_datatype ( Oid  typeOid,
int32  typmod,
Oid  collation 
)

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

2128 {
2129  HeapTuple typeTup;
2130  PLpgSQL_type *typ;
2131 
2132  typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
2133  if (!HeapTupleIsValid(typeTup))
2134  elog(ERROR, "cache lookup failed for type %u", typeOid);
2135 
2136  typ = build_datatype(typeTup, typmod, collation);
2137 
2138  ReleaseSysCache(typeTup);
2139 
2140  return typ;
2141 }
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation)
Definition: pl_comp.c:2147
#define elog
Definition: elog.h:219
PLpgSQL_rec* plpgsql_build_record ( const char *  refname,
int  lineno,
bool  add2namespace 
)

Definition at line 1944 of file pl_comp.c.

References PLpgSQL_rec::dno, PLpgSQL_rec::dtype, PLpgSQL_rec::freetup, PLpgSQL_rec::freetupdesc, PLpgSQL_rec::lineno, NULL, 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().

1945 {
1946  PLpgSQL_rec *rec;
1947 
1948  rec = palloc0(sizeof(PLpgSQL_rec));
1949  rec->dtype = PLPGSQL_DTYPE_REC;
1950  rec->refname = pstrdup(refname);
1951  rec->lineno = lineno;
1952  rec->tup = NULL;
1953  rec->tupdesc = NULL;
1954  rec->freetup = false;
1955  rec->freetupdesc = false;
1957  if (add2namespace)
1959 
1960  return rec;
1961 }
PLpgSQL_datum_type dtype
Definition: plpgsql.h:302
TupleDesc tupdesc
Definition: plpgsql.h:308
char * pstrdup(const char *in)
Definition: mcxt.c:1077
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:878
#define NULL
Definition: c.h:229
bool freetupdesc
Definition: plpgsql.h:310
HeapTuple tup
Definition: plpgsql.h:307
void plpgsql_adddatum(PLpgSQL_datum *new)
Definition: pl_comp.c:2330
int lineno
Definition: plpgsql.h:305
PLpgSQL_variable* plpgsql_build_variable ( const char *  refname,
int  lineno,
PLpgSQL_type dtype,
bool  add2namespace 
)

Definition at line 1864 of file pl_comp.c.

References build_row_from_class(), PLpgSQL_var::datatype, PLpgSQL_var::dno, PLpgSQL_row::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, NULL, 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, result, 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().

1866 {
1868 
1869  switch (dtype->ttype)
1870  {
1871  case PLPGSQL_TTYPE_SCALAR:
1872  {
1873  /* Ordinary scalar datatype */
1874  PLpgSQL_var *var;
1875 
1876  var = palloc0(sizeof(PLpgSQL_var));
1877  var->dtype = PLPGSQL_DTYPE_VAR;
1878  var->refname = pstrdup(refname);
1879  var->lineno = lineno;
1880  var->datatype = dtype;
1881  /* other fields might be filled by caller */
1882 
1883  /* preset to NULL */
1884  var->value = 0;
1885  var->isnull = true;
1886  var->freeval = false;
1887 
1889  if (add2namespace)
1891  var->dno,
1892  refname);
1893  result = (PLpgSQL_variable *) var;
1894  break;
1895  }
1896  case PLPGSQL_TTYPE_ROW:
1897  {
1898  /* Composite type -- build a row variable */
1899  PLpgSQL_row *row;
1900 
1901  row = build_row_from_class(dtype->typrelid);
1902 
1903  row->dtype = PLPGSQL_DTYPE_ROW;
1904  row->refname = pstrdup(refname);
1905  row->lineno = lineno;
1906 
1908  if (add2namespace)
1910  row->dno,
1911  refname);
1912  result = (PLpgSQL_variable *) row;
1913  break;
1914  }
1915  case PLPGSQL_TTYPE_REC:
1916  {
1917  /* "record" type -- build a record variable */
1918  PLpgSQL_rec *rec;
1919 
1920  rec = plpgsql_build_record(refname, lineno, add2namespace);
1921  result = (PLpgSQL_variable *) rec;
1922  break;
1923  }
1924  case PLPGSQL_TTYPE_PSEUDO:
1925  ereport(ERROR,
1926  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1927  errmsg("variable \"%s\" has pseudo-type %s",
1928  refname, format_type_be(dtype->typoid))));
1929  result = NULL; /* keep compiler quiet */
1930  break;
1931  default:
1932  elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
1933  result = NULL; /* keep compiler quiet */
1934  break;
1935  }
1936 
1937  return result;
1938 }
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:1967
PLpgSQL_datum_type dtype
Definition: plpgsql.h:256
char * pstrdup(const char *in)
Definition: mcxt.c:1077
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:1944
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
return result
Definition: formatting.c:1633
#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:878
Datum value
Definition: plpgsql.h:269
#define NULL
Definition: c.h:229
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:2330
#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_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, function, GETSTRUCT, HeapTupleHeaderGetRawXmin, HeapTupleIsValid, ItemPointerEquals(), NULL, ObjectIdGetDatum, plpgsql_HashTableLookup(), PROCOID, ReleaseSysCache(), SearchSysCache1, HeapTupleData::t_data, and HeapTupleData::t_self.

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:656
static void compute_function_hashkey(FunctionCallInfo fcinfo, Form_pg_proc procStruct, PLpgSQL_func_hashkey *hashkey, bool forValidator)
Definition: pl_comp.c:2443
unsigned int Oid
Definition: postgres_ext.h:31
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
HeapTupleHeader t_data
Definition: htup.h:67
static void delete_function(PLpgSQL_function *func)
Definition: pl_comp.c:2554
FmgrInfo * flinfo
Definition: fmgr.h:79
static PLpgSQL_function * plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key)
Definition: pl_comp.c:2583
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
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 NULL
Definition: c.h:229
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:302
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
static void plpgsql_compile_error_callback ( void *  arg)
static

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

926 {
927  if (arg)
928  {
929  /*
930  * Try to convert syntax error position to reference text of original
931  * CREATE FUNCTION or DO command.
932  */
933  if (function_parse_error_transpose((const char *) arg))
934  return;
935 
936  /*
937  * Done if a syntax error position was reported; otherwise we have to
938  * fall back to a "near line N" report.
939  */
940  }
941 
943  errcontext("compilation of PL/pgSQL function \"%s\" near line %d",
945 }
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:984
#define errcontext
Definition: elog.h:164
void * arg
PLpgSQL_function* plpgsql_compile_inline ( char *  proc_source)

Definition at line 794 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, function, InvalidOid, MemoryContextSwitchTo(), NULL, 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().

795 {
796  char *func_name = "inline_code_block";
797  PLpgSQL_function *function;
798  ErrorContextCallback plerrcontext;
799  PLpgSQL_variable *var;
800  int parse_rc;
801  MemoryContext func_cxt;
802 
803  /*
804  * Setup the scanner input and error info. We assume that this function
805  * cannot be invoked recursively, so there's no need to save and restore
806  * the static variables used here.
807  */
808  plpgsql_scanner_init(proc_source);
809 
810  plpgsql_error_funcname = func_name;
811 
812  /*
813  * Setup error traceback support for ereport()
814  */
816  plerrcontext.arg = proc_source;
817  plerrcontext.previous = error_context_stack;
818  error_context_stack = &plerrcontext;
819 
820  /* Do extra syntax checking if check_function_bodies is on */
822 
823  /* Function struct does not live past current statement */
824  function = (PLpgSQL_function *) palloc0(sizeof(PLpgSQL_function));
825 
826  plpgsql_curr_compile = function;
827 
828  /*
829  * All the rest of the compile-time storage (e.g. parse tree) is kept in
830  * its own memory context, so it can be reclaimed easily.
831  */
833  "PL/pgSQL inline code context",
836 
837  function->fn_signature = pstrdup(func_name);
838  function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
839  function->fn_input_collation = InvalidOid;
840  function->fn_cxt = func_cxt;
841  function->out_param_varno = -1; /* set up for no OUT param */
842  function->resolve_option = plpgsql_variable_conflict;
843  function->print_strict_params = plpgsql_print_strict_params;
844 
845  /*
846  * don't do extra validation for inline code as we don't want to add spam
847  * at runtime
848  */
849  function->extra_warnings = 0;
850  function->extra_errors = 0;
851 
852  plpgsql_ns_init();
854  plpgsql_DumpExecTree = false;
856 
857  /* Set up as though in a function returning VOID */
858  function->fn_rettype = VOIDOID;
859  function->fn_retset = false;
860  function->fn_retistuple = false;
861  /* a bit of hardwired knowledge about type VOID here */
862  function->fn_retbyval = true;
863  function->fn_rettyplen = sizeof(int32);
864 
865  /*
866  * Remember if function is STABLE/IMMUTABLE. XXX would it be better to
867  * set this TRUE inside a read-only transaction? Not clear.
868  */
869  function->fn_readonly = false;
870 
871  /*
872  * Create the magic FOUND variable.
873  */
874  var = plpgsql_build_variable("found", 0,
876  -1,
877  InvalidOid),
878  true);
879  function->found_varno = var->dno;
880 
881  /*
882  * Now parse the function's text
883  */
884  parse_rc = plpgsql_yyparse();
885  if (parse_rc != 0)
886  elog(ERROR, "plpgsql parser returned %d", parse_rc);
887  function->action = plpgsql_parse_result;
888 
890 
891  /*
892  * If it returns VOID (always true at the moment), we allow control to
893  * fall off the end without an explicit RETURN statement.
894  */
895  if (function->fn_rettype == VOIDOID)
896  add_dummy_return(function);
897 
898  /*
899  * Complete the function's info
900  */
901  function->fn_nargs = 0;
902 
903  plpgsql_finish_datums(function);
904 
905  /*
906  * Pop the error context stack
907  */
908  error_context_stack = plerrcontext.previous;
910 
911  plpgsql_check_syntax = false;
912 
915  return function;
916 }
int plpgsql_yyparse(void)
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation)
Definition: pl_comp.c:2127
char * pstrdup(const char *in)
Definition: mcxt.c:1077
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool check_function_bodies
Definition: guc.c:447
struct ErrorContextCallback * previous
Definition: elog.h:238
static void plpgsql_start_datums(void)
Definition: pl_comp.c:2313
signed int int32
Definition: c.h:256
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:165
static void add_dummy_return(PLpgSQL_function *function)
Definition: pl_comp.c:977
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
void plpgsql_ns_init(void)
Definition: pl_funcs.c:45
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
void * palloc0(Size size)
Definition: mcxt.c:878
#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:925
int plpgsql_variable_conflict
Definition: pl_handler.c:46
#define NULL
Definition: c.h:229
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:1864
#define BOOLOID
Definition: pg_type.h:288
on_exit_nicely_callback function
void plpgsql_scanner_init(const char *str)
Definition: pl_scanner.c:702
void(* callback)(void *arg)
Definition: elog.h:239
static void plpgsql_finish_datums(PLpgSQL_function *function)
Definition: pl_comp.c:2350
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
static void plpgsql_finish_datums ( PLpgSQL_function function)
static

Definition at line 2350 of file pl_comp.c.

References bms_add_member(), function, i, NULL, palloc(), PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_RECFIELD, PLPGSQL_DTYPE_ROW, and plpgsql_nDatums.

Referenced by do_compile(), and plpgsql_compile_inline().

2351 {
2352  Bitmapset *resettable_datums = NULL;
2353  int i;
2354 
2355  function->ndatums = plpgsql_nDatums;
2356  function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
2357  for (i = 0; i < plpgsql_nDatums; i++)
2358  {
2359  function->datums[i] = plpgsql_Datums[i];
2360  switch (function->datums[i]->dtype)
2361  {
2362  case PLPGSQL_DTYPE_ROW:
2363  case PLPGSQL_DTYPE_REC:
2365  resettable_datums = bms_add_member(resettable_datums, i);
2366  break;
2367 
2368  default:
2369  break;
2370  }
2371  }
2372  function->resettable_datums = resettable_datums;
2373 }
int plpgsql_nDatums
Definition: pl_comp.c:46
PLpgSQL_datum ** datums
Definition: plpgsql.h:867
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:47
PLpgSQL_datum_type dtype
Definition: plpgsql.h:198
#define NULL
Definition: c.h:229
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:698
void * palloc(Size size)
Definition: mcxt.c:849
int i
static void plpgsql_HashTableDelete ( PLpgSQL_function function)
static

Definition at line 2617 of file pl_comp.c.

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

Referenced by delete_function().

2618 {
2619  plpgsql_HashEnt *hentry;
2620 
2621  /* do nothing if not in table */
2622  if (function->fn_hashkey == NULL)
2623  return;
2624 
2626  (void *) function->fn_hashkey,
2627  HASH_REMOVE,
2628  NULL);
2629  if (hentry == NULL)
2630  elog(WARNING, "trying to delete function that does not exist");
2631 
2632  /* remove back link, which no longer points to allocated storage */
2633  function->fn_hashkey = NULL;
2634 }
PLpgSQL_func_hashkey * fn_hashkey
Definition: plpgsql.h:826
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:63
#define WARNING
Definition: elog.h:40
#define NULL
Definition: c.h:229
#define elog
Definition: elog.h:219
void plpgsql_HashTableInit ( void  )

Definition at line 2566 of file pl_comp.c.

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

Referenced by _PG_init().

2567 {
2568  HASHCTL ctl;
2569 
2570  /* don't allow double-initialization */
2572 
2573  memset(&ctl, 0, sizeof(ctl));
2574  ctl.keysize = sizeof(PLpgSQL_func_hashkey);
2575  ctl.entrysize = sizeof(plpgsql_HashEnt);
2576  plpgsql_HashTable = hash_create("PLpgSQL function cache",
2578  &ctl,
2579  HASH_ELEM | HASH_BLOBS);
2580 }
#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 NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
static void plpgsql_HashTableInsert ( PLpgSQL_function function,
PLpgSQL_func_hashkey func_key 
)
static

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

2600 {
2601  plpgsql_HashEnt *hentry;
2602  bool found;
2603 
2605  (void *) func_key,
2606  HASH_ENTER,
2607  &found);
2608  if (found)
2609  elog(WARNING, "trying to insert a function that already exists");
2610 
2611  hentry->function = function;
2612  /* prepare back link from function to hashtable key */
2613  function->fn_hashkey = &hentry->key;
2614 }
PLpgSQL_func_hashkey * fn_hashkey
Definition: plpgsql.h:826
PLpgSQL_func_hashkey key
Definition: pl_comp.c:67
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
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
static PLpgSQL_function * plpgsql_HashTableLookup ( PLpgSQL_func_hashkey func_key)
static

Definition at line 2583 of file pl_comp.c.

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

Referenced by plpgsql_compile().

2584 {
2585  plpgsql_HashEnt *hentry;
2586 
2588  (void *) func_key,
2589  HASH_FIND,
2590  NULL);
2591  if (hentry)
2592  return hentry->function;
2593  else
2594  return NULL;
2595 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:63
PLpgSQL_function * function
Definition: pl_comp.c:68
#define NULL
Definition: c.h:229
static Node * plpgsql_param_ref ( ParseState pstate,
ParamRef pref 
)
static

Definition at line 1089 of file pl_comp.c.

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

Referenced by plpgsql_parser_setup().

1090 {
1091  PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1092  char pname[32];
1093  PLpgSQL_nsitem *nse;
1094 
1095  snprintf(pname, sizeof(pname), "$%d", pref->number);
1096 
1097  nse = plpgsql_ns_lookup(expr->ns, false,
1098  pname, NULL, NULL,
1099  NULL);
1100 
1101  if (nse == NULL)
1102  return NULL; /* name not known to plpgsql */
1103 
1104  return make_datum_param(expr, nse->itemno, pref->location);
1105 }
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
#define NULL
Definition: c.h:229
void * p_ref_hook_state
Definition: parse_node.h:214
static Node * make_datum_param(PLpgSQL_expr *expr, int dno, int location)
Definition: pl_comp.c:1305
PLpgSQL_type* plpgsql_parse_cwordrowtype ( List idents)

Definition at line 1830 of file pl_comp.c.

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

1831 {
1832  Oid classOid;
1833  RangeVar *relvar;
1834  MemoryContext oldCxt;
1835 
1836  if (list_length(idents) != 2)
1837  return NULL;
1838 
1839  /* Avoid memory leaks in long-term function context */
1841 
1842  /* Look up relation name. Can't lock it - we might not have privileges. */
1843  relvar = makeRangeVar(strVal(linitial(idents)),
1844  strVal(lsecond(idents)),
1845  -1);
1846  classOid = RangeVarGetRelid(relvar, NoLock, false);
1847 
1848  MemoryContextSwitchTo(oldCxt);
1849 
1850  /* Build and return the row type struct */
1851  return plpgsql_build_datatype(get_rel_type_id(classOid), -1, InvalidOid);
1852 }
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation)
Definition: pl_comp.c:2127
#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:1777
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:229
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:419
PLpgSQL_type* plpgsql_parse_cwordtype ( List idents)

Definition at line 1691 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, NULL, 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.

1692 {
1693  PLpgSQL_type *dtype = NULL;
1694  PLpgSQL_nsitem *nse;
1695  const char *fldname;
1696  Oid classOid;
1697  HeapTuple classtup = NULL;
1698  HeapTuple attrtup = NULL;
1699  HeapTuple typetup = NULL;
1700  Form_pg_class classStruct;
1701  Form_pg_attribute attrStruct;
1702  MemoryContext oldCxt;
1703 
1704  /* Avoid memory leaks in the long-term function context */
1706 
1707  if (list_length(idents) == 2)
1708  {
1709  /*
1710  * Do a lookup in the current namespace stack. We don't need to check
1711  * number of names matched, because we will only consider scalar
1712  * variables.
1713  */
1714  nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1715  strVal(linitial(idents)),
1716  strVal(lsecond(idents)),
1717  NULL,
1718  NULL);
1719 
1720  if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_VAR)
1721  {
1722  dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1723  goto done;
1724  }
1725 
1726  /*
1727  * First word could also be a table name
1728  */
1729  classOid = RelnameGetRelid(strVal(linitial(idents)));
1730  if (!OidIsValid(classOid))
1731  goto done;
1732  fldname = strVal(lsecond(idents));
1733  }
1734  else if (list_length(idents) == 3)
1735  {
1736  RangeVar *relvar;
1737 
1738  relvar = makeRangeVar(strVal(linitial(idents)),
1739  strVal(lsecond(idents)),
1740  -1);
1741  /* Can't lock relation - we might not have privileges. */
1742  classOid = RangeVarGetRelid(relvar, NoLock, true);
1743  if (!OidIsValid(classOid))
1744  goto done;
1745  fldname = strVal(lthird(idents));
1746  }
1747  else
1748  goto done;
1749 
1750  classtup = SearchSysCache1(RELOID, ObjectIdGetDatum(classOid));
1751  if (!HeapTupleIsValid(classtup))
1752  goto done;
1753  classStruct = (Form_pg_class) GETSTRUCT(classtup);
1754 
1755  /*
1756  * It must be a relation, sequence, view, materialized view, composite
1757  * type, or foreign table
1758  */
1759  if (classStruct->relkind != RELKIND_RELATION &&
1760  classStruct->relkind != RELKIND_SEQUENCE &&
1761  classStruct->relkind != RELKIND_VIEW &&
1762  classStruct->relkind != RELKIND_MATVIEW &&
1763  classStruct->relkind != RELKIND_COMPOSITE_TYPE &&
1764  classStruct->relkind != RELKIND_FOREIGN_TABLE &&
1765  classStruct->relkind != RELKIND_PARTITIONED_TABLE)
1766  goto done;
1767 
1768  /*
1769  * Fetch the named table field and its type
1770  */
1771  attrtup = SearchSysCacheAttName(classOid, fldname);
1772  if (!HeapTupleIsValid(attrtup))
1773  goto done;
1774  attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1775 
1776  typetup = SearchSysCache1(TYPEOID,
1777  ObjectIdGetDatum(attrStruct->atttypid));
1778  if (!HeapTupleIsValid(typetup))
1779  elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1780 
1781  /*
1782  * Found that - build a compiler type struct in the caller's cxt and
1783  * return it
1784  */
1785  MemoryContextSwitchTo(oldCxt);
1786  dtype = build_datatype(typetup,
1787  attrStruct->atttypmod,
1788  attrStruct->attcollation);
1790 
1791 done:
1792  if (HeapTupleIsValid(classtup))
1793  ReleaseSysCache(classtup);
1794  if (HeapTupleIsValid(attrtup))
1795  ReleaseSysCache(attrtup);
1796  if (HeapTupleIsValid(typetup))
1797  ReleaseSysCache(typetup);
1798 
1799  MemoryContextSwitchTo(oldCxt);
1800  return dtype;
1801 }
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:656
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:538
#define lsecond(l)
Definition: pg_list.h:116
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
#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
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
static int list_length(const List *l)
Definition: pg_list.h:89
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1205
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:2147
#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:419
bool plpgsql_parse_dblword ( char *  word1,
char *  word2,
PLwdatum wdatum,
PLcword cword 
)

Definition at line 1411 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, NULL, 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().

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

Definition at line 2262 of file pl_comp.c.

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

2263 {
2264  int i;
2265  PLpgSQL_condition *new;
2266  PLpgSQL_condition *prev;
2267 
2268  /*
2269  * XXX Eventually we will want to look for user-defined exception names
2270  * here.
2271  */
2272 
2273  /*
2274  * OTHERS is represented as code 0 (which would map to '00000', but we
2275  * have no need to represent that as an exception condition).
2276  */
2277  if (strcmp(condname, "others") == 0)
2278  {
2279  new = palloc(sizeof(PLpgSQL_condition));
2280  new->sqlerrstate = 0;
2281  new->condname = condname;
2282  new->next = NULL;
2283  return new;
2284  }
2285 
2286  prev = NULL;
2287  for (i = 0; exception_label_map[i].label != NULL; i++)
2288  {
2289  if (strcmp(condname, exception_label_map[i].label) == 0)
2290  {
2291  new = palloc(sizeof(PLpgSQL_condition));
2292  new->sqlerrstate = exception_label_map[i].sqlerrstate;
2293  new->condname = condname;
2294  new->next = prev;
2295  prev = new;
2296  }
2297  }
2298 
2299  if (!prev)
2300  ereport(ERROR,
2301  (errcode(ERRCODE_UNDEFINED_OBJECT),
2302  errmsg("unrecognized exception condition \"%s\"",
2303  condname)));
2304 
2305  return prev;
2306 }
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:81
#define NULL
Definition: c.h:229
static const ExceptionLabelMap exception_label_map[]
Definition: pl_comp.c:83
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
bool plpgsql_parse_tripword ( char *  word1,
char *  word2,
char *  word3,
PLwdatum wdatum,
PLcword cword 
)

Definition at line 1531 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, NULL, 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().

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

Definition at line 1355 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, NULL, 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().

1357 {
1358  PLpgSQL_nsitem *ns;
1359 
1360  /*
1361  * We should do nothing in DECLARE sections. In SQL expressions, there's
1362  * no need to do anything either --- lookup will happen when the
1363  * expression is compiled.
1364  */
1366  {
1367  /*
1368  * Do a lookup in the current namespace stack
1369  */
1370  ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1371  word1, NULL, NULL,
1372  NULL);
1373 
1374  if (ns != NULL)
1375  {
1376  switch (ns->itemtype)
1377  {
1378  case PLPGSQL_NSTYPE_VAR:
1379  case PLPGSQL_NSTYPE_ROW:
1380  case PLPGSQL_NSTYPE_REC:
1381  wdatum->datum = plpgsql_Datums[ns->itemno];
1382  wdatum->ident = word1;
1383  wdatum->quoted = (yytxt[0] == '"');
1384  wdatum->idents = NIL;
1385  return true;
1386 
1387  default:
1388  /* plpgsql_ns_lookup should never return anything else */
1389  elog(ERROR, "unrecognized plpgsql itemtype: %d",
1390  ns->itemtype);
1391  }
1392  }
1393  }
1394 
1395  /*
1396  * Nothing found - up to now it's a word without any special meaning for
1397  * us.
1398  */
1399  word->ident = word1;
1400  word->quoted = (yytxt[0] == '"');
1401  return false;
1402 }
#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:989
#define ERROR
Definition: elog.h:43
List * idents
Definition: plpgsql.h:1003
IdentifierLookup plpgsql_IdentifierLookup
Definition: pl_scanner.c:29
bool quoted
Definition: plpgsql.h:990
#define NULL
Definition: c.h:229
PLpgSQL_datum * datum
Definition: plpgsql.h:1000
bool quoted
Definition: plpgsql.h:1002
char * ident
Definition: plpgsql.h:1001
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:351
#define elog
Definition: elog.h:219
PLpgSQL_type* plpgsql_parse_wordrowtype ( char *  ident)

Definition at line 1809 of file pl_comp.c.

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

1810 {
1811  Oid classOid;
1812 
1813  /* Lookup the relation */
1814  classOid = RelnameGetRelid(ident);
1815  if (!OidIsValid(classOid))
1816  ereport(ERROR,
1818  errmsg("relation \"%s\" does not exist", ident)));
1819 
1820  /* Build and return the row type struct */
1821  return plpgsql_build_datatype(get_rel_type_id(classOid), -1, InvalidOid);
1822 }
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation)
Definition: pl_comp.c:2127
#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:538
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
Oid get_rel_type_id(Oid relid)
Definition: lsyscache.c:1777
#define InvalidOid
Definition: postgres_ext.h:36
int errmsg(const char *fmt,...)
Definition: elog.c:797
PLpgSQL_type* plpgsql_parse_wordtype ( char *  ident)

Definition at line 1628 of file pl_comp.c.

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

1629 {
1630  PLpgSQL_type *dtype;
1631  PLpgSQL_nsitem *nse;
1632  HeapTuple typeTup;
1633 
1634  /*
1635  * Do a lookup in the current namespace stack
1636  */
1637  nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1638  ident, NULL, NULL,
1639  NULL);
1640 
1641  if (nse != NULL)
1642  {
1643  switch (nse->itemtype)
1644  {
1645  case PLPGSQL_NSTYPE_VAR:
1646  return ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1647 
1648  /* XXX perhaps allow REC/ROW here? */
1649 
1650  default:
1651  return NULL;
1652  }
1653  }
1654 
1655  /*
1656  * Word wasn't found in the namespace stack. Try to find a data type with
1657  * that name, but ignore shell types and complex types.
1658  */
1659  typeTup = LookupTypeName(NULL, makeTypeName(ident), NULL, false);
1660  if (typeTup)
1661  {
1662  Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1663 
1664  if (!typeStruct->typisdefined ||
1665  typeStruct->typrelid != InvalidOid)
1666  {
1667  ReleaseSysCache(typeTup);
1668  return NULL;
1669  }
1670 
1671  dtype = build_datatype(typeTup, -1,
1673 
1674  ReleaseSysCache(typeTup);
1675  return dtype;
1676  }
1677 
1678  /*
1679  * Nothing found - up to now it's a word without any special meaning for
1680  * us.
1681  */
1682  return NULL;
1683 }
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:656
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:825
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
#define InvalidOid
Definition: postgres_ext.h:36
TypeName * makeTypeName(char *typnam)
Definition: makefuncs.c:441
#define NULL
Definition: c.h:229
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation)
Definition: pl_comp.c:2147
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:351
PLpgSQL_function * plpgsql_curr_compile
Definition: pl_comp.c:54
void plpgsql_parser_setup ( struct ParseState pstate,
PLpgSQL_expr expr 
)

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

1019 {
1023  /* no need to use p_coerce_param_hook */
1024  pstate->p_ref_hook_state = (void *) expr;
1025 }
static Node * plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref)
Definition: pl_comp.c:1031
PostParseColumnRefHook p_post_columnref_hook
Definition: parse_node.h:211
ParseParamRefHook p_paramref_hook
Definition: parse_node.h:212
static Node * plpgsql_param_ref(ParseState *pstate, ParamRef *pref)
Definition: pl_comp.c:1089
void * p_ref_hook_state
Definition: parse_node.h:214
PreParseColumnRefHook p_pre_columnref_hook
Definition: parse_node.h:210
static Node * plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
Definition: pl_comp.c:1045
static Node * plpgsql_post_column_ref ( ParseState pstate,
ColumnRef cref,
Node var 
)
static

Definition at line 1045 of file pl_comp.c.

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

1046 {
1047  PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1048  Node *myvar;
1049 
1051  return NULL; /* we already found there's no match */
1052 
1053  if (expr->func->resolve_option == PLPGSQL_RESOLVE_COLUMN && var != NULL)
1054  return NULL; /* there's a table column, prefer that */
1055 
1056  /*
1057  * If we find a record/row variable but can't match a field name, throw
1058  * error if there was no core resolution for the ColumnRef either. In
1059  * that situation, the reference is inevitably going to fail, and
1060  * complaining about the record/row variable is likely to be more on-point
1061  * than the core parser's error message. (It's too bad we don't have
1062  * access to transformColumnRef's internal crerr state here, as in case of
1063  * a conflict with a table name this could still be less than the most
1064  * helpful error message possible.)
1065  */
1066  myvar = resolve_column_ref(pstate, expr, cref, (var == NULL));
1067 
1068  if (myvar != NULL && var != NULL)
1069  {
1070  /*
1071  * We could leave it to the core parser to throw this error, but we
1072  * can add a more useful detail message than the core could.
1073  */
1074  ereport(ERROR,
1075  (errcode(ERRCODE_AMBIGUOUS_COLUMN),
1076  errmsg("column reference \"%s\" is ambiguous",
1077  NameListToString(cref->fields)),
1078  errdetail("It could refer to either a PL/pgSQL variable or a table column."),
1079  parser_errposition(pstate, cref->location)));
1080  }
1081 
1082  return myvar;
1083 }
Definition: nodes.h:509
int errcode(int sqlerrcode)
Definition: elog.c:575
PLpgSQL_resolve_option resolve_option
Definition: plpgsql.h:857
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
#define NULL
Definition: c.h:229
void * p_ref_hook_state
Definition: parse_node.h:214
static Node * resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr, ColumnRef *cref, bool error_if_no_field)
Definition: pl_comp.c:1116
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
static Node * plpgsql_pre_column_ref ( ParseState pstate,
ColumnRef cref 
)
static

Definition at line 1031 of file pl_comp.c.

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

Referenced by plpgsql_parser_setup().

1032 {
1033  PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1034 
1036  return resolve_column_ref(pstate, expr, cref, false);
1037  else
1038  return NULL;
1039 }
PLpgSQL_resolve_option resolve_option
Definition: plpgsql.h:857
struct PLpgSQL_function * func
Definition: plpgsql.h:229
#define NULL
Definition: c.h:229
void * p_ref_hook_state
Definition: parse_node.h:214
static Node * resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr, ColumnRef *cref, bool error_if_no_field)
Definition: pl_comp.c:1116
int plpgsql_recognize_err_condition ( const char *  condname,
bool  allow_sqlstate 
)

Definition at line 2226 of file pl_comp.c.

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

Referenced by exec_stmt_raise().

2227 {
2228  int i;
2229 
2230  if (allow_sqlstate)
2231  {
2232  if (strlen(condname) == 5 &&
2233  strspn(condname, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") == 5)
2234  return MAKE_SQLSTATE(condname[0],
2235  condname[1],
2236  condname[2],
2237  condname[3],
2238  condname[4]);
2239  }
2240 
2241  for (i = 0; exception_label_map[i].label != NULL; i++)
2242  {
2243  if (strcmp(condname, exception_label_map[i].label) == 0)
2245  }
2246 
2247  ereport(ERROR,
2248  (errcode(ERRCODE_UNDEFINED_OBJECT),
2249  errmsg("unrecognized exception condition \"%s\"",
2250  condname)));
2251  return 0; /* keep compiler quiet */
2252 }
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:81
#define NULL
Definition: c.h:229
static const ExceptionLabelMap exception_label_map[]
Definition: pl_comp.c:83
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
static void plpgsql_resolve_polymorphic_argtypes ( int  numargs,
Oid argtypes,
char *  argmodes,
Node call_expr,
bool  forValidator,
const char *  proname 
)
static

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

2500 {
2501  int i;
2502 
2503  if (!forValidator)
2504  {
2505  /* normal case, pass to standard routine */
2506  if (!resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
2507  call_expr))
2508  ereport(ERROR,
2509  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2510  errmsg("could not determine actual argument "
2511  "type for polymorphic function \"%s\"",
2512  proname)));
2513  }
2514  else
2515  {
2516  /* special validation case */
2517  for (i = 0; i < numargs; i++)
2518  {
2519  switch (argtypes[i])
2520  {
2521  case ANYELEMENTOID:
2522  case ANYNONARRAYOID:
2523  case ANYENUMOID: /* XXX dubious */
2524  argtypes[i] = INT4OID;
2525  break;
2526  case ANYARRAYOID:
2527  argtypes[i] = INT4ARRAYOID;
2528  break;
2529  case ANYRANGEOID:
2530  argtypes[i] = INT4RANGEOID;
2531  break;
2532  default:
2533  break;
2534  }
2535  }
2536  }
2537 }
bool resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, Node *call_expr)
Definition: funcapi.c:599
#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
static void plpgsql_start_datums ( void  )
static

Definition at line 2313 of file pl_comp.c.

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

Referenced by do_compile(), and plpgsql_compile_inline().

2314 {
2315  datums_alloc = 128;
2316  plpgsql_nDatums = 0;
2317  /* This is short-lived, so needn't allocate in function's cxt */
2319  sizeof(PLpgSQL_datum *) * datums_alloc);
2320  /* datums_last tracks what's been seen by plpgsql_add_initdatums() */
2321  datums_last = 0;
2322 }
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:707
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:57
static int datums_last
Definition: pl_comp.c:48
static Node * resolve_column_ref ( ParseState pstate,
PLpgSQL_expr expr,
ColumnRef cref,
bool  error_if_no_field 
)
static

Definition at line 1116 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, NULL, 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().

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

Variable Documentation

int datums_alloc
static

Definition at line 45 of file pl_comp.c.

Referenced by plpgsql_adddatum(), and plpgsql_start_datums().

int datums_last
static

Definition at line 48 of file pl_comp.c.

Referenced by plpgsql_add_initdatums(), and plpgsql_start_datums().

const ExceptionLabelMap exception_label_map[]
static
Initial value:
= {
{NULL, 0}
}
#define NULL
Definition: c.h:229

Definition at line 83 of file pl_comp.c.

bool plpgsql_check_syntax = false

Definition at line 52 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().

MemoryContext plpgsql_compile_tmp_cxt

Definition at line 57 of file pl_comp.c.

PLpgSQL_function* plpgsql_curr_compile

Definition at line 54 of file pl_comp.c.

PLpgSQL_datum** plpgsql_Datums

Definition at line 47 of file pl_comp.c.

bool plpgsql_DumpExecTree = false

Definition at line 51 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().

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

HTAB* plpgsql_HashTable = NULL
static

Definition at line 63 of file pl_comp.c.

int plpgsql_nDatums
PLpgSQL_stmt_block* plpgsql_parse_result

Definition at line 43 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().