2 /**********************************************************************
3 * gram.y - Parser for the PL/pgSQL
7 * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.30 2002/03/02 21:39:35 momjian Exp $
9 * This software is copyrighted by Jan Wieck - Hamburg.
11 * The author hereby grants permission to use, copy, modify,
12 * distribute, and license this software and its documentation
13 * for any purpose, provided that existing copyright notices are
14 * retained in all copies and that this notice is included
15 * verbatim in any distributions. No written agreement, license,
16 * or royalty fee is required for any of the authorized uses.
17 * Modifications to this software may be copyrighted by their
18 * author and need not follow the licensing terms described
19 * here, provided that the new terms are clearly indicated on
20 * the first page of each file where they apply.
22 * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
23 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
24 * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
25 * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
26 * IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
29 * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
30 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
32 * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
33 * AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
34 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
35 * ENHANCEMENTS, OR MODIFICATIONS.
37 **********************************************************************/
42 static PLpgSQL_expr *read_sql_construct(int until,
45 const char *sqlstart);
46 static PLpgSQL_expr *read_sql_stmt(const char *sqlstart);
47 static PLpgSQL_type *read_datatype(int tok);
48 static PLpgSQL_stmt *make_select_stmt(void);
49 static PLpgSQL_stmt *make_fetch_stmt(void);
50 static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
72 PLpgSQL_diag_item *dtitems;
89 PLpgSQL_recfield *recfield;
90 PLpgSQL_trigarg *trigarg;
94 PLpgSQL_stmt_block *program;
95 PLpgSQL_nsitem *nsitem;
98 %type <declhdr> decl_sect
99 %type <varname> decl_varname
100 %type <str> decl_renname
101 %type <ival> decl_const, decl_notnull
102 %type <expr> decl_defval, decl_cursor_query
103 %type <dtype> decl_datatype
104 %type <row> decl_rowtype, decl_cursor_args, decl_cursor_arglist
105 %type <nsitem> decl_aliasitem
106 %type <str> decl_stmts, decl_stmt
108 %type <expr> expr_until_semi, expr_until_then, expr_until_loop
109 %type <expr> opt_exitcond
111 %type <ival> assign_var, cursor_variable
112 %type <var> fori_var, cursor_varptr, decl_cursor_arg
113 %type <varname> fori_varname
114 %type <forilow> fori_lower
115 %type <rec> fors_target
117 %type <str> opt_lblname, opt_label
118 %type <str> opt_exitlabel
119 %type <str> execsql_start
121 %type <stmts> proc_sect, proc_stmts, stmt_else, loop_body
122 %type <stmt> proc_stmt, pl_block
123 %type <stmt> stmt_assign, stmt_if, stmt_loop, stmt_while, stmt_exit
124 %type <stmt> stmt_return, stmt_raise, stmt_execsql, stmt_fori
125 %type <stmt> stmt_fors, stmt_select, stmt_perform
126 %type <stmt> stmt_dynexecute, stmt_dynfors, stmt_getdiag
127 %type <stmt> stmt_open, stmt_fetch, stmt_close
129 %type <intlist> raise_params
130 %type <ival> raise_level, raise_param
131 %type <str> raise_msg
133 %type <dtlist> getdiag_list
134 %type <ival> getdiag_item, getdiag_target
209 pl_function : T_FUNCTION comp_optsect pl_block opt_semi
211 yylval.program = (PLpgSQL_stmt_block *)$3;
213 | T_TRIGGER comp_optsect pl_block opt_semi
215 yylval.program = (PLpgSQL_stmt_block *)$3;
223 comp_options : comp_options comp_option
227 comp_option : O_OPTION O_DUMP
229 plpgsql_DumpExecTree = 1;
237 pl_block : decl_sect K_BEGIN lno proc_sect K_END
239 PLpgSQL_stmt_block *new;
241 new = malloc(sizeof(PLpgSQL_stmt_block));
242 memset(new, 0, sizeof(PLpgSQL_stmt_block));
244 new->cmd_type = PLPGSQL_STMT_BLOCK;
246 new->label = $1.label;
247 new->n_initvars = $1.n_initvars;
248 new->initvarnos = $1.initvarnos;
253 $$ = (PLpgSQL_stmt *)new;
258 decl_sect : opt_label
260 plpgsql_ns_setlocal(false);
263 $$.initvarnos = NULL;
264 plpgsql_add_initdatums(NULL);
266 | opt_label decl_start
268 plpgsql_ns_setlocal(false);
271 $$.initvarnos = NULL;
272 plpgsql_add_initdatums(NULL);
274 | opt_label decl_start decl_stmts
276 plpgsql_ns_setlocal(false);
281 $$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos));
285 decl_start : K_DECLARE
287 plpgsql_ns_setlocal(true);
291 decl_stmts : decl_stmts decl_stmt
297 decl_stmt : '<' '<' opt_lblname '>' '>'
305 decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
309 new = malloc(sizeof(PLpgSQL_var));
310 memset(new, 0, sizeof(PLpgSQL_var));
312 new->dtype = PLPGSQL_DTYPE_VAR;
313 new->refname = $1.name;
314 new->lineno = $1.lineno;
319 new->default_val = $5;
321 plpgsql_adddatum((PLpgSQL_datum *)new);
322 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
325 | decl_varname K_RECORD ';'
329 new = malloc(sizeof(PLpgSQL_rec));
331 new->dtype = PLPGSQL_DTYPE_REC;
332 new->refname = $1.name;
333 new->lineno = $1.lineno;
335 plpgsql_adddatum((PLpgSQL_datum *)new);
336 plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, new->recno,
339 | decl_varname decl_rowtype ';'
341 $2->dtype = PLPGSQL_DTYPE_ROW;
342 $2->refname = $1.name;
343 $2->lineno = $1.lineno;
345 plpgsql_adddatum((PLpgSQL_datum *)$2);
346 plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, $2->rowno,
349 | decl_varname K_ALIAS K_FOR decl_aliasitem ';'
351 plpgsql_ns_additem($4->itemtype,
352 $4->itemno, $1.name);
354 | K_RENAME decl_renname K_TO decl_renname ';'
356 plpgsql_ns_rename($2, $4);
358 | decl_varname K_CURSOR
359 { plpgsql_ns_push(NULL); }
360 decl_cursor_args decl_is_from K_SELECT decl_cursor_query
363 PLpgSQL_expr *curname_def;
368 /* pop local namespace for cursor args */
371 new = malloc(sizeof(PLpgSQL_var));
372 memset(new, 0, sizeof(PLpgSQL_var));
374 curname_def = malloc(sizeof(PLpgSQL_expr));
375 memset(curname_def, 0, sizeof(PLpgSQL_expr));
377 new->dtype = PLPGSQL_DTYPE_VAR;
378 new->refname = $1.name;
379 new->lineno = $1.lineno;
381 curname_def->dtype = PLPGSQL_DTYPE_EXPR;
382 strcpy(buf, "SELECT '");
384 cp2 = buf + strlen(buf);
387 if (*cp1 == '\\' || *cp1 == '\'')
391 strcpy(cp2, "'::refcursor");
392 curname_def->query = strdup(buf);
393 new->default_val = curname_def;
395 new->datatype = plpgsql_parse_datatype("refcursor");
397 new->cursor_explicit_expr = $7;
399 new->cursor_explicit_argrow = -1;
401 new->cursor_explicit_argrow = $4->rowno;
403 plpgsql_adddatum((PLpgSQL_datum *)new);
404 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
413 plpgsql_ns_setlocal(false);
414 query = read_sql_stmt("SELECT ");
415 plpgsql_ns_setlocal(true);
425 | '(' decl_cursor_arglist ')'
427 /* Copy the temp arrays to malloc'd storage */
428 int nfields = $2->nfields;
432 ftmp = malloc(nfields * sizeof(char *));
433 vtmp = malloc(nfields * sizeof(int));
434 memcpy(ftmp, $2->fieldnames, nfields * sizeof(char *));
435 memcpy(vtmp, $2->varnos, nfields * sizeof(int));
437 pfree((char *)($2->fieldnames));
438 pfree((char *)($2->varnos));
440 $2->fieldnames = ftmp;
443 plpgsql_adddatum((PLpgSQL_datum *)$2);
449 decl_cursor_arglist : decl_cursor_arg
453 new = malloc(sizeof(PLpgSQL_row));
454 memset(new, 0, sizeof(PLpgSQL_row));
456 new->dtype = PLPGSQL_DTYPE_ROW;
457 new->refname = strdup("*internal*");
458 new->lineno = yylineno;
459 new->rowtypeclass = InvalidOid;
461 * We make temporary fieldnames/varnos arrays that
462 * are much bigger than necessary. We will resize
463 * them to just the needed size in the
464 * decl_cursor_args production.
466 new->fieldnames = palloc(1024 * sizeof(char *));
467 new->varnos = palloc(1024 * sizeof(int));
470 new->fieldnames[0] = $1->refname;
471 new->varnos[0] = $1->varno;
475 | decl_cursor_arglist ',' decl_cursor_arg
477 int i = $1->nfields++;
479 $1->fieldnames[i] = $3->refname;
480 $1->varnos[i] = $3->varno;
486 decl_cursor_arg : decl_varname decl_datatype
490 new = malloc(sizeof(PLpgSQL_var));
491 memset(new, 0, sizeof(PLpgSQL_var));
493 new->dtype = PLPGSQL_DTYPE_VAR;
494 new->refname = $1.name;
495 new->lineno = $1.lineno;
498 new->isconst = false;
499 new->notnull = false;
501 plpgsql_adddatum((PLpgSQL_datum *)new);
502 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
509 decl_is_from : K_IS | /* Oracle */
512 decl_aliasitem : T_WORD
517 plpgsql_ns_setlocal(false);
518 name = plpgsql_tolower(yytext);
521 plpgsql_error_lineno = yylineno;
522 elog(ERROR, "can only alias positional parameters");
524 nsi = plpgsql_ns_lookup(name, NULL);
527 plpgsql_error_lineno = yylineno;
528 elog(ERROR, "function has no parameter %s", name);
531 plpgsql_ns_setlocal(true);
543 decl_varname : T_WORD
545 /* name should be malloc'd for use as varname */
546 $$.name = strdup(plpgsql_tolower(yytext));
547 $$.lineno = yylineno;
551 decl_renname : T_WORD
553 /* the result must be palloc'd, see plpgsql_ns_rename */
554 $$ = plpgsql_tolower(yytext);
567 * If there's a lookahead token, read_datatype
570 $$ = read_datatype(yychar);
591 expr = malloc(sizeof(PLpgSQL_expr));
592 plpgsql_dstring_init(&ds);
593 plpgsql_dstring_append(&ds, "SELECT ");
595 expr->dtype = PLPGSQL_DTYPE_EXPR;
603 plpgsql_error_lineno = lno;
604 elog(ERROR, "unexpected end of file");
608 plpgsql_error_lineno = lno;
609 elog(ERROR, "expected ; after NULL");
612 plpgsql_dstring_free(&ds);
618 plpgsql_dstring_append(&ds, yytext);
619 while ((tok = yylex()) != ';')
623 plpgsql_error_lineno = lno;
624 elog(ERROR, "unterminated default value");
626 if (plpgsql_SpaceScanned)
627 plpgsql_dstring_append(&ds, " ");
628 plpgsql_dstring_append(&ds, yytext);
630 expr->query = strdup(plpgsql_dstring_get(&ds));
631 plpgsql_dstring_free(&ds);
639 decl_defkey : K_ASSIGN
646 new = malloc(sizeof(PLpgSQL_stmts));
647 memset(new, 0, sizeof(PLpgSQL_stmts));
654 proc_stmts : proc_stmts proc_stmt
656 if ($1->stmts_used == $1->stmts_alloc) {
657 $1->stmts_alloc *= 2;
658 $1->stmts = realloc($1->stmts, sizeof(PLpgSQL_stmt *) * $1->stmts_alloc);
660 $1->stmts[$1->stmts_used++] = (struct PLpgSQL_stmt *)$2;
668 new = malloc(sizeof(PLpgSQL_stmts));
669 memset(new, 0, sizeof(PLpgSQL_stmts));
671 new->stmts_alloc = 64;
673 new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
674 new->stmts[0] = (struct PLpgSQL_stmt *)$1;
681 proc_stmt : pl_block ';'
721 stmt_perform : K_PERFORM lno expr_until_semi
723 PLpgSQL_stmt_assign *new;
725 new = malloc(sizeof(PLpgSQL_stmt_assign));
726 memset(new, 0, sizeof(PLpgSQL_stmt_assign));
728 new->cmd_type = PLPGSQL_STMT_ASSIGN;
733 $$ = (PLpgSQL_stmt *)new;
737 stmt_assign : assign_var lno K_ASSIGN expr_until_semi
739 PLpgSQL_stmt_assign *new;
741 new = malloc(sizeof(PLpgSQL_stmt_assign));
742 memset(new, 0, sizeof(PLpgSQL_stmt_assign));
744 new->cmd_type = PLPGSQL_STMT_ASSIGN;
749 $$ = (PLpgSQL_stmt *)new;
753 stmt_getdiag : K_GET K_DIAGNOSTICS lno getdiag_list ';'
755 PLpgSQL_stmt_getdiag *new;
757 new = malloc(sizeof(PLpgSQL_stmt_getdiag));
758 memset(new, 0, sizeof(PLpgSQL_stmt_getdiag));
760 new->cmd_type = PLPGSQL_STMT_GETDIAG;
762 new->ndtitems = $4.nused;
763 new->dtitems = malloc(sizeof(PLpgSQL_diag_item) * $4.nused);
764 memcpy(new->dtitems, $4.dtitems, sizeof(PLpgSQL_diag_item) * $4.nused);
766 $$ = (PLpgSQL_stmt *)new;
770 getdiag_list : getdiag_list ',' getdiag_target K_ASSIGN getdiag_item
772 if ($1.nused == $1.nalloc)
775 $1.dtitems = repalloc($1.dtitems, sizeof(PLpgSQL_diag_item) * $1.nalloc);
777 $1.dtitems[$1.nused].target = $3;
778 $1.dtitems[$1.nused].item = $5;
781 $$.nalloc = $1.nalloc;
783 $$.dtitems = $1.dtitems;
785 | getdiag_target K_ASSIGN getdiag_item
789 $$.dtitems = palloc(sizeof(PLpgSQL_diag_item) * $$.nalloc);
790 $$.dtitems[0].target = $1;
791 $$.dtitems[0].item = $3;
795 getdiag_item : K_ROW_COUNT
797 $$ = PLPGSQL_GETDIAG_ROW_COUNT;
801 $$ = PLPGSQL_GETDIAG_RESULT_OID;
805 getdiag_target : T_VARIABLE
807 if (yylval.var->isconst)
809 plpgsql_error_lineno = yylineno;
810 elog(ERROR, "%s is declared CONSTANT; can not receive diagnostics", yylval.var->refname);
812 $$ = yylval.var->varno;
816 $$ = yylval.recfield->rfno;
821 assign_var : T_VARIABLE
823 if (yylval.var->isconst)
825 plpgsql_error_lineno = yylineno;
826 elog(ERROR, "%s is declared CONSTANT", yylval.var->refname);
828 $$ = yylval.var->varno;
832 $$ = yylval.recfield->rfno;
836 stmt_if : K_IF lno expr_until_then proc_sect stmt_else K_END K_IF ';'
838 PLpgSQL_stmt_if *new;
840 new = malloc(sizeof(PLpgSQL_stmt_if));
841 memset(new, 0, sizeof(PLpgSQL_stmt_if));
843 new->cmd_type = PLPGSQL_STMT_IF;
847 new->false_body = $5;
849 $$ = (PLpgSQL_stmt *)new;
857 new = malloc(sizeof(PLpgSQL_stmts));
858 memset(new, 0, sizeof(PLpgSQL_stmts));
861 | K_ELSIF lno expr_until_then proc_sect stmt_else
864 * Translate the structure: into:
866 * IF c1 THEN IF c1 THEN
879 PLpgSQL_stmt_if *new_if;
881 /* first create a new if-statement */
882 new_if = malloc(sizeof(PLpgSQL_stmt_if));
883 memset(new_if, 0, sizeof(PLpgSQL_stmt_if));
885 new_if->cmd_type = PLPGSQL_STMT_IF;
888 new_if->true_body = $4;
889 new_if->false_body = $5;
891 /* this is a 'container' for the if-statement */
892 new = malloc(sizeof(PLpgSQL_stmts));
893 memset(new, 0, sizeof(PLpgSQL_stmts));
895 new->stmts_alloc = 64;
897 new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
898 new->stmts[0] = (struct PLpgSQL_stmt *)new_if;
910 stmt_loop : opt_label K_LOOP lno loop_body
912 PLpgSQL_stmt_loop *new;
914 new = malloc(sizeof(PLpgSQL_stmt_loop));
915 memset(new, 0, sizeof(PLpgSQL_stmt_loop));
917 new->cmd_type = PLPGSQL_STMT_LOOP;
924 $$ = (PLpgSQL_stmt *)new;
928 stmt_while : opt_label K_WHILE lno expr_until_loop loop_body
930 PLpgSQL_stmt_while *new;
932 new = malloc(sizeof(PLpgSQL_stmt_while));
933 memset(new, 0, sizeof(PLpgSQL_stmt_while));
935 new->cmd_type = PLPGSQL_STMT_WHILE;
943 $$ = (PLpgSQL_stmt *)new;
947 stmt_fori : opt_label K_FOR lno fori_var K_IN fori_lower expr_until_loop loop_body
949 PLpgSQL_stmt_fori *new;
951 new = malloc(sizeof(PLpgSQL_stmt_fori));
952 memset(new, 0, sizeof(PLpgSQL_stmt_fori));
954 new->cmd_type = PLPGSQL_STMT_FORI;
958 new->reverse = $6.reverse;
959 new->lower = $6.expr;
965 $$ = (PLpgSQL_stmt *)new;
969 fori_var : fori_varname
973 new = malloc(sizeof(PLpgSQL_var));
974 memset(new, 0, sizeof(PLpgSQL_var));
976 new->dtype = PLPGSQL_DTYPE_VAR;
977 new->refname = $1.name;
978 new->lineno = $1.lineno;
980 new->datatype = plpgsql_parse_datatype("integer");
981 new->isconst = false;
982 new->notnull = false;
983 new->default_val = NULL;
985 plpgsql_adddatum((PLpgSQL_datum *)new);
986 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
989 plpgsql_add_initdatums(NULL);
995 fori_varname : T_VARIABLE
997 $$.name = strdup(yytext);
998 $$.lineno = yylineno;
1002 $$.name = strdup(yytext);
1003 $$.lineno = yylineno;
1012 if (tok == K_REVERSE)
1019 plpgsql_push_back_token(tok);
1022 $$.expr = plpgsql_read_expression(K_DOTDOT, "..");
1025 stmt_fors : opt_label K_FOR lno fors_target K_IN K_SELECT expr_until_loop loop_body
1027 PLpgSQL_stmt_fors *new;
1029 new = malloc(sizeof(PLpgSQL_stmt_fors));
1030 memset(new, 0, sizeof(PLpgSQL_stmt_fors));
1032 new->cmd_type = PLPGSQL_STMT_FORS;
1037 case PLPGSQL_DTYPE_REC:
1040 case PLPGSQL_DTYPE_ROW:
1041 new->row = (PLpgSQL_row *)$4;
1044 elog(ERROR, "unknown dtype %d in stmt_fors", $4->dtype);
1051 $$ = (PLpgSQL_stmt *)new;
1054 stmt_dynfors : opt_label K_FOR lno fors_target K_IN K_EXECUTE expr_until_loop loop_body
1056 PLpgSQL_stmt_dynfors *new;
1058 new = malloc(sizeof(PLpgSQL_stmt_dynfors));
1059 memset(new, 0, sizeof(PLpgSQL_stmt_dynfors));
1061 new->cmd_type = PLPGSQL_STMT_DYNFORS;
1066 case PLPGSQL_DTYPE_REC:
1069 case PLPGSQL_DTYPE_ROW:
1070 new->row = (PLpgSQL_row *)$4;
1073 elog(ERROR, "unknown dtype %d in stmt_dynfors", $4->dtype);
1080 $$ = (PLpgSQL_stmt *)new;
1083 fors_target : T_RECORD
1084 { $$ = yylval.rec; }
1087 $$ = (PLpgSQL_rec *)(yylval.row);
1091 stmt_select : K_SELECT lno
1093 $$ = make_select_stmt();
1098 stmt_exit : K_EXIT lno opt_exitlabel opt_exitcond
1100 PLpgSQL_stmt_exit *new;
1102 new = malloc(sizeof(PLpgSQL_stmt_exit));
1103 memset(new, 0, sizeof(PLpgSQL_stmt_exit));
1105 new->cmd_type = PLPGSQL_STMT_EXIT;
1110 $$ = (PLpgSQL_stmt *)new;
1114 stmt_return : K_RETURN lno
1116 PLpgSQL_stmt_return *new;
1117 PLpgSQL_expr *expr = NULL;
1120 new = malloc(sizeof(PLpgSQL_stmt_return));
1121 memset(new, 0, sizeof(PLpgSQL_stmt_return));
1123 if (plpgsql_curr_compile->fn_retistuple)
1125 new->retistuple = true;
1127 switch (tok = yylex())
1134 expr = make_tupret_expr(yylval.row);
1138 new->retrecno = yylval.rec->recno;
1143 yyerror("return type mismatch in function returning table row");
1147 yyerror("expected ';'");
1149 new->retistuple = false;
1150 expr = plpgsql_read_expression(';', ";");
1153 new->cmd_type = PLPGSQL_STMT_RETURN;
1157 $$ = (PLpgSQL_stmt *)new;
1161 stmt_raise : K_RAISE lno raise_level raise_msg raise_params ';'
1163 PLpgSQL_stmt_raise *new;
1165 new = malloc(sizeof(PLpgSQL_stmt_raise));
1167 new->cmd_type = PLPGSQL_STMT_RAISE;
1169 new->elog_level = $3;
1171 new->nparams = $5.nused;
1172 new->params = malloc(sizeof(int) * $5.nused);
1173 memcpy(new->params, $5.nums, sizeof(int) * $5.nused);
1175 $$ = (PLpgSQL_stmt *)new;
1177 | K_RAISE lno raise_level raise_msg ';'
1179 PLpgSQL_stmt_raise *new;
1181 new = malloc(sizeof(PLpgSQL_stmt_raise));
1183 new->cmd_type = PLPGSQL_STMT_RAISE;
1185 new->elog_level = $3;
1190 $$ = (PLpgSQL_stmt *)new;
1194 raise_msg : T_STRING
1196 $$ = strdup(yytext);
1200 raise_level : K_EXCEPTION
1214 raise_params : raise_params raise_param
1216 if ($1.nused == $1.nalloc)
1219 $1.nums = repalloc($1.nums, sizeof(int) * $1.nalloc);
1221 $1.nums[$1.nused++] = $2;
1223 $$.nalloc = $1.nalloc;
1224 $$.nused = $1.nused;
1231 $$.nums = palloc(sizeof(int) * $$.nalloc);
1236 raise_param : ',' T_VARIABLE
1238 $$ = yylval.var->varno;
1242 $$ = yylval.recfield->rfno;
1246 $$ = yylval.trigarg->dno;
1250 loop_body : proc_sect K_END K_LOOP ';'
1254 stmt_execsql : execsql_start lno
1256 PLpgSQL_stmt_execsql *new;
1258 new = malloc(sizeof(PLpgSQL_stmt_execsql));
1259 new->cmd_type = PLPGSQL_STMT_EXECSQL;
1261 new->sqlstmt = read_sql_stmt($1);
1263 $$ = (PLpgSQL_stmt *)new;
1267 stmt_dynexecute : K_EXECUTE lno expr_until_semi
1269 PLpgSQL_stmt_dynexecute *new;
1271 new = malloc(sizeof(PLpgSQL_stmt_dynexecute));
1272 new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
1276 $$ = (PLpgSQL_stmt *)new;
1280 stmt_open : K_OPEN lno cursor_varptr
1282 PLpgSQL_stmt_open *new;
1285 new = malloc(sizeof(PLpgSQL_stmt_open));
1286 memset(new, 0, sizeof(PLpgSQL_stmt_open));
1288 new->cmd_type = PLPGSQL_STMT_OPEN;
1290 new->curvar = $3->varno;
1292 if ($3->cursor_explicit_expr == NULL)
1298 plpgsql_error_lineno = $2;
1299 elog(ERROR, "syntax error at \"%s\" - expected FOR to open a reference cursor", yytext);
1306 new->query = read_sql_stmt("SELECT ");
1310 new->dynquery = read_sql_stmt("SELECT ");
1314 plpgsql_error_lineno = $2;
1315 elog(ERROR, "syntax error at \"%s\"", yytext);
1321 if ($3->cursor_explicit_argrow >= 0)
1329 plpgsql_error_lineno = yylineno;
1330 elog(ERROR, "cursor %s has arguments", $3->refname);
1333 new->argquery = read_sql_stmt("SELECT ");
1334 /* Remove the trailing right paren,
1335 * because we want "select 1, 2", not
1338 cp = new->argquery->query;
1343 plpgsql_error_lineno = yylineno;
1344 elog(ERROR, "missing )");
1354 plpgsql_error_lineno = yylineno;
1355 elog(ERROR, "cursor %s has no arguments", $3->refname);
1360 plpgsql_error_lineno = yylineno;
1361 elog(ERROR, "syntax error at \"%s\"", yytext);
1366 $$ = (PLpgSQL_stmt *)new;
1370 stmt_fetch : K_FETCH lno cursor_variable K_INTO
1372 PLpgSQL_stmt_fetch *new;
1374 new = (PLpgSQL_stmt_fetch *)make_fetch_stmt();
1377 $$ = (PLpgSQL_stmt *)new;
1382 stmt_close : K_CLOSE lno cursor_variable ';'
1384 PLpgSQL_stmt_close *new;
1386 new = malloc(sizeof(PLpgSQL_stmt_close));
1387 new->cmd_type = PLPGSQL_STMT_CLOSE;
1391 $$ = (PLpgSQL_stmt *)new;
1395 cursor_varptr : T_VARIABLE
1397 if (yylval.var->datatype->typoid != REFCURSOROID)
1399 plpgsql_error_lineno = yylineno;
1400 elog(ERROR, "%s must be of type cursor or refcursor", yylval.var->refname);
1406 cursor_variable : T_VARIABLE
1408 if (yylval.var->datatype->typoid != REFCURSOROID)
1410 plpgsql_error_lineno = yylineno;
1411 elog(ERROR, "%s must be of type refcursor", yylval.var->refname);
1413 $$ = yylval.var->varno;
1417 execsql_start : T_WORD
1418 { $$ = strdup(yytext); }
1420 { $$ = strdup(yytext); }
1424 { $$ = plpgsql_read_expression(';', ";"); }
1428 { $$ = plpgsql_read_expression(K_THEN, "THEN"); }
1432 { $$ = plpgsql_read_expression(K_LOOP, "LOOP"); }
1437 plpgsql_ns_push(NULL);
1440 | '<' '<' opt_lblname '>' '>'
1442 plpgsql_ns_push($3);
1450 { $$ = strdup(yytext); }
1455 | K_WHEN expr_until_semi
1459 opt_lblname : T_WORD
1460 { $$ = strdup(yytext); }
1465 plpgsql_error_lineno = yylineno;
1474 plpgsql_read_expression(int until, const char *expected)
1476 return read_sql_construct(until, expected, true, "SELECT ");
1479 static PLpgSQL_expr *
1480 read_sql_stmt(const char *sqlstart)
1482 return read_sql_construct(';', ";", false, sqlstart);
1485 static PLpgSQL_expr *
1486 read_sql_construct(int until,
1487 const char *expected,
1489 const char *sqlstart)
1501 plpgsql_dstring_init(&ds);
1502 plpgsql_dstring_append(&ds, (char *) sqlstart);
1509 else if (tok == ')')
1513 elog(ERROR, "mismatched parentheses");
1515 else if (parenlevel == 0 && tok == until)
1518 * End of function definition is an error, and we don't expect to
1519 * hit a semicolon either (unless it's the until symbol, in which
1520 * case we should have fallen out above).
1522 if (tok == 0 || tok == ';')
1524 plpgsql_error_lineno = lno;
1525 if (parenlevel != 0)
1526 elog(ERROR, "mismatched parentheses");
1528 elog(ERROR, "missing %s at end of SQL expression",
1531 elog(ERROR, "missing %s at end of SQL statement",
1535 if (plpgsql_SpaceScanned)
1536 plpgsql_dstring_append(&ds, " ");
1540 params[nparams] = yylval.var->varno;
1541 sprintf(buf, " $%d ", ++nparams);
1542 plpgsql_dstring_append(&ds, buf);
1546 params[nparams] = yylval.recfield->rfno;
1547 sprintf(buf, " $%d ", ++nparams);
1548 plpgsql_dstring_append(&ds, buf);
1552 params[nparams] = yylval.trigarg->dno;
1553 sprintf(buf, " $%d ", ++nparams);
1554 plpgsql_dstring_append(&ds, buf);
1558 plpgsql_dstring_append(&ds, yytext);
1563 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
1564 expr->dtype = PLPGSQL_DTYPE_EXPR;
1565 expr->query = strdup(plpgsql_dstring_get(&ds));
1567 expr->nparams = nparams;
1568 while(nparams-- > 0)
1569 expr->params[nparams] = params[nparams];
1570 plpgsql_dstring_free(&ds);
1575 static PLpgSQL_type *
1576 read_datatype(int tok)
1580 PLpgSQL_type *result;
1581 bool needspace = false;
1586 /* Often there will be a lookahead token, but if not, get one */
1592 /* lexer found word%TYPE and did its thing already */
1593 return yylval.dtype;
1596 plpgsql_dstring_init(&ds);
1602 plpgsql_error_lineno = lno;
1603 if (parenlevel != 0)
1604 elog(ERROR, "mismatched parentheses");
1605 elog(ERROR, "incomplete datatype declaration");
1607 /* Possible followers for datatype in a declaration */
1608 if (tok == K_NOT || tok == K_ASSIGN || tok == K_DEFAULT)
1610 /* Possible followers for datatype in a cursor_arg list */
1611 if ((tok == ',' || tok == ')') && parenlevel == 0)
1615 else if (tok == ')')
1618 plpgsql_dstring_append(&ds, " ");
1620 plpgsql_dstring_append(&ds, yytext);
1625 plpgsql_push_back_token(tok);
1627 plpgsql_error_lineno = lno; /* in case of error in parse_datatype */
1629 result = plpgsql_parse_datatype(plpgsql_dstring_get(&ds));
1631 plpgsql_dstring_free(&ds);
1637 static PLpgSQL_stmt *
1647 PLpgSQL_row *row = NULL;
1648 PLpgSQL_rec *rec = NULL;
1649 PLpgSQL_stmt_select *select;
1650 int have_nexttok = 0;
1653 plpgsql_dstring_init(&ds);
1654 plpgsql_dstring_append(&ds, "SELECT ");
1656 while((tok = yylex()) != K_INTO)
1660 PLpgSQL_stmt_execsql *execsql;
1662 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
1663 expr->dtype = PLPGSQL_DTYPE_EXPR;
1664 expr->query = strdup(plpgsql_dstring_get(&ds));
1666 expr->nparams = nparams;
1667 while(nparams-- > 0)
1668 expr->params[nparams] = params[nparams];
1669 plpgsql_dstring_free(&ds);
1671 execsql = malloc(sizeof(PLpgSQL_stmt_execsql));
1672 execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
1673 execsql->sqlstmt = expr;
1675 return (PLpgSQL_stmt *)execsql;
1678 if (plpgsql_SpaceScanned)
1679 plpgsql_dstring_append(&ds, " ");
1683 params[nparams] = yylval.var->varno;
1684 sprintf(buf, " $%d ", ++nparams);
1685 plpgsql_dstring_append(&ds, buf);
1689 params[nparams] = yylval.recfield->rfno;
1690 sprintf(buf, " $%d ", ++nparams);
1691 plpgsql_dstring_append(&ds, buf);
1695 params[nparams] = yylval.trigarg->dno;
1696 sprintf(buf, " $%d ", ++nparams);
1697 plpgsql_dstring_append(&ds, buf);
1703 plpgsql_error_lineno = yylineno;
1704 elog(ERROR, "unexpected end of file");
1706 plpgsql_dstring_append(&ds, yytext);
1726 PLpgSQL_recfield *recfield;
1728 char *fieldnames[1024];
1735 fieldnames[0] = strdup(yytext);
1736 varnos[0] = var->varno;
1740 recfield = yylval.recfield;
1741 fieldnames[0] = strdup(yytext);
1742 varnos[0] = recfield->rfno;
1746 while ((tok = yylex()) == ',')
1753 fieldnames[nfields] = strdup(yytext);
1754 varnos[nfields++] = var->varno;
1758 recfield = yylval.recfield;
1759 fieldnames[0] = strdup(yytext);
1760 varnos[0] = recfield->rfno;
1764 plpgsql_error_lineno = yylineno;
1765 elog(ERROR, "plpgsql: %s is not a variable or record field", yytext);
1768 row = malloc(sizeof(PLpgSQL_row));
1769 row->dtype = PLPGSQL_DTYPE_ROW;
1770 row->refname = strdup("*internal*");
1771 row->lineno = yylineno;
1772 row->rowtypeclass = InvalidOid;
1773 row->nfields = nfields;
1774 row->fieldnames = malloc(sizeof(char *) * nfields);
1775 row->varnos = malloc(sizeof(int) * nfields);
1776 while (--nfields >= 0)
1778 row->fieldnames[nfields] = fieldnames[nfields];
1779 row->varnos[nfields] = varnos[nfields];
1782 plpgsql_adddatum((PLpgSQL_datum *)row);
1790 if (plpgsql_SpaceScanned)
1791 plpgsql_dstring_append(&ds, " ");
1792 plpgsql_dstring_append(&ds, yytext);
1799 PLpgSQL_stmt_execsql *execsql;
1801 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
1802 expr->dtype = PLPGSQL_DTYPE_EXPR;
1803 expr->query = strdup(plpgsql_dstring_get(&ds));
1805 expr->nparams = nparams;
1806 while (nparams-- > 0)
1807 expr->params[nparams] = params[nparams];
1808 plpgsql_dstring_free(&ds);
1810 execsql = malloc(sizeof(PLpgSQL_stmt_execsql));
1811 execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
1812 execsql->sqlstmt = expr;
1814 return (PLpgSQL_stmt *)execsql;
1817 if (plpgsql_SpaceScanned)
1818 plpgsql_dstring_append(&ds, " ");
1822 params[nparams] = yylval.var->varno;
1823 sprintf(buf, " $%d ", ++nparams);
1824 plpgsql_dstring_append(&ds, buf);
1828 params[nparams] = yylval.recfield->rfno;
1829 sprintf(buf, " $%d ", ++nparams);
1830 plpgsql_dstring_append(&ds, buf);
1834 params[nparams] = yylval.trigarg->dno;
1835 sprintf(buf, " $%d ", ++nparams);
1836 plpgsql_dstring_append(&ds, buf);
1842 plpgsql_error_lineno = yylineno;
1843 elog(ERROR, "unexpected end of file");
1845 plpgsql_dstring_append(&ds, yytext);
1852 /************************************************************
1853 * Eat up the rest of the statement after the target fields
1854 ************************************************************/
1857 if (!have_nexttok) {
1865 if (plpgsql_SpaceScanned)
1866 plpgsql_dstring_append(&ds, " ");
1870 params[nparams] = yylval.var->varno;
1871 sprintf(buf, " $%d ", ++nparams);
1872 plpgsql_dstring_append(&ds, buf);
1876 params[nparams] = yylval.recfield->rfno;
1877 sprintf(buf, " $%d ", ++nparams);
1878 plpgsql_dstring_append(&ds, buf);
1882 params[nparams] = yylval.trigarg->dno;
1883 sprintf(buf, " $%d ", ++nparams);
1884 plpgsql_dstring_append(&ds, buf);
1890 plpgsql_error_lineno = yylineno;
1891 elog(ERROR, "unexpected end of file");
1893 plpgsql_dstring_append(&ds, yytext);
1898 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
1899 expr->dtype = PLPGSQL_DTYPE_EXPR;
1900 expr->query = strdup(plpgsql_dstring_get(&ds));
1902 expr->nparams = nparams;
1903 while(nparams-- > 0)
1904 expr->params[nparams] = params[nparams];
1905 plpgsql_dstring_free(&ds);
1907 select = malloc(sizeof(PLpgSQL_stmt_select));
1908 memset(select, 0, sizeof(PLpgSQL_stmt_select));
1909 select->cmd_type = PLPGSQL_STMT_SELECT;
1912 select->query = expr;
1914 return (PLpgSQL_stmt *)select;
1918 static PLpgSQL_stmt *
1922 PLpgSQL_row *row = NULL;
1923 PLpgSQL_rec *rec = NULL;
1924 PLpgSQL_stmt_fetch *fetch;
1925 int have_nexttok = 0;
1942 PLpgSQL_recfield *recfield;
1944 char *fieldnames[1024];
1951 fieldnames[0] = strdup(yytext);
1952 varnos[0] = var->varno;
1956 recfield = yylval.recfield;
1957 fieldnames[0] = strdup(yytext);
1958 varnos[0] = recfield->rfno;
1962 while ((tok = yylex()) == ',')
1969 fieldnames[nfields] = strdup(yytext);
1970 varnos[nfields++] = var->varno;
1974 recfield = yylval.recfield;
1975 fieldnames[0] = strdup(yytext);
1976 varnos[0] = recfield->rfno;
1980 plpgsql_error_lineno = yylineno;
1981 elog(ERROR, "plpgsql: %s is not a variable or record field", yytext);
1984 row = malloc(sizeof(PLpgSQL_row));
1985 row->dtype = PLPGSQL_DTYPE_ROW;
1986 row->refname = strdup("*internal*");
1987 row->lineno = yylineno;
1988 row->rowtypeclass = InvalidOid;
1989 row->nfields = nfields;
1990 row->fieldnames = malloc(sizeof(char *) * nfields);
1991 row->varnos = malloc(sizeof(int) * nfields);
1992 while (--nfields >= 0)
1994 row->fieldnames[nfields] = fieldnames[nfields];
1995 row->varnos[nfields] = varnos[nfields];
1998 plpgsql_adddatum((PLpgSQL_datum *)row);
2005 plpgsql_error_lineno = yylineno;
2006 elog(ERROR, "syntax error at '%s'", yytext);
2014 plpgsql_error_lineno = yylineno;
2015 elog(ERROR, "syntax error at '%s'", yytext);
2018 fetch = malloc(sizeof(PLpgSQL_stmt_select));
2019 memset(fetch, 0, sizeof(PLpgSQL_stmt_fetch));
2020 fetch->cmd_type = PLPGSQL_STMT_FETCH;
2024 return (PLpgSQL_stmt *)fetch;
2028 static PLpgSQL_expr *
2029 make_tupret_expr(PLpgSQL_row *row)
2036 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * (row->nfields - 1));
2037 expr->dtype = PLPGSQL_DTYPE_EXPR;
2039 plpgsql_dstring_init(&ds);
2040 plpgsql_dstring_append(&ds, "SELECT ");
2042 for (i = 0; i < row->nfields; i++)
2044 sprintf(buf, "%s$%d", (i > 0) ? "," : "", i + 1);
2045 plpgsql_dstring_append(&ds, buf);
2046 expr->params[i] = row->varnos[i];
2049 expr->query = strdup(plpgsql_dstring_get(&ds));
2051 expr->plan_argtypes = NULL;
2052 expr->nparams = row->nfields;
2054 plpgsql_dstring_free(&ds);