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