PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
pl_comp.c File Reference
#include "postgres.h"
#include <ctype.h>
#include "access/htup_details.h"
#include "catalog/namespace.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "nodes/makefuncs.h"
#include "parser/parse_node.h"
#include "plpgsql.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/regproc.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
#include "plerrcodes.h"
Include dependency graph for pl_comp.c:

Go to the source code of this file.

Data Structures

struct  ExceptionLabelMap
 
struct  compile_error_callback_arg
 

Functions

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

Variables

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 const ExceptionLabelMap exception_label_map []
 

Function Documentation

◆ add_dummy_return()

static void add_dummy_return ( PLpgSQL_function function)
static

Definition at line 930 of file pl_comp.c.

931{
932 /*
933 * If the outer block has an EXCEPTION clause, we need to make a new outer
934 * block, since the added RETURN shouldn't act like it is inside the
935 * EXCEPTION clause. Likewise, if it has a label, wrap it in a new outer
936 * block so that EXIT doesn't skip the RETURN.
937 */
938 if (function->action->exceptions != NULL ||
939 function->action->label != NULL)
940 {
942
943 new = palloc0(sizeof(PLpgSQL_stmt_block));
944 new->cmd_type = PLPGSQL_STMT_BLOCK;
945 new->stmtid = ++function->nstatements;
946 new->body = list_make1(function->action);
947
948 function->action = new;
949 }
950 if (function->action->body == NIL ||
951 ((PLpgSQL_stmt *) llast(function->action->body))->cmd_type != PLPGSQL_STMT_RETURN)
952 {
954
955 new = palloc0(sizeof(PLpgSQL_stmt_return));
956 new->cmd_type = PLPGSQL_STMT_RETURN;
957 new->stmtid = ++function->nstatements;
958 new->expr = NULL;
959 new->retvarno = function->out_param_varno;
960
961 function->action->body = lappend(function->action->body, new);
962 }
963}
List * lappend(List *list, void *datum)
Definition: list.c:339
void * palloc0(Size size)
Definition: mcxt.c:1970
on_exit_nicely_callback function
#define llast(l)
Definition: pg_list.h:198
#define NIL
Definition: pg_list.h:68
#define list_make1(x1)
Definition: pg_list.h:212
@ PLPGSQL_STMT_RETURN
Definition: plpgsql.h:116
@ PLPGSQL_STMT_BLOCK
Definition: plpgsql.h:105

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

Referenced by plpgsql_compile_callback(), and plpgsql_compile_inline().

◆ add_parameter_name()

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

Definition at line 905 of file pl_comp.c.

906{
907 /*
908 * Before adding the name, check for duplicates. We need this even though
909 * functioncmds.c has a similar check, because that code explicitly
910 * doesn't complain about conflicting IN and OUT parameter names. In
911 * plpgsql, such names are in the same namespace, so there is no way to
912 * disambiguate.
913 */
915 name, NULL, NULL,
916 NULL) != NULL)
918 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
919 errmsg("parameter name \"%s\" used more than once",
920 name)));
921
922 /* OK, add the name */
923 plpgsql_ns_additem(itemtype, itemno, name);
924}
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
PLpgSQL_nsitem * plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode, const char *name1, const char *name2, const char *name3, int *names_used)
Definition: pl_funcs.c:130
void plpgsql_ns_additem(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
Definition: pl_funcs.c:92
PLpgSQL_nsitem * plpgsql_ns_top(void)
Definition: pl_funcs.c:81
const char * name

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

Referenced by plpgsql_compile_callback().

◆ build_datatype()

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

Definition at line 1964 of file pl_comp.c.

1966{
1967 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1968 PLpgSQL_type *typ;
1969
1970 if (!typeStruct->typisdefined)
1971 ereport(ERROR,
1972 (errcode(ERRCODE_UNDEFINED_OBJECT),
1973 errmsg("type \"%s\" is only a shell",
1974 NameStr(typeStruct->typname))));
1975
1976 typ = (PLpgSQL_type *) palloc(sizeof(PLpgSQL_type));
1977
1978 typ->typname = pstrdup(NameStr(typeStruct->typname));
1979 typ->typoid = typeStruct->oid;
1980 switch (typeStruct->typtype)
1981 {
1982 case TYPTYPE_BASE:
1983 case TYPTYPE_ENUM:
1984 case TYPTYPE_RANGE:
1985 case TYPTYPE_MULTIRANGE:
1987 break;
1988 case TYPTYPE_COMPOSITE:
1989 typ->ttype = PLPGSQL_TTYPE_REC;
1990 break;
1991 case TYPTYPE_DOMAIN:
1992 if (type_is_rowtype(typeStruct->typbasetype))
1993 typ->ttype = PLPGSQL_TTYPE_REC;
1994 else
1996 break;
1997 case TYPTYPE_PSEUDO:
1998 if (typ->typoid == RECORDOID)
1999 typ->ttype = PLPGSQL_TTYPE_REC;
2000 else
2002 break;
2003 default:
2004 elog(ERROR, "unrecognized typtype: %d",
2005 (int) typeStruct->typtype);
2006 break;
2007 }
2008 typ->typlen = typeStruct->typlen;
2009 typ->typbyval = typeStruct->typbyval;
2010 typ->typtype = typeStruct->typtype;
2011 typ->collation = typeStruct->typcollation;
2012 if (OidIsValid(collation) && OidIsValid(typ->collation))
2013 typ->collation = collation;
2014 /* Detect if type is true array, or domain thereof */
2015 /* NB: this is only used to decide whether to apply expand_array */
2016 if (typeStruct->typtype == TYPTYPE_BASE)
2017 {
2018 /*
2019 * This test should include what get_element_type() checks. We also
2020 * disallow non-toastable array types (i.e. oidvector and int2vector).
2021 */
2022 typ->typisarray = (IsTrueArrayType(typeStruct) &&
2023 typeStruct->typstorage != TYPSTORAGE_PLAIN);
2024 }
2025 else if (typeStruct->typtype == TYPTYPE_DOMAIN)
2026 {
2027 /* we can short-circuit looking up base types if it's not varlena */
2028 typ->typisarray = (typeStruct->typlen == -1 &&
2029 typeStruct->typstorage != TYPSTORAGE_PLAIN &&
2030 OidIsValid(get_base_element_type(typeStruct->typbasetype)));
2031 }
2032 else
2033 typ->typisarray = false;
2034 typ->atttypmod = typmod;
2035
2036 /*
2037 * If it's a named composite type (or domain over one), find the typcache
2038 * entry and record the current tupdesc ID, so we can detect changes
2039 * (including drops). We don't currently support on-the-fly replacement
2040 * of non-composite types, else we might want to do this for them too.
2041 */
2042 if (typ->ttype == PLPGSQL_TTYPE_REC && typ->typoid != RECORDOID)
2043 {
2044 TypeCacheEntry *typentry;
2045
2046 typentry = lookup_type_cache(typ->typoid,
2049 if (typentry->typtype == TYPTYPE_DOMAIN)
2050 typentry = lookup_type_cache(typentry->domainBaseType,
2052 if (typentry->tupDesc == NULL)
2053 ereport(ERROR,
2054 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2055 errmsg("type %s is not composite",
2056 format_type_be(typ->typoid))));
2057
2058 typ->origtypname = origtypname;
2059 typ->tcache = typentry;
2060 typ->tupdesc_id = typentry->tupDesc_identifier;
2061 }
2062 else
2063 {
2064 typ->origtypname = NULL;
2065 typ->tcache = NULL;
2066 typ->tupdesc_id = 0;
2067 }
2068
2069 return typ;
2070}
#define NameStr(name)
Definition: c.h:717
#define OidIsValid(objectId)
Definition: c.h:746
#define elog(elevel,...)
Definition: elog.h:226
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2795
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2972
char * pstrdup(const char *in)
Definition: mcxt.c:2322
void * palloc(Size size)
Definition: mcxt.c:1940
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
@ PLPGSQL_TTYPE_PSEUDO
Definition: plpgsql.h:97
@ PLPGSQL_TTYPE_REC
Definition: plpgsql.h:96
@ PLPGSQL_TTYPE_SCALAR
Definition: plpgsql.h:95
char typtype
Definition: plpgsql.h:217
TypeName * origtypname
Definition: plpgsql.h:222
bool typisarray
Definition: plpgsql.h:219
TypeCacheEntry * tcache
Definition: plpgsql.h:223
uint64 tupdesc_id
Definition: plpgsql.h:224
Oid collation
Definition: plpgsql.h:218
PLpgSQL_type_type ttype
Definition: plpgsql.h:214
Oid typoid
Definition: plpgsql.h:213
char * typname
Definition: plpgsql.h:212
int16 typlen
Definition: plpgsql.h:215
int32 atttypmod
Definition: plpgsql.h:220
bool typbyval
Definition: plpgsql.h:216
uint64 tupDesc_identifier
Definition: typcache.h:91
char typtype
Definition: typcache.h:43
TupleDesc tupDesc
Definition: typcache.h:90
Oid domainBaseType
Definition: typcache.h:115
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:386
#define TYPECACHE_TUPDESC
Definition: typcache.h:146
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:150

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

Referenced by plpgsql_build_datatype(), plpgsql_compile_callback(), and plpgsql_parse_cwordtype().

◆ build_row_from_vars()

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

Definition at line 1828 of file pl_comp.c.

1829{
1830 PLpgSQL_row *row;
1831 int i;
1832
1833 row = palloc0(sizeof(PLpgSQL_row));
1834 row->dtype = PLPGSQL_DTYPE_ROW;
1835 row->refname = "(unnamed row)";
1836 row->lineno = -1;
1837 row->rowtupdesc = CreateTemplateTupleDesc(numvars);
1838 row->nfields = numvars;
1839 row->fieldnames = palloc(numvars * sizeof(char *));
1840 row->varnos = palloc(numvars * sizeof(int));
1841
1842 for (i = 0; i < numvars; i++)
1843 {
1844 PLpgSQL_variable *var = vars[i];
1845 Oid typoid;
1846 int32 typmod;
1847 Oid typcoll;
1848
1849 /* Member vars of a row should never be const */
1850 Assert(!var->isconst);
1851
1852 switch (var->dtype)
1853 {
1854 case PLPGSQL_DTYPE_VAR:
1856 typoid = ((PLpgSQL_var *) var)->datatype->typoid;
1857 typmod = ((PLpgSQL_var *) var)->datatype->atttypmod;
1858 typcoll = ((PLpgSQL_var *) var)->datatype->collation;
1859 break;
1860
1861 case PLPGSQL_DTYPE_REC:
1862 /* shouldn't need to revalidate rectypeid already... */
1863 typoid = ((PLpgSQL_rec *) var)->rectypeid;
1864 typmod = -1; /* don't know typmod, if it's used at all */
1865 typcoll = InvalidOid; /* composite types have no collation */
1866 break;
1867
1868 default:
1869 elog(ERROR, "unrecognized dtype: %d", var->dtype);
1870 typoid = InvalidOid; /* keep compiler quiet */
1871 typmod = 0;
1872 typcoll = InvalidOid;
1873 break;
1874 }
1875
1876 row->fieldnames[i] = var->refname;
1877 row->varnos[i] = var->dno;
1878
1880 var->refname,
1881 typoid, typmod,
1882 0);
1883 TupleDescInitEntryCollation(row->rowtupdesc, i + 1, typcoll);
1884 }
1885
1886 return row;
1887}
int32_t int32
Definition: c.h:498
Assert(PointerIsAligned(start, uint64))
int i
Definition: isn.c:77
@ PLPGSQL_DTYPE_ROW
Definition: plpgsql.h:65
@ PLPGSQL_DTYPE_PROMISE
Definition: plpgsql.h:68
@ PLPGSQL_DTYPE_REC
Definition: plpgsql.h:66
@ PLPGSQL_DTYPE_VAR
Definition: plpgsql.h:64
#define InvalidOid
Definition: postgres_ext.h:35
unsigned int Oid
Definition: postgres_ext.h:30
TupleDesc rowtupdesc
Definition: plpgsql.h:402
int lineno
Definition: plpgsql.h:391
PLpgSQL_datum_type dtype
Definition: plpgsql.h:388
int * varnos
Definition: plpgsql.h:406
char * refname
Definition: plpgsql.h:390
char ** fieldnames
Definition: plpgsql.h:405
int nfields
Definition: plpgsql.h:404
PLpgSQL_datum_type dtype
Definition: plpgsql.h:312
char * refname
Definition: plpgsql.h:314
Definition: regcomp.c:282
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:175
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition: tupdesc.c:1019
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:835

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

Referenced by plpgsql_compile_callback().

◆ make_datum_param()

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

Definition at line 1231 of file pl_comp.c.

1232{
1233 PLpgSQL_execstate *estate;
1234 PLpgSQL_datum *datum;
1235 Param *param;
1236 MemoryContext oldcontext;
1237
1238 /* see comment in resolve_column_ref */
1239 estate = expr->func->cur_estate;
1240 Assert(dno >= 0 && dno < estate->ndatums);
1241 datum = estate->datums[dno];
1242
1243 /*
1244 * Bitmapset must be allocated in function's permanent memory context
1245 */
1246 oldcontext = MemoryContextSwitchTo(expr->func->fn_cxt);
1247 expr->paramnos = bms_add_member(expr->paramnos, dno);
1248 MemoryContextSwitchTo(oldcontext);
1249
1250 param = makeNode(Param);
1251 param->paramkind = PARAM_EXTERN;
1252 param->paramid = dno + 1;
1254 datum,
1255 &param->paramtype,
1256 &param->paramtypmod,
1257 &param->paramcollid);
1258 param->location = location;
1259
1260 return (Node *) param;
1261}
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
#define makeNode(_type_)
Definition: nodes.h:161
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
void plpgsql_exec_get_datum_type_info(PLpgSQL_execstate *estate, PLpgSQL_datum *datum, Oid *typeId, int32 *typMod, Oid *collation)
Definition: pl_exec.c:5538
@ PARAM_EXTERN
Definition: primnodes.h:384
Definition: nodes.h:135
PLpgSQL_datum ** datums
Definition: plpgsql.h:1049
struct PLpgSQL_function * func
Definition: plpgsql.h:234
Bitmapset * paramnos
Definition: plpgsql.h:252
MemoryContext fn_cxt
Definition: plpgsql.h:966
struct PLpgSQL_execstate * cur_estate
Definition: plpgsql.h:1006
ParseLoc location
Definition: primnodes.h:401
int paramid
Definition: primnodes.h:394
Oid paramtype
Definition: primnodes.h:395
ParamKind paramkind
Definition: primnodes.h:393

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

Referenced by plpgsql_param_ref(), and resolve_column_ref().

◆ plpgsql_add_initdatums()

int plpgsql_add_initdatums ( int **  varnos)

Definition at line 2268 of file pl_comp.c.

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

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

◆ plpgsql_adddatum()

void plpgsql_adddatum ( PLpgSQL_datum newdatum)

Definition at line 2207 of file pl_comp.c.

2208{
2210 {
2211 datums_alloc *= 2;
2213 }
2214
2215 newdatum->dno = plpgsql_nDatums;
2216 plpgsql_Datums[plpgsql_nDatums++] = newdatum;
2217}
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:2167
static int datums_alloc
Definition: pl_comp.c:41

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

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

◆ plpgsql_build_datatype()

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

Definition at line 1942 of file pl_comp.c.

1944{
1945 HeapTuple typeTup;
1946 PLpgSQL_type *typ;
1947
1948 typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
1949 if (!HeapTupleIsValid(typeTup))
1950 elog(ERROR, "cache lookup failed for type %u", typeOid);
1951
1952 typ = build_datatype(typeTup, typmod, collation, origtypname);
1953
1954 ReleaseSysCache(typeTup);
1955
1956 return typ;
1957}
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:1964
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221

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

Referenced by exec_stmt_case(), plpgsql_build_datatype_arrayof(), plpgsql_compile_callback(), plpgsql_compile_inline(), plpgsql_parse_cwordrowtype(), and plpgsql_parse_wordrowtype().

◆ plpgsql_build_datatype_arrayof()

PLpgSQL_type * plpgsql_build_datatype_arrayof ( PLpgSQL_type dtype)

Definition at line 2076 of file pl_comp.c.

2077{
2078 Oid array_typeid;
2079
2080 /*
2081 * If it's already an array type, use it as-is: Postgres doesn't do nested
2082 * arrays.
2083 */
2084 if (dtype->typisarray)
2085 return dtype;
2086
2087 array_typeid = get_array_type(dtype->typoid);
2088 if (!OidIsValid(array_typeid))
2089 ereport(ERROR,
2090 (errcode(ERRCODE_UNDEFINED_OBJECT),
2091 errmsg("could not find array type for data type %s",
2092 format_type_be(dtype->typoid))));
2093
2094 /* Note we inherit typmod and collation, if any, from the element type */
2095 return plpgsql_build_datatype(array_typeid, dtype->atttypmod,
2096 dtype->collation, NULL);
2097}
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2927
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:1942

References PLpgSQL_type::atttypmod, PLpgSQL_type::collation, ereport, errcode(), errmsg(), ERROR, format_type_be(), get_array_type(), OidIsValid, plpgsql_build_datatype(), PLpgSQL_type::typisarray, and PLpgSQL_type::typoid.

◆ plpgsql_build_recfield()

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

Definition at line 1895 of file pl_comp.c.

1896{
1897 PLpgSQL_recfield *recfield;
1898 int i;
1899
1900 /* search for an existing datum referencing this field */
1901 i = rec->firstfield;
1902 while (i >= 0)
1903 {
1905
1907 fld->recparentno == rec->dno);
1908 if (strcmp(fld->fieldname, fldname) == 0)
1909 return fld;
1910 i = fld->nextfield;
1911 }
1912
1913 /* nope, so make a new one */
1914 recfield = palloc0(sizeof(PLpgSQL_recfield));
1915 recfield->dtype = PLPGSQL_DTYPE_RECFIELD;
1916 recfield->fieldname = pstrdup(fldname);
1917 recfield->recparentno = rec->dno;
1919
1920 plpgsql_adddatum((PLpgSQL_datum *) recfield);
1921
1922 /* now we can link it into the parent's chain */
1923 recfield->nextfield = rec->firstfield;
1924 rec->firstfield = recfield->dno;
1925
1926 return recfield;
1927}
void plpgsql_adddatum(PLpgSQL_datum *newdatum)
Definition: pl_comp.c:2207
@ PLPGSQL_DTYPE_RECFIELD
Definition: plpgsql.h:67
int firstfield
Definition: plpgsql.h:432
uint64 rectupledescid
Definition: plpgsql.h:452
PLpgSQL_datum_type dtype
Definition: plpgsql.h:445
char * fieldname
Definition: plpgsql.h:449
#define INVALID_TUPLEDESC_IDENTIFIER
Definition: typcache.h:157

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

Referenced by plpgsql_parse_dblword(), and plpgsql_parse_tripword().

◆ plpgsql_build_record()

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

Definition at line 1801 of file pl_comp.c.

1804{
1805 PLpgSQL_rec *rec;
1806
1807 rec = palloc0(sizeof(PLpgSQL_rec));
1808 rec->dtype = PLPGSQL_DTYPE_REC;
1809 rec->refname = pstrdup(refname);
1810 rec->lineno = lineno;
1811 /* other fields are left as 0, might be changed by caller */
1812 rec->datatype = dtype;
1813 rec->rectypeid = rectypeid;
1814 rec->firstfield = -1;
1815 rec->erh = NULL;
1817 if (add2namespace)
1819
1820 return rec;
1821}
@ PLPGSQL_NSTYPE_REC
Definition: plpgsql.h:46
ExpandedRecordHeader * erh
Definition: plpgsql.h:437
PLpgSQL_type * datatype
Definition: plpgsql.h:429
PLpgSQL_datum_type dtype
Definition: plpgsql.h:414
Oid rectypeid
Definition: plpgsql.h:430
int lineno
Definition: plpgsql.h:417
char * refname
Definition: plpgsql.h:416

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

Referenced by plpgsql_build_variable(), and plpgsql_compile_callback().

◆ plpgsql_build_variable()

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

Definition at line 1738 of file pl_comp.c.

1740{
1741 PLpgSQL_variable *result;
1742
1743 switch (dtype->ttype)
1744 {
1746 {
1747 /* Ordinary scalar datatype */
1748 PLpgSQL_var *var;
1749
1750 var = palloc0(sizeof(PLpgSQL_var));
1751 var->dtype = PLPGSQL_DTYPE_VAR;
1752 var->refname = pstrdup(refname);
1753 var->lineno = lineno;
1754 var->datatype = dtype;
1755 /* other fields are left as 0, might be changed by caller */
1756
1757 /* preset to NULL */
1758 var->value = 0;
1759 var->isnull = true;
1760 var->freeval = false;
1761
1763 if (add2namespace)
1765 var->dno,
1766 refname);
1767 result = (PLpgSQL_variable *) var;
1768 break;
1769 }
1770 case PLPGSQL_TTYPE_REC:
1771 {
1772 /* Composite type -- build a record variable */
1773 PLpgSQL_rec *rec;
1774
1775 rec = plpgsql_build_record(refname, lineno,
1776 dtype, dtype->typoid,
1777 add2namespace);
1778 result = (PLpgSQL_variable *) rec;
1779 break;
1780 }
1782 ereport(ERROR,
1783 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1784 errmsg("variable \"%s\" has pseudo-type %s",
1785 refname, format_type_be(dtype->typoid))));
1786 result = NULL; /* keep compiler quiet */
1787 break;
1788 default:
1789 elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
1790 result = NULL; /* keep compiler quiet */
1791 break;
1792 }
1793
1794 return result;
1795}
PLpgSQL_rec * plpgsql_build_record(const char *refname, int lineno, PLpgSQL_type *dtype, Oid rectypeid, bool add2namespace)
Definition: pl_comp.c:1801
@ PLPGSQL_NSTYPE_VAR
Definition: plpgsql.h:45
int lineno
Definition: plpgsql.h:337
PLpgSQL_datum_type dtype
Definition: plpgsql.h:334
bool freeval
Definition: plpgsql.h:358
bool isnull
Definition: plpgsql.h:357
PLpgSQL_type * datatype
Definition: plpgsql.h:343
char * refname
Definition: plpgsql.h:336
Datum value
Definition: plpgsql.h:356

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

Referenced by plpgsql_compile_callback(), and plpgsql_compile_inline().

◆ plpgsql_compile()

PLpgSQL_function * plpgsql_compile ( FunctionCallInfo  fcinfo,
bool  forValidator 
)

Definition at line 106 of file pl_comp.c.

107{
109
110 /*
111 * funccache.c manages re-use of existing PLpgSQL_function caches.
112 *
113 * In PL/pgSQL we use fn_extra directly as the pointer to the long-lived
114 * function cache entry; we have no need for any query-lifespan cache.
115 * Also, we don't need to make the cache key depend on composite result
116 * type (at least for now).
117 */
120 fcinfo->flinfo->fn_extra,
123 sizeof(PLpgSQL_function),
124 false,
125 forValidator);
126
127 /*
128 * Save pointer in FmgrInfo to avoid search on subsequent calls
129 */
130 fcinfo->flinfo->fn_extra = function;
131
132 /*
133 * Finally return the compiled function
134 */
135 return function;
136}
CachedFunction * cached_function_compile(FunctionCallInfo fcinfo, CachedFunction *function, CachedFunctionCompileCallback ccallback, CachedFunctionDeleteCallback dcallback, Size cacheEntrySize, bool includeResultType, bool forValidator)
Definition: funccache.c:480
static void plpgsql_compile_callback(FunctionCallInfo fcinfo, HeapTuple procTup, const CachedFunctionHashKey *hashkey, CachedFunction *cfunc, bool forValidator)
Definition: pl_comp.c:167
void plpgsql_delete_callback(CachedFunction *cfunc)
Definition: pl_funcs.c:772
void * fn_extra
Definition: fmgr.h:64
FmgrInfo * flinfo
Definition: fmgr.h:87

References cached_function_compile(), FunctionCallInfoBaseData::flinfo, FmgrInfo::fn_extra, function, plpgsql_compile_callback(), and plpgsql_delete_callback().

Referenced by plpgsql_call_handler(), and plpgsql_validator().

◆ plpgsql_compile_callback()

static void plpgsql_compile_callback ( FunctionCallInfo  fcinfo,
HeapTuple  procTup,
const CachedFunctionHashKey hashkey,
CachedFunction cfunc,
bool  forValidator 
)
static

Definition at line 167 of file pl_comp.c.

172{
174 Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
175 bool is_dml_trigger = CALLED_AS_TRIGGER(fcinfo);
176 bool is_event_trigger = CALLED_AS_EVENT_TRIGGER(fcinfo);
177 yyscan_t scanner;
178 Datum prosrcdatum;
179 char *proc_source;
180 HeapTuple typeTup;
181 Form_pg_type typeStruct;
182 PLpgSQL_variable *var;
183 PLpgSQL_rec *rec;
184 int i;
185 struct compile_error_callback_arg cbarg;
186 ErrorContextCallback plerrcontext;
187 int parse_rc;
188 Oid rettypeid;
189 int numargs;
190 int num_in_args = 0;
191 int num_out_args = 0;
192 Oid *argtypes;
193 char **argnames;
194 char *argmodes;
195 int *in_arg_varnos = NULL;
196 PLpgSQL_variable **out_arg_variables;
197 MemoryContext func_cxt;
198
199 /*
200 * Setup the scanner input and error info.
201 */
202 prosrcdatum = SysCacheGetAttrNotNull(PROCOID, procTup, Anum_pg_proc_prosrc);
203 proc_source = TextDatumGetCString(prosrcdatum);
205
206 plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname));
207
208 /*
209 * Setup error traceback support for ereport()
210 */
211 cbarg.proc_source = forValidator ? proc_source : NULL;
212 cbarg.yyscanner = scanner;
213 plerrcontext.callback = plpgsql_compile_error_callback;
214 plerrcontext.arg = &cbarg;
215 plerrcontext.previous = error_context_stack;
216 error_context_stack = &plerrcontext;
217
218 /*
219 * Do extra syntax checks when validating the function definition. We skip
220 * this when actually compiling functions for execution, for performance
221 * reasons.
222 */
223 plpgsql_check_syntax = forValidator;
225
226 /*
227 * All the permanent output of compilation (e.g. parse tree) is kept in a
228 * per-function memory context, so it can be reclaimed easily.
229 */
231 "PL/pgSQL function",
234
235 function->fn_signature = format_procedure(fcinfo->flinfo->fn_oid);
236 MemoryContextSetIdentifier(func_cxt, function->fn_signature);
237 function->fn_oid = fcinfo->flinfo->fn_oid;
238 function->fn_input_collation = fcinfo->fncollation;
239 function->fn_cxt = func_cxt;
240 function->out_param_varno = -1; /* set up for no OUT param */
241 function->resolve_option = plpgsql_variable_conflict;
242 function->print_strict_params = plpgsql_print_strict_params;
243 /* only promote extra warnings and errors at CREATE FUNCTION time */
244 function->extra_warnings = forValidator ? plpgsql_extra_warnings : 0;
245 function->extra_errors = forValidator ? plpgsql_extra_errors : 0;
246
247 if (is_dml_trigger)
248 function->fn_is_trigger = PLPGSQL_DML_TRIGGER;
249 else if (is_event_trigger)
250 function->fn_is_trigger = PLPGSQL_EVENT_TRIGGER;
251 else
252 function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
253
254 function->fn_prokind = procStruct->prokind;
255
256 function->nstatements = 0;
257 function->requires_procedure_resowner = false;
258 function->has_exception_block = false;
259
260 /*
261 * Initialize the compiler, particularly the namespace stack. The
262 * outermost namespace contains function parameters and other special
263 * variables (such as FOUND), and is named after the function itself.
264 */
266 plpgsql_ns_push(NameStr(procStruct->proname), PLPGSQL_LABEL_BLOCK);
267 plpgsql_DumpExecTree = false;
269
270 switch (function->fn_is_trigger)
271 {
273
274 /*
275 * Fetch info about the procedure's parameters. Allocations aren't
276 * needed permanently, so make them in tmp cxt.
277 *
278 * We also need to resolve any polymorphic input or output
279 * argument types. In validation mode we won't be able to, so we
280 * arbitrarily assume we are dealing with integers.
281 */
283
284 numargs = get_func_arg_info(procTup,
285 &argtypes, &argnames, &argmodes);
286
287 cfunc_resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
288 fcinfo->flinfo->fn_expr,
289 forValidator,
291
292 in_arg_varnos = (int *) palloc(numargs * sizeof(int));
293 out_arg_variables = (PLpgSQL_variable **) palloc(numargs * sizeof(PLpgSQL_variable *));
294
295 MemoryContextSwitchTo(func_cxt);
296
297 /*
298 * Create the variables for the procedure's parameters.
299 */
300 for (i = 0; i < numargs; i++)
301 {
302 char buf[32];
303 Oid argtypeid = argtypes[i];
304 char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
305 PLpgSQL_type *argdtype;
306 PLpgSQL_variable *argvariable;
307 PLpgSQL_nsitem_type argitemtype;
308
309 /* Create $n name for variable */
310 snprintf(buf, sizeof(buf), "$%d", i + 1);
311
312 /* Create datatype info */
313 argdtype = plpgsql_build_datatype(argtypeid,
314 -1,
315 function->fn_input_collation,
316 NULL);
317
318 /* Disallow pseudotype argument */
319 /* (note we already replaced polymorphic types) */
320 /* (build_variable would do this, but wrong message) */
321 if (argdtype->ttype == PLPGSQL_TTYPE_PSEUDO)
323 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
324 errmsg("PL/pgSQL functions cannot accept type %s",
325 format_type_be(argtypeid))));
326
327 /*
328 * Build variable and add to datum list. If there's a name
329 * for the argument, use that as refname, else use $n name.
330 */
331 argvariable = plpgsql_build_variable((argnames &&
332 argnames[i][0] != '\0') ?
333 argnames[i] : buf,
334 0, argdtype, false);
335
336 if (argvariable->dtype == PLPGSQL_DTYPE_VAR)
337 {
338 argitemtype = PLPGSQL_NSTYPE_VAR;
339 }
340 else
341 {
342 Assert(argvariable->dtype == PLPGSQL_DTYPE_REC);
343 argitemtype = PLPGSQL_NSTYPE_REC;
344 }
345
346 /* Remember arguments in appropriate arrays */
347 if (argmode == PROARGMODE_IN ||
348 argmode == PROARGMODE_INOUT ||
349 argmode == PROARGMODE_VARIADIC)
350 in_arg_varnos[num_in_args++] = argvariable->dno;
351 if (argmode == PROARGMODE_OUT ||
352 argmode == PROARGMODE_INOUT ||
353 argmode == PROARGMODE_TABLE)
354 out_arg_variables[num_out_args++] = argvariable;
355
356 /* Add to namespace under the $n name */
357 add_parameter_name(argitemtype, argvariable->dno, buf);
358
359 /* If there's a name for the argument, make an alias */
360 if (argnames && argnames[i][0] != '\0')
361 add_parameter_name(argitemtype, argvariable->dno,
362 argnames[i]);
363 }
364
365 /*
366 * If there's just one OUT parameter, out_param_varno points
367 * directly to it. If there's more than one, build a row that
368 * holds all of them. Procedures return a row even for one OUT
369 * parameter.
370 */
371 if (num_out_args > 1 ||
372 (num_out_args == 1 && function->fn_prokind == PROKIND_PROCEDURE))
373 {
374 PLpgSQL_row *row = build_row_from_vars(out_arg_variables,
375 num_out_args);
376
378 function->out_param_varno = row->dno;
379 }
380 else if (num_out_args == 1)
381 function->out_param_varno = out_arg_variables[0]->dno;
382
383 /*
384 * Check for a polymorphic returntype. If found, use the actual
385 * returntype type from the caller's FuncExpr node, if we have
386 * one. (In validation mode we arbitrarily assume we are dealing
387 * with integers.)
388 *
389 * Note: errcode is FEATURE_NOT_SUPPORTED because it should always
390 * work; if it doesn't we're in some context that fails to make
391 * the info available.
392 */
393 rettypeid = procStruct->prorettype;
394 if (IsPolymorphicType(rettypeid))
395 {
396 if (forValidator)
397 {
398 if (rettypeid == ANYARRAYOID ||
399 rettypeid == ANYCOMPATIBLEARRAYOID)
400 rettypeid = INT4ARRAYOID;
401 else if (rettypeid == ANYRANGEOID ||
402 rettypeid == ANYCOMPATIBLERANGEOID)
403 rettypeid = INT4RANGEOID;
404 else if (rettypeid == ANYMULTIRANGEOID)
405 rettypeid = INT4MULTIRANGEOID;
406 else /* ANYELEMENT or ANYNONARRAY or ANYCOMPATIBLE */
407 rettypeid = INT4OID;
408 /* XXX what could we use for ANYENUM? */
409 }
410 else
411 {
412 rettypeid = get_fn_expr_rettype(fcinfo->flinfo);
413 if (!OidIsValid(rettypeid))
415 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
416 errmsg("could not determine actual return type "
417 "for polymorphic function \"%s\"",
419 }
420 }
421
422 /*
423 * Normal function has a defined returntype
424 */
425 function->fn_rettype = rettypeid;
426 function->fn_retset = procStruct->proretset;
427
428 /*
429 * Lookup the function's return type
430 */
431 typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(rettypeid));
432 if (!HeapTupleIsValid(typeTup))
433 elog(ERROR, "cache lookup failed for type %u", rettypeid);
434 typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
435
436 /* Disallow pseudotype result, except VOID or RECORD */
437 /* (note we already replaced polymorphic types) */
438 if (typeStruct->typtype == TYPTYPE_PSEUDO)
439 {
440 if (rettypeid == VOIDOID ||
441 rettypeid == RECORDOID)
442 /* okay */ ;
443 else if (rettypeid == TRIGGEROID || rettypeid == EVENT_TRIGGEROID)
445 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
446 errmsg("trigger functions can only be called as triggers")));
447 else
449 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
450 errmsg("PL/pgSQL functions cannot return type %s",
451 format_type_be(rettypeid))));
452 }
453
454 function->fn_retistuple = type_is_rowtype(rettypeid);
455 function->fn_retisdomain = (typeStruct->typtype == TYPTYPE_DOMAIN);
456 function->fn_retbyval = typeStruct->typbyval;
457 function->fn_rettyplen = typeStruct->typlen;
458
459 /*
460 * install $0 reference, but only for polymorphic return types,
461 * and not when the return is specified through an output
462 * parameter.
463 */
464 if (IsPolymorphicType(procStruct->prorettype) &&
465 num_out_args == 0)
466 {
467 (void) plpgsql_build_variable("$0", 0,
468 build_datatype(typeTup,
469 -1,
470 function->fn_input_collation,
471 NULL),
472 true);
473 }
474
475 ReleaseSysCache(typeTup);
476 break;
477
479 /* Trigger procedure's return type is unknown yet */
480 function->fn_rettype = InvalidOid;
481 function->fn_retbyval = false;
482 function->fn_retistuple = true;
483 function->fn_retisdomain = false;
484 function->fn_retset = false;
485
486 /* shouldn't be any declared arguments */
487 if (procStruct->pronargs != 0)
489 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
490 errmsg("trigger functions cannot have declared arguments"),
491 errhint("The arguments of the trigger can be accessed through TG_NARGS and TG_ARGV instead.")));
492
493 /* Add the record for referencing NEW ROW */
494 rec = plpgsql_build_record("new", 0, NULL, RECORDOID, true);
495 function->new_varno = rec->dno;
496
497 /* Add the record for referencing OLD ROW */
498 rec = plpgsql_build_record("old", 0, NULL, RECORDOID, true);
499 function->old_varno = rec->dno;
500
501 /* Add the variable tg_name */
502 var = plpgsql_build_variable("tg_name", 0,
504 -1,
505 function->fn_input_collation,
506 NULL),
507 true);
510 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_NAME;
511
512 /* Add the variable tg_when */
513 var = plpgsql_build_variable("tg_when", 0,
515 -1,
516 function->fn_input_collation,
517 NULL),
518 true);
521 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_WHEN;
522
523 /* Add the variable tg_level */
524 var = plpgsql_build_variable("tg_level", 0,
526 -1,
527 function->fn_input_collation,
528 NULL),
529 true);
532 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_LEVEL;
533
534 /* Add the variable tg_op */
535 var = plpgsql_build_variable("tg_op", 0,
537 -1,
538 function->fn_input_collation,
539 NULL),
540 true);
543 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_OP;
544
545 /* Add the variable tg_relid */
546 var = plpgsql_build_variable("tg_relid", 0,
548 -1,
550 NULL),
551 true);
554 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_RELID;
555
556 /* Add the variable tg_relname */
557 var = plpgsql_build_variable("tg_relname", 0,
559 -1,
560 function->fn_input_collation,
561 NULL),
562 true);
565 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_NAME;
566
567 /* tg_table_name is now preferred to tg_relname */
568 var = plpgsql_build_variable("tg_table_name", 0,
570 -1,
571 function->fn_input_collation,
572 NULL),
573 true);
576 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_NAME;
577
578 /* add the variable tg_table_schema */
579 var = plpgsql_build_variable("tg_table_schema", 0,
581 -1,
582 function->fn_input_collation,
583 NULL),
584 true);
587 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_SCHEMA;
588
589 /* Add the variable tg_nargs */
590 var = plpgsql_build_variable("tg_nargs", 0,
592 -1,
594 NULL),
595 true);
598 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_NARGS;
599
600 /* Add the variable tg_argv */
601 var = plpgsql_build_variable("tg_argv", 0,
602 plpgsql_build_datatype(TEXTARRAYOID,
603 -1,
604 function->fn_input_collation,
605 NULL),
606 true);
609 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_ARGV;
610
611 break;
612
614 function->fn_rettype = VOIDOID;
615 function->fn_retbyval = false;
616 function->fn_retistuple = true;
617 function->fn_retisdomain = false;
618 function->fn_retset = false;
619
620 /* shouldn't be any declared arguments */
621 if (procStruct->pronargs != 0)
623 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
624 errmsg("event trigger functions cannot have declared arguments")));
625
626 /* Add the variable tg_event */
627 var = plpgsql_build_variable("tg_event", 0,
629 -1,
630 function->fn_input_collation,
631 NULL),
632 true);
635 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_EVENT;
636
637 /* Add the variable tg_tag */
638 var = plpgsql_build_variable("tg_tag", 0,
640 -1,
641 function->fn_input_collation,
642 NULL),
643 true);
646 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TAG;
647
648 break;
649
650 default:
651 elog(ERROR, "unrecognized function typecode: %d",
652 (int) function->fn_is_trigger);
653 break;
654 }
655
656 /* Remember if function is STABLE/IMMUTABLE */
657 function->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
658
659 /*
660 * Create the magic FOUND variable.
661 */
662 var = plpgsql_build_variable("found", 0,
664 -1,
666 NULL),
667 true);
668 function->found_varno = var->dno;
669
670 /*
671 * Now parse the function's text
672 */
673 parse_rc = plpgsql_yyparse(&function->action, scanner);
674 if (parse_rc != 0)
675 elog(ERROR, "plpgsql parser returned %d", parse_rc);
676
677 plpgsql_scanner_finish(scanner);
679
680 /*
681 * If it has OUT parameters or returns VOID or returns a set, we allow
682 * control to fall off the end without an explicit RETURN statement. The
683 * easiest way to implement this is to add a RETURN statement to the end
684 * of the statement list during parsing.
685 */
686 if (num_out_args > 0 || function->fn_rettype == VOIDOID ||
687 function->fn_retset)
689
690 /*
691 * Complete the function's info
692 */
693 function->fn_nargs = procStruct->pronargs;
694 for (i = 0; i < function->fn_nargs; i++)
695 function->fn_argvarnos[i] = in_arg_varnos[i];
696
698
699 if (function->has_exception_block)
701
702 /* Debug dump for completed functions */
705
706 /*
707 * Pop the error context stack
708 */
709 error_context_stack = plerrcontext.previous;
711
712 plpgsql_check_syntax = false;
713
716}
#define TextDatumGetCString(d)
Definition: builtins.h:98
void * yyscan_t
Definition: cubedata.h:67
ErrorContextCallback * error_context_stack
Definition: elog.c:95
int errhint(const char *fmt,...)
Definition: elog.c:1318
#define CALLED_AS_EVENT_TRIGGER(fcinfo)
Definition: event_trigger.h:49
Oid get_fn_expr_rettype(FmgrInfo *flinfo)
Definition: fmgr.c:1888
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
Definition: funcapi.c:1379
void cfunc_resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, Node *call_expr, bool forValidator, const char *proname)
Definition: funccache.c:348
void pfree(void *pointer)
Definition: mcxt.c:2147
MemoryContext TopMemoryContext
Definition: mcxt.c:165
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
Definition: mcxt.c:643
#define AllocSetContextCreate
Definition: memutils.h:149
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:180
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
static char * buf
Definition: pg_test_fsync.c:72
static void add_dummy_return(PLpgSQL_function *function)
Definition: pl_comp.c:930
static PLpgSQL_row * build_row_from_vars(PLpgSQL_variable **vars, int numvars)
Definition: pl_comp.c:1828
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:53
static void plpgsql_compile_error_callback(void *arg)
Definition: pl_comp.c:875
static void plpgsql_start_datums(void)
Definition: pl_comp.c:2190
char * plpgsql_error_funcname
Definition: pl_comp.c:46
bool plpgsql_check_syntax
Definition: pl_comp.c:48
static void plpgsql_finish_datums(PLpgSQL_function *function)
Definition: pl_comp.c:2224
PLpgSQL_function * plpgsql_curr_compile
Definition: pl_comp.c:50
bool plpgsql_DumpExecTree
Definition: pl_comp.c:47
static void add_parameter_name(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
Definition: pl_comp.c:905
PLpgSQL_variable * plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype, bool add2namespace)
Definition: pl_comp.c:1738
void plpgsql_ns_init(void)
Definition: pl_funcs.c:43
void plpgsql_dumptree(PLpgSQL_function *func)
Definition: pl_funcs.c:1601
void plpgsql_mark_local_assignment_targets(PLpgSQL_function *func)
Definition: pl_funcs.c:673
void plpgsql_ns_push(const char *label, PLpgSQL_label_type label_type)
Definition: pl_funcs.c:54
int plpgsql_variable_conflict
Definition: pl_handler.c:47
int plpgsql_extra_warnings
Definition: pl_handler.c:55
bool plpgsql_print_strict_params
Definition: pl_handler.c:49
int plpgsql_extra_errors
Definition: pl_handler.c:56
void plpgsql_scanner_finish(yyscan_t yyscanner)
Definition: pl_scanner.c:653
yyscan_t plpgsql_scanner_init(const char *str)
Definition: pl_scanner.c:621
@ PLPGSQL_DML_TRIGGER
Definition: plpgsql.h:950
@ PLPGSQL_NOT_TRIGGER
Definition: plpgsql.h:952
@ PLPGSQL_EVENT_TRIGGER
Definition: plpgsql.h:951
@ PLPGSQL_PROMISE_TG_RELID
Definition: plpgsql.h:81
@ PLPGSQL_PROMISE_TG_WHEN
Definition: plpgsql.h:78
@ PLPGSQL_PROMISE_TG_ARGV
Definition: plpgsql.h:85
@ PLPGSQL_PROMISE_TG_TABLE_SCHEMA
Definition: plpgsql.h:83
@ PLPGSQL_PROMISE_TG_EVENT
Definition: plpgsql.h:86
@ PLPGSQL_PROMISE_TG_TABLE_NAME
Definition: plpgsql.h:82
@ PLPGSQL_PROMISE_TG_TAG
Definition: plpgsql.h:87
@ PLPGSQL_PROMISE_TG_OP
Definition: plpgsql.h:80
@ PLPGSQL_PROMISE_TG_LEVEL
Definition: plpgsql.h:79
@ PLPGSQL_PROMISE_TG_NARGS
Definition: plpgsql.h:84
@ PLPGSQL_PROMISE_TG_NAME
Definition: plpgsql.h:77
@ PLPGSQL_LABEL_BLOCK
Definition: plpgsql.h:54
int plpgsql_yyparse(PLpgSQL_stmt_block **plpgsql_parse_result_p, yyscan_t yyscanner)
PLpgSQL_nsitem_type
Definition: plpgsql.h:43
#define snprintf
Definition: port.h:239
uintptr_t Datum
Definition: postgres.h:69
char * format_procedure(Oid procedure_oid)
Definition: regproc.c:299
struct ErrorContextCallback * previous
Definition: elog.h:297
fmNodePtr fn_expr
Definition: fmgr.h:66
Oid fn_oid
Definition: fmgr.h:59
const char * proc_source
Definition: pl_comp.c:140
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:631
#define CALLED_AS_TRIGGER(fcinfo)
Definition: trigger.h:26

References add_dummy_return(), add_parameter_name(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert(), buf, build_datatype(), build_row_from_vars(), CALLED_AS_EVENT_TRIGGER, CALLED_AS_TRIGGER, cfunc_resolve_polymorphic_argtypes(), PLpgSQL_variable::dno, PLpgSQL_row::dno, PLpgSQL_rec::dno, PLpgSQL_variable::dtype, elog, ereport, errcode(), errhint(), errmsg(), ERROR, error_context_stack, FunctionCallInfoBaseData::flinfo, FmgrInfo::fn_expr, FmgrInfo::fn_oid, FunctionCallInfoBaseData::fncollation, format_procedure(), format_type_be(), function, get_fn_expr_rettype(), get_func_arg_info(), GETSTRUCT(), HeapTupleIsValid, i, InvalidOid, MemoryContextSetIdentifier(), MemoryContextSwitchTo(), NameStr, ObjectIdGetDatum(), OidIsValid, palloc(), pfree(), plpgsql_adddatum(), plpgsql_build_datatype(), plpgsql_build_record(), plpgsql_build_variable(), plpgsql_check_syntax, plpgsql_compile_error_callback(), plpgsql_compile_tmp_cxt, plpgsql_curr_compile, PLPGSQL_DML_TRIGGER, PLPGSQL_DTYPE_PROMISE, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_VAR, plpgsql_DumpExecTree, plpgsql_dumptree(), plpgsql_error_funcname, PLPGSQL_EVENT_TRIGGER, plpgsql_extra_errors, plpgsql_extra_warnings, plpgsql_finish_datums(), PLPGSQL_LABEL_BLOCK, plpgsql_mark_local_assignment_targets(), PLPGSQL_NOT_TRIGGER, plpgsql_ns_init(), plpgsql_ns_push(), PLPGSQL_NSTYPE_REC, PLPGSQL_NSTYPE_VAR, 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_scanner_finish(), plpgsql_scanner_init(), plpgsql_start_datums(), PLPGSQL_TTYPE_PSEUDO, plpgsql_variable_conflict, plpgsql_yyparse(), ErrorContextCallback::previous, compile_error_callback_arg::proc_source, pstrdup(), ReleaseSysCache(), SearchSysCache1(), snprintf, SysCacheGetAttrNotNull(), TextDatumGetCString, TopMemoryContext, PLpgSQL_type::ttype, type_is_rowtype(), and compile_error_callback_arg::yyscanner.

Referenced by plpgsql_compile().

◆ plpgsql_compile_error_callback()

static void plpgsql_compile_error_callback ( void *  arg)
static

Definition at line 875 of file pl_comp.c.

876{
879
880 if (cbarg->proc_source)
881 {
882 /*
883 * Try to convert syntax error position to reference text of original
884 * CREATE FUNCTION or DO command.
885 */
887 return;
888
889 /*
890 * Done if a syntax error position was reported; otherwise we have to
891 * fall back to a "near line N" report.
892 */
893 }
894
896 errcontext("compilation of PL/pgSQL function \"%s\" near line %d",
898}
#define errcontext
Definition: elog.h:197
void * arg
bool function_parse_error_transpose(const char *prosrc)
Definition: pg_proc.c:1023
int plpgsql_latest_lineno(yyscan_t yyscanner)
Definition: pl_scanner.c:607

References arg, errcontext, function_parse_error_transpose(), plpgsql_error_funcname, plpgsql_latest_lineno(), compile_error_callback_arg::proc_source, and compile_error_callback_arg::yyscanner.

Referenced by plpgsql_compile_callback(), and plpgsql_compile_inline().

◆ plpgsql_compile_inline()

PLpgSQL_function * plpgsql_compile_inline ( char *  proc_source)

Definition at line 729 of file pl_comp.c.

730{
731 yyscan_t scanner;
732 char *func_name = "inline_code_block";
734 struct compile_error_callback_arg cbarg;
735 ErrorContextCallback plerrcontext;
736 PLpgSQL_variable *var;
737 int parse_rc;
738 MemoryContext func_cxt;
739
740 /*
741 * Setup the scanner input and error info.
742 */
744
745 plpgsql_error_funcname = func_name;
746
747 /*
748 * Setup error traceback support for ereport()
749 */
750 cbarg.proc_source = proc_source;
751 cbarg.yyscanner = scanner;
752 plerrcontext.callback = plpgsql_compile_error_callback;
753 plerrcontext.arg = &cbarg;
754 plerrcontext.previous = error_context_stack;
755 error_context_stack = &plerrcontext;
756
757 /* Do extra syntax checking if check_function_bodies is on */
759
760 /* Function struct does not live past current statement */
762
764
765 /*
766 * All the rest of the compile-time storage (e.g. parse tree) is kept in
767 * its own memory context, so it can be reclaimed easily.
768 */
770 "PL/pgSQL inline code context",
773
774 function->fn_signature = pstrdup(func_name);
775 function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
776 function->fn_input_collation = InvalidOid;
777 function->fn_cxt = func_cxt;
778 function->out_param_varno = -1; /* set up for no OUT param */
779 function->resolve_option = plpgsql_variable_conflict;
780 function->print_strict_params = plpgsql_print_strict_params;
781
782 /*
783 * don't do extra validation for inline code as we don't want to add spam
784 * at runtime
785 */
786 function->extra_warnings = 0;
787 function->extra_errors = 0;
788
789 function->nstatements = 0;
790 function->requires_procedure_resowner = false;
791 function->has_exception_block = false;
792
795 plpgsql_DumpExecTree = false;
797
798 /* Set up as though in a function returning VOID */
799 function->fn_rettype = VOIDOID;
800 function->fn_retset = false;
801 function->fn_retistuple = false;
802 function->fn_retisdomain = false;
803 function->fn_prokind = PROKIND_FUNCTION;
804 /* a bit of hardwired knowledge about type VOID here */
805 function->fn_retbyval = true;
806 function->fn_rettyplen = sizeof(int32);
807
808 /*
809 * Remember if function is STABLE/IMMUTABLE. XXX would it be better to
810 * set this true inside a read-only transaction? Not clear.
811 */
812 function->fn_readonly = false;
813
814 /*
815 * Create the magic FOUND variable.
816 */
817 var = plpgsql_build_variable("found", 0,
819 -1,
821 NULL),
822 true);
823 function->found_varno = var->dno;
824
825 /*
826 * Now parse the function's text
827 */
828 parse_rc = plpgsql_yyparse(&function->action, scanner);
829 if (parse_rc != 0)
830 elog(ERROR, "plpgsql parser returned %d", parse_rc);
831
832 plpgsql_scanner_finish(scanner);
833
834 /*
835 * If it returns VOID (always true at the moment), we allow control to
836 * fall off the end without an explicit RETURN statement.
837 */
838 if (function->fn_rettype == VOIDOID)
840
841 /*
842 * Complete the function's info
843 */
844 function->fn_nargs = 0;
845
847
848 if (function->has_exception_block)
850
851 /* Debug dump for completed functions */
854
855 /*
856 * Pop the error context stack
857 */
858 error_context_stack = plerrcontext.previous;
860
861 plpgsql_check_syntax = false;
862
865 return function;
866}
bool check_function_bodies
Definition: guc_tables.c:528
MemoryContext CurrentMemoryContext
Definition: mcxt.c:159

References add_dummy_return(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, check_function_bodies, CurrentMemoryContext, PLpgSQL_variable::dno, elog, ERROR, error_context_stack, function, InvalidOid, MemoryContextSwitchTo(), palloc0(), plpgsql_build_datatype(), plpgsql_build_variable(), plpgsql_check_syntax, plpgsql_compile_error_callback(), plpgsql_compile_tmp_cxt, plpgsql_curr_compile, plpgsql_DumpExecTree, plpgsql_dumptree(), plpgsql_error_funcname, plpgsql_finish_datums(), PLPGSQL_LABEL_BLOCK, plpgsql_mark_local_assignment_targets(), PLPGSQL_NOT_TRIGGER, plpgsql_ns_init(), plpgsql_ns_push(), plpgsql_print_strict_params, plpgsql_scanner_finish(), plpgsql_scanner_init(), plpgsql_start_datums(), plpgsql_variable_conflict, plpgsql_yyparse(), ErrorContextCallback::previous, compile_error_callback_arg::proc_source, pstrdup(), and compile_error_callback_arg::yyscanner.

Referenced by plpgsql_inline_handler().

◆ plpgsql_finish_datums()

static void plpgsql_finish_datums ( PLpgSQL_function function)
static

Definition at line 2224 of file pl_comp.c.

2225{
2226 Size copiable_size = 0;
2227 int i;
2228
2229 function->ndatums = plpgsql_nDatums;
2230 function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
2231 for (i = 0; i < plpgsql_nDatums; i++)
2232 {
2233 function->datums[i] = plpgsql_Datums[i];
2234
2235 /* This must agree with copy_plpgsql_datums on what is copiable */
2236 switch (function->datums[i]->dtype)
2237 {
2238 case PLPGSQL_DTYPE_VAR:
2240 copiable_size += MAXALIGN(sizeof(PLpgSQL_var));
2241 break;
2242 case PLPGSQL_DTYPE_REC:
2243 copiable_size += MAXALIGN(sizeof(PLpgSQL_rec));
2244 break;
2245 default:
2246 break;
2247 }
2248 }
2249 function->copiable_size = copiable_size;
2250}
#define MAXALIGN(LEN)
Definition: c.h:782
size_t Size
Definition: c.h:576

References function, i, MAXALIGN, palloc(), plpgsql_Datums, PLPGSQL_DTYPE_PROMISE, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_VAR, and plpgsql_nDatums.

Referenced by plpgsql_compile_callback(), and plpgsql_compile_inline().

◆ plpgsql_param_ref()

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

Definition at line 1046 of file pl_comp.c.

1047{
1048 PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1049 char pname[32];
1050 PLpgSQL_nsitem *nse;
1051
1052 snprintf(pname, sizeof(pname), "$%d", pref->number);
1053
1054 nse = plpgsql_ns_lookup(expr->ns, false,
1055 pname, NULL, NULL,
1056 NULL);
1057
1058 if (nse == NULL)
1059 return NULL; /* name not known to plpgsql */
1060
1061 return make_datum_param(expr, nse->itemno, pref->location);
1062}
static Node * make_datum_param(PLpgSQL_expr *expr, int dno, int location)
Definition: pl_comp.c:1231
struct PLpgSQL_nsitem * ns
Definition: plpgsql.h:235
ParseLoc location
Definition: parsenodes.h:316
int number
Definition: parsenodes.h:315
void * p_ref_hook_state
Definition: parse_node.h:258

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

Referenced by plpgsql_parser_setup().

◆ plpgsql_parse_cwordrowtype()

PLpgSQL_type * plpgsql_parse_cwordrowtype ( List idents)

Definition at line 1694 of file pl_comp.c.

1695{
1696 Oid classOid;
1697 Oid typOid;
1698 RangeVar *relvar;
1699 MemoryContext oldCxt;
1700
1701 /*
1702 * As above, this is a relation lookup but could be a type lookup if we
1703 * weren't being backwards-compatible about error wording.
1704 */
1705
1706 /* Avoid memory leaks in long-term function context */
1708
1709 /* Look up relation name. Can't lock it - we might not have privileges. */
1710 relvar = makeRangeVarFromNameList(idents);
1711 classOid = RangeVarGetRelid(relvar, NoLock, false);
1712
1713 /* Some relkinds lack type OIDs */
1714 typOid = get_rel_type_id(classOid);
1715 if (!OidIsValid(typOid))
1716 ereport(ERROR,
1717 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1718 errmsg("relation \"%s\" does not have a composite type",
1719 relvar->relname)));
1720
1721 MemoryContextSwitchTo(oldCxt);
1722
1723 /* Build and return the row type struct */
1724 return plpgsql_build_datatype(typOid, -1, InvalidOid,
1725 makeTypeNameFromNameList(idents));
1726}
#define NoLock
Definition: lockdefs.h:34
Oid get_rel_type_id(Oid relid)
Definition: lsyscache.c:2119
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:531
RangeVar * makeRangeVarFromNameList(const List *names)
Definition: namespace.c:3554
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:80
char * relname
Definition: primnodes.h:83

References ereport, errcode(), errmsg(), ERROR, get_rel_type_id(), InvalidOid, makeRangeVarFromNameList(), makeTypeNameFromNameList(), MemoryContextSwitchTo(), NoLock, OidIsValid, plpgsql_build_datatype(), plpgsql_compile_tmp_cxt, RangeVarGetRelid, and RangeVar::relname.

◆ plpgsql_parse_cwordtype()

PLpgSQL_type * plpgsql_parse_cwordtype ( List idents)

Definition at line 1545 of file pl_comp.c.

1546{
1547 PLpgSQL_type *dtype = NULL;
1548 PLpgSQL_nsitem *nse;
1549 int nnames;
1550 RangeVar *relvar = NULL;
1551 const char *fldname = NULL;
1552 Oid classOid;
1553 HeapTuple attrtup = NULL;
1554 HeapTuple typetup = NULL;
1555 Form_pg_attribute attrStruct;
1556 MemoryContext oldCxt;
1557
1558 /* Avoid memory leaks in the long-term function context */
1560
1561 if (list_length(idents) == 2)
1562 {
1563 /*
1564 * Do a lookup in the current namespace stack
1565 */
1566 nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1567 strVal(linitial(idents)),
1568 strVal(lsecond(idents)),
1569 NULL,
1570 &nnames);
1571
1572 if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_VAR)
1573 {
1574 /* Block-qualified reference to scalar variable. */
1575 dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1576 goto done;
1577 }
1578 else if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_REC &&
1579 nnames == 2)
1580 {
1581 /* Block-qualified reference to record variable. */
1582 dtype = ((PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]))->datatype;
1583 goto done;
1584 }
1585
1586 /*
1587 * First word could also be a table name
1588 */
1589 relvar = makeRangeVar(NULL,
1590 strVal(linitial(idents)),
1591 -1);
1592 fldname = strVal(lsecond(idents));
1593 }
1594 else
1595 {
1596 /*
1597 * We could check for a block-qualified reference to a field of a
1598 * record variable, but %TYPE is documented as applying to variables,
1599 * not fields of variables. Things would get rather ambiguous if we
1600 * allowed either interpretation.
1601 */
1602 List *rvnames;
1603
1604 Assert(list_length(idents) > 2);
1605 rvnames = list_delete_last(list_copy(idents));
1606 relvar = makeRangeVarFromNameList(rvnames);
1607 fldname = strVal(llast(idents));
1608 }
1609
1610 /* Look up relation name. Can't lock it - we might not have privileges. */
1611 classOid = RangeVarGetRelid(relvar, NoLock, false);
1612
1613 /*
1614 * Fetch the named table field and its type
1615 */
1616 attrtup = SearchSysCacheAttName(classOid, fldname);
1617 if (!HeapTupleIsValid(attrtup))
1618 ereport(ERROR,
1619 (errcode(ERRCODE_UNDEFINED_COLUMN),
1620 errmsg("column \"%s\" of relation \"%s\" does not exist",
1621 fldname, relvar->relname)));
1622 attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1623
1624 typetup = SearchSysCache1(TYPEOID,
1625 ObjectIdGetDatum(attrStruct->atttypid));
1626 if (!HeapTupleIsValid(typetup))
1627 elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1628
1629 /*
1630 * Found that - build a compiler type struct in the caller's cxt and
1631 * return it. Note that we treat the type as being found-by-OID; no
1632 * attempt to re-look-up the type name will happen during invalidations.
1633 */
1634 MemoryContextSwitchTo(oldCxt);
1635 dtype = build_datatype(typetup,
1636 attrStruct->atttypmod,
1637 attrStruct->attcollation,
1638 NULL);
1640
1641done:
1642 if (HeapTupleIsValid(attrtup))
1643 ReleaseSysCache(attrtup);
1644 if (HeapTupleIsValid(typetup))
1645 ReleaseSysCache(typetup);
1646
1647 MemoryContextSwitchTo(oldCxt);
1648 return dtype;
1649}
List * list_copy(const List *oldlist)
Definition: list.c:1573
List * list_delete_last(List *list)
Definition: list.c:957
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:473
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:202
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
Definition: pg_list.h:54
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:462
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:480
#define strVal(v)
Definition: value.h:82

References Assert(), build_datatype(), elog, ereport, errcode(), errmsg(), ERROR, GETSTRUCT(), HeapTupleIsValid, PLpgSQL_nsitem::itemno, PLpgSQL_nsitem::itemtype, linitial, list_copy(), list_delete_last(), list_length(), llast, lsecond, makeRangeVar(), makeRangeVarFromNameList(), MemoryContextSwitchTo(), NoLock, ObjectIdGetDatum(), plpgsql_compile_tmp_cxt, plpgsql_Datums, plpgsql_ns_lookup(), plpgsql_ns_top(), PLPGSQL_NSTYPE_REC, PLPGSQL_NSTYPE_VAR, RangeVarGetRelid, ReleaseSysCache(), RangeVar::relname, SearchSysCache1(), SearchSysCacheAttName(), and strVal.

◆ plpgsql_parse_dblword()

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

Definition at line 1339 of file pl_comp.c.

1341{
1342 PLpgSQL_nsitem *ns;
1343 List *idents;
1344 int nnames;
1345
1346 idents = list_make2(makeString(word1),
1347 makeString(word2));
1348
1349 /*
1350 * We should do nothing in DECLARE sections. In SQL expressions, we
1351 * really only need to make sure that RECFIELD datums are created when
1352 * needed. In all the cases handled by this function, returning a T_DATUM
1353 * with a two-word idents string is the right thing.
1354 */
1356 {
1357 /*
1358 * Do a lookup in the current namespace stack
1359 */
1360 ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1361 word1, word2, NULL,
1362 &nnames);
1363 if (ns != NULL)
1364 {
1365 switch (ns->itemtype)
1366 {
1367 case PLPGSQL_NSTYPE_VAR:
1368 /* Block-qualified reference to scalar variable. */
1369 wdatum->datum = plpgsql_Datums[ns->itemno];
1370 wdatum->ident = NULL;
1371 wdatum->quoted = false; /* not used */
1372 wdatum->idents = idents;
1373 return true;
1374
1375 case PLPGSQL_NSTYPE_REC:
1376 if (nnames == 1)
1377 {
1378 /*
1379 * First word is a record name, so second word could
1380 * be a field in this record. We build a RECFIELD
1381 * datum whether it is or not --- any error will be
1382 * detected later.
1383 */
1384 PLpgSQL_rec *rec;
1385 PLpgSQL_recfield *new;
1386
1387 rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
1388 new = plpgsql_build_recfield(rec, word2);
1389
1390 wdatum->datum = (PLpgSQL_datum *) new;
1391 }
1392 else
1393 {
1394 /* Block-qualified reference to record variable. */
1395 wdatum->datum = plpgsql_Datums[ns->itemno];
1396 }
1397 wdatum->ident = NULL;
1398 wdatum->quoted = false; /* not used */
1399 wdatum->idents = idents;
1400 return true;
1401
1402 default:
1403 break;
1404 }
1405 }
1406 }
1407
1408 /* Nothing found */
1409 cword->idents = idents;
1410 return false;
1411}
#define list_make2(x1, x2)
Definition: pg_list.h:214
PLpgSQL_recfield * plpgsql_build_recfield(PLpgSQL_rec *rec, const char *fldname)
Definition: pl_comp.c:1895
IdentifierLookup plpgsql_IdentifierLookup
Definition: pl_scanner.c:26
@ IDENTIFIER_LOOKUP_DECLARE
Definition: plpgsql.h:1181
List * idents
Definition: plpgsql.h:1163
List * idents
Definition: plpgsql.h:1171
char * ident
Definition: plpgsql.h:1169
PLpgSQL_datum * datum
Definition: plpgsql.h:1168
bool quoted
Definition: plpgsql.h:1170
String * makeString(char *str)
Definition: value.c:63

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

Referenced by plpgsql_yylex().

◆ plpgsql_parse_err_condition()

PLpgSQL_condition * plpgsql_parse_err_condition ( char *  condname)

Definition at line 2143 of file pl_comp.c.

2144{
2145 int i;
2146 PLpgSQL_condition *new;
2147 PLpgSQL_condition *prev;
2148
2149 /*
2150 * XXX Eventually we will want to look for user-defined exception names
2151 * here.
2152 */
2153
2154 if (strcmp(condname, "others") == 0)
2155 {
2156 new = palloc(sizeof(PLpgSQL_condition));
2157 new->sqlerrstate = PLPGSQL_OTHERS;
2158 new->condname = condname;
2159 new->next = NULL;
2160 return new;
2161 }
2162
2163 prev = NULL;
2164 for (i = 0; exception_label_map[i].label != NULL; i++)
2165 {
2166 if (strcmp(condname, exception_label_map[i].label) == 0)
2167 {
2168 new = palloc(sizeof(PLpgSQL_condition));
2169 new->sqlerrstate = exception_label_map[i].sqlerrstate;
2170 new->condname = condname;
2171 new->next = prev;
2172 prev = new;
2173 }
2174 }
2175
2176 if (!prev)
2177 ereport(ERROR,
2178 (errcode(ERRCODE_UNDEFINED_OBJECT),
2179 errmsg("unrecognized exception condition \"%s\"",
2180 condname)));
2181
2182 return prev;
2183}
static char * label
static const ExceptionLabelMap exception_label_map[]
Definition: pl_comp.c:65
#define PLPGSQL_OTHERS
Definition: plpgsql.h:500
const char * label
Definition: pl_comp.c:61

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

◆ plpgsql_parse_tripword()

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

Definition at line 1420 of file pl_comp.c.

1422{
1423 PLpgSQL_nsitem *ns;
1424 List *idents;
1425 int nnames;
1426
1427 /*
1428 * We should do nothing in DECLARE sections. In SQL expressions, we need
1429 * to make sure that RECFIELD datums are created when needed, and we need
1430 * to be careful about how many names are reported as belonging to the
1431 * T_DATUM: the third word could be a sub-field reference, which we don't
1432 * care about here.
1433 */
1435 {
1436 /*
1437 * Do a lookup in the current namespace stack. Must find a record
1438 * reference, else ignore.
1439 */
1440 ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1441 word1, word2, word3,
1442 &nnames);
1443 if (ns != NULL)
1444 {
1445 switch (ns->itemtype)
1446 {
1447 case PLPGSQL_NSTYPE_REC:
1448 {
1449 PLpgSQL_rec *rec;
1450 PLpgSQL_recfield *new;
1451
1452 rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
1453 if (nnames == 1)
1454 {
1455 /*
1456 * First word is a record name, so second word
1457 * could be a field in this record (and the third,
1458 * a sub-field). We build a RECFIELD datum
1459 * whether it is or not --- any error will be
1460 * detected later.
1461 */
1462 new = plpgsql_build_recfield(rec, word2);
1463 idents = list_make2(makeString(word1),
1464 makeString(word2));
1465 }
1466 else
1467 {
1468 /* Block-qualified reference to record variable. */
1469 new = plpgsql_build_recfield(rec, word3);
1470 idents = list_make3(makeString(word1),
1471 makeString(word2),
1472 makeString(word3));
1473 }
1474 wdatum->datum = (PLpgSQL_datum *) new;
1475 wdatum->ident = NULL;
1476 wdatum->quoted = false; /* not used */
1477 wdatum->idents = idents;
1478 return true;
1479 }
1480
1481 default:
1482 break;
1483 }
1484 }
1485 }
1486
1487 /* Nothing found */
1488 idents = list_make3(makeString(word1),
1489 makeString(word2),
1490 makeString(word3));
1491 cword->idents = idents;
1492 return false;
1493}
#define list_make3(x1, x2, x3)
Definition: pg_list.h:216

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

Referenced by plpgsql_yylex().

◆ plpgsql_parse_word()

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

Definition at line 1284 of file pl_comp.c.

1286{
1287 PLpgSQL_nsitem *ns;
1288
1289 /*
1290 * We should not lookup variables in DECLARE sections. In SQL
1291 * expressions, there's no need to do so either --- lookup will happen
1292 * when the expression is compiled.
1293 */
1295 {
1296 /*
1297 * Do a lookup in the current namespace stack
1298 */
1299 ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1300 word1, NULL, NULL,
1301 NULL);
1302
1303 if (ns != NULL)
1304 {
1305 switch (ns->itemtype)
1306 {
1307 case PLPGSQL_NSTYPE_VAR:
1308 case PLPGSQL_NSTYPE_REC:
1309 wdatum->datum = plpgsql_Datums[ns->itemno];
1310 wdatum->ident = word1;
1311 wdatum->quoted = (yytxt[0] == '"');
1312 wdatum->idents = NIL;
1313 return true;
1314
1315 default:
1316 /* plpgsql_ns_lookup should never return anything else */
1317 elog(ERROR, "unrecognized plpgsql itemtype: %d",
1318 ns->itemtype);
1319 }
1320 }
1321 }
1322
1323 /*
1324 * Nothing found - up to now it's a word without any special meaning for
1325 * us.
1326 */
1327 word->ident = word1;
1328 word->quoted = (yytxt[0] == '"');
1329 return false;
1330}
@ IDENTIFIER_LOOKUP_NORMAL
Definition: plpgsql.h:1180
static void word(struct vars *v, int dir, struct state *lp, struct state *rp)
Definition: regcomp.c:1476
Definition: zic.c:304

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

Referenced by plpgsql_yylex().

◆ plpgsql_parse_wordrowtype()

PLpgSQL_type * plpgsql_parse_wordrowtype ( char *  ident)

Definition at line 1657 of file pl_comp.c.

1658{
1659 Oid classOid;
1660 Oid typOid;
1661
1662 /*
1663 * Look up the relation. Note that because relation rowtypes have the
1664 * same names as their relations, this could be handled as a type lookup
1665 * equally well; we use the relation lookup code path only because the
1666 * errors thrown here have traditionally referred to relations not types.
1667 * But we'll make a TypeName in case we have to do re-look-up of the type.
1668 */
1669 classOid = RelnameGetRelid(ident);
1670 if (!OidIsValid(classOid))
1671 ereport(ERROR,
1673 errmsg("relation \"%s\" does not exist", ident)));
1674
1675 /* Some relkinds lack type OIDs */
1676 typOid = get_rel_type_id(classOid);
1677 if (!OidIsValid(typOid))
1678 ereport(ERROR,
1679 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1680 errmsg("relation \"%s\" does not have a composite type",
1681 ident)));
1682
1683 /* Build and return the row type struct */
1684 return plpgsql_build_datatype(typOid, -1, InvalidOid,
1686}
#define ident
Definition: indent_codes.h:47
TypeName * makeTypeName(char *typnam)
Definition: makefuncs.c:519
Oid RelnameGetRelid(const char *relname)
Definition: namespace.c:885
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:79

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

◆ plpgsql_parse_wordtype()

PLpgSQL_type * plpgsql_parse_wordtype ( char *  ident)

Definition at line 1504 of file pl_comp.c.

1505{
1506 PLpgSQL_nsitem *nse;
1507
1508 /*
1509 * Do a lookup in the current namespace stack
1510 */
1511 nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1512 ident, NULL, NULL,
1513 NULL);
1514
1515 if (nse != NULL)
1516 {
1517 switch (nse->itemtype)
1518 {
1519 case PLPGSQL_NSTYPE_VAR:
1520 return ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1521 case PLPGSQL_NSTYPE_REC:
1522 return ((PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]))->datatype;
1523 default:
1524 break;
1525 }
1526 }
1527
1528 /* No match, complain */
1529 ereport(ERROR,
1530 (errcode(ERRCODE_UNDEFINED_OBJECT),
1531 errmsg("variable \"%s\" does not exist", ident)));
1532 return NULL; /* keep compiler quiet */
1533}

References ereport, errcode(), errmsg(), ERROR, ident, PLpgSQL_nsitem::itemno, PLpgSQL_nsitem::itemtype, plpgsql_Datums, plpgsql_ns_lookup(), plpgsql_ns_top(), PLPGSQL_NSTYPE_REC, and PLPGSQL_NSTYPE_VAR.

◆ plpgsql_parser_setup()

void plpgsql_parser_setup ( struct ParseState pstate,
PLpgSQL_expr expr 
)

Definition at line 975 of file pl_comp.c.

976{
980 /* no need to use p_coerce_param_hook */
981 pstate->p_ref_hook_state = expr;
982}
static Node * plpgsql_param_ref(ParseState *pstate, ParamRef *pref)
Definition: pl_comp.c:1046
static Node * plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref)
Definition: pl_comp.c:988
static Node * plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
Definition: pl_comp.c:1002
ParseParamRefHook p_paramref_hook
Definition: parse_node.h:256
PreParseColumnRefHook p_pre_columnref_hook
Definition: parse_node.h:254
PostParseColumnRefHook p_post_columnref_hook
Definition: parse_node.h:255

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

Referenced by exec_prepare_plan(), and plpgsql_estate_setup().

◆ plpgsql_post_column_ref()

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

Definition at line 1002 of file pl_comp.c.

1003{
1004 PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1005 Node *myvar;
1006
1008 return NULL; /* we already found there's no match */
1009
1010 if (expr->func->resolve_option == PLPGSQL_RESOLVE_COLUMN && var != NULL)
1011 return NULL; /* there's a table column, prefer that */
1012
1013 /*
1014 * If we find a record/row variable but can't match a field name, throw
1015 * error if there was no core resolution for the ColumnRef either. In
1016 * that situation, the reference is inevitably going to fail, and
1017 * complaining about the record/row variable is likely to be more on-point
1018 * than the core parser's error message. (It's too bad we don't have
1019 * access to transformColumnRef's internal crerr state here, as in case of
1020 * a conflict with a table name this could still be less than the most
1021 * helpful error message possible.)
1022 */
1023 myvar = resolve_column_ref(pstate, expr, cref, (var == NULL));
1024
1025 if (myvar != NULL && var != NULL)
1026 {
1027 /*
1028 * We could leave it to the core parser to throw this error, but we
1029 * can add a more useful detail message than the core could.
1030 */
1031 ereport(ERROR,
1032 (errcode(ERRCODE_AMBIGUOUS_COLUMN),
1033 errmsg("column reference \"%s\" is ambiguous",
1034 NameListToString(cref->fields)),
1035 errdetail("It could refer to either a PL/pgSQL variable or a table column."),
1036 parser_errposition(pstate, cref->location)));
1037 }
1038
1039 return myvar;
1040}
int errdetail(const char *fmt,...)
Definition: elog.c:1204
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
char * NameListToString(const List *names)
Definition: namespace.c:3594
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:106
static Node * resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr, ColumnRef *cref, bool error_if_no_field)
Definition: pl_comp.c:1073
@ PLPGSQL_RESOLVE_COLUMN
Definition: plpgsql.h:188
@ PLPGSQL_RESOLVE_VARIABLE
Definition: plpgsql.h:187
ParseLoc location
Definition: parsenodes.h:306
List * fields
Definition: parsenodes.h:305
PLpgSQL_resolve_option resolve_option
Definition: plpgsql.h:984

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

Referenced by plpgsql_parser_setup().

◆ plpgsql_pre_column_ref()

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

Definition at line 988 of file pl_comp.c.

989{
990 PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
991
993 return resolve_column_ref(pstate, expr, cref, false);
994 else
995 return NULL;
996}

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

Referenced by plpgsql_parser_setup().

◆ plpgsql_recognize_err_condition()

int plpgsql_recognize_err_condition ( const char *  condname,
bool  allow_sqlstate 
)

Definition at line 2107 of file pl_comp.c.

2108{
2109 int i;
2110
2111 if (allow_sqlstate)
2112 {
2113 if (strlen(condname) == 5 &&
2114 strspn(condname, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") == 5)
2115 return MAKE_SQLSTATE(condname[0],
2116 condname[1],
2117 condname[2],
2118 condname[3],
2119 condname[4]);
2120 }
2121
2122 for (i = 0; exception_label_map[i].label != NULL; i++)
2123 {
2124 if (strcmp(condname, exception_label_map[i].label) == 0)
2126 }
2127
2128 ereport(ERROR,
2129 (errcode(ERRCODE_UNDEFINED_OBJECT),
2130 errmsg("unrecognized exception condition \"%s\"",
2131 condname)));
2132 return 0; /* keep compiler quiet */
2133}
#define MAKE_SQLSTATE(ch1, ch2, ch3, ch4, ch5)
Definition: elog.h:56

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

Referenced by exec_stmt_raise().

◆ plpgsql_start_datums()

static void plpgsql_start_datums ( void  )
static

Definition at line 2190 of file pl_comp.c.

2191{
2192 datums_alloc = 128;
2193 plpgsql_nDatums = 0;
2194 /* This is short-lived, so needn't allocate in function's cxt */
2196 sizeof(PLpgSQL_datum *) * datums_alloc);
2197 /* datums_last tracks what's been seen by plpgsql_add_initdatums() */
2198 datums_last = 0;
2199}
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1256

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

Referenced by plpgsql_compile_callback(), and plpgsql_compile_inline().

◆ resolve_column_ref()

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

Definition at line 1073 of file pl_comp.c.

1075{
1076 PLpgSQL_execstate *estate;
1077 PLpgSQL_nsitem *nse;
1078 const char *name1;
1079 const char *name2 = NULL;
1080 const char *name3 = NULL;
1081 const char *colname = NULL;
1082 int nnames;
1083 int nnames_scalar = 0;
1084 int nnames_wholerow = 0;
1085 int nnames_field = 0;
1086
1087 /*
1088 * We use the function's current estate to resolve parameter data types.
1089 * This is really pretty bogus because there is no provision for updating
1090 * plans when those types change ...
1091 */
1092 estate = expr->func->cur_estate;
1093
1094 /*----------
1095 * The allowed syntaxes are:
1096 *
1097 * A Scalar variable reference, or whole-row record reference.
1098 * A.B Qualified scalar or whole-row reference, or field reference.
1099 * A.B.C Qualified record field reference.
1100 * A.* Whole-row record reference.
1101 * A.B.* Qualified whole-row record reference.
1102 *----------
1103 */
1104 switch (list_length(cref->fields))
1105 {
1106 case 1:
1107 {
1108 Node *field1 = (Node *) linitial(cref->fields);
1109
1110 name1 = strVal(field1);
1111 nnames_scalar = 1;
1112 nnames_wholerow = 1;
1113 break;
1114 }
1115 case 2:
1116 {
1117 Node *field1 = (Node *) linitial(cref->fields);
1118 Node *field2 = (Node *) lsecond(cref->fields);
1119
1120 name1 = strVal(field1);
1121
1122 /* Whole-row reference? */
1123 if (IsA(field2, A_Star))
1124 {
1125 /* Set name2 to prevent matches to scalar variables */
1126 name2 = "*";
1127 nnames_wholerow = 1;
1128 break;
1129 }
1130
1131 name2 = strVal(field2);
1132 colname = name2;
1133 nnames_scalar = 2;
1134 nnames_wholerow = 2;
1135 nnames_field = 1;
1136 break;
1137 }
1138 case 3:
1139 {
1140 Node *field1 = (Node *) linitial(cref->fields);
1141 Node *field2 = (Node *) lsecond(cref->fields);
1142 Node *field3 = (Node *) lthird(cref->fields);
1143
1144 name1 = strVal(field1);
1145 name2 = strVal(field2);
1146
1147 /* Whole-row reference? */
1148 if (IsA(field3, A_Star))
1149 {
1150 /* Set name3 to prevent matches to scalar variables */
1151 name3 = "*";
1152 nnames_wholerow = 2;
1153 break;
1154 }
1155
1156 name3 = strVal(field3);
1157 colname = name3;
1158 nnames_field = 2;
1159 break;
1160 }
1161 default:
1162 /* too many names, ignore */
1163 return NULL;
1164 }
1165
1166 nse = plpgsql_ns_lookup(expr->ns, false,
1167 name1, name2, name3,
1168 &nnames);
1169
1170 if (nse == NULL)
1171 return NULL; /* name not known to plpgsql */
1172
1173 switch (nse->itemtype)
1174 {
1175 case PLPGSQL_NSTYPE_VAR:
1176 if (nnames == nnames_scalar)
1177 return make_datum_param(expr, nse->itemno, cref->location);
1178 break;
1179 case PLPGSQL_NSTYPE_REC:
1180 if (nnames == nnames_wholerow)
1181 return make_datum_param(expr, nse->itemno, cref->location);
1182 if (nnames == nnames_field)
1183 {
1184 /* colname could be a field in this record */
1185 PLpgSQL_rec *rec = (PLpgSQL_rec *) estate->datums[nse->itemno];
1186 int i;
1187
1188 /* search for a datum referencing this field */
1189 i = rec->firstfield;
1190 while (i >= 0)
1191 {
1192 PLpgSQL_recfield *fld = (PLpgSQL_recfield *) estate->datums[i];
1193
1195 fld->recparentno == nse->itemno);
1196 if (strcmp(fld->fieldname, colname) == 0)
1197 {
1198 return make_datum_param(expr, i, cref->location);
1199 }
1200 i = fld->nextfield;
1201 }
1202
1203 /*
1204 * We should not get here, because a RECFIELD datum should
1205 * have been built at parse time for every possible qualified
1206 * reference to fields of this record. But if we do, handle
1207 * it like field-not-found: throw error or return NULL.
1208 */
1209 if (error_if_no_field)
1210 ereport(ERROR,
1211 (errcode(ERRCODE_UNDEFINED_COLUMN),
1212 errmsg("record \"%s\" has no field \"%s\"",
1213 (nnames_field == 1) ? name1 : name2,
1214 colname),
1215 parser_errposition(pstate, cref->location)));
1216 }
1217 break;
1218 default:
1219 elog(ERROR, "unrecognized plpgsql itemtype: %d", nse->itemtype);
1220 }
1221
1222 /* Name format doesn't match the plpgsql variable type */
1223 return NULL;
1224}
#define IsA(nodeptr, _type_)
Definition: nodes.h:164
while(p+4<=pend)
#define lthird(l)
Definition: pg_list.h:188

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

Referenced by plpgsql_post_column_ref(), and plpgsql_pre_column_ref().

Variable Documentation

◆ datums_alloc

int datums_alloc
static

Definition at line 41 of file pl_comp.c.

Referenced by plpgsql_adddatum(), and plpgsql_start_datums().

◆ datums_last

int datums_last
static

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

Referenced by plpgsql_parse_err_condition(), and plpgsql_recognize_err_condition().

◆ plpgsql_check_syntax

bool plpgsql_check_syntax = false

Definition at line 48 of file pl_comp.c.

Referenced by plpgsql_compile_callback(), and plpgsql_compile_inline().

◆ plpgsql_compile_tmp_cxt

◆ plpgsql_curr_compile

PLpgSQL_function* plpgsql_curr_compile

Definition at line 50 of file pl_comp.c.

Referenced by plpgsql_compile_callback(), and plpgsql_compile_inline().

◆ plpgsql_Datums

◆ plpgsql_DumpExecTree

bool plpgsql_DumpExecTree = false

Definition at line 47 of file pl_comp.c.

Referenced by plpgsql_compile_callback(), and plpgsql_compile_inline().

◆ plpgsql_error_funcname

char* plpgsql_error_funcname

◆ plpgsql_nDatums

int plpgsql_nDatums