2 /**********************************************************************
3 * gram.y - Parser for the PL/pgSQL
7 * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.48 2003/10/30 17:18:55 tgl 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 void check_assignable(PLpgSQL_datum *datum);
72 PLpgSQL_diag_item *dtitems;
86 PLpgSQL_datum *variable; /* a VAR, RECFIELD, or TRIGARG */
93 PLpgSQL_stmt_block *program;
94 PLpgSQL_nsitem *nsitem;
97 %type <declhdr> decl_sect
98 %type <varname> decl_varname
99 %type <str> decl_renname
100 %type <ival> decl_const decl_notnull
101 %type <expr> decl_defval decl_cursor_query
102 %type <dtype> decl_datatype
103 %type <row> decl_rowtype decl_cursor_args decl_cursor_arglist
104 %type <nsitem> decl_aliasitem
105 %type <str> decl_stmts decl_stmt
107 %type <expr> expr_until_semi expr_until_rightbracket
108 %type <expr> 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_return_next stmt_raise stmt_execsql
125 %type <stmt> stmt_fori 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
198 %token T_VARIABLE /* a VAR, RECFIELD, or TRIGARG */
211 pl_function : T_FUNCTION comp_optsect pl_block opt_semi
213 yylval.program = (PLpgSQL_stmt_block *)$3;
215 | T_TRIGGER comp_optsect pl_block opt_semi
217 yylval.program = (PLpgSQL_stmt_block *)$3;
225 comp_options : comp_options comp_option
229 comp_option : O_OPTION O_DUMP
231 plpgsql_DumpExecTree = 1;
239 pl_block : decl_sect K_BEGIN lno proc_sect K_END
241 PLpgSQL_stmt_block *new;
243 new = malloc(sizeof(PLpgSQL_stmt_block));
244 memset(new, 0, sizeof(PLpgSQL_stmt_block));
246 new->cmd_type = PLPGSQL_STMT_BLOCK;
248 new->label = $1.label;
249 new->n_initvars = $1.n_initvars;
250 new->initvarnos = $1.initvarnos;
255 $$ = (PLpgSQL_stmt *)new;
260 decl_sect : opt_label
262 plpgsql_ns_setlocal(false);
265 $$.initvarnos = NULL;
266 plpgsql_add_initdatums(NULL);
268 | opt_label decl_start
270 plpgsql_ns_setlocal(false);
273 $$.initvarnos = NULL;
274 plpgsql_add_initdatums(NULL);
276 | opt_label decl_start decl_stmts
278 plpgsql_ns_setlocal(false);
283 $$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos));
287 decl_start : K_DECLARE
289 plpgsql_ns_setlocal(true);
293 decl_stmts : decl_stmts decl_stmt
299 decl_stmt : '<' '<' opt_lblname '>' '>'
307 decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
309 if (!OidIsValid($3->typrelid))
311 /* Ordinary scalar datatype */
314 var = malloc(sizeof(PLpgSQL_var));
315 memset(var, 0, sizeof(PLpgSQL_var));
317 var->dtype = PLPGSQL_DTYPE_VAR;
318 var->refname = $1.name;
319 var->lineno = $1.lineno;
324 var->default_val = $5;
326 plpgsql_adddatum((PLpgSQL_datum *)var);
327 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR,
333 /* Composite type --- treat as rowtype */
336 row = plpgsql_build_rowtype($3->typrelid);
337 row->dtype = PLPGSQL_DTYPE_ROW;
338 row->refname = $1.name;
339 row->lineno = $1.lineno;
343 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
344 errmsg("rowtype variable cannot be CONSTANT")));
347 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
348 errmsg("rowtype variable cannot be NOT NULL")));
351 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
352 errmsg("default value for rowtype variable is not supported")));
354 plpgsql_adddatum((PLpgSQL_datum *)row);
355 plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW,
361 | decl_varname K_RECORD ';'
365 var = malloc(sizeof(PLpgSQL_rec));
367 var->dtype = PLPGSQL_DTYPE_REC;
368 var->refname = $1.name;
369 var->lineno = $1.lineno;
371 plpgsql_adddatum((PLpgSQL_datum *)var);
372 plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, var->recno,
375 | decl_varname decl_rowtype ';'
377 $2->dtype = PLPGSQL_DTYPE_ROW;
378 $2->refname = $1.name;
379 $2->lineno = $1.lineno;
381 plpgsql_adddatum((PLpgSQL_datum *)$2);
382 plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, $2->rowno,
385 | decl_varname K_ALIAS K_FOR decl_aliasitem ';'
387 plpgsql_ns_additem($4->itemtype,
388 $4->itemno, $1.name);
390 | K_RENAME decl_renname K_TO decl_renname ';'
392 plpgsql_ns_rename($2, $4);
394 | decl_varname K_CURSOR
395 { plpgsql_ns_push(NULL); }
396 decl_cursor_args decl_is_from decl_cursor_query
399 PLpgSQL_expr *curname_def;
404 /* pop local namespace for cursor args */
407 new = malloc(sizeof(PLpgSQL_var));
408 memset(new, 0, sizeof(PLpgSQL_var));
410 curname_def = malloc(sizeof(PLpgSQL_expr));
411 memset(curname_def, 0, sizeof(PLpgSQL_expr));
413 new->dtype = PLPGSQL_DTYPE_VAR;
414 new->refname = $1.name;
415 new->lineno = $1.lineno;
417 curname_def->dtype = PLPGSQL_DTYPE_EXPR;
418 strcpy(buf, "SELECT '");
420 cp2 = buf + strlen(buf);
423 if (*cp1 == '\\' || *cp1 == '\'')
427 strcpy(cp2, "'::refcursor");
428 curname_def->query = strdup(buf);
429 new->default_val = curname_def;
431 new->datatype = plpgsql_parse_datatype("refcursor");
433 new->cursor_explicit_expr = $6;
435 new->cursor_explicit_argrow = -1;
437 new->cursor_explicit_argrow = $4->rowno;
439 plpgsql_adddatum((PLpgSQL_datum *)new);
440 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
449 plpgsql_ns_setlocal(false);
450 query = read_sql_stmt("");
451 plpgsql_ns_setlocal(true);
461 | '(' decl_cursor_arglist ')'
463 /* Copy the temp arrays to malloc'd storage */
464 int nfields = $2->nfields;
468 ftmp = malloc(nfields * sizeof(char *));
469 vtmp = malloc(nfields * sizeof(int));
470 memcpy(ftmp, $2->fieldnames, nfields * sizeof(char *));
471 memcpy(vtmp, $2->varnos, nfields * sizeof(int));
473 pfree((char *)($2->fieldnames));
474 pfree((char *)($2->varnos));
476 $2->fieldnames = ftmp;
479 plpgsql_adddatum((PLpgSQL_datum *)$2);
485 decl_cursor_arglist : decl_cursor_arg
489 new = malloc(sizeof(PLpgSQL_row));
490 memset(new, 0, sizeof(PLpgSQL_row));
492 new->dtype = PLPGSQL_DTYPE_ROW;
493 new->refname = strdup("*internal*");
494 new->lineno = plpgsql_scanner_lineno();
495 new->rowtupdesc = NULL;
497 * We make temporary fieldnames/varnos arrays that
498 * are much bigger than necessary. We will resize
499 * them to just the needed size in the
500 * decl_cursor_args production.
502 new->fieldnames = palloc(1024 * sizeof(char *));
503 new->varnos = palloc(1024 * sizeof(int));
506 new->fieldnames[0] = $1->refname;
507 new->varnos[0] = $1->varno;
511 | decl_cursor_arglist ',' decl_cursor_arg
513 int i = $1->nfields++;
515 $1->fieldnames[i] = $3->refname;
516 $1->varnos[i] = $3->varno;
522 decl_cursor_arg : decl_varname decl_datatype
526 new = malloc(sizeof(PLpgSQL_var));
527 memset(new, 0, sizeof(PLpgSQL_var));
529 new->dtype = PLPGSQL_DTYPE_VAR;
530 new->refname = $1.name;
531 new->lineno = $1.lineno;
534 new->isconst = false;
535 new->notnull = false;
537 plpgsql_adddatum((PLpgSQL_datum *)new);
538 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
545 decl_is_from : K_IS | /* Oracle */
548 decl_aliasitem : T_WORD
553 plpgsql_convert_ident(yytext, &name, 1);
555 yyerror("only positional parameters may be aliased");
557 plpgsql_ns_setlocal(false);
558 nsi = plpgsql_ns_lookup(name, NULL);
561 plpgsql_error_lineno = plpgsql_scanner_lineno();
563 (errcode(ERRCODE_UNDEFINED_PARAMETER),
564 errmsg("function has no parameter \"%s\"",
568 plpgsql_ns_setlocal(true);
582 decl_varname : T_WORD
586 plpgsql_convert_ident(yytext, &name, 1);
587 /* name should be malloc'd for use as varname */
588 $$.name = strdup(name);
589 $$.lineno = plpgsql_scanner_lineno();
594 decl_renname : T_WORD
598 plpgsql_convert_ident(yytext, &name, 1);
599 /* the result must be palloc'd, see plpgsql_ns_rename */
613 * If there's a lookahead token, read_datatype
616 $$ = read_datatype(yychar);
636 lno = plpgsql_scanner_lineno();
637 expr = malloc(sizeof(PLpgSQL_expr));
638 plpgsql_dstring_init(&ds);
639 plpgsql_dstring_append(&ds, "SELECT ");
641 expr->dtype = PLPGSQL_DTYPE_EXPR;
649 yyerror("unexpected end of function");
652 yyerror("expected \";\" after \"NULL\"");
655 plpgsql_dstring_free(&ds);
661 plpgsql_dstring_append(&ds, yytext);
662 while ((tok = yylex()) != ';')
665 yyerror("unterminated default value");
667 if (plpgsql_SpaceScanned)
668 plpgsql_dstring_append(&ds, " ");
669 plpgsql_dstring_append(&ds, yytext);
671 expr->query = strdup(plpgsql_dstring_get(&ds));
672 plpgsql_dstring_free(&ds);
680 decl_defkey : K_ASSIGN
688 new = malloc(sizeof(PLpgSQL_stmts));
689 memset(new, 0, sizeof(PLpgSQL_stmts));
696 proc_stmts : proc_stmts proc_stmt
698 if ($1->stmts_used == $1->stmts_alloc)
700 $1->stmts_alloc *= 2;
701 $1->stmts = realloc($1->stmts, sizeof(PLpgSQL_stmt *) * $1->stmts_alloc);
703 $1->stmts[$1->stmts_used++] = (struct PLpgSQL_stmt *)$2;
711 new = malloc(sizeof(PLpgSQL_stmts));
712 memset(new, 0, sizeof(PLpgSQL_stmts));
714 new->stmts_alloc = 64;
716 new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
717 new->stmts[0] = (struct PLpgSQL_stmt *)$1;
724 proc_stmt : pl_block ';'
766 stmt_perform : K_PERFORM lno expr_until_semi
768 PLpgSQL_stmt_perform *new;
770 new = malloc(sizeof(PLpgSQL_stmt_perform));
771 memset(new, 0, sizeof(PLpgSQL_stmt_perform));
773 new->cmd_type = PLPGSQL_STMT_PERFORM;
777 $$ = (PLpgSQL_stmt *)new;
781 stmt_assign : assign_var lno K_ASSIGN expr_until_semi
783 PLpgSQL_stmt_assign *new;
785 new = malloc(sizeof(PLpgSQL_stmt_assign));
786 memset(new, 0, sizeof(PLpgSQL_stmt_assign));
788 new->cmd_type = PLPGSQL_STMT_ASSIGN;
793 $$ = (PLpgSQL_stmt *)new;
797 stmt_getdiag : K_GET K_DIAGNOSTICS lno getdiag_list ';'
799 PLpgSQL_stmt_getdiag *new;
801 new = malloc(sizeof(PLpgSQL_stmt_getdiag));
802 memset(new, 0, sizeof(PLpgSQL_stmt_getdiag));
804 new->cmd_type = PLPGSQL_STMT_GETDIAG;
806 new->ndtitems = $4.nused;
807 new->dtitems = malloc(sizeof(PLpgSQL_diag_item) * $4.nused);
808 memcpy(new->dtitems, $4.dtitems, sizeof(PLpgSQL_diag_item) * $4.nused);
810 $$ = (PLpgSQL_stmt *)new;
814 getdiag_list : getdiag_list ',' getdiag_target K_ASSIGN getdiag_item
816 if ($1.nused == $1.nalloc)
819 $1.dtitems = repalloc($1.dtitems, sizeof(PLpgSQL_diag_item) * $1.nalloc);
821 $1.dtitems[$1.nused].target = $3;
822 $1.dtitems[$1.nused].item = $5;
825 $$.nalloc = $1.nalloc;
827 $$.dtitems = $1.dtitems;
829 | getdiag_target K_ASSIGN getdiag_item
833 $$.dtitems = palloc(sizeof(PLpgSQL_diag_item) * $$.nalloc);
834 $$.dtitems[0].target = $1;
835 $$.dtitems[0].item = $3;
839 getdiag_item : K_ROW_COUNT
841 $$ = PLPGSQL_GETDIAG_ROW_COUNT;
845 $$ = PLPGSQL_GETDIAG_RESULT_OID;
849 getdiag_target : T_VARIABLE
851 check_assignable(yylval.variable);
852 $$ = yylval.variable->dno;
857 assign_var : T_VARIABLE
859 check_assignable(yylval.variable);
860 $$ = yylval.variable->dno;
862 | assign_var '[' expr_until_rightbracket
864 PLpgSQL_arrayelem *new;
866 new = malloc(sizeof(PLpgSQL_arrayelem));
867 memset(new, 0, sizeof(PLpgSQL_arrayelem));
869 new->dtype = PLPGSQL_DTYPE_ARRAYELEM;
871 new->arrayparentno = $1;
873 plpgsql_adddatum((PLpgSQL_datum *)new);
879 stmt_if : K_IF lno expr_until_then proc_sect stmt_else K_END K_IF ';'
881 PLpgSQL_stmt_if *new;
883 new = malloc(sizeof(PLpgSQL_stmt_if));
884 memset(new, 0, sizeof(PLpgSQL_stmt_if));
886 new->cmd_type = PLPGSQL_STMT_IF;
890 new->false_body = $5;
892 $$ = (PLpgSQL_stmt *)new;
900 new = malloc(sizeof(PLpgSQL_stmts));
901 memset(new, 0, sizeof(PLpgSQL_stmts));
904 | K_ELSIF lno expr_until_then proc_sect stmt_else
907 * Translate the structure: into:
909 * IF c1 THEN IF c1 THEN
922 PLpgSQL_stmt_if *new_if;
924 /* first create a new if-statement */
925 new_if = malloc(sizeof(PLpgSQL_stmt_if));
926 memset(new_if, 0, sizeof(PLpgSQL_stmt_if));
928 new_if->cmd_type = PLPGSQL_STMT_IF;
931 new_if->true_body = $4;
932 new_if->false_body = $5;
934 /* this is a 'container' for the if-statement */
935 new = malloc(sizeof(PLpgSQL_stmts));
936 memset(new, 0, sizeof(PLpgSQL_stmts));
938 new->stmts_alloc = 64;
940 new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
941 new->stmts[0] = (struct PLpgSQL_stmt *)new_if;
953 stmt_loop : opt_label K_LOOP lno loop_body
955 PLpgSQL_stmt_loop *new;
957 new = malloc(sizeof(PLpgSQL_stmt_loop));
958 memset(new, 0, sizeof(PLpgSQL_stmt_loop));
960 new->cmd_type = PLPGSQL_STMT_LOOP;
967 $$ = (PLpgSQL_stmt *)new;
971 stmt_while : opt_label K_WHILE lno expr_until_loop loop_body
973 PLpgSQL_stmt_while *new;
975 new = malloc(sizeof(PLpgSQL_stmt_while));
976 memset(new, 0, sizeof(PLpgSQL_stmt_while));
978 new->cmd_type = PLPGSQL_STMT_WHILE;
986 $$ = (PLpgSQL_stmt *)new;
990 stmt_fori : opt_label K_FOR lno fori_var K_IN fori_lower expr_until_loop loop_body
992 PLpgSQL_stmt_fori *new;
994 new = malloc(sizeof(PLpgSQL_stmt_fori));
995 memset(new, 0, sizeof(PLpgSQL_stmt_fori));
997 new->cmd_type = PLPGSQL_STMT_FORI;
1001 new->reverse = $6.reverse;
1002 new->lower = $6.expr;
1008 $$ = (PLpgSQL_stmt *)new;
1012 fori_var : fori_varname
1016 new = malloc(sizeof(PLpgSQL_var));
1017 memset(new, 0, sizeof(PLpgSQL_var));
1019 new->dtype = PLPGSQL_DTYPE_VAR;
1020 new->refname = $1.name;
1021 new->lineno = $1.lineno;
1023 new->datatype = plpgsql_parse_datatype("integer");
1024 new->isconst = false;
1025 new->notnull = false;
1026 new->default_val = NULL;
1028 plpgsql_adddatum((PLpgSQL_datum *)new);
1029 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
1032 plpgsql_add_initdatums(NULL);
1038 fori_varname : T_VARIABLE
1042 plpgsql_convert_ident(yytext, &name, 1);
1043 /* name should be malloc'd for use as varname */
1044 $$.name = strdup(name);
1045 $$.lineno = plpgsql_scanner_lineno();
1052 plpgsql_convert_ident(yytext, &name, 1);
1053 /* name should be malloc'd for use as varname */
1054 $$.name = strdup(name);
1055 $$.lineno = plpgsql_scanner_lineno();
1065 if (tok == K_REVERSE)
1072 plpgsql_push_back_token(tok);
1075 $$.expr = plpgsql_read_expression(K_DOTDOT, "..");
1079 stmt_fors : opt_label K_FOR lno fors_target K_IN K_SELECT expr_until_loop loop_body
1081 PLpgSQL_stmt_fors *new;
1083 new = malloc(sizeof(PLpgSQL_stmt_fors));
1084 memset(new, 0, sizeof(PLpgSQL_stmt_fors));
1086 new->cmd_type = PLPGSQL_STMT_FORS;
1091 case PLPGSQL_DTYPE_REC:
1094 case PLPGSQL_DTYPE_ROW:
1095 new->row = (PLpgSQL_row *)$4;
1098 elog(ERROR, "unrecognized dtype: %d",
1106 $$ = (PLpgSQL_stmt *)new;
1110 stmt_dynfors : opt_label K_FOR lno fors_target K_IN K_EXECUTE expr_until_loop loop_body
1112 PLpgSQL_stmt_dynfors *new;
1114 new = malloc(sizeof(PLpgSQL_stmt_dynfors));
1115 memset(new, 0, sizeof(PLpgSQL_stmt_dynfors));
1117 new->cmd_type = PLPGSQL_STMT_DYNFORS;
1122 case PLPGSQL_DTYPE_REC:
1125 case PLPGSQL_DTYPE_ROW:
1126 new->row = (PLpgSQL_row *)$4;
1129 elog(ERROR, "unrecognized dtype: %d",
1137 $$ = (PLpgSQL_stmt *)new;
1141 fors_target : T_RECORD
1142 { $$ = yylval.rec; }
1145 $$ = (PLpgSQL_rec *)(yylval.row);
1149 stmt_select : K_SELECT lno
1151 $$ = make_select_stmt();
1156 stmt_exit : K_EXIT lno opt_exitlabel opt_exitcond
1158 PLpgSQL_stmt_exit *new;
1160 new = malloc(sizeof(PLpgSQL_stmt_exit));
1161 memset(new, 0, sizeof(PLpgSQL_stmt_exit));
1163 new->cmd_type = PLPGSQL_STMT_EXIT;
1168 $$ = (PLpgSQL_stmt *)new;
1172 stmt_return : K_RETURN lno
1174 PLpgSQL_stmt_return *new;
1176 new = malloc(sizeof(PLpgSQL_stmt_return));
1177 memset(new, 0, sizeof(PLpgSQL_stmt_return));
1182 if (plpgsql_curr_compile->fn_retistuple &&
1183 !plpgsql_curr_compile->fn_retset)
1191 new->retrowno = yylval.row->rowno;
1195 new->retrecno = yylval.rec->recno;
1199 yyerror("return type mismatch in function returning tuple");
1203 yyerror("expected \";\"");
1206 new->expr = plpgsql_read_expression(';', ";");
1208 new->cmd_type = PLPGSQL_STMT_RETURN;
1211 $$ = (PLpgSQL_stmt *)new;
1215 stmt_return_next: K_RETURN_NEXT lno
1217 PLpgSQL_stmt_return_next *new;
1219 new = malloc(sizeof(PLpgSQL_stmt_return_next));
1220 memset(new, 0, sizeof(PLpgSQL_stmt_return_next));
1222 new->cmd_type = PLPGSQL_STMT_RETURN_NEXT;
1225 if (plpgsql_curr_compile->fn_retistuple)
1229 if (tok == T_RECORD)
1230 new->rec = yylval.rec;
1231 else if (tok == T_ROW)
1232 new->row = yylval.row;
1234 yyerror("incorrect argument to RETURN NEXT");
1237 yyerror("expected \";\"");
1240 new->expr = plpgsql_read_expression(';', ";");
1242 $$ = (PLpgSQL_stmt *)new;
1246 stmt_raise : K_RAISE lno raise_level raise_msg raise_params ';'
1248 PLpgSQL_stmt_raise *new;
1250 new = malloc(sizeof(PLpgSQL_stmt_raise));
1252 new->cmd_type = PLPGSQL_STMT_RAISE;
1254 new->elog_level = $3;
1256 new->nparams = $5.nused;
1257 new->params = malloc(sizeof(int) * $5.nused);
1258 memcpy(new->params, $5.nums, sizeof(int) * $5.nused);
1260 $$ = (PLpgSQL_stmt *)new;
1262 | K_RAISE lno raise_level raise_msg ';'
1264 PLpgSQL_stmt_raise *new;
1266 new = malloc(sizeof(PLpgSQL_stmt_raise));
1268 new->cmd_type = PLPGSQL_STMT_RAISE;
1270 new->elog_level = $3;
1275 $$ = (PLpgSQL_stmt *)new;
1279 raise_msg : T_STRING
1281 $$ = strdup(yytext);
1285 raise_level : K_EXCEPTION
1311 raise_params : raise_params raise_param
1313 if ($1.nused == $1.nalloc)
1316 $1.nums = repalloc($1.nums, sizeof(int) * $1.nalloc);
1318 $1.nums[$1.nused++] = $2;
1320 $$.nalloc = $1.nalloc;
1321 $$.nused = $1.nused;
1328 $$.nums = palloc(sizeof(int) * $$.nalloc);
1333 raise_param : ',' T_VARIABLE
1335 $$ = yylval.variable->dno;
1339 loop_body : proc_sect K_END K_LOOP ';'
1343 stmt_execsql : execsql_start lno
1345 PLpgSQL_stmt_execsql *new;
1347 new = malloc(sizeof(PLpgSQL_stmt_execsql));
1348 new->cmd_type = PLPGSQL_STMT_EXECSQL;
1350 new->sqlstmt = read_sql_stmt($1);
1352 $$ = (PLpgSQL_stmt *)new;
1356 stmt_dynexecute : K_EXECUTE lno expr_until_semi
1358 PLpgSQL_stmt_dynexecute *new;
1360 new = malloc(sizeof(PLpgSQL_stmt_dynexecute));
1361 new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
1365 $$ = (PLpgSQL_stmt *)new;
1369 stmt_open : K_OPEN lno cursor_varptr
1371 PLpgSQL_stmt_open *new;
1374 new = malloc(sizeof(PLpgSQL_stmt_open));
1375 memset(new, 0, sizeof(PLpgSQL_stmt_open));
1377 new->cmd_type = PLPGSQL_STMT_OPEN;
1379 new->curvar = $3->varno;
1381 if ($3->cursor_explicit_expr == NULL)
1387 plpgsql_error_lineno = $2;
1389 (errcode(ERRCODE_SYNTAX_ERROR),
1390 errmsg("syntax error at \"%s\"",
1392 errdetail("Expected FOR to open a reference cursor.")));
1400 plpgsql_push_back_token(tok);
1401 new->query = read_sql_stmt("");
1405 new->dynquery = read_sql_stmt("SELECT ");
1409 plpgsql_error_lineno = $2;
1411 (errcode(ERRCODE_SYNTAX_ERROR),
1412 errmsg("syntax error at \"%s\"",
1419 if ($3->cursor_explicit_argrow >= 0)
1427 plpgsql_error_lineno = plpgsql_scanner_lineno();
1429 (errcode(ERRCODE_SYNTAX_ERROR),
1430 errmsg("cursor \"%s\" has arguments",
1435 * Push back the '(', else read_sql_stmt
1436 * will complain about unbalanced parens.
1438 plpgsql_push_back_token(tok);
1440 new->argquery = read_sql_stmt("SELECT ");
1443 * Now remove the leading and trailing parens,
1444 * because we want "select 1, 2", not
1447 cp = new->argquery->query;
1449 if (strncmp(cp, "SELECT", 6) != 0)
1451 plpgsql_error_lineno = plpgsql_scanner_lineno();
1452 /* internal error */
1453 elog(ERROR, "expected \"SELECT (\", got \"%s\"",
1454 new->argquery->query);
1457 while (*cp == ' ') /* could be more than 1 space here */
1461 plpgsql_error_lineno = plpgsql_scanner_lineno();
1462 /* internal error */
1463 elog(ERROR, "expected \"SELECT (\", got \"%s\"",
1464 new->argquery->query);
1468 cp += strlen(cp) - 1;
1471 yyerror("expected \")\"");
1480 plpgsql_error_lineno = plpgsql_scanner_lineno();
1482 (errcode(ERRCODE_SYNTAX_ERROR),
1483 errmsg("cursor \"%s\" has no arguments",
1489 plpgsql_error_lineno = plpgsql_scanner_lineno();
1491 (errcode(ERRCODE_SYNTAX_ERROR),
1492 errmsg("syntax error at \"%s\"",
1498 $$ = (PLpgSQL_stmt *)new;
1502 stmt_fetch : K_FETCH lno cursor_variable K_INTO
1504 PLpgSQL_stmt_fetch *new;
1506 new = (PLpgSQL_stmt_fetch *)make_fetch_stmt();
1509 $$ = (PLpgSQL_stmt *)new;
1514 stmt_close : K_CLOSE lno cursor_variable ';'
1516 PLpgSQL_stmt_close *new;
1518 new = malloc(sizeof(PLpgSQL_stmt_close));
1519 new->cmd_type = PLPGSQL_STMT_CLOSE;
1523 $$ = (PLpgSQL_stmt *)new;
1527 cursor_varptr : T_VARIABLE
1529 if (yylval.variable->dtype != PLPGSQL_DTYPE_VAR)
1530 yyerror("cursor variable must be a simple variable");
1532 if (((PLpgSQL_var *) yylval.variable)->datatype->typoid != REFCURSOROID)
1534 plpgsql_error_lineno = plpgsql_scanner_lineno();
1536 (errcode(ERRCODE_DATATYPE_MISMATCH),
1537 errmsg("\"%s\" must be of type cursor or refcursor",
1538 ((PLpgSQL_var *) yylval.variable)->refname)));
1540 $$ = (PLpgSQL_var *) yylval.variable;
1544 cursor_variable : T_VARIABLE
1546 if (yylval.variable->dtype != PLPGSQL_DTYPE_VAR)
1547 yyerror("cursor variable must be a simple variable");
1549 if (((PLpgSQL_var *) yylval.variable)->datatype->typoid != REFCURSOROID)
1551 plpgsql_error_lineno = plpgsql_scanner_lineno();
1553 (errcode(ERRCODE_DATATYPE_MISMATCH),
1554 errmsg("\"%s\" must be of type refcursor",
1555 ((PLpgSQL_var *) yylval.variable)->refname)));
1557 $$ = yylval.variable->dno;
1561 execsql_start : T_WORD
1562 { $$ = strdup(yytext); }
1564 { $$ = strdup(yytext); }
1568 { $$ = plpgsql_read_expression(';', ";"); }
1571 expr_until_rightbracket :
1572 { $$ = plpgsql_read_expression(']', "]"); }
1576 { $$ = plpgsql_read_expression(K_THEN, "THEN"); }
1580 { $$ = plpgsql_read_expression(K_LOOP, "LOOP"); }
1585 plpgsql_ns_push(NULL);
1588 | '<' '<' opt_lblname '>' '>'
1590 plpgsql_ns_push($3);
1598 { $$ = strdup(yytext); }
1603 | K_WHEN expr_until_semi
1607 opt_lblname : T_WORD
1611 plpgsql_convert_ident(yytext, &name, 1);
1619 $$ = plpgsql_error_lineno = plpgsql_scanner_lineno();
1627 plpgsql_read_expression(int until, const char *expected)
1629 return read_sql_construct(until, expected, true, "SELECT ");
1632 static PLpgSQL_expr *
1633 read_sql_stmt(const char *sqlstart)
1635 return read_sql_construct(';', ";", false, sqlstart);
1638 static PLpgSQL_expr *
1639 read_sql_construct(int until,
1640 const char *expected,
1642 const char *sqlstart)
1653 lno = plpgsql_scanner_lineno();
1654 plpgsql_dstring_init(&ds);
1655 plpgsql_dstring_append(&ds, (char *) sqlstart);
1660 if (tok == until && parenlevel == 0)
1662 if (tok == '(' || tok == '[')
1664 else if (tok == ')' || tok == ']')
1669 (errcode(ERRCODE_SYNTAX_ERROR),
1670 errmsg("mismatched parentheses")));
1673 * End of function definition is an error, and we don't expect to
1674 * hit a semicolon either (unless it's the until symbol, in which
1675 * case we should have fallen out above).
1677 if (tok == 0 || tok == ';')
1679 plpgsql_error_lineno = lno;
1680 if (parenlevel != 0)
1682 (errcode(ERRCODE_SYNTAX_ERROR),
1683 errmsg("mismatched parentheses")));
1686 (errcode(ERRCODE_SYNTAX_ERROR),
1687 errmsg("missing \"%s\" at end of SQL expression",
1691 (errcode(ERRCODE_SYNTAX_ERROR),
1692 errmsg("missing \"%s\" at end of SQL statement",
1696 if (plpgsql_SpaceScanned)
1697 plpgsql_dstring_append(&ds, " ");
1701 params[nparams] = yylval.variable->dno;
1702 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1703 plpgsql_dstring_append(&ds, buf);
1707 plpgsql_dstring_append(&ds, yytext);
1712 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
1713 expr->dtype = PLPGSQL_DTYPE_EXPR;
1714 expr->query = strdup(plpgsql_dstring_get(&ds));
1716 expr->nparams = nparams;
1717 while(nparams-- > 0)
1718 expr->params[nparams] = params[nparams];
1719 plpgsql_dstring_free(&ds);
1724 static PLpgSQL_type *
1725 read_datatype(int tok)
1729 PLpgSQL_type *result;
1730 bool needspace = false;
1733 lno = plpgsql_scanner_lineno();
1735 /* Often there will be a lookahead token, but if not, get one */
1741 /* lexer found word%TYPE and did its thing already */
1742 return yylval.dtype;
1745 plpgsql_dstring_init(&ds);
1751 plpgsql_error_lineno = lno;
1752 if (parenlevel != 0)
1754 (errcode(ERRCODE_SYNTAX_ERROR),
1755 errmsg("mismatched parentheses")));
1757 (errcode(ERRCODE_SYNTAX_ERROR),
1758 errmsg("incomplete datatype declaration")));
1760 /* Possible followers for datatype in a declaration */
1761 if (tok == K_NOT || tok == K_ASSIGN || tok == K_DEFAULT)
1763 /* Possible followers for datatype in a cursor_arg list */
1764 if ((tok == ',' || tok == ')') && parenlevel == 0)
1768 else if (tok == ')')
1771 plpgsql_dstring_append(&ds, " ");
1773 plpgsql_dstring_append(&ds, yytext);
1778 plpgsql_push_back_token(tok);
1780 plpgsql_error_lineno = lno; /* in case of error in parse_datatype */
1782 result = plpgsql_parse_datatype(plpgsql_dstring_get(&ds));
1784 plpgsql_dstring_free(&ds);
1790 static PLpgSQL_stmt *
1791 make_select_stmt(void)
1798 PLpgSQL_row *row = NULL;
1799 PLpgSQL_rec *rec = NULL;
1801 int have_nexttok = 0;
1804 plpgsql_dstring_init(&ds);
1805 plpgsql_dstring_append(&ds, "SELECT ");
1816 plpgsql_error_lineno = plpgsql_scanner_lineno();
1818 (errcode(ERRCODE_SYNTAX_ERROR),
1819 errmsg("unexpected end of function definition")));
1825 plpgsql_error_lineno = plpgsql_scanner_lineno();
1827 (errcode(ERRCODE_SYNTAX_ERROR),
1828 errmsg("INTO specified more than once")));
1846 char *fieldnames[1024];
1849 check_assignable(yylval.variable);
1850 fieldnames[0] = strdup(yytext);
1851 varnos[0] = yylval.variable->dno;
1853 while ((tok = yylex()) == ',')
1859 check_assignable(yylval.variable);
1860 fieldnames[nfields] = strdup(yytext);
1861 varnos[nfields++] = yylval.variable->dno;
1865 plpgsql_error_lineno = plpgsql_scanner_lineno();
1867 (errcode(ERRCODE_SYNTAX_ERROR),
1868 errmsg("\"%s\" is not a variable",
1874 row = malloc(sizeof(PLpgSQL_row));
1875 row->dtype = PLPGSQL_DTYPE_ROW;
1876 row->refname = strdup("*internal*");
1877 row->lineno = plpgsql_scanner_lineno();
1878 row->rowtupdesc = NULL;
1879 row->nfields = nfields;
1880 row->fieldnames = malloc(sizeof(char *) * nfields);
1881 row->varnos = malloc(sizeof(int) * nfields);
1882 while (--nfields >= 0)
1884 row->fieldnames[nfields] = fieldnames[nfields];
1885 row->varnos[nfields] = varnos[nfields];
1888 plpgsql_adddatum((PLpgSQL_datum *)row);
1895 /* Treat the INTO as non-special */
1896 plpgsql_dstring_append(&ds, " INTO ");
1903 if (plpgsql_SpaceScanned)
1904 plpgsql_dstring_append(&ds, " ");
1908 params[nparams] = yylval.variable->dno;
1909 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1910 plpgsql_dstring_append(&ds, buf);
1914 plpgsql_dstring_append(&ds, yytext);
1919 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
1920 expr->dtype = PLPGSQL_DTYPE_EXPR;
1921 expr->query = strdup(plpgsql_dstring_get(&ds));
1923 expr->nparams = nparams;
1924 while(nparams-- > 0)
1925 expr->params[nparams] = params[nparams];
1926 plpgsql_dstring_free(&ds);
1930 PLpgSQL_stmt_select *select;
1932 select = malloc(sizeof(PLpgSQL_stmt_select));
1933 memset(select, 0, sizeof(PLpgSQL_stmt_select));
1934 select->cmd_type = PLPGSQL_STMT_SELECT;
1937 select->query = expr;
1939 return (PLpgSQL_stmt *)select;
1943 PLpgSQL_stmt_execsql *execsql;
1945 execsql = malloc(sizeof(PLpgSQL_stmt_execsql));
1946 execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
1947 execsql->sqlstmt = expr;
1949 return (PLpgSQL_stmt *)execsql;
1954 static PLpgSQL_stmt *
1955 make_fetch_stmt(void)
1958 PLpgSQL_row *row = NULL;
1959 PLpgSQL_rec *rec = NULL;
1960 PLpgSQL_stmt_fetch *fetch;
1961 int have_nexttok = 0;
1963 /* We have already parsed everything through the INTO keyword */
1979 char *fieldnames[1024];
1982 check_assignable(yylval.variable);
1983 fieldnames[0] = strdup(yytext);
1984 varnos[0] = yylval.variable->dno;
1986 while ((tok = yylex()) == ',')
1992 check_assignable(yylval.variable);
1993 fieldnames[nfields] = strdup(yytext);
1994 varnos[nfields++] = yylval.variable->dno;
1998 plpgsql_error_lineno = plpgsql_scanner_lineno();
2000 (errcode(ERRCODE_SYNTAX_ERROR),
2001 errmsg("\"%s\" is not a variable",
2007 row = malloc(sizeof(PLpgSQL_row));
2008 row->dtype = PLPGSQL_DTYPE_ROW;
2009 row->refname = strdup("*internal*");
2010 row->lineno = plpgsql_scanner_lineno();
2011 row->rowtupdesc = NULL;
2012 row->nfields = nfields;
2013 row->fieldnames = malloc(sizeof(char *) * nfields);
2014 row->varnos = malloc(sizeof(int) * nfields);
2015 while (--nfields >= 0)
2017 row->fieldnames[nfields] = fieldnames[nfields];
2018 row->varnos[nfields] = varnos[nfields];
2021 plpgsql_adddatum((PLpgSQL_datum *)row);
2026 yyerror("syntax error");
2033 yyerror("syntax error");
2035 fetch = malloc(sizeof(PLpgSQL_stmt_select));
2036 memset(fetch, 0, sizeof(PLpgSQL_stmt_fetch));
2037 fetch->cmd_type = PLPGSQL_STMT_FETCH;
2041 return (PLpgSQL_stmt *)fetch;
2046 check_assignable(PLpgSQL_datum *datum)
2048 switch (datum->dtype)
2050 case PLPGSQL_DTYPE_VAR:
2051 if (((PLpgSQL_var *) datum)->isconst)
2053 plpgsql_error_lineno = plpgsql_scanner_lineno();
2055 (errcode(ERRCODE_ERROR_IN_ASSIGNMENT),
2056 errmsg("\"%s\" is declared CONSTANT",
2057 ((PLpgSQL_var *) datum)->refname)));
2060 case PLPGSQL_DTYPE_RECFIELD:
2061 /* always assignable? */
2063 case PLPGSQL_DTYPE_ARRAYELEM:
2064 /* always assignable? */
2066 case PLPGSQL_DTYPE_TRIGARG:
2067 yyerror("cannot assign to tg_argv");
2070 elog(ERROR, "unrecognized dtype: %d", datum->dtype);
2075 #include "pl_scan.c"