PostgreSQL Source Code: src/pl/plpgsql/src/pl_comp.c Source File

PostgreSQL Source Code git master
pl_comp.c
Go to the documentation of this file.
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 */
75static void plpgsql_compile_callback(FunctionCallInfo fcinfo,
76 HeapTuple procTup,
77 const CachedFunctionHashKey *hashkey,
78 CachedFunction *cfunc,
79 bool forValidator);
80static void plpgsql_compile_error_callback(void *arg);
81static void add_parameter_name(PLpgSQL_nsitem_type itemtype, int itemno, const char *name);
82static void add_dummy_return(PLpgSQL_function *function);
83static Node *plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref);
84static Node *plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var);
85static Node *plpgsql_param_ref(ParseState *pstate, ParamRef *pref);
86static Node *resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr,
87 ColumnRef *cref, bool error_if_no_field);
88static Node *make_datum_param(PLpgSQL_expr *expr, int dno, int location);
89static PLpgSQL_row *build_row_from_vars(PLpgSQL_variable **vars, int numvars);
90static PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod,
91 Oid collation, TypeName *origtypname);
92static void plpgsql_start_datums(void);
93static 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 */
105PLpgSQL_function *
106 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 cached_function_compile(fcinfo,
120 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 fcinfo->flinfo->fn_extra = function;
131
132 /*
133 * Finally return the compiled function
134 */
135 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 */
166static void
167 plpgsql_compile_callback(FunctionCallInfo fcinfo,
168 HeapTuple procTup,
169 const CachedFunctionHashKey *hashkey,
170 CachedFunction *cfunc,
171 bool forValidator)
172{
173 PLpgSQL_function *function = (PLpgSQL_function *) cfunc;
174 Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
175 bool is_dml_trigger = CALLED_AS_TRIGGER(fcinfo);
176 bool is_event_trigger = CALLED_AS_EVENT_TRIGGER(fcinfo);
177 yyscan_t scanner;
178 Datum prosrcdatum;
179 char *proc_source;
180 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 int num_in_args = 0;
192 int num_out_args = 0;
193 Oid *argtypes;
194 char **argnames;
195 char *argmodes;
196 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 prosrcdatum = SysCacheGetAttrNotNull(PROCOID, procTup, Anum_pg_proc_prosrc);
204 proc_source = TextDatumGetCString(prosrcdatum);
205 scanner = plpgsql_scanner_init(proc_source);
206
207 plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname));
208
209 /*
210 * Setup error traceback support for ereport()
211 */
212 cbarg.proc_source = forValidator ? proc_source : NULL;
213 cbarg.yyscanner = scanner;
214 plerrcontext.callback = plpgsql_compile_error_callback;
215 plerrcontext.arg = &cbarg;
216 plerrcontext.previous = error_context_stack;
217 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 plpgsql_check_syntax = forValidator;
225 plpgsql_curr_compile = function;
226
227 /* format_procedure leaks memory, so run it in temp context */
228 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 func_cxt = AllocSetContextCreate(CurrentMemoryContext,
240 "PL/pgSQL function",
241 ALLOCSET_DEFAULT_SIZES);
242 plpgsql_compile_tmp_cxt = MemoryContextSwitchTo(func_cxt);
243
244 function->fn_signature = pstrdup(proc_signature);
245 MemoryContextSetIdentifier(func_cxt, function->fn_signature);
246 function->fn_oid = fcinfo->flinfo->fn_oid;
247 function->fn_input_collation = fcinfo->fncollation;
248 function->fn_cxt = func_cxt;
249 function->out_param_varno = -1; /* set up for no OUT param */
250 function->resolve_option = plpgsql_variable_conflict;
251 function->print_strict_params = plpgsql_print_strict_params;
252 /* only promote extra warnings and errors at CREATE FUNCTION time */
253 function->extra_warnings = forValidator ? plpgsql_extra_warnings : 0;
254 function->extra_errors = forValidator ? plpgsql_extra_errors : 0;
255
256 if (is_dml_trigger)
257 function->fn_is_trigger = PLPGSQL_DML_TRIGGER;
258 else if (is_event_trigger)
259 function->fn_is_trigger = PLPGSQL_EVENT_TRIGGER;
260 else
261 function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
262
263 function->fn_prokind = procStruct->prokind;
264
265 function->nstatements = 0;
266 function->requires_procedure_resowner = false;
267 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 plpgsql_ns_init();
275 plpgsql_ns_push(NameStr(procStruct->proname), PLPGSQL_LABEL_BLOCK);
276 plpgsql_DumpExecTree = false;
277 plpgsql_start_datums();
278
279 switch (function->fn_is_trigger)
280 {
281 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 MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
292
293 numargs = get_func_arg_info(procTup,
294 &argtypes, &argnames, &argmodes);
295
296 cfunc_resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
297 fcinfo->flinfo->fn_expr,
298 forValidator,
299 plpgsql_error_funcname);
300
301 in_arg_varnos = (int *) palloc(numargs * sizeof(int));
302 out_arg_variables = (PLpgSQL_variable **) palloc(numargs * sizeof(PLpgSQL_variable *));
303
304 MemoryContextSwitchTo(func_cxt);
305
306 /*
307 * Create the variables for the procedure's parameters.
308 */
309 for (i = 0; i < numargs; i++)
310 {
311 char buf[32];
312 Oid argtypeid = argtypes[i];
313 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 snprintf(buf, sizeof(buf), "$%d", i + 1);
320
321 /* Create datatype info */
322 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 if (argdtype->ttype == PLPGSQL_TTYPE_PSEUDO)
331 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 argvariable = plpgsql_build_variable((argnames &&
341 argnames[i][0] != '0円') ?
342 argnames[i] : buf,
343 0, argdtype, false);
344
345 if (argvariable->dtype == PLPGSQL_DTYPE_VAR)
346 {
347 argitemtype = PLPGSQL_NSTYPE_VAR;
348 }
349 else
350 {
351 Assert(argvariable->dtype == PLPGSQL_DTYPE_REC);
352 argitemtype = PLPGSQL_NSTYPE_REC;
353 }
354
355 /* Remember arguments in appropriate arrays */
356 if (argmode == PROARGMODE_IN ||
357 argmode == PROARGMODE_INOUT ||
358 argmode == PROARGMODE_VARIADIC)
359 in_arg_varnos[num_in_args++] = argvariable->dno;
360 if (argmode == PROARGMODE_OUT ||
361 argmode == PROARGMODE_INOUT ||
362 argmode == PROARGMODE_TABLE)
363 out_arg_variables[num_out_args++] = argvariable;
364
365 /* Add to namespace under the $n name */
366 add_parameter_name(argitemtype, argvariable->dno, buf);
367
368 /* If there's a name for the argument, make an alias */
369 if (argnames && argnames[i][0] != '0円')
370 add_parameter_name(argitemtype, argvariable->dno,
371 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 if (num_out_args > 1 ||
381 (num_out_args == 1 && function->fn_prokind == PROKIND_PROCEDURE))
382 {
383 PLpgSQL_row *row = build_row_from_vars(out_arg_variables,
384 num_out_args);
385
386 plpgsql_adddatum((PLpgSQL_datum *) row);
387 function->out_param_varno = row->dno;
388 }
389 else if (num_out_args == 1)
390 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 rettypeid = procStruct->prorettype;
403 if (IsPolymorphicType(rettypeid))
404 {
405 if (forValidator)
406 {
407 if (rettypeid == ANYARRAYOID ||
408 rettypeid == ANYCOMPATIBLEARRAYOID)
409 rettypeid = INT4ARRAYOID;
410 else if (rettypeid == ANYRANGEOID ||
411 rettypeid == ANYCOMPATIBLERANGEOID)
412 rettypeid = INT4RANGEOID;
413 else if (rettypeid == ANYMULTIRANGEOID)
414 rettypeid = INT4MULTIRANGEOID;
415 else /* ANYELEMENT or ANYNONARRAY or ANYCOMPATIBLE */
416 rettypeid = INT4OID;
417 /* XXX what could we use for ANYENUM? */
418 }
419 else
420 {
421 rettypeid = get_fn_expr_rettype(fcinfo->flinfo);
422 if (!OidIsValid(rettypeid))
423 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 function->fn_rettype = rettypeid;
435 function->fn_retset = procStruct->proretset;
436
437 /*
438 * Lookup the function's return type
439 */
440 typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(rettypeid));
441 if (!HeapTupleIsValid(typeTup))
442 elog(ERROR, "cache lookup failed for type %u", rettypeid);
443 typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
444
445 /* Disallow pseudotype result, except VOID or RECORD */
446 /* (note we already replaced polymorphic types) */
447 if (typeStruct->typtype == TYPTYPE_PSEUDO)
448 {
449 if (rettypeid == VOIDOID ||
450 rettypeid == RECORDOID)
451 /* okay */ ;
452 else if (rettypeid == TRIGGEROID || rettypeid == EVENT_TRIGGEROID)
453 ereport(ERROR,
454 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
455 errmsg("trigger functions can only be called as triggers")));
456 else
457 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 function->fn_retistuple = type_is_rowtype(rettypeid);
464 function->fn_retisdomain = (typeStruct->typtype == TYPTYPE_DOMAIN);
465 function->fn_retbyval = typeStruct->typbyval;
466 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 if (IsPolymorphicType(procStruct->prorettype) &&
474 num_out_args == 0)
475 {
476 (void) plpgsql_build_variable("0ドル", 0,
477 build_datatype(typeTup,
478 -1,
479 function->fn_input_collation,
480 NULL),
481 true);
482 }
483
484 ReleaseSysCache(typeTup);
485 break;
486
487 case PLPGSQL_DML_TRIGGER:
488 /* Trigger procedure's return type is unknown yet */
489 function->fn_rettype = InvalidOid;
490 function->fn_retbyval = false;
491 function->fn_retistuple = true;
492 function->fn_retisdomain = false;
493 function->fn_retset = false;
494
495 /* shouldn't be any declared arguments */
496 if (procStruct->pronargs != 0)
497 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 rec = plpgsql_build_record("new", 0, NULL, RECORDOID, true);
504 function->new_varno = rec->dno;
505
506 /* Add the record for referencing OLD ROW */
507 rec = plpgsql_build_record("old", 0, NULL, RECORDOID, true);
508 function->old_varno = rec->dno;
509
510 /* Add the variable tg_name */
511 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 var->dtype = PLPGSQL_DTYPE_PROMISE;
519 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_NAME;
520
521 /* Add the variable tg_when */
522 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 var->dtype = PLPGSQL_DTYPE_PROMISE;
530 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_WHEN;
531
532 /* Add the variable tg_level */
533 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 var->dtype = PLPGSQL_DTYPE_PROMISE;
541 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_LEVEL;
542
543 /* Add the variable tg_op */
544 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 var->dtype = PLPGSQL_DTYPE_PROMISE;
552 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_OP;
553
554 /* Add the variable tg_relid */
555 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 var->dtype = PLPGSQL_DTYPE_PROMISE;
563 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_RELID;
564
565 /* Add the variable tg_relname */
566 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 var->dtype = PLPGSQL_DTYPE_PROMISE;
574 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_NAME;
575
576 /* tg_table_name is now preferred to tg_relname */
577 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 var->dtype = PLPGSQL_DTYPE_PROMISE;
585 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_NAME;
586
587 /* add the variable tg_table_schema */
588 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 var->dtype = PLPGSQL_DTYPE_PROMISE;
596 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_SCHEMA;
597
598 /* Add the variable tg_nargs */
599 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 var->dtype = PLPGSQL_DTYPE_PROMISE;
607 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_NARGS;
608
609 /* Add the variable tg_argv */
610 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 var->dtype = PLPGSQL_DTYPE_PROMISE;
618 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_ARGV;
619
620 break;
621
622 case PLPGSQL_EVENT_TRIGGER:
623 function->fn_rettype = VOIDOID;
624 function->fn_retbyval = false;
625 function->fn_retistuple = true;
626 function->fn_retisdomain = false;
627 function->fn_retset = false;
628
629 /* shouldn't be any declared arguments */
630 if (procStruct->pronargs != 0)
631 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 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 var->dtype = PLPGSQL_DTYPE_PROMISE;
644 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_EVENT;
645
646 /* Add the variable tg_tag */
647 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 var->dtype = PLPGSQL_DTYPE_PROMISE;
655 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TAG;
656
657 break;
658
659 default:
660 elog(ERROR, "unrecognized function typecode: %d",
661 (int) function->fn_is_trigger);
662 break;
663 }
664
665 /* Remember if function is STABLE/IMMUTABLE */
666 function->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
667
668 /*
669 * Create the magic FOUND variable.
670 */
671 var = plpgsql_build_variable("found", 0,
672 plpgsql_build_datatype(BOOLOID,
673 -1,
674 InvalidOid,
675 NULL),
676 true);
677 function->found_varno = var->dno;
678
679 /*
680 * Now parse the function's text
681 */
682 parse_rc = plpgsql_yyparse(&function->action, scanner);
683 if (parse_rc != 0)
684 elog(ERROR, "plpgsql parser returned %d", parse_rc);
685
686 plpgsql_scanner_finish(scanner);
687 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 if (num_out_args > 0 || function->fn_rettype == VOIDOID ||
696 function->fn_retset)
697 add_dummy_return(function);
698
699 /*
700 * Complete the function's info
701 */
702 function->fn_nargs = procStruct->pronargs;
703 for (i = 0; i < function->fn_nargs; i++)
704 function->fn_argvarnos[i] = in_arg_varnos[i];
705
706 plpgsql_finish_datums(function);
707
708 if (function->has_exception_block)
709 plpgsql_mark_local_assignment_targets(function);
710
711 /* Debug dump for completed functions */
712 if (plpgsql_DumpExecTree)
713 plpgsql_dumptree(function);
714
715 /*
716 * All is well, so make the func_cxt long-lived
717 */
718 MemoryContextSetParent(func_cxt, CacheMemoryContext);
719
720 /*
721 * Pop the error context stack
722 */
723 error_context_stack = plerrcontext.previous;
724 plpgsql_error_funcname = NULL;
725
726 plpgsql_check_syntax = false;
727
728 MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
729 plpgsql_compile_tmp_cxt = NULL;
730}
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 */
742PLpgSQL_function *
743 plpgsql_compile_inline(char *proc_source)
744{
745 yyscan_t scanner;
746 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 scanner = plpgsql_scanner_init(proc_source);
758
759 plpgsql_error_funcname = func_name;
760
761 /*
762 * Setup error traceback support for ereport()
763 */
764 cbarg.proc_source = proc_source;
765 cbarg.yyscanner = scanner;
766 plerrcontext.callback = plpgsql_compile_error_callback;
767 plerrcontext.arg = &cbarg;
768 plerrcontext.previous = error_context_stack;
769 error_context_stack = &plerrcontext;
770
771 /* Do extra syntax checking if check_function_bodies is on */
772 plpgsql_check_syntax = check_function_bodies;
773
774 /* Function struct does not live past current statement */
775 function = (PLpgSQL_function *) palloc0(sizeof(PLpgSQL_function));
776
777 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 func_cxt = AllocSetContextCreate(CurrentMemoryContext,
784 "PL/pgSQL inline code context",
785 ALLOCSET_DEFAULT_SIZES);
786 plpgsql_compile_tmp_cxt = MemoryContextSwitchTo(func_cxt);
787
788 function->fn_signature = pstrdup(func_name);
789 function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
790 function->fn_input_collation = InvalidOid;
791 function->fn_cxt = func_cxt;
792 function->out_param_varno = -1; /* set up for no OUT param */
793 function->resolve_option = plpgsql_variable_conflict;
794 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 function->extra_warnings = 0;
801 function->extra_errors = 0;
802
803 function->nstatements = 0;
804 function->requires_procedure_resowner = false;
805 function->has_exception_block = false;
806
807 plpgsql_ns_init();
808 plpgsql_ns_push(func_name, PLPGSQL_LABEL_BLOCK);
809 plpgsql_DumpExecTree = false;
810 plpgsql_start_datums();
811
812 /* Set up as though in a function returning VOID */
813 function->fn_rettype = VOIDOID;
814 function->fn_retset = false;
815 function->fn_retistuple = false;
816 function->fn_retisdomain = false;
817 function->fn_prokind = PROKIND_FUNCTION;
818 /* a bit of hardwired knowledge about type VOID here */
819 function->fn_retbyval = true;
820 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 function->fn_readonly = false;
827
828 /*
829 * Create the magic FOUND variable.
830 */
831 var = plpgsql_build_variable("found", 0,
832 plpgsql_build_datatype(BOOLOID,
833 -1,
834 InvalidOid,
835 NULL),
836 true);
837 function->found_varno = var->dno;
838
839 /*
840 * Now parse the function's text
841 */
842 parse_rc = plpgsql_yyparse(&function->action, scanner);
843 if (parse_rc != 0)
844 elog(ERROR, "plpgsql parser returned %d", parse_rc);
845
846 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 if (function->fn_rettype == VOIDOID)
853 add_dummy_return(function);
854
855 /*
856 * Complete the function's info
857 */
858 function->fn_nargs = 0;
859
860 plpgsql_finish_datums(function);
861
862 if (function->has_exception_block)
863 plpgsql_mark_local_assignment_targets(function);
864
865 /* Debug dump for completed functions */
866 if (plpgsql_DumpExecTree)
867 plpgsql_dumptree(function);
868
869 /*
870 * Pop the error context stack
871 */
872 error_context_stack = plerrcontext.previous;
873 plpgsql_error_funcname = NULL;
874
875 plpgsql_check_syntax = false;
876
877 MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
878 plpgsql_compile_tmp_cxt = NULL;
879 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 */
888static void
889 plpgsql_compile_error_callback(void *arg)
890{
891 struct compile_error_callback_arg *cbarg = (struct compile_error_callback_arg *) arg;
892 yyscan_t yyscanner = cbarg->yyscanner;
893
894 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 if (function_parse_error_transpose(cbarg->proc_source))
901 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 if (plpgsql_error_funcname)
910 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 */
918static void
919 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 if (plpgsql_ns_lookup(plpgsql_ns_top(), true,
929 name, NULL, NULL,
930 NULL) != NULL)
931 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 plpgsql_ns_additem(itemtype, itemno, name);
938}
939
940/*
941 * Add a dummy RETURN statement to the given function's body
942 */
943static void
944 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 if (function->action->exceptions != NULL ||
953 function->action->label != NULL)
954 {
955 PLpgSQL_stmt_block *new;
956
957 new = palloc0(sizeof(PLpgSQL_stmt_block));
958 new->cmd_type = PLPGSQL_STMT_BLOCK;
959 new->stmtid = ++function->nstatements;
960 new->body = list_make1(function->action);
961
962 function->action = new;
963 }
964 if (function->action->body == NIL ||
965 ((PLpgSQL_stmt *) llast(function->action->body))->cmd_type != PLPGSQL_STMT_RETURN)
966 {
967 PLpgSQL_stmt_return *new;
968
969 new = palloc0(sizeof(PLpgSQL_stmt_return));
970 new->cmd_type = PLPGSQL_STMT_RETURN;
971 new->stmtid = ++function->nstatements;
972 new->expr = NULL;
973 new->retvarno = function->out_param_varno;
974
975 function->action->body = lappend(function->action->body, new);
976 }
977}
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 */
988void
989 plpgsql_parser_setup(struct ParseState *pstate, PLpgSQL_expr *expr)
990{
991 pstate->p_pre_columnref_hook = plpgsql_pre_column_ref;
992 pstate->p_post_columnref_hook = plpgsql_post_column_ref;
993 pstate->p_paramref_hook = plpgsql_param_ref;
994 /* no need to use p_coerce_param_hook */
995 pstate->p_ref_hook_state = expr;
996}
997
998/*
999 * plpgsql_pre_column_ref parser callback before parsing a ColumnRef
1000 */
1001static Node *
1002 plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref)
1003{
1004 PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1005
1006 if (expr->func->resolve_option == PLPGSQL_RESOLVE_VARIABLE)
1007 return resolve_column_ref(pstate, expr, cref, false);
1008 else
1009 return NULL;
1010}
1011
1012/*
1013 * plpgsql_post_column_ref parser callback after parsing a ColumnRef
1014 */
1015static Node *
1016 plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
1017{
1018 PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1019 Node *myvar;
1020
1021 if (expr->func->resolve_option == PLPGSQL_RESOLVE_VARIABLE)
1022 return NULL; /* we already found there's no match */
1023
1024 if (expr->func->resolve_option == PLPGSQL_RESOLVE_COLUMN && var != NULL)
1025 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 myvar = resolve_column_ref(pstate, expr, cref, (var == NULL));
1038
1039 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 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 return myvar;
1054}
1055
1056/*
1057 * plpgsql_param_ref parser callback for ParamRefs ($n symbols)
1058 */
1059static Node *
1060 plpgsql_param_ref(ParseState *pstate, ParamRef *pref)
1061{
1062 PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1063 char pname[32];
1064 PLpgSQL_nsitem *nse;
1065
1066 snprintf(pname, sizeof(pname), "$%d", pref->number);
1067
1068 nse = plpgsql_ns_lookup(expr->ns, false,
1069 pname, NULL, NULL,
1070 NULL);
1071
1072 if (nse == NULL)
1073 return NULL; /* name not known to plpgsql */
1074
1075 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 */
1086static Node *
1087 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 const char *name2 = NULL;
1094 const char *name3 = NULL;
1095 const char *colname = NULL;
1096 int nnames;
1097 int nnames_scalar = 0;
1098 int nnames_wholerow = 0;
1099 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 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 switch (list_length(cref->fields))
1119 {
1120 case 1:
1121 {
1122 Node *field1 = (Node *) linitial(cref->fields);
1123
1124 name1 = strVal(field1);
1125 nnames_scalar = 1;
1126 nnames_wholerow = 1;
1127 break;
1128 }
1129 case 2:
1130 {
1131 Node *field1 = (Node *) linitial(cref->fields);
1132 Node *field2 = (Node *) lsecond(cref->fields);
1133
1134 name1 = strVal(field1);
1135
1136 /* Whole-row reference? */
1137 if (IsA(field2, A_Star))
1138 {
1139 /* Set name2 to prevent matches to scalar variables */
1140 name2 = "*";
1141 nnames_wholerow = 1;
1142 break;
1143 }
1144
1145 name2 = strVal(field2);
1146 colname = name2;
1147 nnames_scalar = 2;
1148 nnames_wholerow = 2;
1149 nnames_field = 1;
1150 break;
1151 }
1152 case 3:
1153 {
1154 Node *field1 = (Node *) linitial(cref->fields);
1155 Node *field2 = (Node *) lsecond(cref->fields);
1156 Node *field3 = (Node *) lthird(cref->fields);
1157
1158 name1 = strVal(field1);
1159 name2 = strVal(field2);
1160
1161 /* Whole-row reference? */
1162 if (IsA(field3, A_Star))
1163 {
1164 /* Set name3 to prevent matches to scalar variables */
1165 name3 = "*";
1166 nnames_wholerow = 2;
1167 break;
1168 }
1169
1170 name3 = strVal(field3);
1171 colname = name3;
1172 nnames_field = 2;
1173 break;
1174 }
1175 default:
1176 /* too many names, ignore */
1177 return NULL;
1178 }
1179
1180 nse = plpgsql_ns_lookup(expr->ns, false,
1181 name1, name2, name3,
1182 &nnames);
1183
1184 if (nse == NULL)
1185 return NULL; /* name not known to plpgsql */
1186
1187 switch (nse->itemtype)
1188 {
1189 case PLPGSQL_NSTYPE_VAR:
1190 if (nnames == nnames_scalar)
1191 return make_datum_param(expr, nse->itemno, cref->location);
1192 break;
1193 case PLPGSQL_NSTYPE_REC:
1194 if (nnames == nnames_wholerow)
1195 return make_datum_param(expr, nse->itemno, cref->location);
1196 if (nnames == nnames_field)
1197 {
1198 /* colname could be a field in this record */
1199 PLpgSQL_rec *rec = (PLpgSQL_rec *) estate->datums[nse->itemno];
1200 int i;
1201
1202 /* search for a datum referencing this field */
1203 i = rec->firstfield;
1204 while (i >= 0)
1205 {
1206 PLpgSQL_recfield *fld = (PLpgSQL_recfield *) estate->datums[i];
1207
1208 Assert(fld->dtype == PLPGSQL_DTYPE_RECFIELD &&
1209 fld->recparentno == nse->itemno);
1210 if (strcmp(fld->fieldname, colname) == 0)
1211 {
1212 return make_datum_param(expr, i, cref->location);
1213 }
1214 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 if (error_if_no_field)
1229 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 break;
1237 default:
1238 elog(ERROR, "unrecognized plpgsql itemtype: %d", nse->itemtype);
1239 }
1240
1241 /* Name format doesn't match the plpgsql variable type */
1242 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 */
1249static Node *
1250 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 estate = expr->func->cur_estate;
1259 Assert(dno >= 0 && dno < estate->ndatums);
1260 datum = estate->datums[dno];
1261
1262 /*
1263 * Bitmapset must be allocated in function's permanent memory context
1264 */
1265 oldcontext = MemoryContextSwitchTo(expr->func->fn_cxt);
1266 expr->paramnos = bms_add_member(expr->paramnos, dno);
1267 MemoryContextSwitchTo(oldcontext);
1268
1269 param = makeNode(Param);
1270 param->paramkind = PARAM_EXTERN;
1271 param->paramid = dno + 1;
1272 plpgsql_exec_get_datum_type_info(estate,
1273 datum,
1274 &param->paramtype,
1275 &param->paramtypmod,
1276 &param->paramcollid);
1277 param->location = location;
1278
1279 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 */
1302bool
1303 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 if (lookup && plpgsql_IdentifierLookup == IDENTIFIER_LOOKUP_NORMAL)
1314 {
1315 /*
1316 * Do a lookup in the current namespace stack
1317 */
1318 ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1319 word1, NULL, NULL,
1320 NULL);
1321
1322 if (ns != NULL)
1323 {
1324 switch (ns->itemtype)
1325 {
1326 case PLPGSQL_NSTYPE_VAR:
1327 case PLPGSQL_NSTYPE_REC:
1328 wdatum->datum = plpgsql_Datums[ns->itemno];
1329 wdatum->ident = word1;
1330 wdatum->quoted = (yytxt[0] == '"');
1331 wdatum->idents = NIL;
1332 return true;
1333
1334 default:
1335 /* plpgsql_ns_lookup should never return anything else */
1336 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 word->ident = word1;
1347 word->quoted = (yytxt[0] == '"');
1348 return false;
1349}
1350
1351
1352/* ----------
1353 * plpgsql_parse_dblword Same lookup for two words
1354 * separated by a dot.
1355 * ----------
1356 */
1357bool
1358 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 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 if (plpgsql_IdentifierLookup != IDENTIFIER_LOOKUP_DECLARE)
1375 {
1376 /*
1377 * Do a lookup in the current namespace stack
1378 */
1379 ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1380 word1, word2, NULL,
1381 &nnames);
1382 if (ns != NULL)
1383 {
1384 switch (ns->itemtype)
1385 {
1386 case PLPGSQL_NSTYPE_VAR:
1387 /* Block-qualified reference to scalar variable. */
1388 wdatum->datum = plpgsql_Datums[ns->itemno];
1389 wdatum->ident = NULL;
1390 wdatum->quoted = false; /* not used */
1391 wdatum->idents = idents;
1392 return true;
1393
1394 case PLPGSQL_NSTYPE_REC:
1395 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 rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
1407 new = plpgsql_build_recfield(rec, word2);
1408
1409 wdatum->datum = (PLpgSQL_datum *) new;
1410 }
1411 else
1412 {
1413 /* Block-qualified reference to record variable. */
1414 wdatum->datum = plpgsql_Datums[ns->itemno];
1415 }
1416 wdatum->ident = NULL;
1417 wdatum->quoted = false; /* not used */
1418 wdatum->idents = idents;
1419 return true;
1420
1421 default:
1422 break;
1423 }
1424 }
1425 }
1426
1427 /* Nothing found */
1428 cword->idents = idents;
1429 return false;
1430}
1431
1432
1433/* ----------
1434 * plpgsql_parse_tripword Same lookup for three words
1435 * separated by dots.
1436 * ----------
1437 */
1438bool
1439 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 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 ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1460 word1, word2, word3,
1461 &nnames);
1462 if (ns != NULL)
1463 {
1464 switch (ns->itemtype)
1465 {
1466 case PLPGSQL_NSTYPE_REC:
1467 {
1468 PLpgSQL_rec *rec;
1469 PLpgSQL_recfield *new;
1470
1471 rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
1472 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 new = plpgsql_build_recfield(rec, word2);
1482 idents = list_make2(makeString(word1),
1483 makeString(word2));
1484 }
1485 else
1486 {
1487 /* Block-qualified reference to record variable. */
1488 new = plpgsql_build_recfield(rec, word3);
1489 idents = list_make3(makeString(word1),
1490 makeString(word2),
1491 makeString(word3));
1492 }
1493 wdatum->datum = (PLpgSQL_datum *) new;
1494 wdatum->ident = NULL;
1495 wdatum->quoted = false; /* not used */
1496 wdatum->idents = idents;
1497 return true;
1498 }
1499
1500 default:
1501 break;
1502 }
1503 }
1504 }
1505
1506 /* Nothing found */
1507 idents = list_make3(makeString(word1),
1508 makeString(word2),
1509 makeString(word3));
1510 cword->idents = idents;
1511 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 */
1522PLpgSQL_type *
1523 plpgsql_parse_wordtype(char *ident)
1524{
1525 PLpgSQL_nsitem *nse;
1526
1527 /*
1528 * Do a lookup in the current namespace stack
1529 */
1530 nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1531 ident, NULL, NULL,
1532 NULL);
1533
1534 if (nse != NULL)
1535 {
1536 switch (nse->itemtype)
1537 {
1538 case PLPGSQL_NSTYPE_VAR:
1539 return ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1540 case PLPGSQL_NSTYPE_REC:
1541 return ((PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]))->datatype;
1542 default:
1543 break;
1544 }
1545 }
1546
1547 /* No match, complain */
1548 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 */
1563PLpgSQL_type *
1564 plpgsql_parse_cwordtype(List *idents)
1565{
1566 PLpgSQL_type *dtype = NULL;
1567 PLpgSQL_nsitem *nse;
1568 int nnames;
1569 RangeVar *relvar = NULL;
1570 const char *fldname = NULL;
1571 Oid classOid;
1572 HeapTuple attrtup = NULL;
1573 HeapTuple typetup = NULL;
1574 Form_pg_attribute attrStruct;
1575 MemoryContext oldCxt;
1576
1577 /* Avoid memory leaks in the long-term function context */
1578 oldCxt = MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
1579
1580 if (list_length(idents) == 2)
1581 {
1582 /*
1583 * Do a lookup in the current namespace stack
1584 */
1585 nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1586 strVal(linitial(idents)),
1587 strVal(lsecond(idents)),
1588 NULL,
1589 &nnames);
1590
1591 if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_VAR)
1592 {
1593 /* Block-qualified reference to scalar variable. */
1594 dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1595 goto done;
1596 }
1597 else if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_REC &&
1598 nnames == 2)
1599 {
1600 /* Block-qualified reference to record variable. */
1601 dtype = ((PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]))->datatype;
1602 goto done;
1603 }
1604
1605 /*
1606 * First word could also be a table name
1607 */
1608 relvar = makeRangeVar(NULL,
1609 strVal(linitial(idents)),
1610 -1);
1611 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 rvnames = list_delete_last(list_copy(idents));
1625 relvar = makeRangeVarFromNameList(rvnames);
1626 fldname = strVal(llast(idents));
1627 }
1628
1629 /* Look up relation name. Can't lock it - we might not have privileges. */
1630 classOid = RangeVarGetRelid(relvar, NoLock, false);
1631
1632 /*
1633 * Fetch the named table field and its type
1634 */
1635 attrtup = SearchSysCacheAttName(classOid, fldname);
1636 if (!HeapTupleIsValid(attrtup))
1637 ereport(ERROR,
1638 (errcode(ERRCODE_UNDEFINED_COLUMN),
1639 errmsg("column \"%s\" of relation \"%s\" does not exist",
1640 fldname, relvar->relname)));
1641 attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1642
1643 typetup = SearchSysCache1(TYPEOID,
1644 ObjectIdGetDatum(attrStruct->atttypid));
1645 if (!HeapTupleIsValid(typetup))
1646 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 MemoryContextSwitchTo(oldCxt);
1654 dtype = build_datatype(typetup,
1655 attrStruct->atttypmod,
1656 attrStruct->attcollation,
1657 NULL);
1658 MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
1659
1660done:
1661 if (HeapTupleIsValid(attrtup))
1662 ReleaseSysCache(attrtup);
1663 if (HeapTupleIsValid(typetup))
1664 ReleaseSysCache(typetup);
1665
1666 MemoryContextSwitchTo(oldCxt);
1667 return dtype;
1668}
1669
1670/* ----------
1671 * plpgsql_parse_wordrowtype Scanner found word%ROWTYPE.
1672 * So word must be a table name.
1673 * ----------
1674 */
1675PLpgSQL_type *
1676 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 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 classOid = RelnameGetRelid(ident);
1694 if (!OidIsValid(classOid))
1695 ereport(ERROR,
1696 (errcode(ERRCODE_UNDEFINED_TABLE),
1697 errmsg("relation \"%s\" does not exist", ident)));
1698
1699 /* Some relkinds lack type OIDs */
1700 typOid = get_rel_type_id(classOid);
1701 if (!OidIsValid(typOid))
1702 ereport(ERROR,
1703 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1704 errmsg("relation \"%s\" does not have a composite type",
1705 ident)));
1706
1707 typName = makeTypeName(ident);
1708
1709 MemoryContextSwitchTo(oldCxt);
1710
1711 /* Build and return the row type struct */
1712 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 */
1720PLpgSQL_type *
1721 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 oldCxt = MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
1736
1737 /* Look up relation name. Can't lock it - we might not have privileges. */
1738 relvar = makeRangeVarFromNameList(idents);
1739 classOid = RangeVarGetRelid(relvar, NoLock, false);
1740
1741 /* Some relkinds lack type OIDs */
1742 typOid = get_rel_type_id(classOid);
1743 if (!OidIsValid(typOid))
1744 ereport(ERROR,
1745 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1746 errmsg("relation \"%s\" does not have a composite type",
1747 relvar->relname)));
1748
1749 typName = makeTypeNameFromNameList(idents);
1750
1751 MemoryContextSwitchTo(oldCxt);
1752
1753 /* Build and return the row type struct */
1754 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 */
1766PLpgSQL_variable *
1767 plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype,
1768 bool add2namespace)
1769{
1770 PLpgSQL_variable *result;
1771
1772 switch (dtype->ttype)
1773 {
1774 case PLPGSQL_TTYPE_SCALAR:
1775 {
1776 /* Ordinary scalar datatype */
1777 PLpgSQL_var *var;
1778
1779 var = palloc0(sizeof(PLpgSQL_var));
1780 var->dtype = PLPGSQL_DTYPE_VAR;
1781 var->refname = pstrdup(refname);
1782 var->lineno = lineno;
1783 var->datatype = dtype;
1784 /* other fields are left as 0, might be changed by caller */
1785
1786 /* preset to NULL */
1787 var->value = 0;
1788 var->isnull = true;
1789 var->freeval = false;
1790
1791 plpgsql_adddatum((PLpgSQL_datum *) var);
1792 if (add2namespace)
1793 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR,
1794 var->dno,
1795 refname);
1796 result = (PLpgSQL_variable *) var;
1797 break;
1798 }
1799 case PLPGSQL_TTYPE_REC:
1800 {
1801 /* Composite type -- build a record variable */
1802 PLpgSQL_rec *rec;
1803
1804 rec = plpgsql_build_record(refname, lineno,
1805 dtype, dtype->typoid,
1806 add2namespace);
1807 result = (PLpgSQL_variable *) rec;
1808 break;
1809 }
1810 case PLPGSQL_TTYPE_PSEUDO:
1811 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 default:
1818 elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
1819 result = NULL; /* keep compiler quiet */
1820 break;
1821 }
1822
1823 return result;
1824}
1825
1826/*
1827 * Build empty named record variable, and optionally add it to namespace
1828 */
1829PLpgSQL_rec *
1830 plpgsql_build_record(const char *refname, int lineno,
1831 PLpgSQL_type *dtype, Oid rectypeid,
1832 bool add2namespace)
1833{
1834 PLpgSQL_rec *rec;
1835
1836 rec = palloc0(sizeof(PLpgSQL_rec));
1837 rec->dtype = PLPGSQL_DTYPE_REC;
1838 rec->refname = pstrdup(refname);
1839 rec->lineno = lineno;
1840 /* other fields are left as 0, might be changed by caller */
1841 rec->datatype = dtype;
1842 rec->rectypeid = rectypeid;
1843 rec->firstfield = -1;
1844 rec->erh = NULL;
1845 plpgsql_adddatum((PLpgSQL_datum *) rec);
1846 if (add2namespace)
1847 plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->dno, rec->refname);
1848
1849 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 */
1856static PLpgSQL_row *
1857 build_row_from_vars(PLpgSQL_variable **vars, int numvars)
1858{
1859 PLpgSQL_row *row;
1860 int i;
1861
1862 row = palloc0(sizeof(PLpgSQL_row));
1863 row->dtype = PLPGSQL_DTYPE_ROW;
1864 row->refname = "(unnamed row)";
1865 row->lineno = -1;
1866 row->rowtupdesc = CreateTemplateTupleDesc(numvars);
1867 row->nfields = numvars;
1868 row->fieldnames = palloc(numvars * sizeof(char *));
1869 row->varnos = palloc(numvars * sizeof(int));
1870
1871 for (i = 0; i < numvars; i++)
1872 {
1873 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 switch (var->dtype)
1882 {
1883 case PLPGSQL_DTYPE_VAR:
1884 case PLPGSQL_DTYPE_PROMISE:
1885 typoid = ((PLpgSQL_var *) var)->datatype->typoid;
1886 typmod = ((PLpgSQL_var *) var)->datatype->atttypmod;
1887 typcoll = ((PLpgSQL_var *) var)->datatype->collation;
1888 break;
1889
1890 case PLPGSQL_DTYPE_REC:
1891 /* shouldn't need to revalidate rectypeid already... */
1892 typoid = ((PLpgSQL_rec *) var)->rectypeid;
1893 typmod = -1; /* don't know typmod, if it's used at all */
1894 typcoll = InvalidOid; /* composite types have no collation */
1895 break;
1896
1897 default:
1898 elog(ERROR, "unrecognized dtype: %d", var->dtype);
1899 typoid = InvalidOid; /* keep compiler quiet */
1900 typmod = 0;
1901 typcoll = InvalidOid;
1902 break;
1903 }
1904
1905 row->fieldnames[i] = var->refname;
1906 row->varnos[i] = var->dno;
1907
1908 TupleDescInitEntry(row->rowtupdesc, i + 1,
1909 var->refname,
1910 typoid, typmod,
1911 0);
1912 TupleDescInitEntryCollation(row->rowtupdesc, i + 1, typcoll);
1913 }
1914
1915 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 */
1923PLpgSQL_recfield *
1924 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 i = rec->firstfield;
1931 while (i >= 0)
1932 {
1933 PLpgSQL_recfield *fld = (PLpgSQL_recfield *) plpgsql_Datums[i];
1934
1935 Assert(fld->dtype == PLPGSQL_DTYPE_RECFIELD &&
1936 fld->recparentno == rec->dno);
1937 if (strcmp(fld->fieldname, fldname) == 0)
1938 return fld;
1939 i = fld->nextfield;
1940 }
1941
1942 /* nope, so make a new one */
1943 recfield = palloc0(sizeof(PLpgSQL_recfield));
1944 recfield->dtype = PLPGSQL_DTYPE_RECFIELD;
1945 recfield->fieldname = pstrdup(fldname);
1946 recfield->recparentno = rec->dno;
1947 recfield->rectupledescid = INVALID_TUPLEDESC_IDENTIFIER;
1948
1949 plpgsql_adddatum((PLpgSQL_datum *) recfield);
1950
1951 /* now we can link it into the parent's chain */
1952 recfield->nextfield = rec->firstfield;
1953 rec->firstfield = recfield->dno;
1954
1955 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 */
1972PLpgSQL_type *
1973 plpgsql_build_datatype(Oid typeOid, int32 typmod,
1974 Oid collation, TypeName *origtypname)
1975{
1976 HeapTuple typeTup;
1977 PLpgSQL_type *typ;
1978
1979 typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
1980 if (!HeapTupleIsValid(typeTup))
1981 elog(ERROR, "cache lookup failed for type %u", typeOid);
1982
1983 typ = build_datatype(typeTup, typmod, collation, origtypname);
1984
1985 ReleaseSysCache(typeTup);
1986
1987 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 */
1994static PLpgSQL_type *
1995 build_datatype(HeapTuple typeTup, int32 typmod,
1996 Oid collation, TypeName *origtypname)
1997{
1998 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1999 PLpgSQL_type *typ;
2000
2001 if (!typeStruct->typisdefined)
2002 ereport(ERROR,
2003 (errcode(ERRCODE_UNDEFINED_OBJECT),
2004 errmsg("type \"%s\" is only a shell",
2005 NameStr(typeStruct->typname))));
2006
2007 typ = (PLpgSQL_type *) palloc(sizeof(PLpgSQL_type));
2008
2009 typ->typname = pstrdup(NameStr(typeStruct->typname));
2010 typ->typoid = typeStruct->oid;
2011 switch (typeStruct->typtype)
2012 {
2013 case TYPTYPE_BASE:
2014 case TYPTYPE_ENUM:
2015 case TYPTYPE_RANGE:
2016 case TYPTYPE_MULTIRANGE:
2017 typ->ttype = PLPGSQL_TTYPE_SCALAR;
2018 break;
2019 case TYPTYPE_COMPOSITE:
2020 typ->ttype = PLPGSQL_TTYPE_REC;
2021 break;
2022 case TYPTYPE_DOMAIN:
2023 if (type_is_rowtype(typeStruct->typbasetype))
2024 typ->ttype = PLPGSQL_TTYPE_REC;
2025 else
2026 typ->ttype = PLPGSQL_TTYPE_SCALAR;
2027 break;
2028 case TYPTYPE_PSEUDO:
2029 if (typ->typoid == RECORDOID)
2030 typ->ttype = PLPGSQL_TTYPE_REC;
2031 else
2032 typ->ttype = PLPGSQL_TTYPE_PSEUDO;
2033 break;
2034 default:
2035 elog(ERROR, "unrecognized typtype: %d",
2036 (int) typeStruct->typtype);
2037 break;
2038 }
2039 typ->typlen = typeStruct->typlen;
2040 typ->typbyval = typeStruct->typbyval;
2041 typ->typtype = typeStruct->typtype;
2042 typ->collation = typeStruct->typcollation;
2043 if (OidIsValid(collation) && OidIsValid(typ->collation))
2044 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 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 typ->typisarray = (IsTrueArrayType(typeStruct) &&
2054 typeStruct->typstorage != TYPSTORAGE_PLAIN);
2055 }
2056 else if (typeStruct->typtype == TYPTYPE_DOMAIN)
2057 {
2058 /* we can short-circuit looking up base types if it's not varlena */
2059 typ->typisarray = (typeStruct->typlen == -1 &&
2060 typeStruct->typstorage != TYPSTORAGE_PLAIN &&
2061 OidIsValid(get_base_element_type(typeStruct->typbasetype)));
2062 }
2063 else
2064 typ->typisarray = false;
2065 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 if (typ->ttype == PLPGSQL_TTYPE_REC && typ->typoid != RECORDOID)
2074 {
2075 TypeCacheEntry *typentry;
2076
2077 typentry = lookup_type_cache(typ->typoid,
2078 TYPECACHE_TUPDESC |
2079 TYPECACHE_DOMAIN_BASE_INFO);
2080 if (typentry->typtype == TYPTYPE_DOMAIN)
2081 typentry = lookup_type_cache(typentry->domainBaseType,
2082 TYPECACHE_TUPDESC);
2083 if (typentry->tupDesc == NULL)
2084 ereport(ERROR,
2085 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2086 errmsg("type %s is not composite",
2087 format_type_be(typ->typoid))));
2088
2089 typ->origtypname = copyObject(origtypname);
2090 typ->tcache = typentry;
2091 typ->tupdesc_id = typentry->tupDesc_identifier;
2092 }
2093 else
2094 {
2095 typ->origtypname = NULL;
2096 typ->tcache = NULL;
2097 typ->tupdesc_id = 0;
2098 }
2099
2100 return typ;
2101}
2102
2103/*
2104 * Build an array type for the element type specified as argument.
2105 */
2106PLpgSQL_type *
2107 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 if (dtype->typisarray)
2116 return dtype;
2117
2118 array_typeid = get_array_type(dtype->typoid);
2119 if (!OidIsValid(array_typeid))
2120 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 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 */
2137int
2138 plpgsql_recognize_err_condition(const char *condname, bool allow_sqlstate)
2139{
2140 int i;
2141
2142 if (allow_sqlstate)
2143 {
2144 if (strlen(condname) == 5 &&
2145 strspn(condname, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") == 5)
2146 return MAKE_SQLSTATE(condname[0],
2147 condname[1],
2148 condname[2],
2149 condname[3],
2150 condname[4]);
2151 }
2152
2153 for (i = 0; exception_label_map[i].label != NULL; i++)
2154 {
2155 if (strcmp(condname, exception_label_map[i].label) == 0)
2156 return exception_label_map[i].sqlerrstate;
2157 }
2158
2159 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 */
2173PLpgSQL_condition *
2174 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 if (strcmp(condname, "others") == 0)
2186 {
2187 new = palloc(sizeof(PLpgSQL_condition));
2188 new->sqlerrstate = PLPGSQL_OTHERS;
2189 new->condname = condname;
2190 new->next = NULL;
2191 return new;
2192 }
2193
2194 prev = NULL;
2195 for (i = 0; exception_label_map[i].label != NULL; i++)
2196 {
2197 if (strcmp(condname, exception_label_map[i].label) == 0)
2198 {
2199 new = palloc(sizeof(PLpgSQL_condition));
2200 new->sqlerrstate = exception_label_map[i].sqlerrstate;
2201 new->condname = condname;
2202 new->next = prev;
2203 prev = new;
2204 }
2205 }
2206
2207 if (!prev)
2208 ereport(ERROR,
2209 (errcode(ERRCODE_UNDEFINED_OBJECT),
2210 errmsg("unrecognized exception condition \"%s\"",
2211 condname)));
2212
2213 return prev;
2214}
2215
2216/* ----------
2217 * plpgsql_start_datums Initialize datum list at compile startup.
2218 * ----------
2219 */
2220static void
2221 plpgsql_start_datums(void)
2222{
2223 datums_alloc = 128;
2224 plpgsql_nDatums = 0;
2225 /* This is short-lived, so needn't allocate in function's cxt */
2226 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 datums_last = 0;
2230}
2231
2232/* ----------
2233 * plpgsql_adddatum Add a variable, record or row
2234 * to the compiler's datum list.
2235 * ----------
2236 */
2237void
2238 plpgsql_adddatum(PLpgSQL_datum *newdatum)
2239{
2240 if (plpgsql_nDatums == datums_alloc)
2241 {
2242 datums_alloc *= 2;
2243 plpgsql_Datums = repalloc(plpgsql_Datums, sizeof(PLpgSQL_datum *) * datums_alloc);
2244 }
2245
2246 newdatum->dno = plpgsql_nDatums;
2247 plpgsql_Datums[plpgsql_nDatums++] = newdatum;
2248}
2249
2250/* ----------
2251 * plpgsql_finish_datums Copy completed datum info into function struct.
2252 * ----------
2253 */
2254static void
2255 plpgsql_finish_datums(PLpgSQL_function *function)
2256{
2257 Size copiable_size = 0;
2258 int i;
2259
2260 function->ndatums = plpgsql_nDatums;
2261 function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
2262 for (i = 0; i < plpgsql_nDatums; i++)
2263 {
2264 function->datums[i] = plpgsql_Datums[i];
2265
2266 /* This must agree with copy_plpgsql_datums on what is copiable */
2267 switch (function->datums[i]->dtype)
2268 {
2269 case PLPGSQL_DTYPE_VAR:
2270 case PLPGSQL_DTYPE_PROMISE:
2271 copiable_size += MAXALIGN(sizeof(PLpgSQL_var));
2272 break;
2273 case PLPGSQL_DTYPE_REC:
2274 copiable_size += MAXALIGN(sizeof(PLpgSQL_rec));
2275 break;
2276 default:
2277 break;
2278 }
2279 }
2280 function->copiable_size = copiable_size;
2281}
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 */
2298int
2299 plpgsql_add_initdatums(int **varnos)
2300{
2301 int i;
2302 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 for (i = datums_last; i < plpgsql_nDatums; i++)
2309 {
2310 switch (plpgsql_Datums[i]->dtype)
2311 {
2312 case PLPGSQL_DTYPE_VAR:
2313 case PLPGSQL_DTYPE_REC:
2314 n++;
2315 break;
2316
2317 default:
2318 break;
2319 }
2320 }
2321
2322 if (varnos != NULL)
2323 {
2324 if (n > 0)
2325 {
2326 *varnos = (int *) palloc(sizeof(int) * n);
2327
2328 n = 0;
2329 for (i = datums_last; i < plpgsql_nDatums; i++)
2330 {
2331 switch (plpgsql_Datums[i]->dtype)
2332 {
2333 case PLPGSQL_DTYPE_VAR:
2334 case PLPGSQL_DTYPE_REC:
2335 (*varnos)[n++] = plpgsql_Datums[i]->dno;
2336
2337 default:
2338 break;
2339 }
2340 }
2341 }
2342 else
2343 *varnos = NULL;
2344 }
2345
2346 datums_last = plpgsql_nDatums;
2347 return n;
2348}
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define NameStr(name)
Definition: c.h:751
#define MAXALIGN(LEN)
Definition: c.h:810
int32_t int32
Definition: c.h:534
#define OidIsValid(objectId)
Definition: c.h:774
size_t Size
Definition: c.h:610
void * yyscan_t
Definition: cubedata.h:65
int errdetail(const char *fmt,...)
Definition: elog.c:1207
ErrorContextCallback * error_context_stack
Definition: elog.c:95
int errhint(const char *fmt,...)
Definition: elog.c:1321
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define errcontext
Definition: elog.h:198
#define ERROR
Definition: elog.h:39
#define MAKE_SQLSTATE(ch1, ch2, ch3, ch4, ch5)
Definition: elog.h:56
#define elog(elevel,...)
Definition: elog.h:226
#define ereport(elevel,...)
Definition: elog.h:150
#define CALLED_AS_EVENT_TRIGGER(fcinfo)
Definition: event_trigger.h:49
Oid get_fn_expr_rettype(FmgrInfo *flinfo)
Definition: fmgr.c:1853
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
Definition: funcapi.c:1379
void cfunc_resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, Node *call_expr, bool forValidator, const char *proname)
Definition: funccache.c:348
CachedFunction * cached_function_compile(FunctionCallInfo fcinfo, CachedFunction *function, CachedFunctionCompileCallback ccallback, CachedFunctionDeleteCallback dcallback, Size cacheEntrySize, bool includeResultType, bool forValidator)
Definition: funccache.c:480
bool check_function_bodies
Definition: guc_tables.c:529
Assert(PointerIsAligned(start, uint64))
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
#define ident
Definition: indent_codes.h:47
i
int i
Definition: isn.c:77
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
List * lappend(List *list, void *datum)
Definition: list.c:339
List * list_copy(const List *oldlist)
Definition: list.c:1573
List * list_delete_last(List *list)
Definition: list.c:957
#define NoLock
Definition: lockdefs.h:34
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2822
Oid get_rel_type_id(Oid relid)
Definition: lsyscache.c:2146
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2999
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2954
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:531
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:473
TypeName * makeTypeName(char *typnam)
Definition: makefuncs.c:519
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1229
char * pstrdup(const char *in)
Definition: mcxt.c:1759
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:683
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1610
void pfree(void *pointer)
Definition: mcxt.c:1594
void * palloc0(Size size)
Definition: mcxt.c:1395
void * palloc(Size size)
Definition: mcxt.c:1365
MemoryContext CurrentMemoryContext
Definition: mcxt.c:160
MemoryContext CacheMemoryContext
Definition: mcxt.c:169
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
Definition: mcxt.c:658
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
char * NameListToString(const List *names)
Definition: namespace.c:3664
RangeVar * makeRangeVarFromNameList(const List *names)
Definition: namespace.c:3624
Oid RelnameGetRelid(const char *relname)
Definition: namespace.c:884
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:98
#define IsA(nodeptr, _type_)
Definition: nodes.h:164
#define copyObject(obj)
Definition: nodes.h:232
#define makeNode(_type_)
Definition: nodes.h:161
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:106
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:202
on_exit_nicely_callback function
void * arg
static char * label
Definition: pg_basebackup.c:135
while(p+4<=pend)
#define llast(l)
Definition: pg_list.h:198
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
#define lthird(l)
Definition: pg_list.h:188
#define list_make1(x1)
Definition: pg_list.h:212
#define linitial(l)
Definition: pg_list.h:178
#define list_make3(x1, x2, x3)
Definition: pg_list.h:216
#define lsecond(l)
Definition: pg_list.h:183
#define list_make2(x1, x2)
Definition: pg_list.h:214
bool function_parse_error_transpose(const char *prosrc)
Definition: pg_proc.c:1023
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
static char * buf
Definition: pg_test_fsync.c:72
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:79
static void add_dummy_return(PLpgSQL_function *function)
Definition: pl_comp.c:944
static PLpgSQL_row * build_row_from_vars(PLpgSQL_variable **vars, int numvars)
Definition: pl_comp.c:1857
PLpgSQL_condition * plpgsql_parse_err_condition(char *condname)
Definition: pl_comp.c:2174
void plpgsql_parser_setup(struct ParseState *pstate, PLpgSQL_expr *expr)
Definition: pl_comp.c:989
PLpgSQL_recfield * plpgsql_build_recfield(PLpgSQL_rec *rec, const char *fldname)
Definition: pl_comp.c:1924
int plpgsql_add_initdatums(int **varnos)
Definition: pl_comp.c:2299
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:53
static Node * make_datum_param(PLpgSQL_expr *expr, int dno, int location)
Definition: pl_comp.c:1250
int plpgsql_recognize_err_condition(const char *condname, bool allow_sqlstate)
Definition: pl_comp.c:2138
static void plpgsql_compile_error_callback(void *arg)
Definition: pl_comp.c:889
PLpgSQL_type * plpgsql_parse_cwordrowtype(List *idents)
Definition: pl_comp.c:1721
static Node * plpgsql_param_ref(ParseState *pstate, ParamRef *pref)
Definition: pl_comp.c:1060
static void plpgsql_start_datums(void)
Definition: pl_comp.c:2221
char * plpgsql_error_funcname
Definition: pl_comp.c:46
bool plpgsql_check_syntax
Definition: pl_comp.c:48
static const ExceptionLabelMap exception_label_map[]
Definition: pl_comp.c:65
PLpgSQL_type * plpgsql_build_datatype_arrayof(PLpgSQL_type *dtype)
Definition: pl_comp.c:2107
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:1973
static void plpgsql_finish_datums(PLpgSQL_function *function)
Definition: pl_comp.c:2255
PLpgSQL_function * plpgsql_curr_compile
Definition: pl_comp.c:50
PLpgSQL_function * plpgsql_compile(FunctionCallInfo fcinfo, bool forValidator)
Definition: pl_comp.c:106
bool plpgsql_parse_dblword(char *word1, char *word2, PLwdatum *wdatum, PLcword *cword)
Definition: pl_comp.c:1358
PLpgSQL_type * plpgsql_parse_wordtype(char *ident)
Definition: pl_comp.c:1523
void plpgsql_adddatum(PLpgSQL_datum *newdatum)
Definition: pl_comp.c:2238
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:43
bool plpgsql_parse_word(char *word1, const char *yytxt, bool lookup, PLwdatum *wdatum, PLword *word)
Definition: pl_comp.c:1303
bool plpgsql_DumpExecTree
Definition: pl_comp.c:47
PLpgSQL_type * plpgsql_parse_cwordtype(List *idents)
Definition: pl_comp.c:1564
static int datums_last
Definition: pl_comp.c:44
static Node * resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr, ColumnRef *cref, bool error_if_no_field)
Definition: pl_comp.c:1087
PLpgSQL_rec * plpgsql_build_record(const char *refname, int lineno, PLpgSQL_type *dtype, Oid rectypeid, bool add2namespace)
Definition: pl_comp.c:1830
static int datums_alloc
Definition: pl_comp.c:41
static void add_parameter_name(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
Definition: pl_comp.c:919
bool plpgsql_parse_tripword(char *word1, char *word2, char *word3, PLwdatum *wdatum, PLcword *cword)
Definition: pl_comp.c:1439
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:1995
static Node * plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref)
Definition: pl_comp.c:1002
PLpgSQL_type * plpgsql_parse_wordrowtype(char *ident)
Definition: pl_comp.c:1676
static Node * plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
Definition: pl_comp.c:1016
PLpgSQL_variable * plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype, bool add2namespace)
Definition: pl_comp.c:1767
PLpgSQL_function * plpgsql_compile_inline(char *proc_source)
Definition: pl_comp.c:743
int plpgsql_nDatums
Definition: pl_comp.c:42
static void plpgsql_compile_callback(FunctionCallInfo fcinfo, HeapTuple procTup, const CachedFunctionHashKey *hashkey, CachedFunction *cfunc, bool forValidator)
Definition: pl_comp.c:167
void plpgsql_exec_get_datum_type_info(PLpgSQL_execstate *estate, PLpgSQL_datum *datum, Oid *typeId, int32 *typMod, Oid *collation)
Definition: pl_exec.c:5538
void plpgsql_ns_init(void)
Definition: pl_funcs.c:43
PLpgSQL_nsitem * plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode, const char *name1, const char *name2, const char *name3, int *names_used)
Definition: pl_funcs.c:130
void plpgsql_delete_callback(CachedFunction *cfunc)
Definition: pl_funcs.c:772
void plpgsql_dumptree(PLpgSQL_function *func)
Definition: pl_funcs.c:1601
void plpgsql_mark_local_assignment_targets(PLpgSQL_function *func)
Definition: pl_funcs.c:673
void plpgsql_ns_additem(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
Definition: pl_funcs.c:92
void plpgsql_ns_push(const char *label, PLpgSQL_label_type label_type)
Definition: pl_funcs.c:54
PLpgSQL_nsitem * plpgsql_ns_top(void)
Definition: pl_funcs.c:81
int plpgsql_variable_conflict
Definition: pl_handler.c:47
int plpgsql_extra_warnings
Definition: pl_handler.c:55
bool plpgsql_print_strict_params
Definition: pl_handler.c:49
int plpgsql_extra_errors
Definition: pl_handler.c:56
IdentifierLookup plpgsql_IdentifierLookup
Definition: pl_scanner.c:26
void plpgsql_scanner_finish(yyscan_t yyscanner)
Definition: pl_scanner.c:653
yyscan_t plpgsql_scanner_init(const char *str)
Definition: pl_scanner.c:621
int plpgsql_latest_lineno(yyscan_t yyscanner)
Definition: pl_scanner.c:607
@ PLPGSQL_RESOLVE_COLUMN
Definition: plpgsql.h:188
@ PLPGSQL_RESOLVE_VARIABLE
Definition: plpgsql.h:187
@ PLPGSQL_DML_TRIGGER
Definition: plpgsql.h:950
@ PLPGSQL_NOT_TRIGGER
Definition: plpgsql.h:952
@ PLPGSQL_EVENT_TRIGGER
Definition: plpgsql.h:951
@ PLPGSQL_STMT_RETURN
Definition: plpgsql.h:116
@ PLPGSQL_STMT_BLOCK
Definition: plpgsql.h:105
@ PLPGSQL_TTYPE_PSEUDO
Definition: plpgsql.h:97
@ PLPGSQL_TTYPE_REC
Definition: plpgsql.h:96
@ PLPGSQL_TTYPE_SCALAR
Definition: plpgsql.h:95
@ IDENTIFIER_LOOKUP_DECLARE
Definition: plpgsql.h:1181
@ IDENTIFIER_LOOKUP_NORMAL
Definition: plpgsql.h:1180
@ PLPGSQL_PROMISE_TG_RELID
Definition: plpgsql.h:81
@ PLPGSQL_PROMISE_TG_WHEN
Definition: plpgsql.h:78
@ PLPGSQL_PROMISE_TG_ARGV
Definition: plpgsql.h:85
@ PLPGSQL_PROMISE_TG_TABLE_SCHEMA
Definition: plpgsql.h:83
@ PLPGSQL_PROMISE_TG_EVENT
Definition: plpgsql.h:86
@ PLPGSQL_PROMISE_TG_TABLE_NAME
Definition: plpgsql.h:82
@ PLPGSQL_PROMISE_TG_TAG
Definition: plpgsql.h:87
@ PLPGSQL_PROMISE_TG_OP
Definition: plpgsql.h:80
@ PLPGSQL_PROMISE_TG_LEVEL
Definition: plpgsql.h:79
@ PLPGSQL_PROMISE_TG_NARGS
Definition: plpgsql.h:84
@ PLPGSQL_PROMISE_TG_NAME
Definition: plpgsql.h:77
#define PLPGSQL_OTHERS
Definition: plpgsql.h:500
@ PLPGSQL_LABEL_BLOCK
Definition: plpgsql.h:54
int plpgsql_yyparse(PLpgSQL_stmt_block **plpgsql_parse_result_p, yyscan_t yyscanner)
@ PLPGSQL_DTYPE_ROW
Definition: plpgsql.h:65
@ PLPGSQL_DTYPE_PROMISE
Definition: plpgsql.h:68
@ PLPGSQL_DTYPE_RECFIELD
Definition: plpgsql.h:67
@ PLPGSQL_DTYPE_REC
Definition: plpgsql.h:66
@ PLPGSQL_DTYPE_VAR
Definition: plpgsql.h:64
PLpgSQL_nsitem_type
Definition: plpgsql.h:43
@ PLPGSQL_NSTYPE_VAR
Definition: plpgsql.h:45
@ PLPGSQL_NSTYPE_REC
Definition: plpgsql.h:46
#define snprintf
Definition: port.h:239
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:262
uint64_t Datum
Definition: postgres.h:70
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
@ PARAM_EXTERN
Definition: primnodes.h:384
static void word(struct vars *v, int dir, struct state *lp, struct state *rp)
Definition: regcomp.c:1476
char * format_procedure(Oid procedure_oid)
Definition: regproc.c:305
ParseLoc location
Definition: parsenodes.h:312
List * fields
Definition: parsenodes.h:311
struct ErrorContextCallback * previous
Definition: elog.h:297
int sqlerrstate
Definition: pl_comp.c:62
const char * label
Definition: pl_comp.c:61
void * fn_extra
Definition: fmgr.h:64
Node * fn_expr
Definition: fmgr.h:66
Oid fn_oid
Definition: fmgr.h:59
FmgrInfo * flinfo
Definition: fmgr.h:87
Definition: pg_list.h:54
Definition: nodes.h:135
Definition: plpgsql.h:1162
List * idents
Definition: plpgsql.h:1163
int dno
Definition: plpgsql.h:301
PLpgSQL_datum ** datums
Definition: plpgsql.h:1049
struct PLpgSQL_nsitem * ns
Definition: plpgsql.h:235
struct PLpgSQL_function * func
Definition: plpgsql.h:234
Bitmapset * paramnos
Definition: plpgsql.h:252
MemoryContext fn_cxt
Definition: plpgsql.h:966
struct PLpgSQL_execstate * cur_estate
Definition: plpgsql.h:1006
PLpgSQL_resolve_option resolve_option
Definition: plpgsql.h:984
int itemno
Definition: plpgsql.h:468
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:462
ExpandedRecordHeader * erh
Definition: plpgsql.h:437
int dno
Definition: plpgsql.h:415
PLpgSQL_type * datatype
Definition: plpgsql.h:429
PLpgSQL_datum_type dtype
Definition: plpgsql.h:414
int firstfield
Definition: plpgsql.h:432
Oid rectypeid
Definition: plpgsql.h:430
int lineno
Definition: plpgsql.h:417
char * refname
Definition: plpgsql.h:416
uint64 rectupledescid
Definition: plpgsql.h:452
PLpgSQL_datum_type dtype
Definition: plpgsql.h:445
char * fieldname
Definition: plpgsql.h:449
int nextfield
Definition: plpgsql.h:451
int recparentno
Definition: plpgsql.h:450
TupleDesc rowtupdesc
Definition: plpgsql.h:402
int lineno
Definition: plpgsql.h:391
PLpgSQL_datum_type dtype
Definition: plpgsql.h:388
int * varnos
Definition: plpgsql.h:406
char * refname
Definition: plpgsql.h:390
int dno
Definition: plpgsql.h:389
char ** fieldnames
Definition: plpgsql.h:405
int nfields
Definition: plpgsql.h:404
char typtype
Definition: plpgsql.h:217
TypeName * origtypname
Definition: plpgsql.h:222
bool typisarray
Definition: plpgsql.h:219
TypeCacheEntry * tcache
Definition: plpgsql.h:223
uint64 tupdesc_id
Definition: plpgsql.h:224
Oid collation
Definition: plpgsql.h:218
PLpgSQL_type_type ttype
Definition: plpgsql.h:214
Oid typoid
Definition: plpgsql.h:213
char * typname
Definition: plpgsql.h:212
int16 typlen
Definition: plpgsql.h:215
int32 atttypmod
Definition: plpgsql.h:220
bool typbyval
Definition: plpgsql.h:216
int lineno
Definition: plpgsql.h:337
PLpgSQL_datum_type dtype
Definition: plpgsql.h:334
bool freeval
Definition: plpgsql.h:358
int dno
Definition: plpgsql.h:335
bool isnull
Definition: plpgsql.h:357
PLpgSQL_type * datatype
Definition: plpgsql.h:343
char * refname
Definition: plpgsql.h:336
Datum value
Definition: plpgsql.h:356
PLpgSQL_datum_type dtype
Definition: plpgsql.h:312
bool isconst
Definition: plpgsql.h:316
char * refname
Definition: plpgsql.h:314
List * idents
Definition: plpgsql.h:1171
char * ident
Definition: plpgsql.h:1169
PLpgSQL_datum * datum
Definition: plpgsql.h:1168
bool quoted
Definition: plpgsql.h:1170
Definition: plpgsql.h:1156
ParseLoc location
Definition: parsenodes.h:322
int number
Definition: parsenodes.h:321
Definition: primnodes.h:391
ParseLoc location
Definition: primnodes.h:403
int32 paramtypmod
Definition: primnodes.h:399
int paramid
Definition: primnodes.h:396
Oid paramtype
Definition: primnodes.h:397
ParamKind paramkind
Definition: primnodes.h:395
Oid paramcollid
Definition: primnodes.h:401
void * p_ref_hook_state
Definition: parse_node.h:242
ParseParamRefHook p_paramref_hook
Definition: parse_node.h:240
PreParseColumnRefHook p_pre_columnref_hook
Definition: parse_node.h:238
PostParseColumnRefHook p_post_columnref_hook
Definition: parse_node.h:239
char * relname
Definition: primnodes.h:83
uint64 tupDesc_identifier
Definition: typcache.h:91
char typtype
Definition: typcache.h:43
TupleDesc tupDesc
Definition: typcache.h:90
Oid domainBaseType
Definition: typcache.h:115
const char * proc_source
Definition: pl_comp.c:140
Definition: zic.c:304
Definition: regcomp.c:282
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:264
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:220
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:475
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:625
#define CALLED_AS_TRIGGER(fcinfo)
Definition: trigger.h:26
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:182
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition: tupdesc.c:1026
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:842
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:386
#define INVALID_TUPLEDESC_IDENTIFIER
Definition: typcache.h:157
#define TYPECACHE_TUPDESC
Definition: typcache.h:146
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:150
String * makeString(char *str)
Definition: value.c:63
#define strVal(v)
Definition: value.h:82
const char * name

AltStyle によって変換されたページ (->オリジナル) /