Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * pl_comp.c - Compiler part of the PL/pgSQL
4 : * procedural language
5 : *
6 : * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/pl/plpgsql/src/pl_comp.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 :
16 : #include "postgres.h"
17 :
18 : #include <ctype.h>
19 :
20 : #include "access/htup_details.h"
21 : #include "catalog/namespace.h"
22 : #include "catalog/pg_proc.h"
23 : #include "catalog/pg_type.h"
24 : #include "funcapi.h"
25 : #include "nodes/makefuncs.h"
26 : #include "parser/parse_node.h"
27 : #include "plpgsql.h"
28 : #include "utils/builtins.h"
29 : #include "utils/fmgroids.h"
30 : #include "utils/guc.h"
31 : #include "utils/lsyscache.h"
32 : #include "utils/memutils.h"
33 : #include "utils/regproc.h"
34 : #include "utils/syscache.h"
35 : #include "utils/typcache.h"
36 :
37 : /* ----------
38 : * Our own local and global variables
39 : * ----------
40 : */
41 : static int datums_alloc;
42 : int plpgsql_nDatums;
43 : PLpgSQL_datum **plpgsql_Datums;
44 : static int datums_last;
45 :
46 : char *plpgsql_error_funcname;
47 : bool plpgsql_DumpExecTree = false;
48 : bool plpgsql_check_syntax = false;
49 :
50 : PLpgSQL_function *plpgsql_curr_compile;
51 :
52 : /* A context appropriate for short-term allocs during compilation */
53 : MemoryContext plpgsql_compile_tmp_cxt;
54 :
55 : /* ----------
56 : * Lookup table for EXCEPTION condition names
57 : * ----------
58 : */
59 : typedef struct
60 : {
61 : const char *label;
62 : int sqlerrstate;
63 : } ExceptionLabelMap;
64 :
65 : static const ExceptionLabelMap exception_label_map[] = {
66 : #include "plerrcodes.h"
67 : {NULL, 0}
68 : };
69 :
70 :
71 : /* ----------
72 : * static prototypes
73 : * ----------
74 : */
75 : static void plpgsql_compile_callback(FunctionCallInfo fcinfo,
76 : HeapTuple procTup,
77 : const CachedFunctionHashKey *hashkey,
78 : CachedFunction *cfunc,
79 : bool forValidator);
80 : static void plpgsql_compile_error_callback(void *arg);
81 : static void add_parameter_name(PLpgSQL_nsitem_type itemtype, int itemno, const char *name);
82 : static void add_dummy_return(PLpgSQL_function *function);
83 : static Node *plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref);
84 : static Node *plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var);
85 : static Node *plpgsql_param_ref(ParseState *pstate, ParamRef *pref);
86 : static Node *resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr,
87 : ColumnRef *cref, bool error_if_no_field);
88 : static Node *make_datum_param(PLpgSQL_expr *expr, int dno, int location);
89 : static PLpgSQL_row *build_row_from_vars(PLpgSQL_variable **vars, int numvars);
90 : static PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod,
91 : Oid collation, TypeName *origtypname);
92 : static void plpgsql_start_datums(void);
93 : static void plpgsql_finish_datums(PLpgSQL_function *function);
94 :
95 : /* ----------
96 : * plpgsql_compile Make an execution tree for a PL/pgSQL function.
97 : *
98 : * If forValidator is true, we're only compiling for validation purposes,
99 : * and so some checks are skipped.
100 : *
101 : * Note: it's important for this to fall through quickly if the function
102 : * has already been compiled.
103 : * ----------
104 : */
105 : PLpgSQL_function *
106 89882 : plpgsql_compile(FunctionCallInfo fcinfo, bool forValidator)
107 : {
108 : PLpgSQL_function *function;
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 : */
118 : function = (PLpgSQL_function *)
119 89882 : cached_function_compile(fcinfo,
120 89882 : fcinfo->flinfo->fn_extra,
121 : plpgsql_compile_callback,
122 : plpgsql_delete_callback,
123 : sizeof(PLpgSQL_function),
124 : false,
125 : forValidator);
126 :
127 : /*
128 : * Save pointer in FmgrInfo to avoid search on subsequent calls
129 : */
130 89760 : fcinfo->flinfo->fn_extra = function;
131 :
132 : /*
133 : * Finally return the compiled function
134 : */
135 89760 : return function;
136 : }
137 :
138 : struct compile_error_callback_arg
139 : {
140 : const char *proc_source;
141 : yyscan_t yyscanner;
142 : };
143 :
144 : /*
145 : * This is the slow part of plpgsql_compile().
146 : *
147 : * The passed-in "cfunc" struct is expected to be zeroes, except
148 : * for the CachedFunction fields, which we don't touch here.
149 : *
150 : * While compiling a function, the CurrentMemoryContext is the
151 : * per-function memory context of the function we are compiling. That
152 : * means a palloc() will allocate storage with the same lifetime as
153 : * the function itself.
154 : *
155 : * Because palloc()'d storage will not be immediately freed, temporary
156 : * allocations should either be performed in a short-lived memory
157 : * context or explicitly pfree'd. Since not all backend functions are
158 : * careful about pfree'ing their allocations, it is also wise to
159 : * switch into a short-term context before calling into the
160 : * backend. An appropriate context for performing short-term
161 : * allocations is the plpgsql_compile_tmp_cxt.
162 : *
163 : * NB: this code is not re-entrant. We assume that nothing we do here could
164 : * result in the invocation of another plpgsql function.
165 : */
166 : static void
167 8282 : plpgsql_compile_callback(FunctionCallInfo fcinfo,
168 : HeapTuple procTup,
169 : const CachedFunctionHashKey *hashkey,
170 : CachedFunction *cfunc,
171 : bool forValidator)
172 : {
173 8282 : PLpgSQL_function *function = (PLpgSQL_function *) cfunc;
174 8282 : Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
175 8282 : bool is_dml_trigger = CALLED_AS_TRIGGER(fcinfo);
176 8282 : bool is_event_trigger = CALLED_AS_EVENT_TRIGGER(fcinfo);
177 : yyscan_t scanner;
178 : Datum prosrcdatum;
179 : char *proc_source;
180 : char *proc_signature;
181 : HeapTuple typeTup;
182 : Form_pg_type typeStruct;
183 : PLpgSQL_variable *var;
184 : PLpgSQL_rec *rec;
185 : int i;
186 : struct compile_error_callback_arg cbarg;
187 : ErrorContextCallback plerrcontext;
188 : int parse_rc;
189 : Oid rettypeid;
190 : int numargs;
191 8282 : int num_in_args = 0;
192 8282 : int num_out_args = 0;
193 : Oid *argtypes;
194 : char **argnames;
195 : char *argmodes;
196 8282 : int *in_arg_varnos = NULL;
197 : PLpgSQL_variable **out_arg_variables;
198 : MemoryContext func_cxt;
199 :
200 : /*
201 : * Setup the scanner input and error info.
202 : */
203 8282 : prosrcdatum = SysCacheGetAttrNotNull(PROCOID, procTup, Anum_pg_proc_prosrc);
204 8282 : proc_source = TextDatumGetCString(prosrcdatum);
205 8282 : scanner = plpgsql_scanner_init(proc_source);
206 :
207 8282 : plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname));
208 :
209 : /*
210 : * Setup error traceback support for ereport()
211 : */
212 8282 : cbarg.proc_source = forValidator ? proc_source : NULL;
213 8282 : cbarg.yyscanner = scanner;
214 8282 : plerrcontext.callback = plpgsql_compile_error_callback;
215 8282 : plerrcontext.arg = &cbarg;
216 8282 : plerrcontext.previous = error_context_stack;
217 8282 : error_context_stack = &plerrcontext;
218 :
219 : /*
220 : * Do extra syntax checks when validating the function definition. We skip
221 : * this when actually compiling functions for execution, for performance
222 : * reasons.
223 : */
224 8282 : plpgsql_check_syntax = forValidator;
225 8282 : plpgsql_curr_compile = function;
226 :
227 : /* format_procedure leaks memory, so run it in temp context */
228 8282 : proc_signature = format_procedure(fcinfo->flinfo->fn_oid);
229 :
230 : /*
231 : * All the permanent output of compilation (e.g. parse tree) is kept in a
232 : * per-function memory context, so it can be reclaimed easily.
233 : *
234 : * While the func_cxt needs to be long-lived, we initially make it a child
235 : * of the assumed-short-lived caller's context, and reparent it under
236 : * CacheMemoryContext only upon success. This arrangement avoids memory
237 : * leakage during compilation of a faulty function.
238 : */
239 8282 : func_cxt = AllocSetContextCreate(CurrentMemoryContext,
240 : "PL/pgSQL function",
241 : ALLOCSET_DEFAULT_SIZES);
242 8282 : plpgsql_compile_tmp_cxt = MemoryContextSwitchTo(func_cxt);
243 :
244 8282 : function->fn_signature = pstrdup(proc_signature);
245 8282 : MemoryContextSetIdentifier(func_cxt, function->fn_signature);
246 8282 : function->fn_oid = fcinfo->flinfo->fn_oid;
247 8282 : function->fn_input_collation = fcinfo->fncollation;
248 8282 : function->fn_cxt = func_cxt;
249 8282 : function->out_param_varno = -1; /* set up for no OUT param */
250 8282 : function->resolve_option = plpgsql_variable_conflict;
251 8282 : function->print_strict_params = plpgsql_print_strict_params;
252 : /* only promote extra warnings and errors at CREATE FUNCTION time */
253 8282 : function->extra_warnings = forValidator ? plpgsql_extra_warnings : 0;
254 8282 : function->extra_errors = forValidator ? plpgsql_extra_errors : 0;
255 :
256 8282 : if (is_dml_trigger)
257 3828 : function->fn_is_trigger = PLPGSQL_DML_TRIGGER;
258 4454 : else if (is_event_trigger)
259 430 : function->fn_is_trigger = PLPGSQL_EVENT_TRIGGER;
260 : else
261 4024 : function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
262 :
263 8282 : function->fn_prokind = procStruct->prokind;
264 :
265 8282 : function->nstatements = 0;
266 8282 : function->requires_procedure_resowner = false;
267 8282 : function->has_exception_block = false;
268 :
269 : /*
270 : * Initialize the compiler, particularly the namespace stack. The
271 : * outermost namespace contains function parameters and other special
272 : * variables (such as FOUND), and is named after the function itself.
273 : */
274 8282 : plpgsql_ns_init();
275 8282 : plpgsql_ns_push(NameStr(procStruct->proname), PLPGSQL_LABEL_BLOCK);
276 8282 : plpgsql_DumpExecTree = false;
277 8282 : plpgsql_start_datums();
278 :
279 8282 : switch (function->fn_is_trigger)
280 : {
281 4024 : case PLPGSQL_NOT_TRIGGER:
282 :
283 : /*
284 : * Fetch info about the procedure's parameters. Allocations aren't
285 : * needed permanently, so make them in tmp cxt.
286 : *
287 : * We also need to resolve any polymorphic input or output
288 : * argument types. In validation mode we won't be able to, so we
289 : * arbitrarily assume we are dealing with integers.
290 : */
291 4024 : MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
292 :
293 4024 : numargs = get_func_arg_info(procTup,
294 : &argtypes, &argnames, &argmodes);
295 :
296 4024 : cfunc_resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
297 4024 : fcinfo->flinfo->fn_expr,
298 : forValidator,
299 : plpgsql_error_funcname);
300 :
301 4024 : in_arg_varnos = palloc_array(int, numargs);
302 4024 : out_arg_variables = palloc_array(PLpgSQL_variable *, numargs);
303 :
304 4024 : MemoryContextSwitchTo(func_cxt);
305 :
306 : /*
307 : * Create the variables for the procedure's parameters.
308 : */
309 9006 : for (i = 0; i < numargs; i++)
310 : {
311 : char buf[32];
312 4988 : Oid argtypeid = argtypes[i];
313 4988 : char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
314 : PLpgSQL_type *argdtype;
315 : PLpgSQL_variable *argvariable;
316 : PLpgSQL_nsitem_type argitemtype;
317 :
318 : /* Create $n name for variable */
319 4988 : snprintf(buf, sizeof(buf), "$%d", i + 1);
320 :
321 : /* Create datatype info */
322 4988 : argdtype = plpgsql_build_datatype(argtypeid,
323 : -1,
324 : function->fn_input_collation,
325 : NULL);
326 :
327 : /* Disallow pseudotype argument */
328 : /* (note we already replaced polymorphic types) */
329 : /* (build_variable would do this, but wrong message) */
330 4988 : if (argdtype->ttype == PLPGSQL_TTYPE_PSEUDO)
331 6 : ereport(ERROR,
332 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
333 : errmsg("PL/pgSQL functions cannot accept type %s",
334 : format_type_be(argtypeid))));
335 :
336 : /*
337 : * Build variable and add to datum list. If there's a name
338 : * for the argument, use that as refname, else use $n name.
339 : */
340 8616 : argvariable = plpgsql_build_variable((argnames &&
341 3634 : argnames[i][0] != '\0') ?
342 3610 : argnames[i] : buf,
343 : 0, argdtype, false);
344 :
345 4982 : if (argvariable->dtype == PLPGSQL_DTYPE_VAR)
346 : {
347 4900 : argitemtype = PLPGSQL_NSTYPE_VAR;
348 : }
349 : else
350 : {
351 : Assert(argvariable->dtype == PLPGSQL_DTYPE_REC);
352 82 : argitemtype = PLPGSQL_NSTYPE_REC;
353 : }
354 :
355 : /* Remember arguments in appropriate arrays */
356 4982 : if (argmode == PROARGMODE_IN ||
357 450 : argmode == PROARGMODE_INOUT ||
358 : argmode == PROARGMODE_VARIADIC)
359 4546 : in_arg_varnos[num_in_args++] = argvariable->dno;
360 4982 : if (argmode == PROARGMODE_OUT ||
361 4654 : argmode == PROARGMODE_INOUT ||
362 : argmode == PROARGMODE_TABLE)
363 484 : out_arg_variables[num_out_args++] = argvariable;
364 :
365 : /* Add to namespace under the $n name */
366 4982 : add_parameter_name(argitemtype, argvariable->dno, buf);
367 :
368 : /* If there's a name for the argument, make an alias */
369 4982 : if (argnames && argnames[i][0] != '\0')
370 3610 : add_parameter_name(argitemtype, argvariable->dno,
371 3610 : argnames[i]);
372 : }
373 :
374 : /*
375 : * If there's just one OUT parameter, out_param_varno points
376 : * directly to it. If there's more than one, build a row that
377 : * holds all of them. Procedures return a row even for one OUT
378 : * parameter.
379 : */
380 4018 : if (num_out_args > 1 ||
381 78 : (num_out_args == 1 && function->fn_prokind == PROKIND_PROCEDURE))
382 192 : {
383 192 : PLpgSQL_row *row = build_row_from_vars(out_arg_variables,
384 : num_out_args);
385 :
386 192 : plpgsql_adddatum((PLpgSQL_datum *) row);
387 192 : function->out_param_varno = row->dno;
388 : }
389 3826 : else if (num_out_args == 1)
390 60 : function->out_param_varno = out_arg_variables[0]->dno;
391 :
392 : /*
393 : * Check for a polymorphic returntype. If found, use the actual
394 : * returntype type from the caller's FuncExpr node, if we have
395 : * one. (In validation mode we arbitrarily assume we are dealing
396 : * with integers.)
397 : *
398 : * Note: errcode is FEATURE_NOT_SUPPORTED because it should always
399 : * work; if it doesn't we're in some context that fails to make
400 : * the info available.
401 : */
402 4018 : rettypeid = procStruct->prorettype;
403 4018 : if (IsPolymorphicType(rettypeid))
404 : {
405 144 : if (forValidator)
406 : {
407 72 : if (rettypeid == ANYARRAYOID ||
408 : rettypeid == ANYCOMPATIBLEARRAYOID)
409 48 : rettypeid = INT4ARRAYOID;
410 24 : else if (rettypeid == ANYRANGEOID ||
411 : rettypeid == ANYCOMPATIBLERANGEOID)
412 6 : rettypeid = INT4RANGEOID;
413 18 : else if (rettypeid == ANYMULTIRANGEOID)
414 6 : rettypeid = INT4MULTIRANGEOID;
415 : else /* ANYELEMENT or ANYNONARRAY or ANYCOMPATIBLE */
416 12 : rettypeid = INT4OID;
417 : /* XXX what could we use for ANYENUM? */
418 : }
419 : else
420 : {
421 72 : rettypeid = get_fn_expr_rettype(fcinfo->flinfo);
422 72 : if (!OidIsValid(rettypeid))
423 0 : ereport(ERROR,
424 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
425 : errmsg("could not determine actual return type "
426 : "for polymorphic function \"%s\"",
427 : plpgsql_error_funcname)));
428 : }
429 : }
430 :
431 : /*
432 : * Normal function has a defined returntype
433 : */
434 4018 : function->fn_rettype = rettypeid;
435 4018 : function->fn_retset = procStruct->proretset;
436 :
437 : /*
438 : * Lookup the function's return type
439 : */
440 4018 : typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(rettypeid));
441 4018 : if (!HeapTupleIsValid(typeTup))
442 0 : elog(ERROR, "cache lookup failed for type %u", rettypeid);
443 4018 : typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
444 :
445 : /* Disallow pseudotype result, except VOID or RECORD */
446 : /* (note we already replaced polymorphic types) */
447 4018 : if (typeStruct->typtype == TYPTYPE_PSEUDO)
448 : {
449 1510 : if (rettypeid == VOIDOID ||
450 : rettypeid == RECORDOID)
451 : /* okay */ ;
452 6 : else if (rettypeid == TRIGGEROID || rettypeid == EVENT_TRIGGEROID)
453 6 : ereport(ERROR,
454 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
455 : errmsg("trigger functions can only be called as triggers")));
456 : else
457 0 : ereport(ERROR,
458 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
459 : errmsg("PL/pgSQL functions cannot return type %s",
460 : format_type_be(rettypeid))));
461 : }
462 :
463 4012 : function->fn_retistuple = type_is_rowtype(rettypeid);
464 4012 : function->fn_retisdomain = (typeStruct->typtype == TYPTYPE_DOMAIN);
465 4012 : function->fn_retbyval = typeStruct->typbyval;
466 4012 : function->fn_rettyplen = typeStruct->typlen;
467 :
468 : /*
469 : * install $0 reference, but only for polymorphic return types,
470 : * and not when the return is specified through an output
471 : * parameter.
472 : */
473 4012 : if (IsPolymorphicType(procStruct->prorettype) &&
474 : num_out_args == 0)
475 : {
476 144 : (void) plpgsql_build_variable("$0", 0,
477 : build_datatype(typeTup,
478 : -1,
479 : function->fn_input_collation,
480 : NULL),
481 : true);
482 : }
483 :
484 4012 : ReleaseSysCache(typeTup);
485 4012 : break;
486 :
487 3828 : case PLPGSQL_DML_TRIGGER:
488 : /* Trigger procedure's return type is unknown yet */
489 3828 : function->fn_rettype = InvalidOid;
490 3828 : function->fn_retbyval = false;
491 3828 : function->fn_retistuple = true;
492 3828 : function->fn_retisdomain = false;
493 3828 : function->fn_retset = false;
494 :
495 : /* shouldn't be any declared arguments */
496 3828 : if (procStruct->pronargs != 0)
497 0 : ereport(ERROR,
498 : (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
499 : errmsg("trigger functions cannot have declared arguments"),
500 : errhint("The arguments of the trigger can be accessed through TG_NARGS and TG_ARGV instead.")));
501 :
502 : /* Add the record for referencing NEW ROW */
503 3828 : rec = plpgsql_build_record("new", 0, NULL, RECORDOID, true);
504 3828 : function->new_varno = rec->dno;
505 :
506 : /* Add the record for referencing OLD ROW */
507 3828 : rec = plpgsql_build_record("old", 0, NULL, RECORDOID, true);
508 3828 : function->old_varno = rec->dno;
509 :
510 : /* Add the variable tg_name */
511 3828 : var = plpgsql_build_variable("tg_name", 0,
512 : plpgsql_build_datatype(NAMEOID,
513 : -1,
514 : function->fn_input_collation,
515 : NULL),
516 : true);
517 : Assert(var->dtype == PLPGSQL_DTYPE_VAR);
518 3828 : var->dtype = PLPGSQL_DTYPE_PROMISE;
519 3828 : ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_NAME;
520 :
521 : /* Add the variable tg_when */
522 3828 : var = plpgsql_build_variable("tg_when", 0,
523 : plpgsql_build_datatype(TEXTOID,
524 : -1,
525 : function->fn_input_collation,
526 : NULL),
527 : true);
528 : Assert(var->dtype == PLPGSQL_DTYPE_VAR);
529 3828 : var->dtype = PLPGSQL_DTYPE_PROMISE;
530 3828 : ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_WHEN;
531 :
532 : /* Add the variable tg_level */
533 3828 : var = plpgsql_build_variable("tg_level", 0,
534 : plpgsql_build_datatype(TEXTOID,
535 : -1,
536 : function->fn_input_collation,
537 : NULL),
538 : true);
539 : Assert(var->dtype == PLPGSQL_DTYPE_VAR);
540 3828 : var->dtype = PLPGSQL_DTYPE_PROMISE;
541 3828 : ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_LEVEL;
542 :
543 : /* Add the variable tg_op */
544 3828 : var = plpgsql_build_variable("tg_op", 0,
545 : plpgsql_build_datatype(TEXTOID,
546 : -1,
547 : function->fn_input_collation,
548 : NULL),
549 : true);
550 : Assert(var->dtype == PLPGSQL_DTYPE_VAR);
551 3828 : var->dtype = PLPGSQL_DTYPE_PROMISE;
552 3828 : ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_OP;
553 :
554 : /* Add the variable tg_relid */
555 3828 : var = plpgsql_build_variable("tg_relid", 0,
556 : plpgsql_build_datatype(OIDOID,
557 : -1,
558 : InvalidOid,
559 : NULL),
560 : true);
561 : Assert(var->dtype == PLPGSQL_DTYPE_VAR);
562 3828 : var->dtype = PLPGSQL_DTYPE_PROMISE;
563 3828 : ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_RELID;
564 :
565 : /* Add the variable tg_relname */
566 3828 : var = plpgsql_build_variable("tg_relname", 0,
567 : plpgsql_build_datatype(NAMEOID,
568 : -1,
569 : function->fn_input_collation,
570 : NULL),
571 : true);
572 : Assert(var->dtype == PLPGSQL_DTYPE_VAR);
573 3828 : var->dtype = PLPGSQL_DTYPE_PROMISE;
574 3828 : ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_NAME;
575 :
576 : /* tg_table_name is now preferred to tg_relname */
577 3828 : var = plpgsql_build_variable("tg_table_name", 0,
578 : plpgsql_build_datatype(NAMEOID,
579 : -1,
580 : function->fn_input_collation,
581 : NULL),
582 : true);
583 : Assert(var->dtype == PLPGSQL_DTYPE_VAR);
584 3828 : var->dtype = PLPGSQL_DTYPE_PROMISE;
585 3828 : ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_NAME;
586 :
587 : /* add the variable tg_table_schema */
588 3828 : var = plpgsql_build_variable("tg_table_schema", 0,
589 : plpgsql_build_datatype(NAMEOID,
590 : -1,
591 : function->fn_input_collation,
592 : NULL),
593 : true);
594 : Assert(var->dtype == PLPGSQL_DTYPE_VAR);
595 3828 : var->dtype = PLPGSQL_DTYPE_PROMISE;
596 3828 : ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_SCHEMA;
597 :
598 : /* Add the variable tg_nargs */
599 3828 : var = plpgsql_build_variable("tg_nargs", 0,
600 : plpgsql_build_datatype(INT4OID,
601 : -1,
602 : InvalidOid,
603 : NULL),
604 : true);
605 : Assert(var->dtype == PLPGSQL_DTYPE_VAR);
606 3828 : var->dtype = PLPGSQL_DTYPE_PROMISE;
607 3828 : ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_NARGS;
608 :
609 : /* Add the variable tg_argv */
610 3828 : var = plpgsql_build_variable("tg_argv", 0,
611 : plpgsql_build_datatype(TEXTARRAYOID,
612 : -1,
613 : function->fn_input_collation,
614 : NULL),
615 : true);
616 : Assert(var->dtype == PLPGSQL_DTYPE_VAR);
617 3828 : var->dtype = PLPGSQL_DTYPE_PROMISE;
618 3828 : ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_ARGV;
619 :
620 3828 : break;
621 :
622 430 : case PLPGSQL_EVENT_TRIGGER:
623 430 : function->fn_rettype = VOIDOID;
624 430 : function->fn_retbyval = false;
625 430 : function->fn_retistuple = true;
626 430 : function->fn_retisdomain = false;
627 430 : function->fn_retset = false;
628 :
629 : /* shouldn't be any declared arguments */
630 430 : if (procStruct->pronargs != 0)
631 6 : ereport(ERROR,
632 : (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
633 : errmsg("event trigger functions cannot have declared arguments")));
634 :
635 : /* Add the variable tg_event */
636 424 : var = plpgsql_build_variable("tg_event", 0,
637 : plpgsql_build_datatype(TEXTOID,
638 : -1,
639 : function->fn_input_collation,
640 : NULL),
641 : true);
642 : Assert(var->dtype == PLPGSQL_DTYPE_VAR);
643 424 : var->dtype = PLPGSQL_DTYPE_PROMISE;
644 424 : ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_EVENT;
645 :
646 : /* Add the variable tg_tag */
647 424 : var = plpgsql_build_variable("tg_tag", 0,
648 : plpgsql_build_datatype(TEXTOID,
649 : -1,
650 : function->fn_input_collation,
651 : NULL),
652 : true);
653 : Assert(var->dtype == PLPGSQL_DTYPE_VAR);
654 424 : var->dtype = PLPGSQL_DTYPE_PROMISE;
655 424 : ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TAG;
656 :
657 424 : break;
658 :
659 0 : default:
660 0 : elog(ERROR, "unrecognized function typecode: %d",
661 : (int) function->fn_is_trigger);
662 : break;
663 : }
664 :
665 : /* Remember if function is STABLE/IMMUTABLE */
666 8264 : function->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
667 :
668 : /*
669 : * Create the magic FOUND variable.
670 : */
671 8264 : var = plpgsql_build_variable("found", 0,
672 : plpgsql_build_datatype(BOOLOID,
673 : -1,
674 : InvalidOid,
675 : NULL),
676 : true);
677 8264 : function->found_varno = var->dno;
678 :
679 : /*
680 : * Now parse the function's text
681 : */
682 8264 : parse_rc = plpgsql_yyparse(&function->action, scanner);
683 8160 : if (parse_rc != 0)
684 0 : elog(ERROR, "plpgsql parser returned %d", parse_rc);
685 :
686 8160 : plpgsql_scanner_finish(scanner);
687 8160 : pfree(proc_source);
688 :
689 : /*
690 : * If it has OUT parameters or returns VOID or returns a set, we allow
691 : * control to fall off the end without an explicit RETURN statement. The
692 : * easiest way to implement this is to add a RETURN statement to the end
693 : * of the statement list during parsing.
694 : */
695 8160 : if (num_out_args > 0 || function->fn_rettype == VOIDOID ||
696 6294 : function->fn_retset)
697 2188 : add_dummy_return(function);
698 :
699 : /*
700 : * Complete the function's info
701 : */
702 8160 : function->fn_nargs = procStruct->pronargs;
703 12674 : for (i = 0; i < function->fn_nargs; i++)
704 4514 : function->fn_argvarnos[i] = in_arg_varnos[i];
705 :
706 8160 : plpgsql_finish_datums(function);
707 :
708 8160 : if (function->has_exception_block)
709 358 : plpgsql_mark_local_assignment_targets(function);
710 :
711 : /* Debug dump for completed functions */
712 8160 : if (plpgsql_DumpExecTree)
713 0 : plpgsql_dumptree(function);
714 :
715 : /*
716 : * All is well, so make the func_cxt long-lived
717 : */
718 8160 : MemoryContextSetParent(func_cxt, CacheMemoryContext);
719 :
720 : /*
721 : * Pop the error context stack
722 : */
723 8160 : error_context_stack = plerrcontext.previous;
724 8160 : plpgsql_error_funcname = NULL;
725 :
726 8160 : plpgsql_check_syntax = false;
727 :
728 8160 : MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
729 8160 : plpgsql_compile_tmp_cxt = NULL;
730 8160 : }
731 :
732 : /* ----------
733 : * plpgsql_compile_inline Make an execution tree for an anonymous code block.
734 : *
735 : * Note: this is generally parallel to plpgsql_compile_callback(); is it worth
736 : * trying to merge the two?
737 : *
738 : * Note: we assume the block will be thrown away so there is no need to build
739 : * persistent data structures.
740 : * ----------
741 : */
742 : PLpgSQL_function *
743 1514 : plpgsql_compile_inline(char *proc_source)
744 : {
745 : yyscan_t scanner;
746 1514 : char *func_name = "inline_code_block";
747 : PLpgSQL_function *function;
748 : struct compile_error_callback_arg cbarg;
749 : ErrorContextCallback plerrcontext;
750 : PLpgSQL_variable *var;
751 : int parse_rc;
752 : MemoryContext func_cxt;
753 :
754 : /*
755 : * Setup the scanner input and error info.
756 : */
757 1514 : scanner = plpgsql_scanner_init(proc_source);
758 :
759 1514 : plpgsql_error_funcname = func_name;
760 :
761 : /*
762 : * Setup error traceback support for ereport()
763 : */
764 1514 : cbarg.proc_source = proc_source;
765 1514 : cbarg.yyscanner = scanner;
766 1514 : plerrcontext.callback = plpgsql_compile_error_callback;
767 1514 : plerrcontext.arg = &cbarg;
768 1514 : plerrcontext.previous = error_context_stack;
769 1514 : error_context_stack = &plerrcontext;
770 :
771 : /* Do extra syntax checking if check_function_bodies is on */
772 1514 : plpgsql_check_syntax = check_function_bodies;
773 :
774 : /* Function struct does not live past current statement */
775 1514 : function = palloc0_object(PLpgSQL_function);
776 :
777 1514 : plpgsql_curr_compile = function;
778 :
779 : /*
780 : * All the rest of the compile-time storage (e.g. parse tree) is kept in
781 : * its own memory context, so it can be reclaimed easily.
782 : */
783 1514 : func_cxt = AllocSetContextCreate(CurrentMemoryContext,
784 : "PL/pgSQL inline code context",
785 : ALLOCSET_DEFAULT_SIZES);
786 1514 : plpgsql_compile_tmp_cxt = MemoryContextSwitchTo(func_cxt);
787 :
788 1514 : function->fn_signature = pstrdup(func_name);
789 1514 : function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
790 1514 : function->fn_input_collation = InvalidOid;
791 1514 : function->fn_cxt = func_cxt;
792 1514 : function->out_param_varno = -1; /* set up for no OUT param */
793 1514 : function->resolve_option = plpgsql_variable_conflict;
794 1514 : function->print_strict_params = plpgsql_print_strict_params;
795 :
796 : /*
797 : * don't do extra validation for inline code as we don't want to add spam
798 : * at runtime
799 : */
800 1514 : function->extra_warnings = 0;
801 1514 : function->extra_errors = 0;
802 :
803 1514 : function->nstatements = 0;
804 1514 : function->requires_procedure_resowner = false;
805 1514 : function->has_exception_block = false;
806 :
807 1514 : plpgsql_ns_init();
808 1514 : plpgsql_ns_push(func_name, PLPGSQL_LABEL_BLOCK);
809 1514 : plpgsql_DumpExecTree = false;
810 1514 : plpgsql_start_datums();
811 :
812 : /* Set up as though in a function returning VOID */
813 1514 : function->fn_rettype = VOIDOID;
814 1514 : function->fn_retset = false;
815 1514 : function->fn_retistuple = false;
816 1514 : function->fn_retisdomain = false;
817 1514 : function->fn_prokind = PROKIND_FUNCTION;
818 : /* a bit of hardwired knowledge about type VOID here */
819 1514 : function->fn_retbyval = true;
820 1514 : function->fn_rettyplen = sizeof(int32);
821 :
822 : /*
823 : * Remember if function is STABLE/IMMUTABLE. XXX would it be better to
824 : * set this true inside a read-only transaction? Not clear.
825 : */
826 1514 : function->fn_readonly = false;
827 :
828 : /*
829 : * Create the magic FOUND variable.
830 : */
831 1514 : var = plpgsql_build_variable("found", 0,
832 : plpgsql_build_datatype(BOOLOID,
833 : -1,
834 : InvalidOid,
835 : NULL),
836 : true);
837 1514 : function->found_varno = var->dno;
838 :
839 : /*
840 : * Now parse the function's text
841 : */
842 1514 : parse_rc = plpgsql_yyparse(&function->action, scanner);
843 1458 : if (parse_rc != 0)
844 0 : elog(ERROR, "plpgsql parser returned %d", parse_rc);
845 :
846 1458 : plpgsql_scanner_finish(scanner);
847 :
848 : /*
849 : * If it returns VOID (always true at the moment), we allow control to
850 : * fall off the end without an explicit RETURN statement.
851 : */
852 1458 : if (function->fn_rettype == VOIDOID)
853 1458 : add_dummy_return(function);
854 :
855 : /*
856 : * Complete the function's info
857 : */
858 1458 : function->fn_nargs = 0;
859 :
860 1458 : plpgsql_finish_datums(function);
861 :
862 1458 : if (function->has_exception_block)
863 84 : plpgsql_mark_local_assignment_targets(function);
864 :
865 : /* Debug dump for completed functions */
866 1458 : if (plpgsql_DumpExecTree)
867 0 : plpgsql_dumptree(function);
868 :
869 : /*
870 : * Pop the error context stack
871 : */
872 1458 : error_context_stack = plerrcontext.previous;
873 1458 : plpgsql_error_funcname = NULL;
874 :
875 1458 : plpgsql_check_syntax = false;
876 :
877 1458 : MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
878 1458 : plpgsql_compile_tmp_cxt = NULL;
879 1458 : return function;
880 : }
881 :
882 :
883 : /*
884 : * error context callback to let us supply a call-stack traceback.
885 : * If we are validating or executing an anonymous code block, the function
886 : * source text is passed as an argument.
887 : */
888 : static void
889 226 : plpgsql_compile_error_callback(void *arg)
890 : {
891 226 : struct compile_error_callback_arg *cbarg = (struct compile_error_callback_arg *) arg;
892 226 : yyscan_t yyscanner = cbarg->yyscanner;
893 :
894 226 : if (cbarg->proc_source)
895 : {
896 : /*
897 : * Try to convert syntax error position to reference text of original
898 : * CREATE FUNCTION or DO command.
899 : */
900 212 : if (function_parse_error_transpose(cbarg->proc_source))
901 166 : return;
902 :
903 : /*
904 : * Done if a syntax error position was reported; otherwise we have to
905 : * fall back to a "near line N" report.
906 : */
907 : }
908 :
909 60 : if (plpgsql_error_funcname)
910 60 : errcontext("compilation of PL/pgSQL function \"%s\" near line %d",
911 : plpgsql_error_funcname, plpgsql_latest_lineno(yyscanner));
912 : }
913 :
914 :
915 : /*
916 : * Add a name for a function parameter to the function's namespace
917 : */
918 : static void
919 8592 : add_parameter_name(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
920 : {
921 : /*
922 : * Before adding the name, check for duplicates. We need this even though
923 : * functioncmds.c has a similar check, because that code explicitly
924 : * doesn't complain about conflicting IN and OUT parameter names. In
925 : * plpgsql, such names are in the same namespace, so there is no way to
926 : * disambiguate.
927 : */
928 8592 : if (plpgsql_ns_lookup(plpgsql_ns_top(), true,
929 : name, NULL, NULL,
930 : NULL) != NULL)
931 0 : ereport(ERROR,
932 : (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
933 : errmsg("parameter name \"%s\" used more than once",
934 : name)));
935 :
936 : /* OK, add the name */
937 8592 : plpgsql_ns_additem(itemtype, itemno, name);
938 8592 : }
939 :
940 : /*
941 : * Add a dummy RETURN statement to the given function's body
942 : */
943 : static void
944 3646 : add_dummy_return(PLpgSQL_function *function)
945 : {
946 : /*
947 : * If the outer block has an EXCEPTION clause, we need to make a new outer
948 : * block, since the added RETURN shouldn't act like it is inside the
949 : * EXCEPTION clause. Likewise, if it has a label, wrap it in a new outer
950 : * block so that EXIT doesn't skip the RETURN.
951 : */
952 3646 : if (function->action->exceptions != NULL ||
953 3384 : function->action->label != NULL)
954 : {
955 : PLpgSQL_stmt_block *new;
956 :
957 288 : new = palloc0_object(PLpgSQL_stmt_block);
958 288 : new->cmd_type = PLPGSQL_STMT_BLOCK;
959 288 : new->stmtid = ++function->nstatements;
960 288 : new->body = list_make1(function->action);
961 :
962 288 : function->action = new;
963 : }
964 3646 : if (function->action->body == NIL ||
965 3592 : ((PLpgSQL_stmt *) llast(function->action->body))->cmd_type != PLPGSQL_STMT_RETURN)
966 : {
967 : PLpgSQL_stmt_return *new;
968 :
969 3536 : new = palloc0_object(PLpgSQL_stmt_return);
970 3536 : new->cmd_type = PLPGSQL_STMT_RETURN;
971 3536 : new->stmtid = ++function->nstatements;
972 3536 : new->expr = NULL;
973 3536 : new->retvarno = function->out_param_varno;
974 :
975 3536 : function->action->body = lappend(function->action->body, new);
976 : }
977 3646 : }
978 :
979 :
980 : /*
981 : * plpgsql_parser_setup set up parser hooks for dynamic parameters
982 : *
983 : * Note: this routine, and the hook functions it prepares for, are logically
984 : * part of plpgsql parsing. But they actually run during function execution,
985 : * when we are ready to evaluate a SQL query or expression that has not
986 : * previously been parsed and planned.
987 : */
988 : void
989 34070 : plpgsql_parser_setup(struct ParseState *pstate, PLpgSQL_expr *expr)
990 : {
991 34070 : pstate->p_pre_columnref_hook = plpgsql_pre_column_ref;
992 34070 : pstate->p_post_columnref_hook = plpgsql_post_column_ref;
993 34070 : pstate->p_paramref_hook = plpgsql_param_ref;
994 : /* no need to use p_coerce_param_hook */
995 34070 : pstate->p_ref_hook_state = expr;
996 34070 : }
997 :
998 : /*
999 : * plpgsql_pre_column_ref parser callback before parsing a ColumnRef
1000 : */
1001 : static Node *
1002 37528 : plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref)
1003 : {
1004 37528 : PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1005 :
1006 37528 : if (expr->func->resolve_option == PLPGSQL_RESOLVE_VARIABLE)
1007 12 : return resolve_column_ref(pstate, expr, cref, false);
1008 : else
1009 37516 : return NULL;
1010 : }
1011 :
1012 : /*
1013 : * plpgsql_post_column_ref parser callback after parsing a ColumnRef
1014 : */
1015 : static Node *
1016 37522 : plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
1017 : {
1018 37522 : PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1019 : Node *myvar;
1020 :
1021 37522 : if (expr->func->resolve_option == PLPGSQL_RESOLVE_VARIABLE)
1022 6 : return NULL; /* we already found there's no match */
1023 :
1024 37516 : if (expr->func->resolve_option == PLPGSQL_RESOLVE_COLUMN && var != NULL)
1025 12 : return NULL; /* there's a table column, prefer that */
1026 :
1027 : /*
1028 : * If we find a record/row variable but can't match a field name, throw
1029 : * error if there was no core resolution for the ColumnRef either. In
1030 : * that situation, the reference is inevitably going to fail, and
1031 : * complaining about the record/row variable is likely to be more on-point
1032 : * than the core parser's error message. (It's too bad we don't have
1033 : * access to transformColumnRef's internal crerr state here, as in case of
1034 : * a conflict with a table name this could still be less than the most
1035 : * helpful error message possible.)
1036 : */
1037 37504 : myvar = resolve_column_ref(pstate, expr, cref, (var == NULL));
1038 :
1039 37480 : if (myvar != NULL && var != NULL)
1040 : {
1041 : /*
1042 : * We could leave it to the core parser to throw this error, but we
1043 : * can add a more useful detail message than the core could.
1044 : */
1045 12 : ereport(ERROR,
1046 : (errcode(ERRCODE_AMBIGUOUS_COLUMN),
1047 : errmsg("column reference \"%s\" is ambiguous",
1048 : NameListToString(cref->fields)),
1049 : errdetail("It could refer to either a PL/pgSQL variable or a table column."),
1050 : parser_errposition(pstate, cref->location)));
1051 : }
1052 :
1053 37468 : return myvar;
1054 : }
1055 :
1056 : /*
1057 : * plpgsql_param_ref parser callback for ParamRefs ($n symbols)
1058 : */
1059 : static Node *
1060 1158 : plpgsql_param_ref(ParseState *pstate, ParamRef *pref)
1061 : {
1062 1158 : PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1063 : char pname[32];
1064 : PLpgSQL_nsitem *nse;
1065 :
1066 1158 : snprintf(pname, sizeof(pname), "$%d", pref->number);
1067 :
1068 1158 : nse = plpgsql_ns_lookup(expr->ns, false,
1069 : pname, NULL, NULL,
1070 : NULL);
1071 :
1072 1158 : if (nse == NULL)
1073 0 : return NULL; /* name not known to plpgsql */
1074 :
1075 1158 : return make_datum_param(expr, nse->itemno, pref->location);
1076 : }
1077 :
1078 : /*
1079 : * resolve_column_ref attempt to resolve a ColumnRef as a plpgsql var
1080 : *
1081 : * Returns the translated node structure, or NULL if name not found
1082 : *
1083 : * error_if_no_field tells whether to throw error or quietly return NULL if
1084 : * we are able to match a record/row name but don't find a field name match.
1085 : */
1086 : static Node *
1087 37516 : resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr,
1088 : ColumnRef *cref, bool error_if_no_field)
1089 : {
1090 : PLpgSQL_execstate *estate;
1091 : PLpgSQL_nsitem *nse;
1092 : const char *name1;
1093 37516 : const char *name2 = NULL;
1094 37516 : const char *name3 = NULL;
1095 37516 : const char *colname = NULL;
1096 : int nnames;
1097 37516 : int nnames_scalar = 0;
1098 37516 : int nnames_wholerow = 0;
1099 37516 : int nnames_field = 0;
1100 :
1101 : /*
1102 : * We use the function's current estate to resolve parameter data types.
1103 : * This is really pretty bogus because there is no provision for updating
1104 : * plans when those types change ...
1105 : */
1106 37516 : estate = expr->func->cur_estate;
1107 :
1108 : /*----------
1109 : * The allowed syntaxes are:
1110 : *
1111 : * A Scalar variable reference, or whole-row record reference.
1112 : * A.B Qualified scalar or whole-row reference, or field reference.
1113 : * A.B.C Qualified record field reference.
1114 : * A.* Whole-row record reference.
1115 : * A.B.* Qualified whole-row record reference.
1116 : *----------
1117 : */
1118 37516 : switch (list_length(cref->fields))
1119 : {
1120 31738 : case 1:
1121 : {
1122 31738 : Node *field1 = (Node *) linitial(cref->fields);
1123 :
1124 31738 : name1 = strVal(field1);
1125 31738 : nnames_scalar = 1;
1126 31738 : nnames_wholerow = 1;
1127 31738 : break;
1128 : }
1129 5748 : case 2:
1130 : {
1131 5748 : Node *field1 = (Node *) linitial(cref->fields);
1132 5748 : Node *field2 = (Node *) lsecond(cref->fields);
1133 :
1134 5748 : name1 = strVal(field1);
1135 :
1136 : /* Whole-row reference? */
1137 5748 : if (IsA(field2, A_Star))
1138 : {
1139 : /* Set name2 to prevent matches to scalar variables */
1140 100 : name2 = "*";
1141 100 : nnames_wholerow = 1;
1142 100 : break;
1143 : }
1144 :
1145 5648 : name2 = strVal(field2);
1146 5648 : colname = name2;
1147 5648 : nnames_scalar = 2;
1148 5648 : nnames_wholerow = 2;
1149 5648 : nnames_field = 1;
1150 5648 : break;
1151 : }
1152 30 : case 3:
1153 : {
1154 30 : Node *field1 = (Node *) linitial(cref->fields);
1155 30 : Node *field2 = (Node *) lsecond(cref->fields);
1156 30 : Node *field3 = (Node *) lthird(cref->fields);
1157 :
1158 30 : name1 = strVal(field1);
1159 30 : name2 = strVal(field2);
1160 :
1161 : /* Whole-row reference? */
1162 30 : if (IsA(field3, A_Star))
1163 : {
1164 : /* Set name3 to prevent matches to scalar variables */
1165 0 : name3 = "*";
1166 0 : nnames_wholerow = 2;
1167 0 : break;
1168 : }
1169 :
1170 30 : name3 = strVal(field3);
1171 30 : colname = name3;
1172 30 : nnames_field = 2;
1173 30 : break;
1174 : }
1175 0 : default:
1176 : /* too many names, ignore */
1177 0 : return NULL;
1178 : }
1179 :
1180 37516 : nse = plpgsql_ns_lookup(expr->ns, false,
1181 : name1, name2, name3,
1182 : &nnames);
1183 :
1184 37516 : if (nse == NULL)
1185 4268 : return NULL; /* name not known to plpgsql */
1186 :
1187 33248 : switch (nse->itemtype)
1188 : {
1189 25470 : case PLPGSQL_NSTYPE_VAR:
1190 25470 : if (nnames == nnames_scalar)
1191 25470 : return make_datum_param(expr, nse->itemno, cref->location);
1192 0 : break;
1193 7778 : case PLPGSQL_NSTYPE_REC:
1194 7778 : if (nnames == nnames_wholerow)
1195 2620 : return make_datum_param(expr, nse->itemno, cref->location);
1196 5158 : if (nnames == nnames_field)
1197 : {
1198 : /* colname could be a field in this record */
1199 5158 : PLpgSQL_rec *rec = (PLpgSQL_rec *) estate->datums[nse->itemno];
1200 : int i;
1201 :
1202 : /* search for a datum referencing this field */
1203 5158 : i = rec->firstfield;
1204 13208 : while (i >= 0)
1205 : {
1206 13206 : PLpgSQL_recfield *fld = (PLpgSQL_recfield *) estate->datums[i];
1207 :
1208 : Assert(fld->dtype == PLPGSQL_DTYPE_RECFIELD &&
1209 : fld->recparentno == nse->itemno);
1210 13206 : if (strcmp(fld->fieldname, colname) == 0)
1211 : {
1212 5156 : return make_datum_param(expr, i, cref->location);
1213 : }
1214 8050 : i = fld->nextfield;
1215 : }
1216 :
1217 : /*
1218 : * Ideally we'd never get here, because a RECFIELD datum
1219 : * should have been built at parse time for every qualified
1220 : * reference to a field of this record that appears in the
1221 : * source text. However, plpgsql_yylex will not build such a
1222 : * datum unless the field name lexes as token type IDENT.
1223 : * Hence, if the would-be field name is a PL/pgSQL reserved
1224 : * word, we lose. Assume that that's what happened and tell
1225 : * the user to quote it, unless the caller prefers we just
1226 : * return NULL.
1227 : */
1228 2 : if (error_if_no_field)
1229 2 : ereport(ERROR,
1230 : (errcode(ERRCODE_SYNTAX_ERROR),
1231 : errmsg("field name \"%s\" is a reserved key word",
1232 : colname),
1233 : errhint("Use double quotes to quote it."),
1234 : parser_errposition(pstate, cref->location)));
1235 : }
1236 0 : break;
1237 0 : default:
1238 0 : elog(ERROR, "unrecognized plpgsql itemtype: %d", nse->itemtype);
1239 : }
1240 :
1241 : /* Name format doesn't match the plpgsql variable type */
1242 0 : return NULL;
1243 : }
1244 :
1245 : /*
1246 : * Helper for columnref parsing: build a Param referencing a plpgsql datum,
1247 : * and make sure that that datum is listed in the expression's paramnos.
1248 : */
1249 : static Node *
1250 34404 : make_datum_param(PLpgSQL_expr *expr, int dno, int location)
1251 : {
1252 : PLpgSQL_execstate *estate;
1253 : PLpgSQL_datum *datum;
1254 : Param *param;
1255 : MemoryContext oldcontext;
1256 :
1257 : /* see comment in resolve_column_ref */
1258 34404 : estate = expr->func->cur_estate;
1259 : Assert(dno >= 0 && dno < estate->ndatums);
1260 34404 : datum = estate->datums[dno];
1261 :
1262 : /*
1263 : * Bitmapset must be allocated in function's permanent memory context
1264 : */
1265 34404 : oldcontext = MemoryContextSwitchTo(expr->func->fn_cxt);
1266 34404 : expr->paramnos = bms_add_member(expr->paramnos, dno);
1267 34404 : MemoryContextSwitchTo(oldcontext);
1268 :
1269 34404 : param = makeNode(Param);
1270 34404 : param->paramkind = PARAM_EXTERN;
1271 34404 : param->paramid = dno + 1;
1272 34404 : plpgsql_exec_get_datum_type_info(estate,
1273 : datum,
1274 : ¶m->paramtype,
1275 : ¶m->paramtypmod,
1276 : ¶m->paramcollid);
1277 34382 : param->location = location;
1278 :
1279 34382 : return (Node *) param;
1280 : }
1281 :
1282 :
1283 : /* ----------
1284 : * plpgsql_parse_word The scanner calls this to postparse
1285 : * any single word that is not a reserved keyword.
1286 : *
1287 : * word1 is the downcased/dequoted identifier; it must be palloc'd in the
1288 : * function's long-term memory context.
1289 : *
1290 : * yytxt is the original token text; we need this to check for quoting,
1291 : * so that later checks for unreserved keywords work properly.
1292 : *
1293 : * We attempt to recognize the token as a variable only if lookup is true
1294 : * and the plpgsql_IdentifierLookup context permits it.
1295 : *
1296 : * If recognized as a variable, fill in *wdatum and return true;
1297 : * if not recognized, fill in *word and return false.
1298 : * (Note: those two pointers actually point to members of the same union,
1299 : * but for notational reasons we pass them separately.)
1300 : * ----------
1301 : */
1302 : bool
1303 131428 : plpgsql_parse_word(char *word1, const char *yytxt, bool lookup,
1304 : PLwdatum *wdatum, PLword *word)
1305 : {
1306 : PLpgSQL_nsitem *ns;
1307 :
1308 : /*
1309 : * We should not lookup variables in DECLARE sections. In SQL
1310 : * expressions, there's no need to do so either --- lookup will happen
1311 : * when the expression is compiled.
1312 : */
1313 131428 : if (lookup && plpgsql_IdentifierLookup == IDENTIFIER_LOOKUP_NORMAL)
1314 : {
1315 : /*
1316 : * Do a lookup in the current namespace stack
1317 : */
1318 29592 : ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1319 : word1, NULL, NULL,
1320 : NULL);
1321 :
1322 29592 : if (ns != NULL)
1323 : {
1324 15962 : switch (ns->itemtype)
1325 : {
1326 15962 : case PLPGSQL_NSTYPE_VAR:
1327 : case PLPGSQL_NSTYPE_REC:
1328 15962 : wdatum->datum = plpgsql_Datums[ns->itemno];
1329 15962 : wdatum->ident = word1;
1330 15962 : wdatum->quoted = (yytxt[0] == '"');
1331 15962 : wdatum->idents = NIL;
1332 15962 : return true;
1333 :
1334 0 : default:
1335 : /* plpgsql_ns_lookup should never return anything else */
1336 0 : elog(ERROR, "unrecognized plpgsql itemtype: %d",
1337 : ns->itemtype);
1338 : }
1339 : }
1340 : }
1341 :
1342 : /*
1343 : * Nothing found - up to now it's a word without any special meaning for
1344 : * us.
1345 : */
1346 115466 : word->ident = word1;
1347 115466 : word->quoted = (yytxt[0] == '"');
1348 115466 : return false;
1349 : }
1350 :
1351 :
1352 : /* ----------
1353 : * plpgsql_parse_dblword Same lookup for two words
1354 : * separated by a dot.
1355 : * ----------
1356 : */
1357 : bool
1358 8432 : plpgsql_parse_dblword(char *word1, char *word2,
1359 : PLwdatum *wdatum, PLcword *cword)
1360 : {
1361 : PLpgSQL_nsitem *ns;
1362 : List *idents;
1363 : int nnames;
1364 :
1365 8432 : idents = list_make2(makeString(word1),
1366 : makeString(word2));
1367 :
1368 : /*
1369 : * We should do nothing in DECLARE sections. In SQL expressions, we
1370 : * really only need to make sure that RECFIELD datums are created when
1371 : * needed. In all the cases handled by this function, returning a T_DATUM
1372 : * with a two-word idents string is the right thing.
1373 : */
1374 8432 : if (plpgsql_IdentifierLookup != IDENTIFIER_LOOKUP_DECLARE)
1375 : {
1376 : /*
1377 : * Do a lookup in the current namespace stack
1378 : */
1379 8374 : ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1380 : word1, word2, NULL,
1381 : &nnames);
1382 8374 : if (ns != NULL)
1383 : {
1384 7440 : switch (ns->itemtype)
1385 : {
1386 24 : case PLPGSQL_NSTYPE_VAR:
1387 : /* Block-qualified reference to scalar variable. */
1388 24 : wdatum->datum = plpgsql_Datums[ns->itemno];
1389 24 : wdatum->ident = NULL;
1390 24 : wdatum->quoted = false; /* not used */
1391 24 : wdatum->idents = idents;
1392 24 : return true;
1393 :
1394 7416 : case PLPGSQL_NSTYPE_REC:
1395 7416 : if (nnames == 1)
1396 : {
1397 : /*
1398 : * First word is a record name, so second word could
1399 : * be a field in this record. We build a RECFIELD
1400 : * datum whether it is or not --- any error will be
1401 : * detected later.
1402 : */
1403 : PLpgSQL_rec *rec;
1404 : PLpgSQL_recfield *new;
1405 :
1406 7400 : rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
1407 7400 : new = plpgsql_build_recfield(rec, word2);
1408 :
1409 7400 : wdatum->datum = (PLpgSQL_datum *) new;
1410 : }
1411 : else
1412 : {
1413 : /* Block-qualified reference to record variable. */
1414 16 : wdatum->datum = plpgsql_Datums[ns->itemno];
1415 : }
1416 7416 : wdatum->ident = NULL;
1417 7416 : wdatum->quoted = false; /* not used */
1418 7416 : wdatum->idents = idents;
1419 7416 : return true;
1420 :
1421 0 : default:
1422 0 : break;
1423 : }
1424 : }
1425 : }
1426 :
1427 : /* Nothing found */
1428 992 : cword->idents = idents;
1429 992 : return false;
1430 : }
1431 :
1432 :
1433 : /* ----------
1434 : * plpgsql_parse_tripword Same lookup for three words
1435 : * separated by dots.
1436 : * ----------
1437 : */
1438 : bool
1439 60 : plpgsql_parse_tripword(char *word1, char *word2, char *word3,
1440 : PLwdatum *wdatum, PLcword *cword)
1441 : {
1442 : PLpgSQL_nsitem *ns;
1443 : List *idents;
1444 : int nnames;
1445 :
1446 : /*
1447 : * We should do nothing in DECLARE sections. In SQL expressions, we need
1448 : * to make sure that RECFIELD datums are created when needed, and we need
1449 : * to be careful about how many names are reported as belonging to the
1450 : * T_DATUM: the third word could be a sub-field reference, which we don't
1451 : * care about here.
1452 : */
1453 60 : if (plpgsql_IdentifierLookup != IDENTIFIER_LOOKUP_DECLARE)
1454 : {
1455 : /*
1456 : * Do a lookup in the current namespace stack. Must find a record
1457 : * reference, else ignore.
1458 : */
1459 46 : ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1460 : word1, word2, word3,
1461 : &nnames);
1462 46 : if (ns != NULL)
1463 : {
1464 42 : switch (ns->itemtype)
1465 : {
1466 42 : case PLPGSQL_NSTYPE_REC:
1467 : {
1468 : PLpgSQL_rec *rec;
1469 : PLpgSQL_recfield *new;
1470 :
1471 42 : rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
1472 42 : if (nnames == 1)
1473 : {
1474 : /*
1475 : * First word is a record name, so second word
1476 : * could be a field in this record (and the third,
1477 : * a sub-field). We build a RECFIELD datum
1478 : * whether it is or not --- any error will be
1479 : * detected later.
1480 : */
1481 6 : new = plpgsql_build_recfield(rec, word2);
1482 6 : idents = list_make2(makeString(word1),
1483 : makeString(word2));
1484 : }
1485 : else
1486 : {
1487 : /* Block-qualified reference to record variable. */
1488 36 : new = plpgsql_build_recfield(rec, word3);
1489 36 : idents = list_make3(makeString(word1),
1490 : makeString(word2),
1491 : makeString(word3));
1492 : }
1493 42 : wdatum->datum = (PLpgSQL_datum *) new;
1494 42 : wdatum->ident = NULL;
1495 42 : wdatum->quoted = false; /* not used */
1496 42 : wdatum->idents = idents;
1497 42 : return true;
1498 : }
1499 :
1500 0 : default:
1501 0 : break;
1502 : }
1503 : }
1504 : }
1505 :
1506 : /* Nothing found */
1507 18 : idents = list_make3(makeString(word1),
1508 : makeString(word2),
1509 : makeString(word3));
1510 18 : cword->idents = idents;
1511 18 : return false;
1512 : }
1513 :
1514 :
1515 : /* ----------
1516 : * plpgsql_parse_wordtype The scanner found word%TYPE. word should be
1517 : * a pre-existing variable name.
1518 : *
1519 : * Returns datatype struct. Throws error if no match found for word.
1520 : * ----------
1521 : */
1522 : PLpgSQL_type *
1523 48 : plpgsql_parse_wordtype(char *ident)
1524 : {
1525 : PLpgSQL_nsitem *nse;
1526 :
1527 : /*
1528 : * Do a lookup in the current namespace stack
1529 : */
1530 48 : nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1531 : ident, NULL, NULL,
1532 : NULL);
1533 :
1534 48 : if (nse != NULL)
1535 : {
1536 44 : switch (nse->itemtype)
1537 : {
1538 38 : case PLPGSQL_NSTYPE_VAR:
1539 38 : return ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1540 6 : case PLPGSQL_NSTYPE_REC:
1541 6 : return ((PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]))->datatype;
1542 0 : default:
1543 0 : break;
1544 : }
1545 : }
1546 :
1547 : /* No match, complain */
1548 4 : ereport(ERROR,
1549 : (errcode(ERRCODE_UNDEFINED_OBJECT),
1550 : errmsg("variable \"%s\" does not exist", ident)));
1551 : return NULL; /* keep compiler quiet */
1552 : }
1553 :
1554 :
1555 : /* ----------
1556 : * plpgsql_parse_cwordtype Same lookup for compositeword%TYPE
1557 : *
1558 : * Here, we allow either a block-qualified variable name, or a reference
1559 : * to a column of some table. (If we must throw error, we assume that the
1560 : * latter case was intended.)
1561 : * ----------
1562 : */
1563 : PLpgSQL_type *
1564 36 : plpgsql_parse_cwordtype(List *idents)
1565 : {
1566 36 : PLpgSQL_type *dtype = NULL;
1567 : PLpgSQL_nsitem *nse;
1568 : int nnames;
1569 36 : RangeVar *relvar = NULL;
1570 36 : const char *fldname = NULL;
1571 : Oid classOid;
1572 36 : HeapTuple attrtup = NULL;
1573 36 : HeapTuple typetup = NULL;
1574 : Form_pg_attribute attrStruct;
1575 : MemoryContext oldCxt;
1576 :
1577 : /* Avoid memory leaks in the long-term function context */
1578 36 : oldCxt = MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
1579 :
1580 36 : if (list_length(idents) == 2)
1581 : {
1582 : /*
1583 : * Do a lookup in the current namespace stack
1584 : */
1585 24 : nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1586 24 : strVal(linitial(idents)),
1587 24 : strVal(lsecond(idents)),
1588 : NULL,
1589 : &nnames);
1590 :
1591 24 : if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_VAR)
1592 : {
1593 : /* Block-qualified reference to scalar variable. */
1594 2 : dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1595 2 : goto done;
1596 : }
1597 22 : else if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_REC &&
1598 2 : nnames == 2)
1599 : {
1600 : /* Block-qualified reference to record variable. */
1601 2 : dtype = ((PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]))->datatype;
1602 2 : goto done;
1603 : }
1604 :
1605 : /*
1606 : * First word could also be a table name
1607 : */
1608 20 : relvar = makeRangeVar(NULL,
1609 20 : strVal(linitial(idents)),
1610 : -1);
1611 20 : fldname = strVal(lsecond(idents));
1612 : }
1613 : else
1614 : {
1615 : /*
1616 : * We could check for a block-qualified reference to a field of a
1617 : * record variable, but %TYPE is documented as applying to variables,
1618 : * not fields of variables. Things would get rather ambiguous if we
1619 : * allowed either interpretation.
1620 : */
1621 : List *rvnames;
1622 :
1623 : Assert(list_length(idents) > 2);
1624 12 : rvnames = list_delete_last(list_copy(idents));
1625 12 : relvar = makeRangeVarFromNameList(rvnames);
1626 12 : fldname = strVal(llast(idents));
1627 : }
1628 :
1629 : /* Look up relation name. Can't lock it - we might not have privileges. */
1630 32 : classOid = RangeVarGetRelid(relvar, NoLock, false);
1631 :
1632 : /*
1633 : * Fetch the named table field and its type
1634 : */
1635 26 : attrtup = SearchSysCacheAttName(classOid, fldname);
1636 26 : if (!HeapTupleIsValid(attrtup))
1637 2 : ereport(ERROR,
1638 : (errcode(ERRCODE_UNDEFINED_COLUMN),
1639 : errmsg("column \"%s\" of relation \"%s\" does not exist",
1640 : fldname, relvar->relname)));
1641 24 : attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1642 :
1643 24 : typetup = SearchSysCache1(TYPEOID,
1644 : ObjectIdGetDatum(attrStruct->atttypid));
1645 24 : if (!HeapTupleIsValid(typetup))
1646 0 : elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1647 :
1648 : /*
1649 : * Found that - build a compiler type struct in the caller's cxt and
1650 : * return it. Note that we treat the type as being found-by-OID; no
1651 : * attempt to re-look-up the type name will happen during invalidations.
1652 : */
1653 24 : MemoryContextSwitchTo(oldCxt);
1654 24 : dtype = build_datatype(typetup,
1655 : attrStruct->atttypmod,
1656 : attrStruct->attcollation,
1657 : NULL);
1658 24 : MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
1659 :
1660 28 : done:
1661 28 : if (HeapTupleIsValid(attrtup))
1662 24 : ReleaseSysCache(attrtup);
1663 28 : if (HeapTupleIsValid(typetup))
1664 24 : ReleaseSysCache(typetup);
1665 :
1666 28 : MemoryContextSwitchTo(oldCxt);
1667 28 : return dtype;
1668 : }
1669 :
1670 : /* ----------
1671 : * plpgsql_parse_wordrowtype Scanner found word%ROWTYPE.
1672 : * So word must be a table name.
1673 : * ----------
1674 : */
1675 : PLpgSQL_type *
1676 60 : plpgsql_parse_wordrowtype(char *ident)
1677 : {
1678 : Oid classOid;
1679 : Oid typOid;
1680 : TypeName *typName;
1681 : MemoryContext oldCxt;
1682 :
1683 : /* Avoid memory leaks in long-term function context */
1684 60 : oldCxt = MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
1685 :
1686 : /*
1687 : * Look up the relation. Note that because relation rowtypes have the
1688 : * same names as their relations, this could be handled as a type lookup
1689 : * equally well; we use the relation lookup code path only because the
1690 : * errors thrown here have traditionally referred to relations not types.
1691 : * But we'll make a TypeName in case we have to do re-look-up of the type.
1692 : */
1693 60 : classOid = RelnameGetRelid(ident);
1694 60 : if (!OidIsValid(classOid))
1695 4 : ereport(ERROR,
1696 : (errcode(ERRCODE_UNDEFINED_TABLE),
1697 : errmsg("relation \"%s\" does not exist", ident)));
1698 :
1699 : /* Some relkinds lack type OIDs */
1700 56 : typOid = get_rel_type_id(classOid);
1701 56 : if (!OidIsValid(typOid))
1702 0 : ereport(ERROR,
1703 : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1704 : errmsg("relation \"%s\" does not have a composite type",
1705 : ident)));
1706 :
1707 56 : typName = makeTypeName(ident);
1708 :
1709 56 : MemoryContextSwitchTo(oldCxt);
1710 :
1711 : /* Build and return the row type struct */
1712 56 : return plpgsql_build_datatype(typOid, -1, InvalidOid, typName);
1713 : }
1714 :
1715 : /* ----------
1716 : * plpgsql_parse_cwordrowtype Scanner found compositeword%ROWTYPE.
1717 : * So word must be a namespace qualified table name.
1718 : * ----------
1719 : */
1720 : PLpgSQL_type *
1721 16 : plpgsql_parse_cwordrowtype(List *idents)
1722 : {
1723 : Oid classOid;
1724 : Oid typOid;
1725 : RangeVar *relvar;
1726 : TypeName *typName;
1727 : MemoryContext oldCxt;
1728 :
1729 : /*
1730 : * As above, this is a relation lookup but could be a type lookup if we
1731 : * weren't being backwards-compatible about error wording.
1732 : */
1733 :
1734 : /* Avoid memory leaks in long-term function context */
1735 16 : oldCxt = MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
1736 :
1737 : /* Look up relation name. Can't lock it - we might not have privileges. */
1738 16 : relvar = makeRangeVarFromNameList(idents);
1739 16 : classOid = RangeVarGetRelid(relvar, NoLock, false);
1740 :
1741 : /* Some relkinds lack type OIDs */
1742 10 : typOid = get_rel_type_id(classOid);
1743 10 : if (!OidIsValid(typOid))
1744 0 : ereport(ERROR,
1745 : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1746 : errmsg("relation \"%s\" does not have a composite type",
1747 : relvar->relname)));
1748 :
1749 10 : typName = makeTypeNameFromNameList(idents);
1750 :
1751 10 : MemoryContextSwitchTo(oldCxt);
1752 :
1753 : /* Build and return the row type struct */
1754 10 : return plpgsql_build_datatype(typOid, -1, InvalidOid, typName);
1755 : }
1756 :
1757 : /*
1758 : * plpgsql_build_variable - build a datum-array entry of a given
1759 : * datatype
1760 : *
1761 : * The returned struct may be a PLpgSQL_var or PLpgSQL_rec
1762 : * depending on the given datatype, and is allocated via
1763 : * palloc. The struct is automatically added to the current datum
1764 : * array, and optionally to the current namespace.
1765 : */
1766 : PLpgSQL_variable *
1767 61984 : plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype,
1768 : bool add2namespace)
1769 : {
1770 : PLpgSQL_variable *result;
1771 :
1772 61984 : switch (dtype->ttype)
1773 : {
1774 60494 : case PLPGSQL_TTYPE_SCALAR:
1775 : {
1776 : /* Ordinary scalar datatype */
1777 : PLpgSQL_var *var;
1778 :
1779 60494 : var = palloc0_object(PLpgSQL_var);
1780 60494 : var->dtype = PLPGSQL_DTYPE_VAR;
1781 60494 : var->refname = pstrdup(refname);
1782 60494 : var->lineno = lineno;
1783 60494 : var->datatype = dtype;
1784 : /* other fields are left as 0, might be changed by caller */
1785 :
1786 : /* preset to NULL */
1787 60494 : var->value = 0;
1788 60494 : var->isnull = true;
1789 60494 : var->freeval = false;
1790 :
1791 60494 : plpgsql_adddatum((PLpgSQL_datum *) var);
1792 60494 : if (add2namespace)
1793 55594 : plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR,
1794 : var->dno,
1795 : refname);
1796 60494 : result = (PLpgSQL_variable *) var;
1797 60494 : break;
1798 : }
1799 1486 : case PLPGSQL_TTYPE_REC:
1800 : {
1801 : /* Composite type -- build a record variable */
1802 : PLpgSQL_rec *rec;
1803 :
1804 1486 : rec = plpgsql_build_record(refname, lineno,
1805 : dtype, dtype->typoid,
1806 : add2namespace);
1807 1486 : result = (PLpgSQL_variable *) rec;
1808 1486 : break;
1809 : }
1810 4 : case PLPGSQL_TTYPE_PSEUDO:
1811 4 : ereport(ERROR,
1812 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1813 : errmsg("variable \"%s\" has pseudo-type %s",
1814 : refname, format_type_be(dtype->typoid))));
1815 : result = NULL; /* keep compiler quiet */
1816 : break;
1817 0 : default:
1818 0 : elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
1819 : result = NULL; /* keep compiler quiet */
1820 : break;
1821 : }
1822 :
1823 61980 : return result;
1824 : }
1825 :
1826 : /*
1827 : * Build empty named record variable, and optionally add it to namespace
1828 : */
1829 : PLpgSQL_rec *
1830 9192 : plpgsql_build_record(const char *refname, int lineno,
1831 : PLpgSQL_type *dtype, Oid rectypeid,
1832 : bool add2namespace)
1833 : {
1834 : PLpgSQL_rec *rec;
1835 :
1836 9192 : rec = palloc0_object(PLpgSQL_rec);
1837 9192 : rec->dtype = PLPGSQL_DTYPE_REC;
1838 9192 : rec->refname = pstrdup(refname);
1839 9192 : rec->lineno = lineno;
1840 : /* other fields are left as 0, might be changed by caller */
1841 9192 : rec->datatype = dtype;
1842 9192 : rec->rectypeid = rectypeid;
1843 9192 : rec->firstfield = -1;
1844 9192 : rec->erh = NULL;
1845 9192 : plpgsql_adddatum((PLpgSQL_datum *) rec);
1846 9192 : if (add2namespace)
1847 9110 : plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->dno, rec->refname);
1848 :
1849 9192 : return rec;
1850 : }
1851 :
1852 : /*
1853 : * Build a row-variable data structure given the component variables.
1854 : * Include a rowtupdesc, since we will need to materialize the row result.
1855 : */
1856 : static PLpgSQL_row *
1857 192 : build_row_from_vars(PLpgSQL_variable **vars, int numvars)
1858 : {
1859 : PLpgSQL_row *row;
1860 : int i;
1861 :
1862 192 : row = palloc0_object(PLpgSQL_row);
1863 192 : row->dtype = PLPGSQL_DTYPE_ROW;
1864 192 : row->refname = "(unnamed row)";
1865 192 : row->lineno = -1;
1866 192 : row->rowtupdesc = CreateTemplateTupleDesc(numvars);
1867 192 : row->nfields = numvars;
1868 192 : row->fieldnames = palloc_array(char *, numvars);
1869 192 : row->varnos = palloc_array(int, numvars);
1870 :
1871 616 : for (i = 0; i < numvars; i++)
1872 : {
1873 424 : PLpgSQL_variable *var = vars[i];
1874 : Oid typoid;
1875 : int32 typmod;
1876 : Oid typcoll;
1877 :
1878 : /* Member vars of a row should never be const */
1879 : Assert(!var->isconst);
1880 :
1881 424 : switch (var->dtype)
1882 : {
1883 424 : case PLPGSQL_DTYPE_VAR:
1884 : case PLPGSQL_DTYPE_PROMISE:
1885 424 : typoid = ((PLpgSQL_var *) var)->datatype->typoid;
1886 424 : typmod = ((PLpgSQL_var *) var)->datatype->atttypmod;
1887 424 : typcoll = ((PLpgSQL_var *) var)->datatype->collation;
1888 424 : break;
1889 :
1890 0 : case PLPGSQL_DTYPE_REC:
1891 : /* shouldn't need to revalidate rectypeid already... */
1892 0 : typoid = ((PLpgSQL_rec *) var)->rectypeid;
1893 0 : typmod = -1; /* don't know typmod, if it's used at all */
1894 0 : typcoll = InvalidOid; /* composite types have no collation */
1895 0 : break;
1896 :
1897 0 : default:
1898 0 : elog(ERROR, "unrecognized dtype: %d", var->dtype);
1899 : typoid = InvalidOid; /* keep compiler quiet */
1900 : typmod = 0;
1901 : typcoll = InvalidOid;
1902 : break;
1903 : }
1904 :
1905 424 : row->fieldnames[i] = var->refname;
1906 424 : row->varnos[i] = var->dno;
1907 :
1908 424 : TupleDescInitEntry(row->rowtupdesc, i + 1,
1909 424 : var->refname,
1910 : typoid, typmod,
1911 : 0);
1912 424 : TupleDescInitEntryCollation(row->rowtupdesc, i + 1, typcoll);
1913 : }
1914 :
1915 192 : return row;
1916 : }
1917 :
1918 : /*
1919 : * Build a RECFIELD datum for the named field of the specified record variable
1920 : *
1921 : * If there's already such a datum, just return it; we don't need duplicates.
1922 : */
1923 : PLpgSQL_recfield *
1924 7442 : plpgsql_build_recfield(PLpgSQL_rec *rec, const char *fldname)
1925 : {
1926 : PLpgSQL_recfield *recfield;
1927 : int i;
1928 :
1929 : /* search for an existing datum referencing this field */
1930 7442 : i = rec->firstfield;
1931 12070 : while (i >= 0)
1932 : {
1933 7766 : PLpgSQL_recfield *fld = (PLpgSQL_recfield *) plpgsql_Datums[i];
1934 :
1935 : Assert(fld->dtype == PLPGSQL_DTYPE_RECFIELD &&
1936 : fld->recparentno == rec->dno);
1937 7766 : if (strcmp(fld->fieldname, fldname) == 0)
1938 3138 : return fld;
1939 4628 : i = fld->nextfield;
1940 : }
1941 :
1942 : /* nope, so make a new one */
1943 4304 : recfield = palloc0_object(PLpgSQL_recfield);
1944 4304 : recfield->dtype = PLPGSQL_DTYPE_RECFIELD;
1945 4304 : recfield->fieldname = pstrdup(fldname);
1946 4304 : recfield->recparentno = rec->dno;
1947 4304 : recfield->rectupledescid = INVALID_TUPLEDESC_IDENTIFIER;
1948 :
1949 4304 : plpgsql_adddatum((PLpgSQL_datum *) recfield);
1950 :
1951 : /* now we can link it into the parent's chain */
1952 4304 : recfield->nextfield = rec->firstfield;
1953 4304 : rec->firstfield = recfield->dno;
1954 :
1955 4304 : return recfield;
1956 : }
1957 :
1958 : /*
1959 : * plpgsql_build_datatype
1960 : * Build PLpgSQL_type struct given type OID, typmod, collation,
1961 : * and type's parsed name.
1962 : *
1963 : * If collation is not InvalidOid then it overrides the type's default
1964 : * collation. But collation is ignored if the datatype is non-collatable.
1965 : *
1966 : * origtypname is the parsed form of what the user wrote as the type name.
1967 : * It can be NULL if the type could not be a composite type, or if it was
1968 : * identified by OID to begin with (e.g., it's a function argument type).
1969 : * origtypname is in short-lived storage and must be copied if we choose
1970 : * to incorporate it into the function's parse tree.
1971 : */
1972 : PLpgSQL_type *
1973 61848 : plpgsql_build_datatype(Oid typeOid, int32 typmod,
1974 : Oid collation, TypeName *origtypname)
1975 : {
1976 : HeapTuple typeTup;
1977 : PLpgSQL_type *typ;
1978 :
1979 61848 : typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
1980 61848 : if (!HeapTupleIsValid(typeTup))
1981 0 : elog(ERROR, "cache lookup failed for type %u", typeOid);
1982 :
1983 61848 : typ = build_datatype(typeTup, typmod, collation, origtypname);
1984 :
1985 61848 : ReleaseSysCache(typeTup);
1986 :
1987 61848 : return typ;
1988 : }
1989 :
1990 : /*
1991 : * Utility subroutine to make a PLpgSQL_type struct given a pg_type entry
1992 : * and additional details (see comments for plpgsql_build_datatype).
1993 : */
1994 : static PLpgSQL_type *
1995 62016 : build_datatype(HeapTuple typeTup, int32 typmod,
1996 : Oid collation, TypeName *origtypname)
1997 : {
1998 62016 : Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1999 : PLpgSQL_type *typ;
2000 :
2001 62016 : if (!typeStruct->typisdefined)
2002 0 : ereport(ERROR,
2003 : (errcode(ERRCODE_UNDEFINED_OBJECT),
2004 : errmsg("type \"%s\" is only a shell",
2005 : NameStr(typeStruct->typname))));
2006 :
2007 62016 : typ = palloc_object(PLpgSQL_type);
2008 :
2009 62016 : typ->typname = pstrdup(NameStr(typeStruct->typname));
2010 62016 : typ->typoid = typeStruct->oid;
2011 62016 : switch (typeStruct->typtype)
2012 : {
2013 60384 : case TYPTYPE_BASE:
2014 : case TYPTYPE_ENUM:
2015 : case TYPTYPE_RANGE:
2016 : case TYPTYPE_MULTIRANGE:
2017 60384 : typ->ttype = PLPGSQL_TTYPE_SCALAR;
2018 60384 : break;
2019 256 : case TYPTYPE_COMPOSITE:
2020 256 : typ->ttype = PLPGSQL_TTYPE_REC;
2021 256 : break;
2022 174 : case TYPTYPE_DOMAIN:
2023 174 : if (type_is_rowtype(typeStruct->typbasetype))
2024 36 : typ->ttype = PLPGSQL_TTYPE_REC;
2025 : else
2026 138 : typ->ttype = PLPGSQL_TTYPE_SCALAR;
2027 174 : break;
2028 1202 : case TYPTYPE_PSEUDO:
2029 1202 : if (typ->typoid == RECORDOID)
2030 1192 : typ->ttype = PLPGSQL_TTYPE_REC;
2031 : else
2032 10 : typ->ttype = PLPGSQL_TTYPE_PSEUDO;
2033 1202 : break;
2034 0 : default:
2035 0 : elog(ERROR, "unrecognized typtype: %d",
2036 : (int) typeStruct->typtype);
2037 : break;
2038 : }
2039 62016 : typ->typlen = typeStruct->typlen;
2040 62016 : typ->typbyval = typeStruct->typbyval;
2041 62016 : typ->typtype = typeStruct->typtype;
2042 62016 : typ->collation = typeStruct->typcollation;
2043 62016 : if (OidIsValid(collation) && OidIsValid(typ->collation))
2044 1598 : typ->collation = collation;
2045 : /* Detect if type is true array, or domain thereof */
2046 : /* NB: this is only used to decide whether to apply expand_array */
2047 62016 : if (typeStruct->typtype == TYPTYPE_BASE)
2048 : {
2049 : /*
2050 : * This test should include what get_element_type() checks. We also
2051 : * disallow non-toastable array types (i.e. oidvector and int2vector).
2052 : */
2053 64768 : typ->typisarray = (IsTrueArrayType(typeStruct) &&
2054 4468 : typeStruct->typstorage != TYPSTORAGE_PLAIN);
2055 : }
2056 1716 : else if (typeStruct->typtype == TYPTYPE_DOMAIN)
2057 : {
2058 : /* we can short-circuit looking up base types if it's not varlena */
2059 444 : typ->typisarray = (typeStruct->typlen == -1 &&
2060 270 : typeStruct->typstorage != TYPSTORAGE_PLAIN &&
2061 96 : OidIsValid(get_base_element_type(typeStruct->typbasetype)));
2062 : }
2063 : else
2064 1542 : typ->typisarray = false;
2065 62016 : typ->atttypmod = typmod;
2066 :
2067 : /*
2068 : * If it's a named composite type (or domain over one), find the typcache
2069 : * entry and record the current tupdesc ID, so we can detect changes
2070 : * (including drops). We don't currently support on-the-fly replacement
2071 : * of non-composite types, else we might want to do this for them too.
2072 : */
2073 62016 : if (typ->ttype == PLPGSQL_TTYPE_REC && typ->typoid != RECORDOID)
2074 292 : {
2075 : TypeCacheEntry *typentry;
2076 :
2077 292 : typentry = lookup_type_cache(typ->typoid,
2078 : TYPECACHE_TUPDESC |
2079 : TYPECACHE_DOMAIN_BASE_INFO);
2080 292 : if (typentry->typtype == TYPTYPE_DOMAIN)
2081 36 : typentry = lookup_type_cache(typentry->domainBaseType,
2082 : TYPECACHE_TUPDESC);
2083 292 : if (typentry->tupDesc == NULL)
2084 0 : ereport(ERROR,
2085 : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2086 : errmsg("type %s is not composite",
2087 : format_type_be(typ->typoid))));
2088 :
2089 292 : typ->origtypname = copyObject(origtypname);
2090 292 : typ->tcache = typentry;
2091 292 : typ->tupdesc_id = typentry->tupDesc_identifier;
2092 : }
2093 : else
2094 : {
2095 61724 : typ->origtypname = NULL;
2096 61724 : typ->tcache = NULL;
2097 61724 : typ->tupdesc_id = 0;
2098 : }
2099 :
2100 62016 : return typ;
2101 : }
2102 :
2103 : /*
2104 : * Build an array type for the element type specified as argument.
2105 : */
2106 : PLpgSQL_type *
2107 28 : plpgsql_build_datatype_arrayof(PLpgSQL_type *dtype)
2108 : {
2109 : Oid array_typeid;
2110 :
2111 : /*
2112 : * If it's already an array type, use it as-is: Postgres doesn't do nested
2113 : * arrays.
2114 : */
2115 28 : if (dtype->typisarray)
2116 0 : return dtype;
2117 :
2118 28 : array_typeid = get_array_type(dtype->typoid);
2119 28 : if (!OidIsValid(array_typeid))
2120 2 : ereport(ERROR,
2121 : (errcode(ERRCODE_UNDEFINED_OBJECT),
2122 : errmsg("could not find array type for data type %s",
2123 : format_type_be(dtype->typoid))));
2124 :
2125 : /* Note we inherit typmod and collation, if any, from the element type */
2126 26 : return plpgsql_build_datatype(array_typeid, dtype->atttypmod,
2127 : dtype->collation, NULL);
2128 : }
2129 :
2130 : /*
2131 : * plpgsql_recognize_err_condition
2132 : * Check condition name and translate it to SQLSTATE.
2133 : *
2134 : * Note: there are some cases where the same condition name has multiple
2135 : * entries in the table. We arbitrarily return the first match.
2136 : */
2137 : int
2138 736 : plpgsql_recognize_err_condition(const char *condname, bool allow_sqlstate)
2139 : {
2140 : int i;
2141 :
2142 736 : if (allow_sqlstate)
2143 : {
2144 694 : if (strlen(condname) == 5 &&
2145 52 : strspn(condname, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") == 5)
2146 52 : return MAKE_SQLSTATE(condname[0],
2147 : condname[1],
2148 : condname[2],
2149 : condname[3],
2150 : condname[4]);
2151 : }
2152 :
2153 78732 : for (i = 0; exception_label_map[i].label != NULL; i++)
2154 : {
2155 78732 : if (strcmp(condname, exception_label_map[i].label) == 0)
2156 684 : return exception_label_map[i].sqlerrstate;
2157 : }
2158 :
2159 0 : ereport(ERROR,
2160 : (errcode(ERRCODE_UNDEFINED_OBJECT),
2161 : errmsg("unrecognized exception condition \"%s\"",
2162 : condname)));
2163 : return 0; /* keep compiler quiet */
2164 : }
2165 :
2166 : /*
2167 : * plpgsql_parse_err_condition
2168 : * Generate PLpgSQL_condition entry(s) for an exception condition name
2169 : *
2170 : * This has to be able to return a list because there are some duplicate
2171 : * names in the table of error code names.
2172 : */
2173 : PLpgSQL_condition *
2174 458 : plpgsql_parse_err_condition(char *condname)
2175 : {
2176 : int i;
2177 : PLpgSQL_condition *new;
2178 : PLpgSQL_condition *prev;
2179 :
2180 : /*
2181 : * XXX Eventually we will want to look for user-defined exception names
2182 : * here.
2183 : */
2184 :
2185 458 : if (strcmp(condname, "others") == 0)
2186 : {
2187 164 : new = palloc_object(PLpgSQL_condition);
2188 164 : new->sqlerrstate = PLPGSQL_OTHERS;
2189 164 : new->condname = condname;
2190 164 : new->next = NULL;
2191 164 : return new;
2192 : }
2193 :
2194 294 : prev = NULL;
2195 74088 : for (i = 0; exception_label_map[i].label != NULL; i++)
2196 : {
2197 73794 : if (strcmp(condname, exception_label_map[i].label) == 0)
2198 : {
2199 300 : new = palloc_object(PLpgSQL_condition);
2200 300 : new->sqlerrstate = exception_label_map[i].sqlerrstate;
2201 300 : new->condname = condname;
2202 300 : new->next = prev;
2203 300 : prev = new;
2204 : }
2205 : }
2206 :
2207 294 : if (!prev)
2208 0 : ereport(ERROR,
2209 : (errcode(ERRCODE_UNDEFINED_OBJECT),
2210 : errmsg("unrecognized exception condition \"%s\"",
2211 : condname)));
2212 :
2213 294 : return prev;
2214 : }
2215 :
2216 : /* ----------
2217 : * plpgsql_start_datums Initialize datum list at compile startup.
2218 : * ----------
2219 : */
2220 : static void
2221 9796 : plpgsql_start_datums(void)
2222 : {
2223 9796 : datums_alloc = 128;
2224 9796 : plpgsql_nDatums = 0;
2225 : /* This is short-lived, so needn't allocate in function's cxt */
2226 9796 : plpgsql_Datums = MemoryContextAlloc(plpgsql_compile_tmp_cxt,
2227 : sizeof(PLpgSQL_datum *) * datums_alloc);
2228 : /* datums_last tracks what's been seen by plpgsql_add_initdatums() */
2229 9796 : datums_last = 0;
2230 9796 : }
2231 :
2232 : /* ----------
2233 : * plpgsql_adddatum Add a variable, record or row
2234 : * to the compiler's datum list.
2235 : * ----------
2236 : */
2237 : void
2238 75630 : plpgsql_adddatum(PLpgSQL_datum *newdatum)
2239 : {
2240 75630 : if (plpgsql_nDatums == datums_alloc)
2241 : {
2242 0 : datums_alloc *= 2;
2243 0 : plpgsql_Datums = repalloc(plpgsql_Datums, sizeof(PLpgSQL_datum *) * datums_alloc);
2244 : }
2245 :
2246 75630 : newdatum->dno = plpgsql_nDatums;
2247 75630 : plpgsql_Datums[plpgsql_nDatums++] = newdatum;
2248 75630 : }
2249 :
2250 : /* ----------
2251 : * plpgsql_finish_datums Copy completed datum info into function struct.
2252 : * ----------
2253 : */
2254 : static void
2255 9618 : plpgsql_finish_datums(PLpgSQL_function *function)
2256 : {
2257 9618 : Size copiable_size = 0;
2258 : int i;
2259 :
2260 9618 : function->ndatums = plpgsql_nDatums;
2261 9618 : function->datums = palloc_array(PLpgSQL_datum *, plpgsql_nDatums);
2262 84894 : for (i = 0; i < plpgsql_nDatums; i++)
2263 : {
2264 75276 : function->datums[i] = plpgsql_Datums[i];
2265 :
2266 : /* This must agree with copy_plpgsql_datums on what is copiable */
2267 75276 : switch (function->datums[i]->dtype)
2268 : {
2269 60194 : case PLPGSQL_DTYPE_VAR:
2270 : case PLPGSQL_DTYPE_PROMISE:
2271 60194 : copiable_size += MAXALIGN(sizeof(PLpgSQL_var));
2272 60194 : break;
2273 9166 : case PLPGSQL_DTYPE_REC:
2274 9166 : copiable_size += MAXALIGN(sizeof(PLpgSQL_rec));
2275 9166 : break;
2276 5916 : default:
2277 5916 : break;
2278 : }
2279 : }
2280 9618 : function->copiable_size = copiable_size;
2281 9618 : }
2282 :
2283 :
2284 : /* ----------
2285 : * plpgsql_add_initdatums Make an array of the datum numbers of
2286 : * all the initializable datums created since the last call
2287 : * to this function.
2288 : *
2289 : * If varnos is NULL, we just forget any datum entries created since the
2290 : * last call.
2291 : *
2292 : * This is used around a DECLARE section to create a list of the datums
2293 : * that have to be initialized at block entry. Note that datums can also
2294 : * be created elsewhere than DECLARE, eg by a FOR-loop, but it is then
2295 : * the responsibility of special-purpose code to initialize them.
2296 : * ----------
2297 : */
2298 : int
2299 7336 : plpgsql_add_initdatums(int **varnos)
2300 : {
2301 : int i;
2302 7336 : int n = 0;
2303 :
2304 : /*
2305 : * The set of dtypes recognized here must match what exec_stmt_block()
2306 : * cares about (re)initializing at block entry.
2307 : */
2308 30422 : for (i = datums_last; i < plpgsql_nDatums; i++)
2309 : {
2310 23086 : switch (plpgsql_Datums[i]->dtype)
2311 : {
2312 14462 : case PLPGSQL_DTYPE_VAR:
2313 : case PLPGSQL_DTYPE_REC:
2314 14462 : n++;
2315 14462 : break;
2316 :
2317 8624 : default:
2318 8624 : break;
2319 : }
2320 : }
2321 :
2322 7336 : if (varnos != NULL)
2323 : {
2324 3642 : if (n > 0)
2325 : {
2326 3642 : *varnos = palloc_array(int, n);
2327 :
2328 3642 : n = 0;
2329 9888 : for (i = datums_last; i < plpgsql_nDatums; i++)
2330 : {
2331 6246 : switch (plpgsql_Datums[i]->dtype)
2332 : {
2333 6174 : case PLPGSQL_DTYPE_VAR:
2334 : case PLPGSQL_DTYPE_REC:
2335 6174 : (*varnos)[n++] = plpgsql_Datums[i]->dno;
2336 :
2337 6246 : default:
2338 6246 : break;
2339 : }
2340 : }
2341 : }
2342 : else
2343 0 : *varnos = NULL;
2344 : }
2345 :
2346 7336 : datums_last = plpgsql_nDatums;
2347 7336 : return n;
2348 : }
|