PostgreSQL Source Code  git master
pl_comp.c File Reference
#include "postgres.h"
#include <ctype.h>
#include "access/htup_details.h"
#include "catalog/namespace.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "nodes/makefuncs.h"
#include "parser/parse_type.h"
#include "utils/builtins.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/regproc.h"
#include "utils/rel.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
#include "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_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, PLpgSQL_type *dtype, Oid rectypeid, bool add2namespace)
 
PLpgSQL_recfieldplpgsql_build_recfield (PLpgSQL_rec *rec, const char *fldname)
 
PLpgSQL_typeplpgsql_build_datatype (Oid typeOid, int32 typmod, Oid collation)
 
int plpgsql_recognize_err_condition (const char *condname, bool allow_sqlstate)
 
PLpgSQL_conditionplpgsql_parse_err_condition (char *condname)
 
void plpgsql_adddatum (PLpgSQL_datum *new)
 
int plpgsql_add_initdatums (int **varnos)
 
void plpgsql_HashTableInit (void)
 

Variables

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

Macro Definition Documentation

◆ FUNCS_PER_USER

#define FUNCS_PER_USER   128 /* initial table size */

Definition at line 71 of file pl_comp.c.

Referenced by plpgsql_HashTableInit().

Typedef Documentation

◆ plpgsql_HashEnt

Function Documentation

◆ add_dummy_return()

static void add_dummy_return ( PLpgSQL_function function)
static

Definition at line 1010 of file pl_comp.c.

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

Referenced by do_compile(), and plpgsql_compile_inline().

1011 {
1012  /*
1013  * If the outer block has an EXCEPTION clause, we need to make a new outer
1014  * block, since the added RETURN shouldn't act like it is inside the
1015  * EXCEPTION clause.
1016  */
1017  if (function->action->exceptions != NULL)
1018  {
1019  PLpgSQL_stmt_block *new;
1020 
1021  new = palloc0(sizeof(PLpgSQL_stmt_block));
1022  new->cmd_type = PLPGSQL_STMT_BLOCK;
1023  new->body = list_make1(function->action);
1024 
1025  function->action = new;
1026  }
1027  if (function->action->body == NIL ||
1028  ((PLpgSQL_stmt *) llast(function->action->body))->cmd_type != PLPGSQL_STMT_RETURN)
1029  {
1030  PLpgSQL_stmt_return *new;
1031 
1032  new = palloc0(sizeof(PLpgSQL_stmt_return));
1033  new->cmd_type = PLPGSQL_STMT_RETURN;
1034  new->expr = NULL;
1035  new->retvarno = function->out_param_varno;
1036 
1037  function->action->body = lappend(function->action->body, new);
1038  }
1039 }
#define NIL
Definition: pg_list.h:69
PLpgSQL_stmt_block * action
Definition: plpgsql.h:968
#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:955
PLpgSQL_exception_block * exceptions
Definition: plpgsql.h:489

◆ add_parameter_name()

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

Definition at line 985 of file pl_comp.c.

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

Referenced by do_compile().

986 {
987  /*
988  * Before adding the name, check for duplicates. We need this even though
989  * functioncmds.c has a similar check, because that code explicitly
990  * doesn't complain about conflicting IN and OUT parameter names. In
991  * plpgsql, such names are in the same namespace, so there is no way to
992  * disambiguate.
993  */
994  if (plpgsql_ns_lookup(plpgsql_ns_top(), true,
995  name, NULL, NULL,
996  NULL) != NULL)
997  ereport(ERROR,
998  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
999  errmsg("parameter name \"%s\" used more than once",
1000  name)));
1001 
1002  /* OK, add the name */
1003  plpgsql_ns_additem(itemtype, itemno, name);
1004 }
PLpgSQL_nsitem * plpgsql_ns_top(void)
Definition: pl_funcs.c:83
PLpgSQL_nsitem * plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode, const char *name1, const char *name2, const char *name3, int *names_used)
Definition: pl_funcs.c:132
void plpgsql_ns_additem(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
Definition: pl_funcs.c:94
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
const char * name
Definition: encode.c:521
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ build_datatype()

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

Definition at line 2018 of file pl_comp.c.

References 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_SCALAR, pstrdup(), PLpgSQL_type::ttype, PLpgSQL_type::typbyval, type_is_rowtype(), PLpgSQL_type::typisarray, PLpgSQL_type::typlen, PLpgSQL_type::typname, PLpgSQL_type::typoid, and PLpgSQL_type::typtype.

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

2019 {
2020  Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
2021  PLpgSQL_type *typ;
2022 
2023  if (!typeStruct->typisdefined)
2024  ereport(ERROR,
2025  (errcode(ERRCODE_UNDEFINED_OBJECT),
2026  errmsg("type \"%s\" is only a shell",
2027  NameStr(typeStruct->typname))));
2028 
2029  typ = (PLpgSQL_type *) palloc(sizeof(PLpgSQL_type));
2030 
2031  typ->typname = pstrdup(NameStr(typeStruct->typname));
2032  typ->typoid = HeapTupleGetOid(typeTup);
2033  switch (typeStruct->typtype)
2034  {
2035  case TYPTYPE_BASE:
2036  case TYPTYPE_ENUM:
2037  case TYPTYPE_RANGE:
2038  typ->ttype = PLPGSQL_TTYPE_SCALAR;
2039  break;
2040  case TYPTYPE_COMPOSITE:
2041  typ->ttype = PLPGSQL_TTYPE_REC;
2042  break;
2043  case TYPTYPE_DOMAIN:
2044  if (type_is_rowtype(typeStruct->typbasetype))
2045  typ->ttype = PLPGSQL_TTYPE_REC;
2046  else
2047  typ->ttype = PLPGSQL_TTYPE_SCALAR;
2048  break;
2049  case TYPTYPE_PSEUDO:
2050  if (typ->typoid == RECORDOID)
2051  typ->ttype = PLPGSQL_TTYPE_REC;
2052  else
2053  typ->ttype = PLPGSQL_TTYPE_PSEUDO;
2054  break;
2055  default:
2056  elog(ERROR, "unrecognized typtype: %d",
2057  (int) typeStruct->typtype);
2058  break;
2059  }
2060  typ->typlen = typeStruct->typlen;
2061  typ->typbyval = typeStruct->typbyval;
2062  typ->typtype = typeStruct->typtype;
2063  typ->collation = typeStruct->typcollation;
2064  if (OidIsValid(collation) && OidIsValid(typ->collation))
2065  typ->collation = collation;
2066  /* Detect if type is true array, or domain thereof */
2067  /* NB: this is only used to decide whether to apply expand_array */
2068  if (typeStruct->typtype == TYPTYPE_BASE)
2069  {
2070  /*
2071  * This test should include what get_element_type() checks. We also
2072  * disallow non-toastable array types (i.e. oidvector and int2vector).
2073  */
2074  typ->typisarray = (typeStruct->typlen == -1 &&
2075  OidIsValid(typeStruct->typelem) &&
2076  typeStruct->typstorage != 'p');
2077  }
2078  else if (typeStruct->typtype == TYPTYPE_DOMAIN)
2079  {
2080  /* we can short-circuit looking up base types if it's not varlena */
2081  typ->typisarray = (typeStruct->typlen == -1 &&
2082  typeStruct->typstorage != 'p' &&
2083  OidIsValid(get_base_element_type(typeStruct->typbasetype)));
2084  }
2085  else
2086  typ->typisarray = false;
2087  typ->atttypmod = typmod;
2088 
2089  return typ;
2090 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
char * pstrdup(const char *in)
Definition: mcxt.c:1161
PLpgSQL_type_type ttype
Definition: plpgsql.h:203
int errcode(int sqlerrcode)
Definition: elog.c:575
#define OidIsValid(objectId)
Definition: c.h:605
#define ERROR
Definition: elog.h:43
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2409
#define ereport(elevel, rest)
Definition: elog.h:122
bool typbyval
Definition: plpgsql.h:205
Oid collation
Definition: plpgsql.h:207
bool typisarray
Definition: plpgsql.h:208
FormData_pg_type * Form_pg_type
Definition: pg_type.h:247
char * typname
Definition: plpgsql.h:201
char typtype
Definition: plpgsql.h:206
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2575
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:797
int32 atttypmod
Definition: plpgsql.h:209
#define NameStr(name)
Definition: c.h:576
#define elog
Definition: elog.h:219
int16 typlen
Definition: plpgsql.h:204
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:707
Oid typoid
Definition: plpgsql.h:202

◆ build_row_from_vars()

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

Definition at line 1892 of file pl_comp.c.

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

Referenced by do_compile().

1893 {
1894  PLpgSQL_row *row;
1895  int i;
1896 
1897  row = palloc0(sizeof(PLpgSQL_row));
1898  row->dtype = PLPGSQL_DTYPE_ROW;
1899  row->rowtupdesc = CreateTemplateTupleDesc(numvars, false);
1900  row->nfields = numvars;
1901  row->fieldnames = palloc(numvars * sizeof(char *));
1902  row->varnos = palloc(numvars * sizeof(int));
1903 
1904  for (i = 0; i < numvars; i++)
1905  {
1906  PLpgSQL_variable *var = vars[i];
1907  Oid typoid;
1908  int32 typmod;
1909  Oid typcoll;
1910 
1911  /* Member vars of a row should never be const */
1912  Assert(!var->isconst);
1913 
1914  switch (var->dtype)
1915  {
1916  case PLPGSQL_DTYPE_VAR:
1917  case PLPGSQL_DTYPE_PROMISE:
1918  typoid = ((PLpgSQL_var *) var)->datatype->typoid;
1919  typmod = ((PLpgSQL_var *) var)->datatype->atttypmod;
1920  typcoll = ((PLpgSQL_var *) var)->datatype->collation;
1921  break;
1922 
1923  case PLPGSQL_DTYPE_REC:
1924  typoid = ((PLpgSQL_rec *) var)->rectypeid;
1925  typmod = -1; /* don't know typmod, if it's used at all */
1926  typcoll = InvalidOid; /* composite types have no collation */
1927  break;
1928 
1929  default:
1930  elog(ERROR, "unrecognized dtype: %d", var->dtype);
1931  typoid = InvalidOid; /* keep compiler quiet */
1932  typmod = 0;
1933  typcoll = InvalidOid;
1934  break;
1935  }
1936 
1937  row->fieldnames[i] = var->refname;
1938  row->varnos[i] = var->dno;
1939 
1940  TupleDescInitEntry(row->rowtupdesc, i + 1,
1941  var->refname,
1942  typoid, typmod,
1943  0);
1944  TupleDescInitEntryCollation(row->rowtupdesc, i + 1, typcoll);
1945  }
1946 
1947  return row;
1948 }
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:313
#define ERROR
Definition: elog.h:43
char ** fieldnames
Definition: plpgsql.h:353
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition: tupdesc.c:761
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:600
int * varnos
Definition: plpgsql.h:354
void * palloc0(Size size)
Definition: mcxt.c:955
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:699
int nfields
Definition: plpgsql.h:352
char * refname
Definition: plpgsql.h:267
PLpgSQL_datum_type dtype
Definition: plpgsql.h:265
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:45
void * palloc(Size size)
Definition: mcxt.c:924
int i
TupleDesc rowtupdesc
Definition: plpgsql.h:350
#define elog
Definition: elog.h:219
PLpgSQL_datum_type dtype
Definition: plpgsql.h:336

◆ compute_function_hashkey()

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

Definition at line 2323 of file pl_comp.c.

References PLpgSQL_func_hashkey::argtypes, CALLED_AS_TRIGGER, FunctionCallInfoData::context, FunctionCallInfoData::flinfo, FmgrInfo::fn_expr, FmgrInfo::fn_oid, FunctionCallInfoData::fncollation, PLpgSQL_func_hashkey::funcOid, PLpgSQL_func_hashkey::inputCollation, PLpgSQL_func_hashkey::isTrigger, MemSet, NameStr, plpgsql_resolve_polymorphic_argtypes(), TriggerData::tg_trigger, Trigger::tgoid, and PLpgSQL_func_hashkey::trigOid.

Referenced by plpgsql_compile().

2327 {
2328  /* Make sure any unused bytes of the struct are zero */
2329  MemSet(hashkey, 0, sizeof(PLpgSQL_func_hashkey));
2330 
2331  /* get function OID */
2332  hashkey->funcOid = fcinfo->flinfo->fn_oid;
2333 
2334  /* get call context */
2335  hashkey->isTrigger = CALLED_AS_TRIGGER(fcinfo);
2336 
2337  /*
2338  * if trigger, get its OID. In validation mode we do not know what
2339  * relation or transition table names are intended to be used, so we leave
2340  * trigOid zero; the hash entry built in this case will never really be
2341  * used.
2342  */
2343  if (hashkey->isTrigger && !forValidator)
2344  {
2345  TriggerData *trigdata = (TriggerData *) fcinfo->context;
2346 
2347  hashkey->trigOid = trigdata->tg_trigger->tgoid;
2348  }
2349 
2350  /* get input collation, if known */
2351  hashkey->inputCollation = fcinfo->fncollation;
2352 
2353  if (procStruct->pronargs > 0)
2354  {
2355  /* get the argument types */
2356  memcpy(hashkey->argtypes, procStruct->proargtypes.values,
2357  procStruct->pronargs * sizeof(Oid));
2358 
2359  /* resolve any polymorphic argument types */
2360  plpgsql_resolve_polymorphic_argtypes(procStruct->pronargs,
2361  hashkey->argtypes,
2362  NULL,
2363  fcinfo->flinfo->fn_expr,
2364  forValidator,
2365  NameStr(procStruct->proname));
2366  }
2367 }
Oid argtypes[FUNC_MAX_ARGS]
Definition: plpgsql.h:911
fmNodePtr context
Definition: fmgr.h:80
Oid tgoid
Definition: reltrigger.h:25
#define MemSet(start, val, len)
Definition: c.h:908
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:2376
FmgrInfo * flinfo
Definition: fmgr.h:79
Trigger * tg_trigger
Definition: trigger.h:37
Oid fn_oid
Definition: fmgr.h:59
#define CALLED_AS_TRIGGER(fcinfo)
Definition: trigger.h:25
fmNodePtr fn_expr
Definition: fmgr.h:66
#define NameStr(name)
Definition: c.h:576

◆ delete_function()

static void delete_function ( PLpgSQL_function func)
static

Definition at line 2434 of file pl_comp.c.

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

Referenced by plpgsql_compile().

2435 {
2436  /* remove function from hash table (might be done already) */
2438 
2439  /* release the function's storage if safe and not done already */
2440  if (func->use_count == 0)
2442 }
void plpgsql_free_function_memory(PLpgSQL_function *func)
Definition: pl_funcs.c:741
unsigned long use_count
Definition: plpgsql.h:972
static void plpgsql_HashTableDelete(PLpgSQL_function *function)
Definition: pl_comp.c:2497

◆ do_compile()

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

Definition at line 264 of file pl_comp.c.

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

Referenced by plpgsql_compile().

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

◆ make_datum_param()

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

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

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

◆ plpgsql_add_initdatums()

int plpgsql_add_initdatums ( int **  varnos)

Definition at line 2265 of file pl_comp.c.

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

2266 {
2267  int i;
2268  int n = 0;
2269 
2270  /*
2271  * The set of dtypes recognized here must match what exec_stmt_block()
2272  * cares about (re)initializing at block entry.
2273  */
2274  for (i = datums_last; i < plpgsql_nDatums; i++)
2275  {
2276  switch (plpgsql_Datums[i]->dtype)
2277  {
2278  case PLPGSQL_DTYPE_VAR:
2279  case PLPGSQL_DTYPE_REC:
2280  n++;
2281  break;
2282 
2283  default:
2284  break;
2285  }
2286  }
2287 
2288  if (varnos != NULL)
2289  {
2290  if (n > 0)
2291  {
2292  *varnos = (int *) palloc(sizeof(int) * n);
2293 
2294  n = 0;
2295  for (i = datums_last; i < plpgsql_nDatums; i++)
2296  {
2297  switch (plpgsql_Datums[i]->dtype)
2298  {
2299  case PLPGSQL_DTYPE_VAR:
2300  case PLPGSQL_DTYPE_REC:
2301  (*varnos)[n++] = plpgsql_Datums[i]->dno;
2302 
2303  default:
2304  break;
2305  }
2306  }
2307  }
2308  else
2309  *varnos = NULL;
2310  }
2311 
2313  return n;
2314 }
int plpgsql_nDatums
Definition: pl_comp.c:46
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:47
void * palloc(Size size)
Definition: mcxt.c:924
int i
static int datums_last
Definition: pl_comp.c:48

◆ plpgsql_adddatum()

void plpgsql_adddatum ( PLpgSQL_datum new)

Definition at line 2204 of file pl_comp.c.

References datums_alloc, plpgsql_nDatums, and repalloc().

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

2205 {
2207  {
2208  datums_alloc *= 2;
2210  }
2211 
2212  new->dno = plpgsql_nDatums;
2214 }
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:1044

◆ plpgsql_build_datatype()

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

Definition at line 1998 of file pl_comp.c.

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

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

1999 {
2000  HeapTuple typeTup;
2001  PLpgSQL_type *typ;
2002 
2003  typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
2004  if (!HeapTupleIsValid(typeTup))
2005  elog(ERROR, "cache lookup failed for type %u", typeOid);
2006 
2007  typ = build_datatype(typeTup, typmod, collation);
2008 
2009  ReleaseSysCache(typeTup);
2010 
2011  return typ;
2012 }
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation)
Definition: pl_comp.c:2018
#define elog
Definition: elog.h:219

◆ plpgsql_build_recfield()

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

Definition at line 1956 of file pl_comp.c.

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

Referenced by plpgsql_parse_dblword(), and plpgsql_parse_tripword().

1957 {
1958  PLpgSQL_recfield *recfield;
1959  int i;
1960 
1961  /* search for an existing datum referencing this field */
1962  i = rec->firstfield;
1963  while (i >= 0)
1964  {
1966 
1968  fld->recparentno == rec->dno);
1969  if (strcmp(fld->fieldname, fldname) == 0)
1970  return fld;
1971  i = fld->nextfield;
1972  }
1973 
1974  /* nope, so make a new one */
1975  recfield = palloc0(sizeof(PLpgSQL_recfield));
1976  recfield->dtype = PLPGSQL_DTYPE_RECFIELD;
1977  recfield->fieldname = pstrdup(fldname);
1978  recfield->recparentno = rec->dno;
1980 
1981  plpgsql_adddatum((PLpgSQL_datum *) recfield);
1982 
1983  /* now we can link it into the parent's chain */
1984  recfield->nextfield = rec->firstfield;
1985  rec->firstfield = recfield->dno;
1986 
1987  return recfield;
1988 }
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:47
char * pstrdup(const char *in)
Definition: mcxt.c:1161
#define INVALID_TUPLEDESC_IDENTIFIER
Definition: typcache.h:145
uint64 rectupledescid
Definition: plpgsql.h:394
void * palloc0(Size size)
Definition: mcxt.c:955
PLpgSQL_datum_type dtype
Definition: plpgsql.h:387
#define Assert(condition)
Definition: c.h:699
void plpgsql_adddatum(PLpgSQL_datum *new)
Definition: pl_comp.c:2204
int i
char * fieldname
Definition: plpgsql.h:391
int firstfield
Definition: plpgsql.h:374

◆ plpgsql_build_record()

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

Definition at line 1865 of file pl_comp.c.

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

Referenced by do_compile(), and plpgsql_build_variable().

1868 {
1869  PLpgSQL_rec *rec;
1870 
1871  rec = palloc0(sizeof(PLpgSQL_rec));
1872  rec->dtype = PLPGSQL_DTYPE_REC;
1873  rec->refname = pstrdup(refname);
1874  rec->lineno = lineno;
1875  /* other fields are left as 0, might be changed by caller */
1876  rec->datatype = dtype;
1877  rec->rectypeid = rectypeid;
1878  rec->firstfield = -1;
1879  rec->erh = NULL;
1881  if (add2namespace)
1883 
1884  return rec;
1885 }
PLpgSQL_datum_type dtype
Definition: plpgsql.h:362
PLpgSQL_type * datatype
Definition: plpgsql.h:371
char * pstrdup(const char *in)
Definition: mcxt.c:1161
void plpgsql_ns_additem(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
Definition: pl_funcs.c:94
ExpandedRecordHeader * erh
Definition: plpgsql.h:379
char * refname
Definition: plpgsql.h:364
void * palloc0(Size size)
Definition: mcxt.c:955
void plpgsql_adddatum(PLpgSQL_datum *new)
Definition: pl_comp.c:2204
Oid rectypeid
Definition: plpgsql.h:372
int lineno
Definition: plpgsql.h:365
int firstfield
Definition: plpgsql.h:374

◆ plpgsql_build_variable()

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

Definition at line 1802 of file pl_comp.c.

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

Referenced by do_compile(), and plpgsql_compile_inline().

1804 {
1805  PLpgSQL_variable *result;
1806 
1807  switch (dtype->ttype)
1808  {
1809  case PLPGSQL_TTYPE_SCALAR:
1810  {
1811  /* Ordinary scalar datatype */
1812  PLpgSQL_var *var;
1813 
1814  var = palloc0(sizeof(PLpgSQL_var));
1815  var->dtype = PLPGSQL_DTYPE_VAR;
1816  var->refname = pstrdup(refname);
1817  var->lineno = lineno;
1818  var->datatype = dtype;
1819  /* other fields are left as 0, might be changed by caller */
1820 
1821  /* preset to NULL */
1822  var->value = 0;
1823  var->isnull = true;
1824  var->freeval = false;
1825 
1827  if (add2namespace)
1829  var->dno,
1830  refname);
1831  result = (PLpgSQL_variable *) var;
1832  break;
1833  }
1834  case PLPGSQL_TTYPE_REC:
1835  {
1836  /* Composite type -- build a record variable */
1837  PLpgSQL_rec *rec;
1838 
1839  rec = plpgsql_build_record(refname, lineno,
1840  dtype, dtype->typoid,
1841  add2namespace);
1842  result = (PLpgSQL_variable *) rec;
1843  break;
1844  }
1845  case PLPGSQL_TTYPE_PSEUDO:
1846  ereport(ERROR,
1847  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1848  errmsg("variable \"%s\" has pseudo-type %s",
1849  refname, format_type_be(dtype->typoid))));
1850  result = NULL; /* keep compiler quiet */
1851  break;
1852  default:
1853  elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
1854  result = NULL; /* keep compiler quiet */
1855  break;
1856  }
1857 
1858  return result;
1859 }
char * refname
Definition: plpgsql.h:289
PLpgSQL_rec * plpgsql_build_record(const char *refname, int lineno, PLpgSQL_type *dtype, Oid rectypeid, bool add2namespace)
Definition: pl_comp.c:1865
PLpgSQL_datum_type dtype
Definition: plpgsql.h:287
char * pstrdup(const char *in)
Definition: mcxt.c:1161
PLpgSQL_type * datatype
Definition: plpgsql.h:296
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:203
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:328
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
bool freeval
Definition: plpgsql.h:311
void * palloc0(Size size)
Definition: mcxt.c:955
Datum value
Definition: plpgsql.h:309
int lineno
Definition: plpgsql.h:290
int errmsg(const char *fmt,...)
Definition: elog.c:797
void plpgsql_adddatum(PLpgSQL_datum *new)
Definition: pl_comp.c:2204
#define elog
Definition: elog.h:219
bool isnull
Definition: plpgsql.h:310
Oid typoid
Definition: plpgsql.h:202

◆ plpgsql_compile()

PLpgSQL_function* plpgsql_compile ( FunctionCallInfo  fcinfo,
bool  forValidator 
)

Definition at line 136 of file pl_comp.c.

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

Referenced by plpgsql_call_handler(), and plpgsql_validator().

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

◆ plpgsql_compile_error_callback()

static void plpgsql_compile_error_callback ( void *  arg)
static

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

959 {
960  if (arg)
961  {
962  /*
963  * Try to convert syntax error position to reference text of original
964  * CREATE FUNCTION or DO command.
965  */
966  if (function_parse_error_transpose((const char *) arg))
967  return;
968 
969  /*
970  * Done if a syntax error position was reported; otherwise we have to
971  * fall back to a "near line N" report.
972  */
973  }
974 
976  errcontext("compilation of PL/pgSQL function \"%s\" near line %d",
978 }
int plpgsql_latest_lineno(void)
Definition: pl_scanner.c:694
char * plpgsql_error_funcname
Definition: pl_comp.c:50
bool function_parse_error_transpose(const char *prosrc)
Definition: pg_proc.c:970
#define errcontext
Definition: elog.h:164
void * arg

◆ plpgsql_compile_inline()

PLpgSQL_function* plpgsql_compile_inline ( char *  proc_source)

Definition at line 825 of file pl_comp.c.

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

Referenced by plpgsql_inline_handler().

826 {
827  char *func_name = "inline_code_block";
828  PLpgSQL_function *function;
829  ErrorContextCallback plerrcontext;
830  PLpgSQL_variable *var;
831  int parse_rc;
832  MemoryContext func_cxt;
833 
834  /*
835  * Setup the scanner input and error info. We assume that this function
836  * cannot be invoked recursively, so there's no need to save and restore
837  * the static variables used here.
838  */
839  plpgsql_scanner_init(proc_source);
840 
841  plpgsql_error_funcname = func_name;
842 
843  /*
844  * Setup error traceback support for ereport()
845  */
847  plerrcontext.arg = proc_source;
848  plerrcontext.previous = error_context_stack;
849  error_context_stack = &plerrcontext;
850 
851  /* Do extra syntax checking if check_function_bodies is on */
853 
854  /* Function struct does not live past current statement */
855  function = (PLpgSQL_function *) palloc0(sizeof(PLpgSQL_function));
856 
857  plpgsql_curr_compile = function;
858 
859  /*
860  * All the rest of the compile-time storage (e.g. parse tree) is kept in
861  * its own memory context, so it can be reclaimed easily.
862  */
864  "PL/pgSQL inline code context",
867 
868  function->fn_signature = pstrdup(func_name);
869  function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
870  function->fn_input_collation = InvalidOid;
871  function->fn_cxt = func_cxt;
872  function->out_param_varno = -1; /* set up for no OUT param */
873  function->resolve_option = plpgsql_variable_conflict;
874  function->print_strict_params = plpgsql_print_strict_params;
875 
876  /*
877  * don't do extra validation for inline code as we don't want to add spam
878  * at runtime
879  */
880  function->extra_warnings = 0;
881  function->extra_errors = 0;
882 
883  plpgsql_ns_init();
885  plpgsql_DumpExecTree = false;
887 
888  /* Set up as though in a function returning VOID */
889  function->fn_rettype = VOIDOID;
890  function->fn_retset = false;
891  function->fn_retistuple = false;
892  function->fn_retisdomain = false;
893  function->fn_prokind = PROKIND_FUNCTION;
894  /* a bit of hardwired knowledge about type VOID here */
895  function->fn_retbyval = true;
896  function->fn_rettyplen = sizeof(int32);
897 
898  /*
899  * Remember if function is STABLE/IMMUTABLE. XXX would it be better to
900  * set this true inside a read-only transaction? Not clear.
901  */
902  function->fn_readonly = false;
903 
904  /*
905  * Create the magic FOUND variable.
906  */
907  var = plpgsql_build_variable("found", 0,
908  plpgsql_build_datatype(BOOLOID,
909  -1,
910  InvalidOid),
911  true);
912  function->found_varno = var->dno;
913 
914  /*
915  * Now parse the function's text
916  */
917  parse_rc = plpgsql_yyparse();
918  if (parse_rc != 0)
919  elog(ERROR, "plpgsql parser returned %d", parse_rc);
920  function->action = plpgsql_parse_result;
921 
923 
924  /*
925  * If it returns VOID (always true at the moment), we allow control to
926  * fall off the end without an explicit RETURN statement.
927  */
928  if (function->fn_rettype == VOIDOID)
929  add_dummy_return(function);
930 
931  /*
932  * Complete the function's info
933  */
934  function->fn_nargs = 0;
935 
936  plpgsql_finish_datums(function);
937 
938  /*
939  * Pop the error context stack
940  */
941  error_context_stack = plerrcontext.previous;
942  plpgsql_error_funcname = NULL;
943 
944  plpgsql_check_syntax = false;
945 
948  return function;
949 }
int plpgsql_yyparse(void)
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation)
Definition: pl_comp.c:1998
char * pstrdup(const char *in)
Definition: mcxt.c:1161
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool check_function_bodies
Definition: guc.c:449
void(* callback)(void *arg)
Definition: elog.h:239
struct ErrorContextCallback * previous
Definition: elog.h:238
static void plpgsql_start_datums(void)
Definition: pl_comp.c:2187
signed int int32
Definition: c.h:313
ErrorContextCallback * error_context_stack
Definition: elog.c:88
void plpgsql_scanner_finish(void)
Definition: pl_scanner.c:735
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:192
static void add_dummy_return(PLpgSQL_function *function)
Definition: pl_comp.c:1010
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
void plpgsql_ns_init(void)
Definition: pl_funcs.c:45
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:170
void * palloc0(Size size)
Definition: mcxt.c:955
#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:958
int plpgsql_variable_conflict
Definition: pl_handler.c:46
void plpgsql_ns_push(const char *label, PLpgSQL_label_type label_type)
Definition: pl_funcs.c:56
PLpgSQL_stmt_block * plpgsql_parse_result
Definition: pl_comp.c:43
PLpgSQL_variable * plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype, bool add2namespace)
Definition: pl_comp.c:1802
on_exit_nicely_callback function
void plpgsql_scanner_init(const char *str)
Definition: pl_scanner.c:708
static void plpgsql_finish_datums(PLpgSQL_function *function)
Definition: pl_comp.c:2221
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:57
#define elog
Definition: elog.h:219
PLpgSQL_function * plpgsql_curr_compile
Definition: pl_comp.c:54

◆ plpgsql_finish_datums()

static void plpgsql_finish_datums ( PLpgSQL_function function)
static

Definition at line 2221 of file pl_comp.c.

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

Referenced by do_compile(), and plpgsql_compile_inline().

2222 {
2223  Size copiable_size = 0;
2224  int i;
2225 
2226  function->ndatums = plpgsql_nDatums;
2227  function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
2228  for (i = 0; i < plpgsql_nDatums; i++)
2229  {
2230  function->datums[i] = plpgsql_Datums[i];
2231 
2232  /* This must agree with copy_plpgsql_datums on what is copiable */
2233  switch (function->datums[i]->dtype)
2234  {
2235  case PLPGSQL_DTYPE_VAR:
2236  case PLPGSQL_DTYPE_PROMISE:
2237  copiable_size += MAXALIGN(sizeof(PLpgSQL_var));
2238  break;
2239  case PLPGSQL_DTYPE_REC:
2240  copiable_size += MAXALIGN(sizeof(PLpgSQL_rec));
2241  break;
2242  default:
2243  break;
2244  }
2245  }
2246  function->copiable_size = copiable_size;
2247 }
int plpgsql_nDatums
Definition: pl_comp.c:46
PLpgSQL_datum ** datums
Definition: plpgsql.h:964
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:47
PLpgSQL_datum_type dtype
Definition: plpgsql.h:253
size_t Size
Definition: c.h:433
#define MAXALIGN(LEN)
Definition: c.h:652
void * palloc(Size size)
Definition: mcxt.c:924
int i

◆ plpgsql_HashTableDelete()

static void plpgsql_HashTableDelete ( PLpgSQL_function function)
static

Definition at line 2497 of file pl_comp.c.

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

Referenced by delete_function().

2498 {
2499  plpgsql_HashEnt *hentry;
2500 
2501  /* do nothing if not in table */
2502  if (function->fn_hashkey == NULL)
2503  return;
2504 
2506  (void *) function->fn_hashkey,
2507  HASH_REMOVE,
2508  NULL);
2509  if (hentry == NULL)
2510  elog(WARNING, "trying to delete function that does not exist");
2511 
2512  /* remove back link, which no longer points to allocated storage */
2513  function->fn_hashkey = NULL;
2514 }
PLpgSQL_func_hashkey * fn_hashkey
Definition: plpgsql.h:935
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:63
#define WARNING
Definition: elog.h:40
#define elog
Definition: elog.h:219

◆ plpgsql_HashTableInit()

void plpgsql_HashTableInit ( void  )

Definition at line 2446 of file pl_comp.c.

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

Referenced by _PG_init().

2447 {
2448  HASHCTL ctl;
2449 
2450  /* don't allow double-initialization */
2451  Assert(plpgsql_HashTable == NULL);
2452 
2453  memset(&ctl, 0, sizeof(ctl));
2454  ctl.keysize = sizeof(PLpgSQL_func_hashkey);
2455  ctl.entrysize = sizeof(plpgsql_HashEnt);
2456  plpgsql_HashTable = hash_create("PLpgSQL function hash",
2458  &ctl,
2459  HASH_ELEM | HASH_BLOBS);
2460 }
#define FUNCS_PER_USER
Definition: pl_comp.c:71
#define HASH_ELEM
Definition: hsearch.h:87
Size entrysize
Definition: hsearch.h:73
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:63
struct plpgsql_hashent plpgsql_HashEnt
struct PLpgSQL_func_hashkey PLpgSQL_func_hashkey
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
Size keysize
Definition: hsearch.h:72
#define Assert(condition)
Definition: c.h:699

◆ plpgsql_HashTableInsert()

static void plpgsql_HashTableInsert ( PLpgSQL_function function,
PLpgSQL_func_hashkey func_key 
)
static

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

2480 {
2481  plpgsql_HashEnt *hentry;
2482  bool found;
2483 
2485  (void *) func_key,
2486  HASH_ENTER,
2487  &found);
2488  if (found)
2489  elog(WARNING, "trying to insert a function that already exists");
2490 
2491  hentry->function = function;
2492  /* prepare back link from function to hashtable key */
2493  function->fn_hashkey = &hentry->key;
2494 }
PLpgSQL_func_hashkey * fn_hashkey
Definition: plpgsql.h:935
PLpgSQL_func_hashkey key
Definition: pl_comp.c:67
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:63
PLpgSQL_function * function
Definition: pl_comp.c:68
#define WARNING
Definition: elog.h:40
#define elog
Definition: elog.h:219

◆ plpgsql_HashTableLookup()

static PLpgSQL_function * plpgsql_HashTableLookup ( PLpgSQL_func_hashkey func_key)
static

Definition at line 2463 of file pl_comp.c.

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

Referenced by plpgsql_compile().

2464 {
2465  plpgsql_HashEnt *hentry;
2466 
2468  (void *) func_key,
2469  HASH_FIND,
2470  NULL);
2471  if (hentry)
2472  return hentry->function;
2473  else
2474  return NULL;
2475 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:63
PLpgSQL_function * function
Definition: pl_comp.c:68

◆ plpgsql_param_ref()

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

Definition at line 1122 of file pl_comp.c.

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

Referenced by plpgsql_parser_setup().

1123 {
1124  PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1125  char pname[32];
1126  PLpgSQL_nsitem *nse;
1127 
1128  snprintf(pname, sizeof(pname), "$%d", pref->number);
1129 
1130  nse = plpgsql_ns_lookup(expr->ns, false,
1131  pname, NULL, NULL,
1132  NULL);
1133 
1134  if (nse == NULL)
1135  return NULL; /* name not known to plpgsql */
1136 
1137  return make_datum_param(expr, nse->itemno, pref->location);
1138 }
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:226
int number
Definition: parsenodes.h:246
int location
Definition: parsenodes.h:247
void * p_ref_hook_state
Definition: parse_node.h:216
static Node * make_datum_param(PLpgSQL_expr *expr, int dno, int location)
Definition: pl_comp.c:1313

◆ plpgsql_parse_cwordrowtype()

PLpgSQL_type* plpgsql_parse_cwordrowtype ( List idents)

Definition at line 1768 of file pl_comp.c.

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

1769 {
1770  Oid classOid;
1771  RangeVar *relvar;
1772  MemoryContext oldCxt;
1773 
1774  if (list_length(idents) != 2)
1775  return NULL;
1776 
1777  /* Avoid memory leaks in long-term function context */
1779 
1780  /* Look up relation name. Can't lock it - we might not have privileges. */
1781  relvar = makeRangeVar(strVal(linitial(idents)),
1782  strVal(lsecond(idents)),
1783  -1);
1784  classOid = RangeVarGetRelid(relvar, NoLock, false);
1785 
1786  MemoryContextSwitchTo(oldCxt);
1787 
1788  /* Build and return the row type struct */
1789  return plpgsql_build_datatype(get_rel_type_id(classOid), -1, InvalidOid);
1790 }
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation)
Definition: pl_comp.c:1998
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:63
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define strVal(v)
Definition: value.h:54
unsigned int Oid
Definition: postgres_ext.h:31
#define lsecond(l)
Definition: pg_list.h: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:1781
#define InvalidOid
Definition: postgres_ext.h:36
static int list_length(const List *l)
Definition: pg_list.h:89
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:57
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:421

◆ plpgsql_parse_cwordtype()

PLpgSQL_type* plpgsql_parse_cwordtype ( List idents)

Definition at line 1629 of file pl_comp.c.

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

1630 {
1631  PLpgSQL_type *dtype = NULL;
1632  PLpgSQL_nsitem *nse;
1633  const char *fldname;
1634  Oid classOid;
1635  HeapTuple classtup = NULL;
1636  HeapTuple attrtup = NULL;
1637  HeapTuple typetup = NULL;
1638  Form_pg_class classStruct;
1639  Form_pg_attribute attrStruct;
1640  MemoryContext oldCxt;
1641 
1642  /* Avoid memory leaks in the long-term function context */
1644 
1645  if (list_length(idents) == 2)
1646  {
1647  /*
1648  * Do a lookup in the current namespace stack. We don't need to check
1649  * number of names matched, because we will only consider scalar
1650  * variables.
1651  */
1652  nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1653  strVal(linitial(idents)),
1654  strVal(lsecond(idents)),
1655  NULL,
1656  NULL);
1657 
1658  if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_VAR)
1659  {
1660  dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1661  goto done;
1662  }
1663 
1664  /*
1665  * First word could also be a table name
1666  */
1667  classOid = RelnameGetRelid(strVal(linitial(idents)));
1668  if (!OidIsValid(classOid))
1669  goto done;
1670  fldname = strVal(lsecond(idents));
1671  }
1672  else if (list_length(idents) == 3)
1673  {
1674  RangeVar *relvar;
1675 
1676  relvar = makeRangeVar(strVal(linitial(idents)),
1677  strVal(lsecond(idents)),
1678  -1);
1679  /* Can't lock relation - we might not have privileges. */
1680  classOid = RangeVarGetRelid(relvar, NoLock, true);
1681  if (!OidIsValid(classOid))
1682  goto done;
1683  fldname = strVal(lthird(idents));
1684  }
1685  else
1686  goto done;
1687 
1688  classtup = SearchSysCache1(RELOID, ObjectIdGetDatum(classOid));
1689  if (!HeapTupleIsValid(classtup))
1690  goto done;
1691  classStruct = (Form_pg_class) GETSTRUCT(classtup);
1692 
1693  /*
1694  * It must be a relation, sequence, view, materialized view, composite
1695  * type, or foreign table
1696  */
1697  if (classStruct->relkind != RELKIND_RELATION &&
1698  classStruct->relkind != RELKIND_SEQUENCE &&
1699  classStruct->relkind != RELKIND_VIEW &&
1700  classStruct->relkind != RELKIND_MATVIEW &&
1701  classStruct->relkind != RELKIND_COMPOSITE_TYPE &&
1702  classStruct->relkind != RELKIND_FOREIGN_TABLE &&
1703  classStruct->relkind != RELKIND_PARTITIONED_TABLE)
1704  goto done;
1705 
1706  /*
1707  * Fetch the named table field and its type
1708  */
1709  attrtup = SearchSysCacheAttName(classOid, fldname);
1710  if (!HeapTupleIsValid(attrtup))
1711  goto done;
1712  attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1713 
1714  typetup = SearchSysCache1(TYPEOID,
1715  ObjectIdGetDatum(attrStruct->atttypid));
1716  if (!HeapTupleIsValid(typetup))
1717  elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1718 
1719  /*
1720  * Found that - build a compiler type struct in the caller's cxt and
1721  * return it
1722  */
1723  MemoryContextSwitchTo(oldCxt);
1724  dtype = build_datatype(typetup,
1725  attrStruct->atttypmod,
1726  attrStruct->attcollation);
1728 
1729 done:
1730  if (HeapTupleIsValid(classtup))
1731  ReleaseSysCache(classtup);
1732  if (HeapTupleIsValid(attrtup))
1733  ReleaseSysCache(attrtup);
1734  if (HeapTupleIsValid(typetup))
1735  ReleaseSysCache(typetup);
1736 
1737  MemoryContextSwitchTo(oldCxt);
1738  return dtype;
1739 }
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:668
Oid RelnameGetRelid(const char *relname)
Definition: namespace.c:673
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:63
PLpgSQL_nsitem * plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode, const char *name1, const char *name2, const char *name3, int *names_used)
Definition: pl_funcs.c:132
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:605
#define lsecond(l)
Definition: pg_list.h:116
#define linitial(l)
Definition: pg_list.h:111
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static int list_length(const List *l)
Definition: pg_list.h:89
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1248
FormData_pg_class * Form_pg_class
Definition: pg_class.h:93
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation)
Definition: pl_comp.c:2018
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:428
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:57
#define lthird(l)
Definition: pg_list.h:121
#define elog
Definition: elog.h:219
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:421

◆ plpgsql_parse_dblword()

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

Definition at line 1418 of file pl_comp.c.

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

Referenced by plpgsql_yylex().

1420 {
1421  PLpgSQL_nsitem *ns;
1422  List *idents;
1423  int nnames;
1424 
1425  idents = list_make2(makeString(word1),
1426  makeString(word2));
1427 
1428  /*
1429  * We should do nothing in DECLARE sections. In SQL expressions, we
1430  * really only need to make sure that RECFIELD datums are created when
1431  * needed.
1432  */
1434  {
1435  /*
1436  * Do a lookup in the current namespace stack
1437  */
1438  ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1439  word1, word2, NULL,
1440  &nnames);
1441  if (ns != NULL)
1442  {
1443  switch (ns->itemtype)
1444  {
1445  case PLPGSQL_NSTYPE_VAR:
1446  /* Block-qualified reference to scalar variable. */
1447  wdatum->datum = plpgsql_Datums[ns->itemno];
1448  wdatum->ident = NULL;
1449  wdatum->quoted = false; /* not used */
1450  wdatum->idents = idents;
1451  return true;
1452 
1453  case PLPGSQL_NSTYPE_REC:
1454  if (nnames == 1)
1455  {
1456  /*
1457  * First word is a record name, so second word could
1458  * be a field in this record. We build a RECFIELD
1459  * datum whether it is or not --- any error will be
1460  * detected later.
1461  */
1462  PLpgSQL_rec *rec;
1463  PLpgSQL_recfield *new;
1464 
1465  rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
1466  new = plpgsql_build_recfield(rec, word2);
1467 
1468  wdatum->datum = (PLpgSQL_datum *) new;
1469  }
1470  else
1471  {
1472  /* Block-qualified reference to record variable. */
1473  wdatum->datum = plpgsql_Datums[ns->itemno];
1474  }
1475  wdatum->ident = NULL;
1476  wdatum->quoted = false; /* not used */
1477  wdatum->idents = idents;
1478  return true;
1479 
1480  default:
1481  break;
1482  }
1483  }
1484  }
1485 
1486  /* Nothing found */
1487  cword->idents = idents;
1488  return false;
1489 }
#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
PLpgSQL_recfield * plpgsql_build_recfield(PLpgSQL_rec *rec, const char *fldname)
Definition: pl_comp.c:1956
List * idents
Definition: plpgsql.h:1108
List * idents
Definition: plpgsql.h:1116
IdentifierLookup plpgsql_IdentifierLookup
Definition: pl_scanner.c:29
PLpgSQL_datum * datum
Definition: plpgsql.h:1113
bool quoted
Definition: plpgsql.h:1115
char * ident
Definition: plpgsql.h:1114
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:428
Definition: pg_list.h:45

◆ plpgsql_parse_err_condition()

PLpgSQL_condition* plpgsql_parse_err_condition ( char *  condname)

Definition at line 2136 of file pl_comp.c.

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

2137 {
2138  int i;
2139  PLpgSQL_condition *new;
2140  PLpgSQL_condition *prev;
2141 
2142  /*
2143  * XXX Eventually we will want to look for user-defined exception names
2144  * here.
2145  */
2146 
2147  /*
2148  * OTHERS is represented as code 0 (which would map to '00000', but we
2149  * have no need to represent that as an exception condition).
2150  */
2151  if (strcmp(condname, "others") == 0)
2152  {
2153  new = palloc(sizeof(PLpgSQL_condition));
2154  new->sqlerrstate = 0;
2155  new->condname = condname;
2156  new->next = NULL;
2157  return new;
2158  }
2159 
2160  prev = NULL;
2161  for (i = 0; exception_label_map[i].label != NULL; i++)
2162  {
2163  if (strcmp(condname, exception_label_map[i].label) == 0)
2164  {
2165  new = palloc(sizeof(PLpgSQL_condition));
2166  new->sqlerrstate = exception_label_map[i].sqlerrstate;
2167  new->condname = condname;
2168  new->next = prev;
2169  prev = new;
2170  }
2171  }
2172 
2173  if (!prev)
2174  ereport(ERROR,
2175  (errcode(ERRCODE_UNDEFINED_OBJECT),
2176  errmsg("unrecognized exception condition \"%s\"",
2177  condname)));
2178 
2179  return prev;
2180 }
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:84
static const ExceptionLabelMap exception_label_map[]
Definition: pl_comp.c:83
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i

◆ plpgsql_parse_tripword()

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

Definition at line 1498 of file pl_comp.c.

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

Referenced by plpgsql_yylex().

1500 {
1501  PLpgSQL_nsitem *ns;
1502  List *idents;
1503  int nnames;
1504 
1505  idents = list_make3(makeString(word1),
1506  makeString(word2),
1507  makeString(word3));
1508 
1509  /*
1510  * We should do nothing in DECLARE sections. In SQL expressions, we
1511  * really only need to make sure that RECFIELD datums are created when
1512  * needed.
1513  */
1515  {
1516  /*
1517  * Do a lookup in the current namespace stack. Must find a qualified
1518  * reference, else ignore.
1519  */
1520  ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1521  word1, word2, word3,
1522  &nnames);
1523  if (ns != NULL && nnames == 2)
1524  {
1525  switch (ns->itemtype)
1526  {
1527  case PLPGSQL_NSTYPE_REC:
1528  {
1529  /*
1530  * words 1/2 are a record name, so third word could be
1531  * a field in this record.
1532  */
1533  PLpgSQL_rec *rec;
1534  PLpgSQL_recfield *new;
1535 
1536  rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
1537  new = plpgsql_build_recfield(rec, word3);
1538 
1539  wdatum->datum = (PLpgSQL_datum *) new;
1540  wdatum->ident = NULL;
1541  wdatum->quoted = false; /* not used */
1542  wdatum->idents = idents;
1543  return true;
1544  }
1545 
1546  default:
1547  break;
1548  }
1549  }
1550  }
1551 
1552  /* Nothing found */
1553  cword->idents = idents;
1554  return false;
1555 }
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
PLpgSQL_recfield * plpgsql_build_recfield(PLpgSQL_rec *rec, const char *fldname)
Definition: pl_comp.c:1956
List * idents
Definition: plpgsql.h:1108
List * idents
Definition: plpgsql.h:1116
IdentifierLookup plpgsql_IdentifierLookup
Definition: pl_scanner.c:29
PLpgSQL_datum * datum
Definition: plpgsql.h:1113
bool quoted
Definition: plpgsql.h:1115
char * ident
Definition: plpgsql.h:1114
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:428
Definition: pg_list.h:45

◆ plpgsql_parse_word()

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

Definition at line 1363 of file pl_comp.c.

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

Referenced by plpgsql_yylex().

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

◆ plpgsql_parse_wordrowtype()

PLpgSQL_type* plpgsql_parse_wordrowtype ( char *  ident)

Definition at line 1747 of file pl_comp.c.

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

1748 {
1749  Oid classOid;
1750 
1751  /* Lookup the relation */
1752  classOid = RelnameGetRelid(ident);
1753  if (!OidIsValid(classOid))
1754  ereport(ERROR,
1756  errmsg("relation \"%s\" does not exist", ident)));
1757 
1758  /* Build and return the row type struct */
1759  return plpgsql_build_datatype(get_rel_type_id(classOid), -1, InvalidOid);
1760 }
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation)
Definition: pl_comp.c:1998
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:62
Oid RelnameGetRelid(const char *relname)
Definition: namespace.c:673
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
Oid get_rel_type_id(Oid relid)
Definition: lsyscache.c:1781
#define InvalidOid
Definition: postgres_ext.h:36
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ plpgsql_parse_wordtype()

PLpgSQL_type* plpgsql_parse_wordtype ( char *  ident)

Definition at line 1566 of file pl_comp.c.

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

1567 {
1568  PLpgSQL_type *dtype;
1569  PLpgSQL_nsitem *nse;
1570  HeapTuple typeTup;
1571 
1572  /*
1573  * Do a lookup in the current namespace stack
1574  */
1575  nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1576  ident, NULL, NULL,
1577  NULL);
1578 
1579  if (nse != NULL)
1580  {
1581  switch (nse->itemtype)
1582  {
1583  case PLPGSQL_NSTYPE_VAR:
1584  return ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1585 
1586  /* XXX perhaps allow REC/ROW here? */
1587 
1588  default:
1589  return NULL;
1590  }
1591  }
1592 
1593  /*
1594  * Word wasn't found in the namespace stack. Try to find a data type with
1595  * that name, but ignore shell types and complex types.
1596  */
1597  typeTup = LookupTypeName(NULL, makeTypeName(ident), NULL, false);
1598  if (typeTup)
1599  {
1600  Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1601 
1602  if (!typeStruct->typisdefined ||
1603  typeStruct->typrelid != InvalidOid)
1604  {
1605  ReleaseSysCache(typeTup);
1606  return NULL;
1607  }
1608 
1609  dtype = build_datatype(typeTup, -1,
1611 
1612  ReleaseSysCache(typeTup);
1613  return dtype;
1614  }
1615 
1616  /*
1617  * Nothing found - up to now it's a word without any special meaning for
1618  * us.
1619  */
1620  return NULL;
1621 }
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:668
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
Oid fn_input_collation
Definition: plpgsql.h:934
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define InvalidOid
Definition: postgres_ext.h:36
TypeName * makeTypeName(char *typnam)
Definition: makefuncs.c:443
FormData_pg_type * Form_pg_type
Definition: pg_type.h:247
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation)
Definition: pl_comp.c:2018
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:428
PLpgSQL_function * plpgsql_curr_compile
Definition: pl_comp.c:54

◆ plpgsql_parser_setup()

void plpgsql_parser_setup ( struct ParseState pstate,
PLpgSQL_expr expr 
)

Definition at line 1051 of file pl_comp.c.

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

Referenced by exec_prepare_plan(), and plpgsql_estate_setup().

1052 {
1056  /* no need to use p_coerce_param_hook */
1057  pstate->p_ref_hook_state = (void *) expr;
1058 }
static Node * plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref)
Definition: pl_comp.c:1064
PostParseColumnRefHook p_post_columnref_hook
Definition: parse_node.h:213
ParseParamRefHook p_paramref_hook
Definition: parse_node.h:214
static Node * plpgsql_param_ref(ParseState *pstate, ParamRef *pref)
Definition: pl_comp.c:1122
void * p_ref_hook_state
Definition: parse_node.h:216
PreParseColumnRefHook p_pre_columnref_hook
Definition: parse_node.h:212
static Node * plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
Definition: pl_comp.c:1078

◆ plpgsql_post_column_ref()

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

Definition at line 1078 of file pl_comp.c.

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

Referenced by plpgsql_parser_setup().

1079 {
1080  PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1081  Node *myvar;
1082 
1084  return NULL; /* we already found there's no match */
1085 
1086  if (expr->func->resolve_option == PLPGSQL_RESOLVE_COLUMN && var != NULL)
1087  return NULL; /* there's a table column, prefer that */
1088 
1089  /*
1090  * If we find a record/row variable but can't match a field name, throw
1091  * error if there was no core resolution for the ColumnRef either. In
1092  * that situation, the reference is inevitably going to fail, and
1093  * complaining about the record/row variable is likely to be more on-point
1094  * than the core parser's error message. (It's too bad we don't have
1095  * access to transformColumnRef's internal crerr state here, as in case of
1096  * a conflict with a table name this could still be less than the most
1097  * helpful error message possible.)
1098  */
1099  myvar = resolve_column_ref(pstate, expr, cref, (var == NULL));
1100 
1101  if (myvar != NULL && var != NULL)
1102  {
1103  /*
1104  * We could leave it to the core parser to throw this error, but we
1105  * can add a more useful detail message than the core could.
1106  */
1107  ereport(ERROR,
1108  (errcode(ERRCODE_AMBIGUOUS_COLUMN),
1109  errmsg("column reference \"%s\" is ambiguous",
1110  NameListToString(cref->fields)),
1111  errdetail("It could refer to either a PL/pgSQL variable or a table column."),
1112  parser_errposition(pstate, cref->location)));
1113  }
1114 
1115  return myvar;
1116 }
Definition: nodes.h:517
int errcode(int sqlerrcode)
Definition: elog.c:575
PLpgSQL_resolve_option resolve_option
Definition: plpgsql.h:954
int location
Definition: parsenodes.h:237
#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:3082
struct PLpgSQL_function * func
Definition: plpgsql.h:223
void * p_ref_hook_state
Definition: parse_node.h:216
static Node * resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr, ColumnRef *cref, bool error_if_no_field)
Definition: pl_comp.c:1149
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:236

◆ plpgsql_pre_column_ref()

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

Definition at line 1064 of file pl_comp.c.

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

Referenced by plpgsql_parser_setup().

1065 {
1066  PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1067 
1069  return resolve_column_ref(pstate, expr, cref, false);
1070  else
1071  return NULL;
1072 }
PLpgSQL_resolve_option resolve_option
Definition: plpgsql.h:954
struct PLpgSQL_function * func
Definition: plpgsql.h:223
void * p_ref_hook_state
Definition: parse_node.h:216
static Node * resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr, ColumnRef *cref, bool error_if_no_field)
Definition: pl_comp.c:1149

◆ plpgsql_recognize_err_condition()

int plpgsql_recognize_err_condition ( const char *  condname,
bool  allow_sqlstate 
)

Definition at line 2100 of file pl_comp.c.

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

Referenced by exec_stmt_raise().

2101 {
2102  int i;
2103 
2104  if (allow_sqlstate)
2105  {
2106  if (strlen(condname) == 5 &&
2107  strspn(condname, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") == 5)
2108  return MAKE_SQLSTATE(condname[0],
2109  condname[1],
2110  condname[2],
2111  condname[3],
2112  condname[4]);
2113  }
2114 
2115  for (i = 0; exception_label_map[i].label != NULL; i++)
2116  {
2117  if (strcmp(condname, exception_label_map[i].label) == 0)
2119  }
2120 
2121  ereport(ERROR,
2122  (errcode(ERRCODE_UNDEFINED_OBJECT),
2123  errmsg("unrecognized exception condition \"%s\"",
2124  condname)));
2125  return 0; /* keep compiler quiet */
2126 }
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:84
static const ExceptionLabelMap exception_label_map[]
Definition: pl_comp.c:83
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i

◆ plpgsql_resolve_polymorphic_argtypes()

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

Definition at line 2376 of file pl_comp.c.

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

Referenced by compute_function_hashkey(), and do_compile().

2380 {
2381  int i;
2382 
2383  if (!forValidator)
2384  {
2385  /* normal case, pass to standard routine */
2386  if (!resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
2387  call_expr))
2388  ereport(ERROR,
2389  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2390  errmsg("could not determine actual argument "
2391  "type for polymorphic function \"%s\"",
2392  proname)));
2393  }
2394  else
2395  {
2396  /* special validation case */
2397  for (i = 0; i < numargs; i++)
2398  {
2399  switch (argtypes[i])
2400  {
2401  case ANYELEMENTOID:
2402  case ANYNONARRAYOID:
2403  case ANYENUMOID: /* XXX dubious */
2404  argtypes[i] = INT4OID;
2405  break;
2406  case ANYARRAYOID:
2407  argtypes[i] = INT4ARRAYOID;
2408  break;
2409  case ANYRANGEOID:
2410  argtypes[i] = INT4RANGEOID;
2411  break;
2412  default:
2413  break;
2414  }
2415  }
2416  }
2417 }
bool resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, Node *call_expr)
Definition: funcapi.c:644
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i

◆ plpgsql_start_datums()

static void plpgsql_start_datums ( void  )
static

Definition at line 2187 of file pl_comp.c.

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

Referenced by do_compile(), and plpgsql_compile_inline().

2188 {
2189  datums_alloc = 128;
2190  plpgsql_nDatums = 0;
2191  /* This is short-lived, so needn't allocate in function's cxt */
2193  sizeof(PLpgSQL_datum *) * datums_alloc);
2194  /* datums_last tracks what's been seen by plpgsql_add_initdatums() */
2195  datums_last = 0;
2196 }
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:771
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:57
static int datums_last
Definition: pl_comp.c:48

◆ resolve_column_ref()

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

Definition at line 1149 of file pl_comp.c.

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

Referenced by plpgsql_post_column_ref(), and plpgsql_pre_column_ref().

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

Variable Documentation

◆ datums_alloc

int datums_alloc
static

Definition at line 45 of file pl_comp.c.

Referenced by plpgsql_adddatum(), and plpgsql_start_datums().

◆ datums_last

int datums_last
static

Definition at line 48 of file pl_comp.c.

Referenced by plpgsql_add_initdatums(), and plpgsql_start_datums().

◆ exception_label_map

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

Definition at line 83 of file pl_comp.c.

◆ plpgsql_check_syntax

bool plpgsql_check_syntax = false

Definition at line 52 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_compile_tmp_cxt

MemoryContext plpgsql_compile_tmp_cxt

Definition at line 57 of file pl_comp.c.

◆ plpgsql_curr_compile

PLpgSQL_function* plpgsql_curr_compile

Definition at line 54 of file pl_comp.c.

◆ plpgsql_Datums

PLpgSQL_datum** plpgsql_Datums

Definition at line 47 of file pl_comp.c.

◆ plpgsql_DumpExecTree

bool plpgsql_DumpExecTree = false

Definition at line 51 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_error_funcname

char* plpgsql_error_funcname

Definition at line 50 of file pl_comp.c.

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

◆ plpgsql_HashTable

HTAB* plpgsql_HashTable = NULL
static

Definition at line 63 of file pl_comp.c.

◆ plpgsql_nDatums

int plpgsql_nDatums

◆ plpgsql_parse_result

PLpgSQL_stmt_block* plpgsql_parse_result

Definition at line 43 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().