2 /**********************************************************************
3 * gram.y - Parser for the PL/pgSQL
7 * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.58 2004/07/31 07:39:20 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,
48 static PLpgSQL_expr *read_sql_stmt(const char *sqlstart);
49 static PLpgSQL_type *read_datatype(int tok);
50 static PLpgSQL_stmt *make_select_stmt(void);
51 static PLpgSQL_stmt *make_fetch_stmt(void);
52 static void check_assignable(PLpgSQL_datum *datum);
74 PLpgSQL_diag_item *dtitems;
90 PLpgSQL_datum *scalar; /* a VAR, RECFIELD, or TRIGARG */
91 PLpgSQL_variable *variable; /* a VAR, REC, or ROW */
98 PLpgSQL_stmt_block *program;
99 PLpgSQL_exception *exception;
100 PLpgSQL_exceptions *exceptions;
101 PLpgSQL_nsitem *nsitem;
104 %type <declhdr> decl_sect
105 %type <varname> decl_varname
106 %type <str> decl_renname
107 %type <ival> decl_const decl_notnull
108 %type <expr> decl_defval decl_cursor_query
109 %type <dtype> decl_datatype
110 %type <row> decl_cursor_args decl_cursor_arglist
111 %type <nsitem> decl_aliasitem
112 %type <str> decl_stmts decl_stmt
114 %type <expr> expr_until_semi expr_until_rightbracket
115 %type <expr> expr_until_then expr_until_loop
116 %type <expr> opt_exitcond
118 %type <ival> assign_var cursor_variable
119 %type <var> cursor_varptr
120 %type <variable> decl_cursor_arg
121 %type <forvariable> for_variable
122 %type <stmt> for_control
124 %type <str> opt_lblname opt_label
125 %type <str> opt_exitlabel
126 %type <str> execsql_start
128 %type <stmts> proc_sect proc_stmts stmt_else loop_body
129 %type <stmt> proc_stmt pl_block
130 %type <stmt> stmt_assign stmt_if stmt_loop stmt_while stmt_exit
131 %type <stmt> stmt_return stmt_return_next stmt_raise stmt_execsql
132 %type <stmt> stmt_for stmt_select stmt_perform
133 %type <stmt> stmt_dynexecute stmt_getdiag
134 %type <stmt> stmt_open stmt_fetch stmt_close
136 %type <exceptions> exception_sect proc_exceptions
137 %type <exception> proc_exception
139 %type <intlist> raise_params
140 %type <ival> raise_level raise_param
141 %type <str> raise_msg
143 %type <dtlist> getdiag_list
144 %type <ival> getdiag_item getdiag_target
207 %token T_SCALAR /* a VAR, RECFIELD, or TRIGARG */
220 pl_function : T_FUNCTION comp_optsect pl_block opt_semi
222 yylval.program = (PLpgSQL_stmt_block *)$3;
224 | T_TRIGGER comp_optsect pl_block opt_semi
226 yylval.program = (PLpgSQL_stmt_block *)$3;
234 comp_options : comp_options comp_option
238 comp_option : O_OPTION O_DUMP
240 plpgsql_DumpExecTree = 1;
248 pl_block : decl_sect K_BEGIN lno proc_sect exception_sect K_END
250 PLpgSQL_stmt_block *new;
252 new = malloc(sizeof(PLpgSQL_stmt_block));
253 memset(new, 0, sizeof(PLpgSQL_stmt_block));
255 new->cmd_type = PLPGSQL_STMT_BLOCK;
257 new->label = $1.label;
258 new->n_initvars = $1.n_initvars;
259 new->initvarnos = $1.initvarnos;
261 new->exceptions = $5;
265 $$ = (PLpgSQL_stmt *)new;
270 decl_sect : opt_label
272 plpgsql_ns_setlocal(false);
275 $$.initvarnos = NULL;
276 plpgsql_add_initdatums(NULL);
278 | opt_label decl_start
280 plpgsql_ns_setlocal(false);
283 $$.initvarnos = NULL;
284 plpgsql_add_initdatums(NULL);
286 | opt_label decl_start decl_stmts
288 plpgsql_ns_setlocal(false);
293 $$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos));
297 decl_start : K_DECLARE
299 plpgsql_ns_setlocal(true);
303 decl_stmts : decl_stmts decl_stmt
309 decl_stmt : '<' '<' opt_lblname '>' '>'
317 decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
319 PLpgSQL_variable *var;
321 var = plpgsql_build_variable($1.name, $1.lineno,
325 if (var->dtype == PLPGSQL_DTYPE_VAR)
326 ((PLpgSQL_var *) var)->isconst = $2;
329 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
330 errmsg("row or record variable cannot be CONSTANT")));
334 if (var->dtype == PLPGSQL_DTYPE_VAR)
335 ((PLpgSQL_var *) var)->notnull = $4;
338 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
339 errmsg("row or record variable cannot be NOT NULL")));
343 if (var->dtype == PLPGSQL_DTYPE_VAR)
344 ((PLpgSQL_var *) var)->default_val = $5;
347 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
348 errmsg("default value for row or record variable is not supported")));
351 | decl_varname K_ALIAS K_FOR decl_aliasitem ';'
353 plpgsql_ns_additem($4->itemtype,
354 $4->itemno, $1.name);
356 | K_RENAME decl_renname K_TO decl_renname ';'
358 plpgsql_ns_rename($2, $4);
360 | decl_varname K_CURSOR
361 { plpgsql_ns_push(NULL); }
362 decl_cursor_args decl_is_from decl_cursor_query
365 PLpgSQL_expr *curname_def;
370 /* pop local namespace for cursor args */
373 new = (PLpgSQL_var *)
374 plpgsql_build_variable($1.name, $1.lineno,
375 plpgsql_build_datatype(REFCURSOROID,
379 curname_def = malloc(sizeof(PLpgSQL_expr));
380 memset(curname_def, 0, sizeof(PLpgSQL_expr));
382 curname_def->dtype = PLPGSQL_DTYPE_EXPR;
383 strcpy(buf, "SELECT '");
385 cp2 = buf + strlen(buf);
388 if (*cp1 == '\\' || *cp1 == '\'')
392 strcpy(cp2, "'::refcursor");
393 curname_def->query = strdup(buf);
394 new->default_val = curname_def;
396 new->cursor_explicit_expr = $6;
398 new->cursor_explicit_argrow = -1;
400 new->cursor_explicit_argrow = $4->rowno;
408 plpgsql_ns_setlocal(false);
409 query = read_sql_stmt("");
410 plpgsql_ns_setlocal(true);
420 | '(' decl_cursor_arglist ')'
422 /* Copy the temp arrays to malloc'd storage */
423 int nfields = $2->nfields;
427 ftmp = malloc(nfields * sizeof(char *));
428 vtmp = malloc(nfields * sizeof(int));
429 memcpy(ftmp, $2->fieldnames, nfields * sizeof(char *));
430 memcpy(vtmp, $2->varnos, nfields * sizeof(int));
432 pfree((char *)($2->fieldnames));
433 pfree((char *)($2->varnos));
435 $2->fieldnames = ftmp;
438 plpgsql_adddatum((PLpgSQL_datum *)$2);
444 decl_cursor_arglist : decl_cursor_arg
448 new = malloc(sizeof(PLpgSQL_row));
449 memset(new, 0, sizeof(PLpgSQL_row));
451 new->dtype = PLPGSQL_DTYPE_ROW;
452 new->refname = strdup("*internal*");
453 new->lineno = plpgsql_scanner_lineno();
454 new->rowtupdesc = NULL;
456 * We make temporary fieldnames/varnos arrays that
457 * are much bigger than necessary. We will resize
458 * them to just the needed size in the
459 * decl_cursor_args production.
461 new->fieldnames = palloc(1024 * sizeof(char *));
462 new->varnos = palloc(1024 * sizeof(int));
465 new->fieldnames[0] = $1->refname;
466 new->varnos[0] = $1->dno;
470 | decl_cursor_arglist ',' decl_cursor_arg
472 int i = $1->nfields++;
474 $1->fieldnames[i] = $3->refname;
475 $1->varnos[i] = $3->dno;
481 decl_cursor_arg : decl_varname decl_datatype
483 $$ = plpgsql_build_variable($1.name, $1.lineno,
488 decl_is_from : K_IS | /* Oracle */
491 decl_aliasitem : T_WORD
496 plpgsql_convert_ident(yytext, &name, 1);
498 yyerror("only positional parameters may be aliased");
500 plpgsql_ns_setlocal(false);
501 nsi = plpgsql_ns_lookup(name, NULL);
504 plpgsql_error_lineno = plpgsql_scanner_lineno();
506 (errcode(ERRCODE_UNDEFINED_PARAMETER),
507 errmsg("function has no parameter \"%s\"",
511 plpgsql_ns_setlocal(true);
519 decl_varname : T_WORD
523 plpgsql_convert_ident(yytext, &name, 1);
524 /* name should be malloc'd for use as varname */
525 $$.name = strdup(name);
526 $$.lineno = plpgsql_scanner_lineno();
531 decl_renname : T_WORD
535 plpgsql_convert_ident(yytext, &name, 1);
536 /* the result must be palloc'd, see plpgsql_ns_rename */
550 * If there's a lookahead token, read_datatype
553 $$ = read_datatype(yychar);
568 plpgsql_ns_setlocal(false);
569 $$ = plpgsql_read_expression(';', ";");
570 plpgsql_ns_setlocal(true);
574 decl_defkey : K_ASSIGN
582 new = malloc(sizeof(PLpgSQL_stmts));
583 memset(new, 0, sizeof(PLpgSQL_stmts));
590 proc_stmts : proc_stmts proc_stmt
592 if ($1->stmts_used == $1->stmts_alloc)
594 $1->stmts_alloc *= 2;
595 $1->stmts = realloc($1->stmts, sizeof(PLpgSQL_stmt *) * $1->stmts_alloc);
597 $1->stmts[$1->stmts_used++] = $2;
605 new = malloc(sizeof(PLpgSQL_stmts));
606 memset(new, 0, sizeof(PLpgSQL_stmts));
608 new->stmts_alloc = 64;
610 new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
618 proc_stmt : pl_block ';'
656 stmt_perform : K_PERFORM lno expr_until_semi
658 PLpgSQL_stmt_perform *new;
660 new = malloc(sizeof(PLpgSQL_stmt_perform));
661 memset(new, 0, sizeof(PLpgSQL_stmt_perform));
663 new->cmd_type = PLPGSQL_STMT_PERFORM;
667 $$ = (PLpgSQL_stmt *)new;
671 stmt_assign : assign_var lno K_ASSIGN expr_until_semi
673 PLpgSQL_stmt_assign *new;
675 new = malloc(sizeof(PLpgSQL_stmt_assign));
676 memset(new, 0, sizeof(PLpgSQL_stmt_assign));
678 new->cmd_type = PLPGSQL_STMT_ASSIGN;
683 $$ = (PLpgSQL_stmt *)new;
687 stmt_getdiag : K_GET K_DIAGNOSTICS lno getdiag_list ';'
689 PLpgSQL_stmt_getdiag *new;
691 new = malloc(sizeof(PLpgSQL_stmt_getdiag));
692 memset(new, 0, sizeof(PLpgSQL_stmt_getdiag));
694 new->cmd_type = PLPGSQL_STMT_GETDIAG;
696 new->ndtitems = $4.nused;
697 new->dtitems = malloc(sizeof(PLpgSQL_diag_item) * $4.nused);
698 memcpy(new->dtitems, $4.dtitems, sizeof(PLpgSQL_diag_item) * $4.nused);
700 $$ = (PLpgSQL_stmt *)new;
704 getdiag_list : getdiag_list ',' getdiag_target K_ASSIGN getdiag_item
706 if ($1.nused == $1.nalloc)
709 $1.dtitems = repalloc($1.dtitems, sizeof(PLpgSQL_diag_item) * $1.nalloc);
711 $1.dtitems[$1.nused].target = $3;
712 $1.dtitems[$1.nused].item = $5;
715 $$.nalloc = $1.nalloc;
717 $$.dtitems = $1.dtitems;
719 | getdiag_target K_ASSIGN getdiag_item
723 $$.dtitems = palloc(sizeof(PLpgSQL_diag_item) * $$.nalloc);
724 $$.dtitems[0].target = $1;
725 $$.dtitems[0].item = $3;
729 getdiag_item : K_ROW_COUNT
731 $$ = PLPGSQL_GETDIAG_ROW_COUNT;
735 $$ = PLPGSQL_GETDIAG_RESULT_OID;
739 getdiag_target : T_SCALAR
741 check_assignable(yylval.scalar);
742 $$ = yylval.scalar->dno;
747 assign_var : T_SCALAR
749 check_assignable(yylval.scalar);
750 $$ = yylval.scalar->dno;
754 check_assignable((PLpgSQL_datum *) yylval.row);
755 $$ = yylval.row->rowno;
759 check_assignable((PLpgSQL_datum *) yylval.rec);
760 $$ = yylval.rec->recno;
762 | assign_var '[' expr_until_rightbracket
764 PLpgSQL_arrayelem *new;
766 new = malloc(sizeof(PLpgSQL_arrayelem));
767 memset(new, 0, sizeof(PLpgSQL_arrayelem));
769 new->dtype = PLPGSQL_DTYPE_ARRAYELEM;
771 new->arrayparentno = $1;
773 plpgsql_adddatum((PLpgSQL_datum *)new);
779 stmt_if : K_IF lno expr_until_then proc_sect stmt_else K_END K_IF ';'
781 PLpgSQL_stmt_if *new;
783 new = malloc(sizeof(PLpgSQL_stmt_if));
784 memset(new, 0, sizeof(PLpgSQL_stmt_if));
786 new->cmd_type = PLPGSQL_STMT_IF;
790 new->false_body = $5;
792 $$ = (PLpgSQL_stmt *)new;
800 new = malloc(sizeof(PLpgSQL_stmts));
801 memset(new, 0, sizeof(PLpgSQL_stmts));
804 | K_ELSIF lno expr_until_then proc_sect stmt_else
807 * Translate the structure: into:
809 * IF c1 THEN IF c1 THEN
822 PLpgSQL_stmt_if *new_if;
824 /* first create a new if-statement */
825 new_if = malloc(sizeof(PLpgSQL_stmt_if));
826 memset(new_if, 0, sizeof(PLpgSQL_stmt_if));
828 new_if->cmd_type = PLPGSQL_STMT_IF;
831 new_if->true_body = $4;
832 new_if->false_body = $5;
834 /* this is a 'container' for the if-statement */
835 new = malloc(sizeof(PLpgSQL_stmts));
836 memset(new, 0, sizeof(PLpgSQL_stmts));
838 new->stmts_alloc = 64;
840 new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
841 new->stmts[0] = (PLpgSQL_stmt *) new_if;
853 stmt_loop : opt_label K_LOOP lno loop_body
855 PLpgSQL_stmt_loop *new;
857 new = malloc(sizeof(PLpgSQL_stmt_loop));
858 memset(new, 0, sizeof(PLpgSQL_stmt_loop));
860 new->cmd_type = PLPGSQL_STMT_LOOP;
867 $$ = (PLpgSQL_stmt *)new;
871 stmt_while : opt_label K_WHILE lno expr_until_loop loop_body
873 PLpgSQL_stmt_while *new;
875 new = malloc(sizeof(PLpgSQL_stmt_while));
876 memset(new, 0, sizeof(PLpgSQL_stmt_while));
878 new->cmd_type = PLPGSQL_STMT_WHILE;
886 $$ = (PLpgSQL_stmt *)new;
890 stmt_for : opt_label K_FOR for_control loop_body
892 /* This runs after we've scanned the loop body */
893 if ($3->cmd_type == PLPGSQL_STMT_FORI)
895 PLpgSQL_stmt_fori *new;
897 new = (PLpgSQL_stmt_fori *) $3;
900 $$ = (PLpgSQL_stmt *) new;
902 else if ($3->cmd_type == PLPGSQL_STMT_FORS)
904 PLpgSQL_stmt_fors *new;
906 new = (PLpgSQL_stmt_fors *) $3;
909 $$ = (PLpgSQL_stmt *) new;
913 PLpgSQL_stmt_dynfors *new;
915 Assert($3->cmd_type == PLPGSQL_STMT_DYNFORS);
916 new = (PLpgSQL_stmt_dynfors *) $3;
919 $$ = (PLpgSQL_stmt *) new;
922 /* close namespace started in opt_label */
927 for_control : lno for_variable K_IN
930 bool reverse = false;
931 bool execute = false;
934 /* check for REVERSE and EXECUTE */
936 if (tok == K_REVERSE)
942 if (tok == K_EXECUTE)
945 plpgsql_push_back_token(tok);
947 /* Collect one or two expressions */
948 expr1 = read_sql_construct(K_DOTDOT,
957 /* Found .., so it must be an integer loop */
958 PLpgSQL_stmt_fori *new;
962 expr2 = plpgsql_read_expression(K_LOOP, "LOOP");
966 plpgsql_error_lineno = $1;
967 yyerror("cannot specify EXECUTE in integer for-loop");
970 /* name should be malloc'd for use as varname */
971 fvar = (PLpgSQL_var *)
972 plpgsql_build_variable(strdup($2.name),
974 plpgsql_build_datatype(INT4OID,
978 /* put the for-variable into the local block */
979 plpgsql_add_initdatums(NULL);
981 new = malloc(sizeof(PLpgSQL_stmt_fori));
982 memset(new, 0, sizeof(PLpgSQL_stmt_fori));
984 new->cmd_type = PLPGSQL_STMT_FORI;
987 new->reverse = reverse;
991 $$ = (PLpgSQL_stmt *) new;
995 /* No .., so it must be a loop over rows */
996 PLpgSQL_stmt_dynfors *new;
1000 plpgsql_error_lineno = $1;
1001 yyerror("cannot specify REVERSE in loop over rows");
1004 new = malloc(sizeof(PLpgSQL_stmt_dynfors));
1005 memset(new, 0, sizeof(PLpgSQL_stmt_dynfors));
1007 new->cmd_type = PLPGSQL_STMT_DYNFORS;
1015 plpgsql_error_lineno = $1;
1016 yyerror("loop variable of loop over rows must be a record or row variable");
1020 $$ = (PLpgSQL_stmt *) new;
1024 /* No .., so it must be a loop over rows */
1025 PLpgSQL_stmt_fors *new;
1030 plpgsql_error_lineno = $1;
1031 yyerror("cannot specify REVERSE in loop over rows");
1034 new = malloc(sizeof(PLpgSQL_stmt_fors));
1035 memset(new, 0, sizeof(PLpgSQL_stmt_fors));
1037 new->cmd_type = PLPGSQL_STMT_FORS;
1045 plpgsql_error_lineno = $1;
1046 yyerror("loop variable of loop over rows must be a record or row variable");
1049 * Must get rid of the "SELECT " we prepended
1052 newquery = strdup(expr1->query + 7);
1054 expr1->query = newquery;
1058 $$ = (PLpgSQL_stmt *) new;
1063 for_variable : T_SCALAR
1067 plpgsql_convert_ident(yytext, &name, 1);
1069 $$.lineno = plpgsql_scanner_lineno();
1077 plpgsql_convert_ident(yytext, &name, 1);
1079 $$.lineno = plpgsql_scanner_lineno();
1087 plpgsql_convert_ident(yytext, &name, 1);
1089 $$.lineno = plpgsql_scanner_lineno();
1090 $$.rec = yylval.rec;
1097 plpgsql_convert_ident(yytext, &name, 1);
1099 $$.lineno = plpgsql_scanner_lineno();
1100 $$.row = yylval.row;
1105 stmt_select : K_SELECT lno
1107 $$ = make_select_stmt();
1112 stmt_exit : K_EXIT lno opt_exitlabel opt_exitcond
1114 PLpgSQL_stmt_exit *new;
1116 new = malloc(sizeof(PLpgSQL_stmt_exit));
1117 memset(new, 0, sizeof(PLpgSQL_stmt_exit));
1119 new->cmd_type = PLPGSQL_STMT_EXIT;
1124 $$ = (PLpgSQL_stmt *)new;
1128 stmt_return : K_RETURN lno
1130 PLpgSQL_stmt_return *new;
1132 new = malloc(sizeof(PLpgSQL_stmt_return));
1133 memset(new, 0, sizeof(PLpgSQL_stmt_return));
1138 if (plpgsql_curr_compile->fn_retset)
1141 yyerror("RETURN cannot have a parameter in function returning set; use RETURN NEXT");
1143 else if (plpgsql_curr_compile->fn_retistuple)
1151 new->retrowno = yylval.row->rowno;
1155 new->retrecno = yylval.rec->recno;
1159 yyerror("RETURN must specify a record or row variable in function returning tuple");
1163 yyerror("RETURN must specify a record or row variable in function returning tuple");
1167 /* ordinary expression case */
1168 new->expr = plpgsql_read_expression(';', ";");
1171 new->cmd_type = PLPGSQL_STMT_RETURN;
1174 $$ = (PLpgSQL_stmt *)new;
1178 stmt_return_next: K_RETURN_NEXT lno
1180 PLpgSQL_stmt_return_next *new;
1182 if (!plpgsql_curr_compile->fn_retset)
1183 yyerror("cannot use RETURN NEXT in a non-SETOF function");
1185 new = malloc(sizeof(PLpgSQL_stmt_return_next));
1186 memset(new, 0, sizeof(PLpgSQL_stmt_return_next));
1188 new->cmd_type = PLPGSQL_STMT_RETURN_NEXT;
1191 if (plpgsql_curr_compile->fn_retistuple)
1195 if (tok == T_RECORD)
1196 new->rec = yylval.rec;
1197 else if (tok == T_ROW)
1198 new->row = yylval.row;
1200 yyerror("RETURN NEXT must specify a record or row variable in function returning tuple");
1203 yyerror("RETURN NEXT must specify a record or row variable in function returning tuple");
1206 new->expr = plpgsql_read_expression(';', ";");
1208 $$ = (PLpgSQL_stmt *)new;
1212 stmt_raise : K_RAISE lno raise_level raise_msg raise_params ';'
1214 PLpgSQL_stmt_raise *new;
1216 new = malloc(sizeof(PLpgSQL_stmt_raise));
1218 new->cmd_type = PLPGSQL_STMT_RAISE;
1220 new->elog_level = $3;
1222 new->nparams = $5.nused;
1223 new->params = malloc(sizeof(int) * $5.nused);
1224 memcpy(new->params, $5.nums, sizeof(int) * $5.nused);
1226 $$ = (PLpgSQL_stmt *)new;
1228 | K_RAISE lno raise_level raise_msg ';'
1230 PLpgSQL_stmt_raise *new;
1232 new = malloc(sizeof(PLpgSQL_stmt_raise));
1234 new->cmd_type = PLPGSQL_STMT_RAISE;
1236 new->elog_level = $3;
1241 $$ = (PLpgSQL_stmt *)new;
1245 raise_msg : T_STRING
1247 $$ = plpgsql_get_string_value();
1251 raise_level : K_EXCEPTION
1277 raise_params : raise_params raise_param
1279 if ($1.nused == $1.nalloc)
1282 $1.nums = repalloc($1.nums, sizeof(int) * $1.nalloc);
1284 $1.nums[$1.nused++] = $2;
1286 $$.nalloc = $1.nalloc;
1287 $$.nused = $1.nused;
1294 $$.nums = palloc(sizeof(int) * $$.nalloc);
1299 raise_param : ',' T_SCALAR
1301 $$ = yylval.scalar->dno;
1305 loop_body : proc_sect K_END K_LOOP ';'
1309 stmt_execsql : execsql_start lno
1311 PLpgSQL_stmt_execsql *new;
1313 new = malloc(sizeof(PLpgSQL_stmt_execsql));
1314 new->cmd_type = PLPGSQL_STMT_EXECSQL;
1316 new->sqlstmt = read_sql_stmt($1);
1318 $$ = (PLpgSQL_stmt *)new;
1322 stmt_dynexecute : K_EXECUTE lno expr_until_semi
1324 PLpgSQL_stmt_dynexecute *new;
1326 new = malloc(sizeof(PLpgSQL_stmt_dynexecute));
1327 new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
1331 $$ = (PLpgSQL_stmt *)new;
1335 stmt_open : K_OPEN lno cursor_varptr
1337 PLpgSQL_stmt_open *new;
1340 new = malloc(sizeof(PLpgSQL_stmt_open));
1341 memset(new, 0, sizeof(PLpgSQL_stmt_open));
1343 new->cmd_type = PLPGSQL_STMT_OPEN;
1345 new->curvar = $3->varno;
1347 if ($3->cursor_explicit_expr == NULL)
1353 plpgsql_error_lineno = $2;
1355 (errcode(ERRCODE_SYNTAX_ERROR),
1356 errmsg("syntax error at \"%s\"",
1358 errdetail("Expected FOR to open a reference cursor.")));
1366 plpgsql_push_back_token(tok);
1367 new->query = read_sql_stmt("");
1371 new->dynquery = read_sql_stmt("SELECT ");
1375 plpgsql_error_lineno = $2;
1377 (errcode(ERRCODE_SYNTAX_ERROR),
1378 errmsg("syntax error at \"%s\"",
1385 if ($3->cursor_explicit_argrow >= 0)
1393 plpgsql_error_lineno = plpgsql_scanner_lineno();
1395 (errcode(ERRCODE_SYNTAX_ERROR),
1396 errmsg("cursor \"%s\" has arguments",
1401 * Push back the '(', else read_sql_stmt
1402 * will complain about unbalanced parens.
1404 plpgsql_push_back_token(tok);
1406 new->argquery = read_sql_stmt("SELECT ");
1409 * Now remove the leading and trailing parens,
1410 * because we want "select 1, 2", not
1413 cp = new->argquery->query;
1415 if (strncmp(cp, "SELECT", 6) != 0)
1417 plpgsql_error_lineno = plpgsql_scanner_lineno();
1418 /* internal error */
1419 elog(ERROR, "expected \"SELECT (\", got \"%s\"",
1420 new->argquery->query);
1423 while (*cp == ' ') /* could be more than 1 space here */
1427 plpgsql_error_lineno = plpgsql_scanner_lineno();
1428 /* internal error */
1429 elog(ERROR, "expected \"SELECT (\", got \"%s\"",
1430 new->argquery->query);
1434 cp += strlen(cp) - 1;
1437 yyerror("expected \")\"");
1446 plpgsql_error_lineno = plpgsql_scanner_lineno();
1448 (errcode(ERRCODE_SYNTAX_ERROR),
1449 errmsg("cursor \"%s\" has no arguments",
1455 plpgsql_error_lineno = plpgsql_scanner_lineno();
1457 (errcode(ERRCODE_SYNTAX_ERROR),
1458 errmsg("syntax error at \"%s\"",
1464 $$ = (PLpgSQL_stmt *)new;
1468 stmt_fetch : K_FETCH lno cursor_variable K_INTO
1470 PLpgSQL_stmt_fetch *new;
1472 new = (PLpgSQL_stmt_fetch *)make_fetch_stmt();
1475 $$ = (PLpgSQL_stmt *)new;
1480 stmt_close : K_CLOSE lno cursor_variable ';'
1482 PLpgSQL_stmt_close *new;
1484 new = malloc(sizeof(PLpgSQL_stmt_close));
1485 new->cmd_type = PLPGSQL_STMT_CLOSE;
1489 $$ = (PLpgSQL_stmt *)new;
1493 cursor_varptr : T_SCALAR
1495 if (yylval.scalar->dtype != PLPGSQL_DTYPE_VAR)
1496 yyerror("cursor variable must be a simple variable");
1498 if (((PLpgSQL_var *) yylval.scalar)->datatype->typoid != REFCURSOROID)
1500 plpgsql_error_lineno = plpgsql_scanner_lineno();
1502 (errcode(ERRCODE_DATATYPE_MISMATCH),
1503 errmsg("\"%s\" must be of type cursor or refcursor",
1504 ((PLpgSQL_var *) yylval.scalar)->refname)));
1506 $$ = (PLpgSQL_var *) yylval.scalar;
1510 cursor_variable : T_SCALAR
1512 if (yylval.scalar->dtype != PLPGSQL_DTYPE_VAR)
1513 yyerror("cursor variable must be a simple variable");
1515 if (((PLpgSQL_var *) yylval.scalar)->datatype->typoid != REFCURSOROID)
1517 plpgsql_error_lineno = plpgsql_scanner_lineno();
1519 (errcode(ERRCODE_DATATYPE_MISMATCH),
1520 errmsg("\"%s\" must be of type refcursor",
1521 ((PLpgSQL_var *) yylval.scalar)->refname)));
1523 $$ = yylval.scalar->dno;
1527 execsql_start : T_WORD
1528 { $$ = strdup(yytext); }
1530 { $$ = strdup(yytext); }
1535 | K_EXCEPTION proc_exceptions
1539 proc_exceptions : proc_exceptions proc_exception
1541 if ($1->exceptions_used == $1->exceptions_alloc)
1543 $1->exceptions_alloc *= 2;
1544 $1->exceptions = realloc($1->exceptions, sizeof(PLpgSQL_exception *) * $1->exceptions_alloc);
1546 $1->exceptions[$1->exceptions_used++] = $2;
1552 PLpgSQL_exceptions *new;
1554 new = malloc(sizeof(PLpgSQL_exceptions));
1555 memset(new, 0, sizeof(PLpgSQL_exceptions));
1557 new->exceptions_alloc = 64;
1558 new->exceptions_used = 1;
1559 new->exceptions = malloc(sizeof(PLpgSQL_exception *) * new->exceptions_alloc);
1560 new->exceptions[0] = $1;
1566 proc_exception : K_WHEN lno opt_lblname K_THEN proc_sect
1568 PLpgSQL_exception *new;
1570 new = malloc(sizeof(PLpgSQL_exception));
1571 memset(new, 0, sizeof(PLpgSQL_exception));
1582 { $$ = plpgsql_read_expression(';', ";"); }
1585 expr_until_rightbracket :
1586 { $$ = plpgsql_read_expression(']', "]"); }
1590 { $$ = plpgsql_read_expression(K_THEN, "THEN"); }
1594 { $$ = plpgsql_read_expression(K_LOOP, "LOOP"); }
1599 plpgsql_ns_push(NULL);
1602 | '<' '<' opt_lblname '>' '>'
1604 plpgsql_ns_push($3);
1612 { $$ = strdup(yytext); }
1617 | K_WHEN expr_until_semi
1621 opt_lblname : T_WORD
1625 plpgsql_convert_ident(yytext, &name, 1);
1633 $$ = plpgsql_error_lineno = plpgsql_scanner_lineno();
1641 plpgsql_read_expression(int until, const char *expected)
1643 return read_sql_construct(until, 0, expected, true, "SELECT ", NULL);
1646 static PLpgSQL_expr *
1647 read_sql_stmt(const char *sqlstart)
1649 return read_sql_construct(';', 0, ";", false, sqlstart, NULL);
1653 * Read a SQL construct and build a PLpgSQL_expr for it.
1655 * until: token code for expected terminator
1656 * until2: token code for alternate terminator (pass 0 if none)
1657 * expected: text to use in complaining that terminator was not found
1658 * isexpression: whether to say we're reading an "expression" or a "statement"
1659 * sqlstart: text to prefix to the accumulated SQL text
1660 * endtoken: if not NULL, ending token is stored at *endtoken
1661 * (this is only interesting if until2 isn't zero)
1663 static PLpgSQL_expr *
1664 read_sql_construct(int until,
1666 const char *expected,
1668 const char *sqlstart,
1680 lno = plpgsql_scanner_lineno();
1681 plpgsql_dstring_init(&ds);
1682 plpgsql_dstring_append(&ds, (char *) sqlstart);
1687 if (tok == until && parenlevel == 0)
1689 if (tok == until2 && parenlevel == 0)
1691 if (tok == '(' || tok == '[')
1693 else if (tok == ')' || tok == ']')
1698 (errcode(ERRCODE_SYNTAX_ERROR),
1699 errmsg("mismatched parentheses")));
1702 * End of function definition is an error, and we don't expect to
1703 * hit a semicolon either (unless it's the until symbol, in which
1704 * case we should have fallen out above).
1706 if (tok == 0 || tok == ';')
1708 plpgsql_error_lineno = lno;
1709 if (parenlevel != 0)
1711 (errcode(ERRCODE_SYNTAX_ERROR),
1712 errmsg("mismatched parentheses")));
1715 (errcode(ERRCODE_SYNTAX_ERROR),
1716 errmsg("missing \"%s\" at end of SQL expression",
1720 (errcode(ERRCODE_SYNTAX_ERROR),
1721 errmsg("missing \"%s\" at end of SQL statement",
1724 if (plpgsql_SpaceScanned)
1725 plpgsql_dstring_append(&ds, " ");
1729 params[nparams] = yylval.scalar->dno;
1730 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1731 plpgsql_dstring_append(&ds, buf);
1735 params[nparams] = yylval.row->rowno;
1736 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1737 plpgsql_dstring_append(&ds, buf);
1741 params[nparams] = yylval.rec->recno;
1742 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1743 plpgsql_dstring_append(&ds, buf);
1747 plpgsql_dstring_append(&ds, yytext);
1755 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
1756 expr->dtype = PLPGSQL_DTYPE_EXPR;
1757 expr->query = strdup(plpgsql_dstring_get(&ds));
1759 expr->nparams = nparams;
1760 while(nparams-- > 0)
1761 expr->params[nparams] = params[nparams];
1762 plpgsql_dstring_free(&ds);
1767 static PLpgSQL_type *
1768 read_datatype(int tok)
1772 PLpgSQL_type *result;
1773 bool needspace = false;
1776 lno = plpgsql_scanner_lineno();
1778 /* Often there will be a lookahead token, but if not, get one */
1784 /* lexer found word%TYPE and did its thing already */
1785 return yylval.dtype;
1788 plpgsql_dstring_init(&ds);
1794 plpgsql_error_lineno = lno;
1795 if (parenlevel != 0)
1797 (errcode(ERRCODE_SYNTAX_ERROR),
1798 errmsg("mismatched parentheses")));
1800 (errcode(ERRCODE_SYNTAX_ERROR),
1801 errmsg("incomplete datatype declaration")));
1803 /* Possible followers for datatype in a declaration */
1804 if (tok == K_NOT || tok == K_ASSIGN || tok == K_DEFAULT)
1806 /* Possible followers for datatype in a cursor_arg list */
1807 if ((tok == ',' || tok == ')') && parenlevel == 0)
1811 else if (tok == ')')
1814 plpgsql_dstring_append(&ds, " ");
1816 plpgsql_dstring_append(&ds, yytext);
1821 plpgsql_push_back_token(tok);
1823 plpgsql_error_lineno = lno; /* in case of error in parse_datatype */
1825 result = plpgsql_parse_datatype(plpgsql_dstring_get(&ds));
1827 plpgsql_dstring_free(&ds);
1833 static PLpgSQL_stmt *
1834 make_select_stmt(void)
1841 PLpgSQL_row *row = NULL;
1842 PLpgSQL_rec *rec = NULL;
1844 int have_nexttok = 0;
1847 plpgsql_dstring_init(&ds);
1848 plpgsql_dstring_append(&ds, "SELECT ");
1859 plpgsql_error_lineno = plpgsql_scanner_lineno();
1861 (errcode(ERRCODE_SYNTAX_ERROR),
1862 errmsg("unexpected end of function definition")));
1868 plpgsql_error_lineno = plpgsql_scanner_lineno();
1870 (errcode(ERRCODE_SYNTAX_ERROR),
1871 errmsg("INTO specified more than once")));
1889 char *fieldnames[1024];
1892 check_assignable(yylval.scalar);
1893 fieldnames[0] = strdup(yytext);
1894 varnos[0] = yylval.scalar->dno;
1896 while ((tok = yylex()) == ',')
1902 check_assignable(yylval.scalar);
1903 fieldnames[nfields] = strdup(yytext);
1904 varnos[nfields++] = yylval.scalar->dno;
1908 plpgsql_error_lineno = plpgsql_scanner_lineno();
1910 (errcode(ERRCODE_SYNTAX_ERROR),
1911 errmsg("\"%s\" is not a variable",
1917 row = malloc(sizeof(PLpgSQL_row));
1918 row->dtype = PLPGSQL_DTYPE_ROW;
1919 row->refname = strdup("*internal*");
1920 row->lineno = plpgsql_scanner_lineno();
1921 row->rowtupdesc = NULL;
1922 row->nfields = nfields;
1923 row->fieldnames = malloc(sizeof(char *) * nfields);
1924 row->varnos = malloc(sizeof(int) * nfields);
1925 while (--nfields >= 0)
1927 row->fieldnames[nfields] = fieldnames[nfields];
1928 row->varnos[nfields] = varnos[nfields];
1931 plpgsql_adddatum((PLpgSQL_datum *)row);
1938 /* Treat the INTO as non-special */
1939 plpgsql_dstring_append(&ds, " INTO ");
1946 if (plpgsql_SpaceScanned)
1947 plpgsql_dstring_append(&ds, " ");
1951 params[nparams] = yylval.scalar->dno;
1952 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1953 plpgsql_dstring_append(&ds, buf);
1957 params[nparams] = yylval.row->rowno;
1958 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1959 plpgsql_dstring_append(&ds, buf);
1963 params[nparams] = yylval.rec->recno;
1964 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1965 plpgsql_dstring_append(&ds, buf);
1969 plpgsql_dstring_append(&ds, yytext);
1974 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
1975 expr->dtype = PLPGSQL_DTYPE_EXPR;
1976 expr->query = strdup(plpgsql_dstring_get(&ds));
1978 expr->nparams = nparams;
1979 while(nparams-- > 0)
1980 expr->params[nparams] = params[nparams];
1981 plpgsql_dstring_free(&ds);
1985 PLpgSQL_stmt_select *select;
1987 select = malloc(sizeof(PLpgSQL_stmt_select));
1988 memset(select, 0, sizeof(PLpgSQL_stmt_select));
1989 select->cmd_type = PLPGSQL_STMT_SELECT;
1992 select->query = expr;
1994 return (PLpgSQL_stmt *)select;
1998 PLpgSQL_stmt_execsql *execsql;
2000 execsql = malloc(sizeof(PLpgSQL_stmt_execsql));
2001 execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
2002 execsql->sqlstmt = expr;
2004 return (PLpgSQL_stmt *)execsql;
2009 static PLpgSQL_stmt *
2010 make_fetch_stmt(void)
2013 PLpgSQL_row *row = NULL;
2014 PLpgSQL_rec *rec = NULL;
2015 PLpgSQL_stmt_fetch *fetch;
2016 int have_nexttok = 0;
2018 /* We have already parsed everything through the INTO keyword */
2034 char *fieldnames[1024];
2037 check_assignable(yylval.scalar);
2038 fieldnames[0] = strdup(yytext);
2039 varnos[0] = yylval.scalar->dno;
2041 while ((tok = yylex()) == ',')
2047 check_assignable(yylval.scalar);
2048 fieldnames[nfields] = strdup(yytext);
2049 varnos[nfields++] = yylval.scalar->dno;
2053 plpgsql_error_lineno = plpgsql_scanner_lineno();
2055 (errcode(ERRCODE_SYNTAX_ERROR),
2056 errmsg("\"%s\" is not a variable",
2062 row = malloc(sizeof(PLpgSQL_row));
2063 row->dtype = PLPGSQL_DTYPE_ROW;
2064 row->refname = strdup("*internal*");
2065 row->lineno = plpgsql_scanner_lineno();
2066 row->rowtupdesc = NULL;
2067 row->nfields = nfields;
2068 row->fieldnames = malloc(sizeof(char *) * nfields);
2069 row->varnos = malloc(sizeof(int) * nfields);
2070 while (--nfields >= 0)
2072 row->fieldnames[nfields] = fieldnames[nfields];
2073 row->varnos[nfields] = varnos[nfields];
2076 plpgsql_adddatum((PLpgSQL_datum *)row);
2081 yyerror("syntax error");
2088 yyerror("syntax error");
2090 fetch = malloc(sizeof(PLpgSQL_stmt_select));
2091 memset(fetch, 0, sizeof(PLpgSQL_stmt_fetch));
2092 fetch->cmd_type = PLPGSQL_STMT_FETCH;
2096 return (PLpgSQL_stmt *)fetch;
2101 check_assignable(PLpgSQL_datum *datum)
2103 switch (datum->dtype)
2105 case PLPGSQL_DTYPE_VAR:
2106 if (((PLpgSQL_var *) datum)->isconst)
2108 plpgsql_error_lineno = plpgsql_scanner_lineno();
2110 (errcode(ERRCODE_ERROR_IN_ASSIGNMENT),
2111 errmsg("\"%s\" is declared CONSTANT",
2112 ((PLpgSQL_var *) datum)->refname)));
2115 case PLPGSQL_DTYPE_ROW:
2116 /* always assignable? */
2118 case PLPGSQL_DTYPE_REC:
2119 /* always assignable? What about NEW/OLD? */
2121 case PLPGSQL_DTYPE_RECFIELD:
2122 /* always assignable? */
2124 case PLPGSQL_DTYPE_ARRAYELEM:
2125 /* always assignable? */
2127 case PLPGSQL_DTYPE_TRIGARG:
2128 yyerror("cannot assign to tg_argv");
2131 elog(ERROR, "unrecognized dtype: %d", datum->dtype);
2136 #include "pl_scan.c"