OSDN Git Service

2ee06acbe0b58b3c46bd06b425af67d3bac1b530
[pg-rex/syncrep.git] / src / pl / plpgsql / src / pl_comp.c
1 /**********************************************************************
2  * pl_comp.c            - Compiler part of the PL/pgSQL
3  *                        procedural language
4  *
5  * IDENTIFICATION
6  *        $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.50 2002/09/01 16:28:06 tgl Exp $
7  *
8  *        This software is copyrighted by Jan Wieck - Hamburg.
9  *
10  *        The author hereby grants permission  to  use,  copy,  modify,
11  *        distribute,  and      license this software and its documentation
12  *        for any purpose, provided that existing copyright notices are
13  *        retained      in      all  copies  and  that  this notice is included
14  *        verbatim in any distributions. No written agreement, license,
15  *        or  royalty  fee      is required for any of the authorized uses.
16  *        Modifications to this software may be  copyrighted  by  their
17  *        author  and  need  not  follow  the licensing terms described
18  *        here, provided that the new terms are  clearly  indicated  on
19  *        the first page of each file where they apply.
20  *
21  *        IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
22  *        PARTY  FOR  DIRECT,   INDIRECT,       SPECIAL,   INCIDENTAL,   OR
23  *        CONSEQUENTIAL   DAMAGES  ARISING      OUT  OF  THE  USE  OF  THIS
24  *        SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
25  *        IF  THE  AUTHOR  HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
26  *        DAMAGE.
27  *
28  *        THE  AUTHOR  AND      DISTRIBUTORS  SPECIFICALLY       DISCLAIM       ANY
29  *        WARRANTIES,  INCLUDING,  BUT  NOT  LIMITED  TO,  THE  IMPLIED
30  *        WARRANTIES  OF  MERCHANTABILITY,      FITNESS  FOR  A  PARTICULAR
31  *        PURPOSE,      AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON
32  *        AN "AS IS" BASIS, AND THE AUTHOR      AND  DISTRIBUTORS  HAVE  NO
33  *        OBLIGATION   TO       PROVIDE   MAINTENANCE,   SUPPORT,  UPDATES,
34  *        ENHANCEMENTS, OR MODIFICATIONS.
35  *
36  **********************************************************************/
37
38 #include "plpgsql.h"
39
40 #include <ctype.h>
41 #include <setjmp.h>
42
43 #include "pl.tab.h"
44
45 #include "access/heapam.h"
46 #include "catalog/catname.h"
47 #include "catalog/namespace.h"
48 #include "catalog/pg_attribute.h"
49 #include "catalog/pg_attrdef.h"
50 #include "catalog/pg_class.h"
51 #include "catalog/pg_proc.h"
52 #include "catalog/pg_type.h"
53 #include "nodes/makefuncs.h"
54 #include "parser/gramparse.h"
55 #include "parser/parse_type.h"
56 #include "tcop/tcopprot.h"
57 #include "utils/builtins.h"
58 #include "utils/syscache.h"
59
60
61 /* ----------
62  * Variables in the parser that shouldn't go into plpgsql.h
63  * ----------
64  */
65 extern PLPGSQL_YYSTYPE plpgsql_yylval;
66
67 /* ----------
68  * Our own local and global variables
69  * ----------
70  */
71 static int      datums_alloc;
72 int                     plpgsql_nDatums;
73 PLpgSQL_datum **plpgsql_Datums;
74 static int      datums_last = 0;
75
76 int                     plpgsql_error_lineno;
77 char       *plpgsql_error_funcname;
78 int                     plpgsql_DumpExecTree = 0;
79
80 PLpgSQL_function *plpgsql_curr_compile;
81
82
83 static PLpgSQL_row *build_rowtype(Oid classOid);
84
85
86 /*
87  * This routine is a crock, and so is everyplace that calls it.  The problem
88  * is that the compiled form of a plpgsql function is allocated permanently
89  * (mostly via malloc()) and never released until backend exit.  Subsidiary
90  * data structures such as fmgr info records therefore must live forever
91  * as well.  A better implementation would store all this stuff in a per-
92  * function memory context that could be reclaimed at need.  In the meantime,
93  * fmgr_info_cxt must be called specifying TopMemoryContext so that whatever
94  * it might allocate, and whatever the eventual function might allocate using
95  * fn_mcxt, will live forever too.
96  */
97 static void
98 perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
99 {
100         fmgr_info_cxt(functionId, finfo, TopMemoryContext);
101 }
102
103
104 /* ----------
105  * plpgsql_compile              Given a pg_proc's oid, make
106  *                                              an execution tree for it.
107  * ----------
108  */
109 PLpgSQL_function *
110 plpgsql_compile(Oid fn_oid, int functype)
111 {
112         int                     parse_rc;
113         HeapTuple       procTup;
114         Form_pg_proc procStruct;
115         HeapTuple       typeTup;
116         Form_pg_type typeStruct;
117         char       *proc_source;
118         PLpgSQL_function *function;
119         PLpgSQL_var *var;
120         PLpgSQL_row *row;
121         PLpgSQL_rec *rec;
122         int                     i;
123         int                     arg_varnos[FUNC_MAX_ARGS];
124         sigjmp_buf      save_restart;
125
126         /*
127          * Lookup the pg_proc tuple by Oid
128          */
129         procTup = SearchSysCache(PROCOID,
130                                                          ObjectIdGetDatum(fn_oid),
131                                                          0, 0, 0);
132         if (!HeapTupleIsValid(procTup))
133                 elog(ERROR, "plpgsql: cache lookup for proc %u failed", fn_oid);
134
135         /*
136          * Setup the scanner input and error info
137          */
138         procStruct = (Form_pg_proc) GETSTRUCT(procTup);
139         proc_source = DatumGetCString(DirectFunctionCall1(textout,
140                                                                   PointerGetDatum(&procStruct->prosrc)));
141         plpgsql_setinput(proc_source, functype);
142         plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname));
143         plpgsql_error_lineno = 0;
144
145         /*
146          * Catch elog() so we can provide notice about where the error is
147          */
148         memcpy(&save_restart, &Warn_restart, sizeof(save_restart));
149         if (sigsetjmp(Warn_restart, 1) != 0)
150         {
151                 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
152
153                 /*
154                  * If we are the first of cascaded error catchings, print where
155                  * this happened
156                  */
157                 if (plpgsql_error_funcname != NULL)
158                 {
159                         elog(WARNING, "plpgsql: ERROR during compile of %s near line %d",
160                                  plpgsql_error_funcname, plpgsql_error_lineno);
161
162                         plpgsql_error_funcname = NULL;
163                 }
164
165                 siglongjmp(Warn_restart, 1);
166         }
167
168         /*
169          * Initialize the compiler
170          */
171         plpgsql_ns_init();
172         plpgsql_ns_push(NULL);
173         plpgsql_DumpExecTree = 0;
174
175         datums_alloc = 128;
176         plpgsql_nDatums = 0;
177         plpgsql_Datums = palloc(sizeof(PLpgSQL_datum *) * datums_alloc);
178         datums_last = 0;
179
180         /*
181          * Create the new function node
182          */
183         function = malloc(sizeof(PLpgSQL_function));
184         memset(function, 0, sizeof(PLpgSQL_function));
185         plpgsql_curr_compile = function;
186
187         function->fn_name = strdup(NameStr(procStruct->proname));
188         function->fn_oid = fn_oid;
189         function->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
190         function->fn_cmin = HeapTupleHeaderGetCmin(procTup->t_data);
191         function->fn_functype = functype;
192
193         switch (functype)
194         {
195                 case T_FUNCTION:
196
197                         /*
198                          * Normal function has a defined returntype
199                          */
200                         function->fn_rettype = procStruct->prorettype;
201                         function->fn_retset = procStruct->proretset;
202
203                         /*
204                          * Lookup the functions return type
205                          */
206                         typeTup = SearchSysCache(TYPEOID,
207                                                                 ObjectIdGetDatum(procStruct->prorettype),
208                                                                          0, 0, 0);
209                         if (!HeapTupleIsValid(typeTup))
210                                 elog(ERROR, "cache lookup for return type %u failed",
211                                          procStruct->prorettype);
212                         typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
213
214                         /* Disallow pseudotype result, except VOID or RECORD */
215                         if (typeStruct->typtype == 'p')
216                         {
217                                 if (procStruct->prorettype == VOIDOID ||
218                                         procStruct->prorettype == RECORDOID)
219                                         /* okay */;
220                                 else if (procStruct->prorettype == TRIGGEROID ||
221                                                  procStruct->prorettype == OPAQUEOID)
222                                         elog(ERROR, "plpgsql functions cannot return type %s"
223                                                  "\n\texcept when used as triggers",
224                                                  format_type_be(procStruct->prorettype));
225                                 else
226                                         elog(ERROR, "plpgsql functions cannot return type %s",
227                                                  format_type_be(procStruct->prorettype));
228                         }
229
230                         if (typeStruct->typrelid != InvalidOid ||
231                                 procStruct->prorettype == RECORDOID)
232                                 function->fn_retistuple = true;
233                         else
234                         {
235                                 function->fn_retbyval = typeStruct->typbyval;
236                                 function->fn_rettyplen = typeStruct->typlen;
237                                 function->fn_rettypelem = typeStruct->typelem;
238                                 perm_fmgr_info(typeStruct->typinput, &(function->fn_retinput));
239                         }
240                         ReleaseSysCache(typeTup);
241
242                         /*
243                          * Create the variables for the procedures parameters
244                          */
245                         for (i = 0; i < procStruct->pronargs; i++)
246                         {
247                                 char            buf[32];
248
249                                 snprintf(buf, sizeof(buf), "$%d", i + 1);       /* name for variable */
250
251                                 /*
252                                  * Get the parameters type
253                                  */
254                                 typeTup = SearchSysCache(TYPEOID,
255                                                         ObjectIdGetDatum(procStruct->proargtypes[i]),
256                                                                                  0, 0, 0);
257                                 if (!HeapTupleIsValid(typeTup))
258                                         elog(ERROR, "cache lookup for argument type %u failed",
259                                                  procStruct->proargtypes[i]);
260                                 typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
261
262                                 /* Disallow pseudotype argument */
263                                 if (typeStruct->typtype == 'p')
264                                         elog(ERROR, "plpgsql functions cannot take type %s",
265                                                  format_type_be(procStruct->proargtypes[i]));
266
267                                 if (typeStruct->typrelid != InvalidOid)
268                                 {
269                                         /*
270                                          * For tuple type parameters, we set up a record of
271                                          * that type
272                                          */
273                                         row = build_rowtype(typeStruct->typrelid);
274
275                                         row->refname = strdup(buf);
276
277                                         plpgsql_adddatum((PLpgSQL_datum *) row);
278                                         plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, row->rowno,
279                                                                            row->refname);
280
281                                         arg_varnos[i] = row->rowno;
282                                 }
283                                 else
284                                 {
285                                         /*
286                                          * Normal parameters get a var node
287                                          */
288                                         var = malloc(sizeof(PLpgSQL_var));
289                                         memset(var, 0, sizeof(PLpgSQL_var));
290                                         var->datatype = malloc(sizeof(PLpgSQL_type));
291                                         memset(var->datatype, 0, sizeof(PLpgSQL_type));
292
293                                         var->dtype = PLPGSQL_DTYPE_VAR;
294                                         var->refname = strdup(buf);
295                                         var->lineno = 0;
296                                         var->datatype->typname = strdup(NameStr(typeStruct->typname));
297                                         var->datatype->typoid = procStruct->proargtypes[i];
298                                         perm_fmgr_info(typeStruct->typinput, &(var->datatype->typinput));
299                                         var->datatype->typelem = typeStruct->typelem;
300                                         var->datatype->typbyval = typeStruct->typbyval;
301                                         var->datatype->typlen = typeStruct->typlen;
302                                         var->datatype->atttypmod = -1;
303                                         var->isconst = true;
304                                         var->notnull = false;
305                                         var->default_val = NULL;
306
307                                         plpgsql_adddatum((PLpgSQL_datum *) var);
308                                         plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno,
309                                                                            var->refname);
310
311                                         arg_varnos[i] = var->varno;
312                                 }
313                                 ReleaseSysCache(typeTup);
314                         }
315                         break;
316
317                 case T_TRIGGER:
318
319                         /*
320                          * Trigger procedures return type is unknown yet
321                          */
322                         function->fn_rettype = InvalidOid;
323                         function->fn_retbyval = false;
324                         function->fn_retistuple = true;
325                         function->fn_retset = false;
326
327                         /*
328                          * Add the record for referencing NEW
329                          */
330                         rec = malloc(sizeof(PLpgSQL_rec));
331                         memset(rec, 0, sizeof(PLpgSQL_rec));
332                         rec->dtype = PLPGSQL_DTYPE_REC;
333                         rec->refname = strdup("new");
334                         rec->tup = NULL;
335                         rec->tupdesc = NULL;
336                         rec->freetup = false;
337                         plpgsql_adddatum((PLpgSQL_datum *) rec);
338                         plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->recno, rec->refname);
339                         function->new_varno = rec->recno;
340
341                         /*
342                          * Add the record for referencing OLD
343                          */
344                         rec = malloc(sizeof(PLpgSQL_rec));
345                         memset(rec, 0, sizeof(PLpgSQL_rec));
346                         rec->dtype = PLPGSQL_DTYPE_REC;
347                         rec->refname = strdup("old");
348                         rec->tup = NULL;
349                         rec->tupdesc = NULL;
350                         rec->freetup = false;
351                         plpgsql_adddatum((PLpgSQL_datum *) rec);
352                         plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->recno, rec->refname);
353                         function->old_varno = rec->recno;
354
355                         /*
356                          * Add the variable tg_name
357                          */
358                         var = malloc(sizeof(PLpgSQL_var));
359                         memset(var, 0, sizeof(PLpgSQL_var));
360
361                         var->dtype = PLPGSQL_DTYPE_VAR;
362                         var->refname = strdup("tg_name");
363                         var->lineno = 0;
364                         var->datatype = plpgsql_parse_datatype("name");
365                         var->isconst = false;
366                         var->notnull = false;
367                         var->default_val = NULL;
368
369                         plpgsql_adddatum((PLpgSQL_datum *) var);
370                         plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
371                         function->tg_name_varno = var->varno;
372
373                         /*
374                          * Add the variable tg_when
375                          */
376                         var = malloc(sizeof(PLpgSQL_var));
377                         memset(var, 0, sizeof(PLpgSQL_var));
378
379                         var->dtype = PLPGSQL_DTYPE_VAR;
380                         var->refname = strdup("tg_when");
381                         var->lineno = 0;
382                         var->datatype = plpgsql_parse_datatype("text");
383                         var->isconst = false;
384                         var->notnull = false;
385                         var->default_val = NULL;
386
387                         plpgsql_adddatum((PLpgSQL_datum *) var);
388                         plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
389                         function->tg_when_varno = var->varno;
390
391                         /*
392                          * Add the variable tg_level
393                          */
394                         var = malloc(sizeof(PLpgSQL_var));
395                         memset(var, 0, sizeof(PLpgSQL_var));
396
397                         var->dtype = PLPGSQL_DTYPE_VAR;
398                         var->refname = strdup("tg_level");
399                         var->lineno = 0;
400                         var->datatype = plpgsql_parse_datatype("text");
401                         var->isconst = false;
402                         var->notnull = false;
403                         var->default_val = NULL;
404
405                         plpgsql_adddatum((PLpgSQL_datum *) var);
406                         plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
407                         function->tg_level_varno = var->varno;
408
409                         /*
410                          * Add the variable tg_op
411                          */
412                         var = malloc(sizeof(PLpgSQL_var));
413                         memset(var, 0, sizeof(PLpgSQL_var));
414
415                         var->dtype = PLPGSQL_DTYPE_VAR;
416                         var->refname = strdup("tg_op");
417                         var->lineno = 0;
418                         var->datatype = plpgsql_parse_datatype("text");
419                         var->isconst = false;
420                         var->notnull = false;
421                         var->default_val = NULL;
422
423                         plpgsql_adddatum((PLpgSQL_datum *) var);
424                         plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
425                         function->tg_op_varno = var->varno;
426
427                         /*
428                          * Add the variable tg_relid
429                          */
430                         var = malloc(sizeof(PLpgSQL_var));
431                         memset(var, 0, sizeof(PLpgSQL_var));
432
433                         var->dtype = PLPGSQL_DTYPE_VAR;
434                         var->refname = strdup("tg_relid");
435                         var->lineno = 0;
436                         var->datatype = plpgsql_parse_datatype("oid");
437                         var->isconst = false;
438                         var->notnull = false;
439                         var->default_val = NULL;
440
441                         plpgsql_adddatum((PLpgSQL_datum *) var);
442                         plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
443                         function->tg_relid_varno = var->varno;
444
445                         /*
446                          * Add the variable tg_relname
447                          */
448                         var = malloc(sizeof(PLpgSQL_var));
449                         memset(var, 0, sizeof(PLpgSQL_var));
450
451                         var->dtype = PLPGSQL_DTYPE_VAR;
452                         var->refname = strdup("tg_relname");
453                         var->lineno = 0;
454                         var->datatype = plpgsql_parse_datatype("name");
455                         var->isconst = false;
456                         var->notnull = false;
457                         var->default_val = NULL;
458
459                         plpgsql_adddatum((PLpgSQL_datum *) var);
460                         plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
461                         function->tg_relname_varno = var->varno;
462
463                         /*
464                          * Add the variable tg_nargs
465                          */
466                         var = malloc(sizeof(PLpgSQL_var));
467                         memset(var, 0, sizeof(PLpgSQL_var));
468
469                         var->dtype = PLPGSQL_DTYPE_VAR;
470                         var->refname = strdup("tg_nargs");
471                         var->lineno = 0;
472                         var->datatype = plpgsql_parse_datatype("int4");
473                         var->isconst = false;
474                         var->notnull = false;
475                         var->default_val = NULL;
476
477                         plpgsql_adddatum((PLpgSQL_datum *) var);
478                         plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
479                         function->tg_nargs_varno = var->varno;
480
481                         break;
482
483                 default:
484                         elog(ERROR, "unknown function type %u in plpgsql_compile()",
485                                  functype);
486                         break;
487         }
488
489         /*
490          * Create the magic FOUND variable.
491          */
492         var = malloc(sizeof(PLpgSQL_var));
493         memset(var, 0, sizeof(PLpgSQL_var));
494
495         var->dtype = PLPGSQL_DTYPE_VAR;
496         var->refname = strdup("found");
497         var->lineno = 0;
498         var->datatype = plpgsql_parse_datatype("bool");
499         var->isconst = false;
500         var->notnull = false;
501         var->default_val = NULL;
502
503         plpgsql_adddatum((PLpgSQL_datum *) var);
504         plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
505         function->found_varno = var->varno;
506
507         /*
508          * Forget about the above created variables
509          */
510         plpgsql_add_initdatums(NULL);
511
512         /*
513          * Now parse the functions text
514          */
515         parse_rc = plpgsql_yyparse();
516         if (parse_rc != 0)
517                 elog(ERROR, "plpgsql: parser returned %d ???", parse_rc);
518
519         /*
520          * If that was successful, complete the functions info.
521          */
522         function->fn_nargs = procStruct->pronargs;
523         for (i = 0; i < function->fn_nargs; i++)
524                 function->fn_argvarnos[i] = arg_varnos[i];
525         function->ndatums = plpgsql_nDatums;
526         function->datums = malloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
527         for (i = 0; i < plpgsql_nDatums; i++)
528                 function->datums[i] = plpgsql_Datums[i];
529         function->action = plpgsql_yylval.program;
530
531         ReleaseSysCache(procTup);
532
533         /*
534          * Restore the previous elog() jump target
535          */
536         plpgsql_error_funcname = NULL;
537         plpgsql_error_lineno = 0;
538         memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
539
540         /*
541          * Finally return the compiled function
542          */
543         if (plpgsql_DumpExecTree)
544                 plpgsql_dumptree(function);
545         return function;
546 }
547
548
549 /* ----------
550  * plpgsql_parse_word           The scanner calls this to postparse
551  *                              any single word not found by a
552  *                              keyword rule.
553  * ----------
554  */
555 int
556 plpgsql_parse_word(char *word)
557 {
558         PLpgSQL_nsitem *nse;
559         char       *cp[1];
560
561         /* Do case conversion and word separation */
562         plpgsql_convert_ident(word, cp, 1);
563
564         /*
565          * Recognize tg_argv when compiling triggers
566          */
567         if (plpgsql_curr_compile->fn_functype == T_TRIGGER)
568         {
569                 if (strcmp(cp[0], "tg_argv") == 0)
570                 {
571                         int                     save_spacescanned = plpgsql_SpaceScanned;
572                         PLpgSQL_trigarg *trigarg;
573
574                         trigarg = malloc(sizeof(PLpgSQL_trigarg));
575                         memset(trigarg, 0, sizeof(PLpgSQL_trigarg));
576                         trigarg->dtype = PLPGSQL_DTYPE_TRIGARG;
577
578                         if (plpgsql_yylex() != '[')
579                                 plpgsql_yyerror("expected [");
580
581                         trigarg->argnum = plpgsql_read_expression(']', "]");
582
583                         plpgsql_adddatum((PLpgSQL_datum *) trigarg);
584                         plpgsql_yylval.variable = (PLpgSQL_datum *) trigarg;
585
586                         plpgsql_SpaceScanned = save_spacescanned;
587                         pfree(cp[0]);
588                         return T_VARIABLE;
589                 }
590         }
591
592         /*
593          * Do a lookup on the compilers namestack
594          */
595         nse = plpgsql_ns_lookup(cp[0], NULL);
596         if (nse != NULL)
597         {
598                 pfree(cp[0]);
599                 switch (nse->itemtype)
600                 {
601                         case PLPGSQL_NSTYPE_LABEL:
602                                 return T_LABEL;
603
604                         case PLPGSQL_NSTYPE_VAR:
605                                 plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[nse->itemno]);
606                                 return T_VARIABLE;
607
608                         case PLPGSQL_NSTYPE_REC:
609                                 plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]);
610                                 return T_RECORD;
611
612                         case PLPGSQL_NSTYPE_ROW:
613                                 plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[nse->itemno]);
614                                 return T_ROW;
615
616                         default:
617                                 return T_ERROR;
618                 }
619         }
620
621         /*
622          * Nothing found - up to now it's a word without any special meaning
623          * for us.
624          */
625         pfree(cp[0]);
626         return T_WORD;
627 }
628
629
630 /* ----------
631  * plpgsql_parse_dblword                Same lookup for two words
632  *                                      separated by a dot.
633  * ----------
634  */
635 int
636 plpgsql_parse_dblword(char *word)
637 {
638         PLpgSQL_nsitem *ns;
639         char       *cp[2];
640
641         /* Do case conversion and word separation */
642         plpgsql_convert_ident(word, cp, 2);
643
644         /*
645          * Lookup the first word
646          */
647         ns = plpgsql_ns_lookup(cp[0], NULL);
648         if (ns == NULL)
649         {
650                 pfree(cp[0]);
651                 pfree(cp[1]);
652                 return T_ERROR;
653         }
654
655         switch (ns->itemtype)
656         {
657                 case PLPGSQL_NSTYPE_LABEL:
658
659                         /*
660                          * First word is a label, so second word could be a variable,
661                          * record or row in that bodies namestack. Anything else could
662                          * only be something in a query given to the SPI manager and
663                          * T_ERROR will get eaten up by the collector routines.
664                          */
665                         ns = plpgsql_ns_lookup(cp[1], cp[0]);
666                         pfree(cp[0]);
667                         pfree(cp[1]);
668                         if (ns == NULL)
669                                 return T_ERROR;
670                         switch (ns->itemtype)
671                         {
672                                 case PLPGSQL_NSTYPE_VAR:
673                                         plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[ns->itemno]);
674                                         return T_VARIABLE;
675
676                                 case PLPGSQL_NSTYPE_REC:
677                                         plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
678                                         return T_RECORD;
679
680                                 case PLPGSQL_NSTYPE_ROW:
681                                         plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
682                                         return T_ROW;
683
684                                 default:
685                                         return T_ERROR;
686                         }
687                         break;
688
689                 case PLPGSQL_NSTYPE_REC:
690                         {
691                                 /*
692                                  * First word is a record name, so second word must be a
693                                  * field in this record.
694                                  */
695                                 PLpgSQL_recfield *new;
696
697                                 new = malloc(sizeof(PLpgSQL_recfield));
698                                 new->dtype = PLPGSQL_DTYPE_RECFIELD;
699                                 new->fieldname = strdup(cp[1]);
700                                 new->recno = ns->itemno;
701
702                                 plpgsql_adddatum((PLpgSQL_datum *) new);
703
704                                 plpgsql_yylval.variable = (PLpgSQL_datum *) new;
705
706                                 pfree(cp[0]);
707                                 pfree(cp[1]);
708                                 return T_VARIABLE;
709                         }
710
711                 case PLPGSQL_NSTYPE_ROW:
712                         {
713                                 /*
714                                  * First word is a row name, so second word must be a
715                                  * field in this row.
716                                  */
717                                 PLpgSQL_row *row;
718                                 int                     i;
719
720                                 row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
721                                 for (i = 0; i < row->nfields; i++)
722                                 {
723                                         if (strcmp(row->fieldnames[i], cp[1]) == 0)
724                                         {
725                                                 plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[row->varnos[i]]);
726                                                 pfree(cp[0]);
727                                                 pfree(cp[1]);
728                                                 return T_VARIABLE;
729                                         }
730                                 }
731                                 elog(ERROR, "row %s doesn't have a field %s",
732                                          cp[0], cp[1]);
733                         }
734
735                 default:
736                         break;
737         }
738
739         pfree(cp[0]);
740         pfree(cp[1]);
741         return T_ERROR;
742 }
743
744
745 /* ----------
746  * plpgsql_parse_tripword               Same lookup for three words
747  *                                      separated by dots.
748  * ----------
749  */
750 int
751 plpgsql_parse_tripword(char *word)
752 {
753         PLpgSQL_nsitem *ns;
754         char       *cp[3];
755
756         /* Do case conversion and word separation */
757         plpgsql_convert_ident(word, cp, 3);
758
759         /*
760          * Lookup the first word - it must be a label
761          */
762         ns = plpgsql_ns_lookup(cp[0], NULL);
763         if (ns == NULL)
764         {
765                 pfree(cp[0]);
766                 pfree(cp[1]);
767                 pfree(cp[2]);
768                 return T_ERROR;
769         }
770         if (ns->itemtype != PLPGSQL_NSTYPE_LABEL)
771         {
772                 pfree(cp[0]);
773                 pfree(cp[1]);
774                 pfree(cp[2]);
775                 return T_ERROR;
776         }
777
778         /*
779          * First word is a label, so second word could be a record or row
780          */
781         ns = plpgsql_ns_lookup(cp[1], cp[0]);
782         if (ns == NULL)
783         {
784                 pfree(cp[0]);
785                 pfree(cp[1]);
786                 pfree(cp[2]);
787                 return T_ERROR;
788         }
789
790         switch (ns->itemtype)
791         {
792                 case PLPGSQL_NSTYPE_REC:
793                         {
794                                 /*
795                                  * This word is a record name, so third word must be a
796                                  * field in this record.
797                                  */
798                                 PLpgSQL_recfield *new;
799
800                                 new = malloc(sizeof(PLpgSQL_recfield));
801                                 new->dtype = PLPGSQL_DTYPE_RECFIELD;
802                                 new->fieldname = strdup(cp[2]);
803                                 new->recno = ns->itemno;
804
805                                 plpgsql_adddatum((PLpgSQL_datum *) new);
806
807                                 plpgsql_yylval.variable = (PLpgSQL_datum *) new;
808
809                                 pfree(cp[0]);
810                                 pfree(cp[1]);
811                                 pfree(cp[2]);
812                                 return T_VARIABLE;
813                         }
814
815                 case PLPGSQL_NSTYPE_ROW:
816                         {
817                                 /*
818                                  * This word is a row name, so third word must be a field
819                                  * in this row.
820                                  */
821                                 PLpgSQL_row *row;
822                                 int                     i;
823
824                                 row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
825                                 for (i = 0; i < row->nfields; i++)
826                                 {
827                                         if (strcmp(row->fieldnames[i], cp[2]) == 0)
828                                         {
829                                                 plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[row->varnos[i]]);
830                                                 pfree(cp[0]);
831                                                 pfree(cp[1]);
832                                                 pfree(cp[2]);
833                                                 return T_VARIABLE;
834                                         }
835                                 }
836                                 elog(ERROR, "row %s.%s doesn't have a field %s",
837                                          cp[0], cp[1], cp[2]);
838                         }
839
840                 default:
841                         break;
842         }
843
844         pfree(cp[0]);
845         pfree(cp[1]);
846         pfree(cp[2]);
847         return T_ERROR;
848 }
849
850
851 /* ----------
852  * plpgsql_parse_wordtype       The scanner found word%TYPE. word can be
853  *                              a variable name or a basetype.
854  * ----------
855  */
856 int
857 plpgsql_parse_wordtype(char *word)
858 {
859         PLpgSQL_nsitem *nse;
860         bool            old_nsstate;
861         Oid                     typeOid;
862         char       *cp[2];
863         int                     i;
864
865         /* Do case conversion and word separation */
866         /* We convert %type to .type momentarily to keep converter happy */
867         i = strlen(word) - 5;
868         Assert(word[i] == '%');
869         word[i] = '.';
870         plpgsql_convert_ident(word, cp, 2);
871         word[i] = '%';
872         pfree(cp[1]);
873
874         /*
875          * Do a lookup on the compilers namestack. But ensure it moves up to
876          * the toplevel.
877          */
878         old_nsstate = plpgsql_ns_setlocal(false);
879         nse = plpgsql_ns_lookup(cp[0], NULL);
880         plpgsql_ns_setlocal(old_nsstate);
881
882         if (nse != NULL)
883         {
884                 pfree(cp[0]);
885                 switch (nse->itemtype)
886                 {
887                         case PLPGSQL_NSTYPE_VAR:
888                                 plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
889                                 return T_DTYPE;
890
891                         default:
892                                 return T_ERROR;
893                 }
894         }
895
896         /*
897          * Word wasn't found on the namestack. Try to find a data type with
898          * that name, but ignore pg_type entries that are in fact class types.
899          */
900         typeOid = LookupTypeName(makeTypeName(cp[0]));
901         if (OidIsValid(typeOid))
902         {
903                 HeapTuple       typeTup;
904
905                 typeTup = SearchSysCache(TYPEOID,
906                                                                  ObjectIdGetDatum(typeOid),
907                                                                  0, 0, 0);
908                 if (HeapTupleIsValid(typeTup))
909                 {
910                         Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
911                         PLpgSQL_type *typ;
912
913                         if (!typeStruct->typisdefined ||
914                                 typeStruct->typrelid != InvalidOid)
915                         {
916                                 ReleaseSysCache(typeTup);
917                                 pfree(cp[0]);
918                                 return T_ERROR;
919                         }
920
921                         typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type));
922
923                         typ->typname = strdup(NameStr(typeStruct->typname));
924                         typ->typoid = typeOid;
925                         perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
926                         typ->typelem = typeStruct->typelem;
927                         typ->typbyval = typeStruct->typbyval;
928                         typ->typlen = typeStruct->typlen;
929                         typ->atttypmod = -1;
930
931                         plpgsql_yylval.dtype = typ;
932
933                         ReleaseSysCache(typeTup);
934                         pfree(cp[0]);
935                         return T_DTYPE;
936                 }
937         }
938
939         /*
940          * Nothing found - up to now it's a word without any special meaning
941          * for us.
942          */
943         pfree(cp[0]);
944         return T_ERROR;
945 }
946
947
948 /* ----------
949  * plpgsql_parse_dblwordtype            Same lookup for word.word%TYPE
950  * ----------
951  */
952 int
953 plpgsql_parse_dblwordtype(char *word)
954 {
955         PLpgSQL_nsitem *nse;
956         bool            old_nsstate;
957         Oid                     classOid;
958         HeapTuple       classtup;
959         Form_pg_class classStruct;
960         HeapTuple       attrtup;
961         Form_pg_attribute attrStruct;
962         HeapTuple       typetup;
963         Form_pg_type typeStruct;
964         PLpgSQL_type *typ;
965         char       *cp[3];
966         int                     i;
967
968         /* Do case conversion and word separation */
969         /* We convert %type to .type momentarily to keep converter happy */
970         i = strlen(word) - 5;
971         Assert(word[i] == '%');
972         word[i] = '.';
973         plpgsql_convert_ident(word, cp, 3);
974         word[i] = '%';
975         pfree(cp[2]);
976
977         /*
978          * Lookup the first word
979          */
980         nse = plpgsql_ns_lookup(cp[0], NULL);
981
982         /*
983          * If this is a label lookup the second word in that labels namestack
984          * level
985          */
986         if (nse != NULL)
987         {
988                 if (nse->itemtype == PLPGSQL_NSTYPE_LABEL)
989                 {
990                         old_nsstate = plpgsql_ns_setlocal(false);
991                         nse = plpgsql_ns_lookup(cp[1], cp[0]);
992                         plpgsql_ns_setlocal(old_nsstate);
993
994                         pfree(cp[0]);
995                         pfree(cp[1]);
996
997                         if (nse != NULL)
998                         {
999                                 switch (nse->itemtype)
1000                                 {
1001                                         case PLPGSQL_NSTYPE_VAR:
1002                                                 plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1003                                                 return T_DTYPE;
1004
1005                                         default:
1006                                                 return T_ERROR;
1007                                 }
1008                         }
1009                         return T_ERROR;
1010                 }
1011                 pfree(cp[0]);
1012                 pfree(cp[1]);
1013                 return T_ERROR;
1014         }
1015
1016         /*
1017          * First word could also be a table name
1018          */
1019         classOid = RelnameGetRelid(cp[0]);
1020         if (!OidIsValid(classOid))
1021         {
1022                 pfree(cp[0]);
1023                 pfree(cp[1]);
1024                 return T_ERROR;
1025         }
1026         classtup = SearchSysCache(RELOID,
1027                                                           ObjectIdGetDatum(classOid),
1028                                                           0, 0, 0);
1029         if (!HeapTupleIsValid(classtup))
1030         {
1031                 pfree(cp[0]);
1032                 pfree(cp[1]);
1033                 return T_ERROR;
1034         }
1035
1036         /*
1037          * It must be a relation, sequence, view, or type
1038          */
1039         classStruct = (Form_pg_class) GETSTRUCT(classtup);
1040         if (classStruct->relkind != RELKIND_RELATION &&
1041                 classStruct->relkind != RELKIND_SEQUENCE &&
1042                 classStruct->relkind != RELKIND_VIEW &&
1043                 classStruct->relkind != RELKIND_COMPOSITE_TYPE)
1044         {
1045                 ReleaseSysCache(classtup);
1046                 pfree(cp[0]);
1047                 pfree(cp[1]);
1048                 return T_ERROR;
1049         }
1050
1051         /*
1052          * Fetch the named table field and it's type
1053          */
1054         attrtup = SearchSysCacheAttName(classOid, cp[1]);
1055         if (!HeapTupleIsValid(attrtup))
1056         {
1057                 ReleaseSysCache(classtup);
1058                 pfree(cp[0]);
1059                 pfree(cp[1]);
1060                 return T_ERROR;
1061         }
1062         attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1063
1064         typetup = SearchSysCache(TYPEOID,
1065                                                          ObjectIdGetDatum(attrStruct->atttypid),
1066                                                          0, 0, 0);
1067         if (!HeapTupleIsValid(typetup))
1068                 elog(ERROR, "cache lookup for type %u of %s.%s failed",
1069                          attrStruct->atttypid, cp[0], cp[1]);
1070         typeStruct = (Form_pg_type) GETSTRUCT(typetup);
1071
1072         /*
1073          * Found that - build a compiler type struct and return it
1074          */
1075         typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type));
1076
1077         typ->typname = strdup(NameStr(typeStruct->typname));
1078         typ->typoid = attrStruct->atttypid;
1079         perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
1080         typ->typelem = typeStruct->typelem;
1081         typ->typbyval = typeStruct->typbyval;
1082         typ->typlen = typeStruct->typlen;
1083         typ->atttypmod = attrStruct->atttypmod;
1084
1085         plpgsql_yylval.dtype = typ;
1086
1087         ReleaseSysCache(classtup);
1088         ReleaseSysCache(attrtup);
1089         ReleaseSysCache(typetup);
1090         pfree(cp[0]);
1091         pfree(cp[1]);
1092         return T_DTYPE;
1093 }
1094
1095
1096 /* ----------
1097  * plpgsql_parse_wordrowtype            Scanner found word%ROWTYPE.
1098  *                                      So word must be a table name.
1099  * ----------
1100  */
1101 int
1102 plpgsql_parse_wordrowtype(char *word)
1103 {
1104         Oid                     classOid;
1105         char       *cp[2];
1106         int                     i;
1107
1108         /* Do case conversion and word separation */
1109         /* We convert %rowtype to .rowtype momentarily to keep converter happy */
1110         i = strlen(word) - 8;
1111         Assert(word[i] == '%');
1112         word[i] = '.';
1113         plpgsql_convert_ident(word, cp, 2);
1114         word[i] = '%';
1115
1116         /* Lookup the relation */
1117         classOid = RelnameGetRelid(cp[0]);
1118         if (!OidIsValid(classOid))
1119                 elog(ERROR, "%s: no such class", cp[0]);
1120
1121         /*
1122          * Build and return the complete row definition
1123          */
1124         plpgsql_yylval.row = build_rowtype(classOid);
1125
1126         pfree(cp[0]);
1127         pfree(cp[1]);
1128
1129         return T_ROW;
1130 }
1131
1132 /*
1133  * Build a rowtype data structure given the pg_class OID.
1134  */
1135 static PLpgSQL_row *
1136 build_rowtype(Oid classOid)
1137 {
1138         PLpgSQL_row *row;
1139         HeapTuple       classtup;
1140         Form_pg_class classStruct;
1141         const char  *relname;
1142         int                     i;
1143
1144         /*
1145          * Fetch the pg_class tuple.
1146          */
1147         classtup = SearchSysCache(RELOID,
1148                                                           ObjectIdGetDatum(classOid),
1149                                                           0, 0, 0);
1150         if (!HeapTupleIsValid(classtup))
1151                 elog(ERROR, "cache lookup failed for relation %u", classOid);
1152         classStruct = (Form_pg_class) GETSTRUCT(classtup);
1153         relname = NameStr(classStruct->relname);
1154
1155         /* accept relation, sequence, view, or type pg_class entries */
1156         if (classStruct->relkind != RELKIND_RELATION &&
1157                 classStruct->relkind != RELKIND_SEQUENCE &&
1158                 classStruct->relkind != RELKIND_VIEW &&
1159                 classStruct->relkind != RELKIND_COMPOSITE_TYPE)
1160                 elog(ERROR, "%s isn't a table", relname);
1161
1162         /*
1163          * Create a row datum entry and all the required variables that it
1164          * will point to.
1165          */
1166         row = malloc(sizeof(PLpgSQL_row));
1167         memset(row, 0, sizeof(PLpgSQL_row));
1168
1169         row->dtype = PLPGSQL_DTYPE_ROW;
1170         row->nfields = classStruct->relnatts;
1171         row->rowtypeclass = classStruct->reltype;
1172         row->fieldnames = malloc(sizeof(char *) * row->nfields);
1173         row->varnos = malloc(sizeof(int) * row->nfields);
1174
1175         for (i = 0; i < row->nfields; i++)
1176         {
1177                 HeapTuple       attrtup;
1178                 Form_pg_attribute attrStruct;
1179                 HeapTuple       typetup;
1180                 Form_pg_type typeStruct;
1181                 const char         *attname;
1182                 PLpgSQL_var *var;
1183
1184                 /*
1185                  * Get the attribute and it's type
1186                  */
1187                 attrtup = SearchSysCache(ATTNUM,
1188                                                                  ObjectIdGetDatum(classOid),
1189                                                                  Int16GetDatum(i + 1),
1190                                                                  0, 0);
1191                 if (!HeapTupleIsValid(attrtup))
1192                         elog(ERROR, "cache lookup for attribute %d of class %s failed",
1193                                  i + 1, relname);
1194                 attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1195
1196                 attname = NameStr(attrStruct->attname);
1197
1198                 typetup = SearchSysCache(TYPEOID,
1199                                                                  ObjectIdGetDatum(attrStruct->atttypid),
1200                                                                  0, 0, 0);
1201                 if (!HeapTupleIsValid(typetup))
1202                         elog(ERROR, "cache lookup for type %u of %s.%s failed",
1203                                  attrStruct->atttypid, relname, attname);
1204                 typeStruct = (Form_pg_type) GETSTRUCT(typetup);
1205
1206                 /*
1207                  * Create the internal variable
1208                  *
1209                  * We know if the table definitions contain a default value or if the
1210                  * field is declared in the table as NOT NULL. But it's possible
1211                  * to create a table field as NOT NULL without a default value and
1212                  * that would lead to problems later when initializing the
1213                  * variables due to entering a block at execution time. Thus we
1214                  * ignore this information for now.
1215                  */
1216                 var = malloc(sizeof(PLpgSQL_var));
1217                 memset(var, 0, sizeof(PLpgSQL_var));
1218                 var->dtype = PLPGSQL_DTYPE_VAR;
1219                 var->refname = malloc(strlen(relname) + strlen(attname) + 2);
1220                 strcpy(var->refname, relname);
1221                 strcat(var->refname, ".");
1222                 strcat(var->refname, attname);
1223                 var->datatype = malloc(sizeof(PLpgSQL_type));
1224                 var->datatype->typname = strdup(NameStr(typeStruct->typname));
1225                 var->datatype->typoid = attrStruct->atttypid;
1226                 perm_fmgr_info(typeStruct->typinput, &(var->datatype->typinput));
1227                 var->datatype->typelem = typeStruct->typelem;
1228                 var->datatype->typbyval = typeStruct->typbyval;
1229                 var->datatype->typlen = typeStruct->typlen;
1230                 var->datatype->atttypmod = attrStruct->atttypmod;
1231                 var->isconst = false;
1232                 var->notnull = false;
1233                 var->default_val = NULL;
1234                 var->value = (Datum) 0;
1235                 var->isnull = true;
1236                 var->freeval = false;
1237
1238                 plpgsql_adddatum((PLpgSQL_datum *) var);
1239
1240                 /*
1241                  * Add the variable to the row.
1242                  */
1243                 row->fieldnames[i] = strdup(attname);
1244                 row->varnos[i] = var->varno;
1245
1246                 ReleaseSysCache(typetup);
1247                 ReleaseSysCache(attrtup);
1248         }
1249
1250         ReleaseSysCache(classtup);
1251
1252         return row;
1253 }
1254
1255
1256 /* ----------
1257  * plpgsql_parse_datatype                       Scanner found something that should
1258  *                                      be a datatype name.
1259  * ----------
1260  */
1261 PLpgSQL_type *
1262 plpgsql_parse_datatype(char *string)
1263 {
1264         Oid                     type_id;
1265         int32           typmod;
1266         HeapTuple       typeTup;
1267         Form_pg_type typeStruct;
1268         PLpgSQL_type *typ;
1269
1270         /* Let the main parser try to parse it under standard SQL rules */
1271         parseTypeString(string, &type_id, &typmod);
1272
1273         /* Okay, build a PLpgSQL_type data structure for it */
1274         typeTup = SearchSysCache(TYPEOID,
1275                                                          ObjectIdGetDatum(type_id),
1276                                                          0, 0, 0);
1277         if (!HeapTupleIsValid(typeTup))
1278                 elog(ERROR, "cache lookup failed for type %u", type_id);
1279         typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1280
1281         typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type));
1282
1283         typ->typname = strdup(NameStr(typeStruct->typname));
1284         typ->typoid = type_id;
1285         perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
1286         typ->typelem = typeStruct->typelem;
1287         typ->typbyval = typeStruct->typbyval;
1288         typ->typlen = typeStruct->typlen;
1289         typ->atttypmod = typmod;
1290
1291         ReleaseSysCache(typeTup);
1292
1293         return typ;
1294 }
1295
1296
1297 /* ----------
1298  * plpgsql_adddatum                     Add a variable, record or row
1299  *                                      to the compilers datum list.
1300  * ----------
1301  */
1302 void
1303 plpgsql_adddatum(PLpgSQL_datum * new)
1304 {
1305         if (plpgsql_nDatums == datums_alloc)
1306         {
1307                 datums_alloc *= 2;
1308                 plpgsql_Datums = repalloc(plpgsql_Datums, sizeof(PLpgSQL_datum *) * datums_alloc);
1309         }
1310
1311         new->dno = plpgsql_nDatums;
1312         plpgsql_Datums[plpgsql_nDatums++] = new;
1313 }
1314
1315
1316 /* ----------
1317  * plpgsql_add_initdatums               Put all datum entries created
1318  *                                      since the last call into the
1319  *                                      finishing code block so the
1320  *                                      block knows which variables to
1321  *                                      reinitialize when entered.
1322  * ----------
1323  */
1324 int
1325 plpgsql_add_initdatums(int **varnos)
1326 {
1327         int                     i;
1328         int                     n = 0;
1329
1330         for (i = datums_last; i < plpgsql_nDatums; i++)
1331         {
1332                 switch (plpgsql_Datums[i]->dtype)
1333                 {
1334                         case PLPGSQL_DTYPE_VAR:
1335                                 n++;
1336                                 break;
1337
1338                         default:
1339                                 break;
1340                 }
1341         }
1342
1343         if (varnos != NULL)
1344         {
1345                 *varnos = (int *) malloc(sizeof(int) * n);
1346
1347                 n = 0;
1348                 for (i = datums_last; i < plpgsql_nDatums; i++)
1349                 {
1350                         switch (plpgsql_Datums[i]->dtype)
1351                         {
1352                                 case PLPGSQL_DTYPE_VAR:
1353                                         (*varnos)[n++] = plpgsql_Datums[i]->dno;
1354
1355                                 default:
1356                                         break;
1357                         }
1358                 }
1359         }
1360
1361         datums_last = plpgsql_nDatums;
1362         return n;
1363 }
1364
1365
1366 /* ---------
1367  * plpgsql_yyerror                      Handle parser error
1368  * ---------
1369  */
1370
1371 void
1372 plpgsql_yyerror(const char *s)
1373 {
1374         plpgsql_error_lineno = plpgsql_yylineno;
1375         elog(ERROR, "%s at or near \"%s\"", s, plpgsql_yytext);
1376 }