2 /**********************************************************************
3 * gram.y - Parser for the PL/pgSQL
7 * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.79 2005/07/02 08:59:47 neilc 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 **********************************************************************/
41 #include "parser/parser.h"
43 static PLpgSQL_expr *read_sql_construct(int until,
50 static PLpgSQL_expr *read_sql_stmt(const char *sqlstart);
51 static PLpgSQL_type *read_datatype(int tok);
52 static PLpgSQL_stmt *make_select_stmt(void);
53 static PLpgSQL_stmt *make_fetch_stmt(void);
54 static void check_assignable(PLpgSQL_datum *datum);
55 static PLpgSQL_row *read_into_scalar_list(const char *initial_name,
56 PLpgSQL_datum *initial_datum);
57 static void check_sql_expr(const char *stmt);
58 static void plpgsql_sql_error_callback(void *arg);
59 static void check_labels(const char *start_label,
60 const char *end_label);
93 PLpgSQL_datum *scalar; /* a VAR, RECFIELD, or TRIGARG */
94 PLpgSQL_variable *variable; /* a VAR, REC, or ROW */
100 PLpgSQL_stmt_block *program;
101 PLpgSQL_condition *condition;
102 PLpgSQL_exception *exception;
103 PLpgSQL_exception_block *exception_block;
104 PLpgSQL_nsitem *nsitem;
105 PLpgSQL_diag_item *diagitem;
108 %type <declhdr> decl_sect
109 %type <varname> decl_varname
110 %type <str> decl_renname
111 %type <boolean> decl_const decl_notnull exit_type
112 %type <expr> decl_defval decl_cursor_query
113 %type <dtype> decl_datatype
114 %type <row> decl_cursor_args
115 %type <list> decl_cursor_arglist
116 %type <nsitem> decl_aliasitem
117 %type <str> decl_stmts decl_stmt
119 %type <expr> expr_until_semi expr_until_rightbracket
120 %type <expr> expr_until_then expr_until_loop
121 %type <expr> opt_exitcond
123 %type <ival> assign_var cursor_variable
124 %type <var> cursor_varptr
125 %type <variable> decl_cursor_arg
126 %type <forvariable> for_variable
127 %type <stmt> for_control
129 %type <str> opt_lblname opt_block_label opt_label
130 %type <str> execsql_start
132 %type <list> proc_sect proc_stmts stmt_else
133 %type <loop_body> loop_body
134 %type <stmt> proc_stmt pl_block
135 %type <stmt> stmt_assign stmt_if stmt_loop stmt_while stmt_exit
136 %type <stmt> stmt_return stmt_return_next stmt_raise stmt_execsql
137 %type <stmt> stmt_for stmt_select stmt_perform
138 %type <stmt> stmt_dynexecute stmt_getdiag
139 %type <stmt> stmt_open stmt_fetch stmt_close stmt_null
141 %type <list> proc_exceptions
142 %type <exception_block> exception_sect
143 %type <exception> proc_exception
144 %type <condition> proc_conditions
147 %type <ival> raise_level
148 %type <str> raise_msg
150 %type <list> getdiag_list
151 %type <diagitem> getdiag_list_item
152 %type <ival> getdiag_kind getdiag_target
217 %token T_SCALAR /* a VAR, RECFIELD, or TRIGARG */
230 pl_function : T_FUNCTION comp_optsect pl_block opt_semi
232 yylval.program = (PLpgSQL_stmt_block *)$3;
234 | T_TRIGGER comp_optsect pl_block opt_semi
236 yylval.program = (PLpgSQL_stmt_block *)$3;
244 comp_options : comp_options comp_option
248 comp_option : O_OPTION O_DUMP
250 plpgsql_DumpExecTree = true;
258 pl_block : decl_sect K_BEGIN lno proc_sect exception_sect K_END opt_label
260 PLpgSQL_stmt_block *new;
262 new = palloc0(sizeof(PLpgSQL_stmt_block));
264 new->cmd_type = PLPGSQL_STMT_BLOCK;
266 new->label = $1.label;
267 new->n_initvars = $1.n_initvars;
268 new->initvarnos = $1.initvarnos;
270 new->exceptions = $5;
272 check_labels($1.label, $7);
275 $$ = (PLpgSQL_stmt *)new;
280 decl_sect : opt_block_label
282 plpgsql_ns_setlocal(false);
285 $$.initvarnos = NULL;
286 plpgsql_add_initdatums(NULL);
288 | opt_block_label decl_start
290 plpgsql_ns_setlocal(false);
293 $$.initvarnos = NULL;
294 plpgsql_add_initdatums(NULL);
296 | opt_block_label decl_start decl_stmts
298 plpgsql_ns_setlocal(false);
303 $$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos));
307 decl_start : K_DECLARE
309 plpgsql_ns_setlocal(true);
313 decl_stmts : decl_stmts decl_stmt
319 decl_stmt : '<' '<' opt_lblname '>' '>'
327 decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
329 PLpgSQL_variable *var;
331 var = plpgsql_build_variable($1.name, $1.lineno,
335 if (var->dtype == PLPGSQL_DTYPE_VAR)
336 ((PLpgSQL_var *) var)->isconst = $2;
339 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
340 errmsg("row or record variable cannot be CONSTANT")));
344 if (var->dtype == PLPGSQL_DTYPE_VAR)
345 ((PLpgSQL_var *) var)->notnull = $4;
348 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
349 errmsg("row or record variable cannot be NOT NULL")));
353 if (var->dtype == PLPGSQL_DTYPE_VAR)
354 ((PLpgSQL_var *) var)->default_val = $5;
357 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
358 errmsg("default value for row or record variable is not supported")));
361 | decl_varname K_ALIAS K_FOR decl_aliasitem ';'
363 plpgsql_ns_additem($4->itemtype,
364 $4->itemno, $1.name);
366 | K_RENAME decl_renname K_TO decl_renname ';'
368 plpgsql_ns_rename($2, $4);
370 | decl_varname K_CURSOR
371 { plpgsql_ns_push(NULL); }
372 decl_cursor_args decl_is_from decl_cursor_query
375 PLpgSQL_expr *curname_def;
380 /* pop local namespace for cursor args */
383 new = (PLpgSQL_var *)
384 plpgsql_build_variable($1.name, $1.lineno,
385 plpgsql_build_datatype(REFCURSOROID,
389 curname_def = palloc0(sizeof(PLpgSQL_expr));
391 curname_def->dtype = PLPGSQL_DTYPE_EXPR;
392 strcpy(buf, "SELECT '");
394 cp2 = buf + strlen(buf);
397 if (*cp1 == '\\' || *cp1 == '\'')
398 *cp2++ = *cp1; /* double these */
401 strcpy(cp2, "'::refcursor");
402 curname_def->query = pstrdup(buf);
403 new->default_val = curname_def;
405 new->cursor_explicit_expr = $6;
407 new->cursor_explicit_argrow = -1;
409 new->cursor_explicit_argrow = $4->rowno;
417 plpgsql_ns_setlocal(false);
418 query = read_sql_stmt("");
419 plpgsql_ns_setlocal(true);
429 | '(' decl_cursor_arglist ')'
435 new = palloc0(sizeof(PLpgSQL_row));
436 new->dtype = PLPGSQL_DTYPE_ROW;
437 new->lineno = plpgsql_scanner_lineno();
438 new->rowtupdesc = NULL;
439 new->nfields = list_length($2);
440 new->fieldnames = palloc(new->nfields * sizeof(char *));
441 new->varnos = palloc(new->nfields * sizeof(int));
446 PLpgSQL_variable *arg = (PLpgSQL_variable *) lfirst(l);
447 new->fieldnames[i] = arg->refname;
448 new->varnos[i] = arg->dno;
453 plpgsql_adddatum((PLpgSQL_datum *) new);
458 decl_cursor_arglist : decl_cursor_arglist decl_cursor_arg
460 $$ = lappend($1, $2);
468 decl_cursor_arg : decl_varname decl_datatype
470 $$ = plpgsql_build_variable($1.name, $1.lineno,
475 decl_is_from : K_IS | /* Oracle */
478 decl_aliasitem : T_WORD
483 plpgsql_convert_ident(yytext, &name, 1);
485 yyerror("only positional parameters may be aliased");
487 plpgsql_ns_setlocal(false);
488 nsi = plpgsql_ns_lookup(name, NULL);
491 plpgsql_error_lineno = plpgsql_scanner_lineno();
493 (errcode(ERRCODE_UNDEFINED_PARAMETER),
494 errmsg("function has no parameter \"%s\"",
498 plpgsql_ns_setlocal(true);
506 decl_varname : T_WORD
510 plpgsql_convert_ident(yytext, &name, 1);
512 $$.lineno = plpgsql_scanner_lineno();
516 decl_renname : T_WORD
520 plpgsql_convert_ident(yytext, &name, 1);
521 /* the result must be palloc'd, see plpgsql_ns_rename */
535 * If there's a lookahead token, read_datatype
538 $$ = read_datatype(yychar);
553 plpgsql_ns_setlocal(false);
554 $$ = plpgsql_read_expression(';', ";");
555 plpgsql_ns_setlocal(true);
559 decl_defkey : K_ASSIGN
571 proc_stmts : proc_stmts proc_stmt
576 $$ = lappend($1, $2);
587 proc_stmt : pl_block ';'
627 stmt_perform : K_PERFORM lno expr_until_semi
629 PLpgSQL_stmt_perform *new;
631 new = palloc0(sizeof(PLpgSQL_stmt_perform));
632 new->cmd_type = PLPGSQL_STMT_PERFORM;
636 $$ = (PLpgSQL_stmt *)new;
640 stmt_assign : assign_var lno K_ASSIGN expr_until_semi
642 PLpgSQL_stmt_assign *new;
644 new = palloc0(sizeof(PLpgSQL_stmt_assign));
645 new->cmd_type = PLPGSQL_STMT_ASSIGN;
650 $$ = (PLpgSQL_stmt *)new;
654 stmt_getdiag : K_GET K_DIAGNOSTICS lno getdiag_list ';'
656 PLpgSQL_stmt_getdiag *new;
658 new = palloc0(sizeof(PLpgSQL_stmt_getdiag));
659 new->cmd_type = PLPGSQL_STMT_GETDIAG;
661 new->diag_items = $4;
663 $$ = (PLpgSQL_stmt *)new;
667 getdiag_list : getdiag_list ',' getdiag_list_item
669 $$ = lappend($1, $3);
677 getdiag_list_item : getdiag_target K_ASSIGN getdiag_kind
679 PLpgSQL_diag_item *new;
681 new = palloc(sizeof(PLpgSQL_diag_item));
689 getdiag_kind : K_ROW_COUNT
691 $$ = PLPGSQL_GETDIAG_ROW_COUNT;
695 $$ = PLPGSQL_GETDIAG_RESULT_OID;
699 getdiag_target : T_SCALAR
701 check_assignable(yylval.scalar);
702 $$ = yylval.scalar->dno;
707 assign_var : T_SCALAR
709 check_assignable(yylval.scalar);
710 $$ = yylval.scalar->dno;
714 check_assignable((PLpgSQL_datum *) yylval.row);
715 $$ = yylval.row->rowno;
719 check_assignable((PLpgSQL_datum *) yylval.rec);
720 $$ = yylval.rec->recno;
722 | assign_var '[' expr_until_rightbracket
724 PLpgSQL_arrayelem *new;
726 new = palloc0(sizeof(PLpgSQL_arrayelem));
727 new->dtype = PLPGSQL_DTYPE_ARRAYELEM;
729 new->arrayparentno = $1;
731 plpgsql_adddatum((PLpgSQL_datum *)new);
737 stmt_if : K_IF lno expr_until_then proc_sect stmt_else K_END K_IF ';'
739 PLpgSQL_stmt_if *new;
741 new = palloc0(sizeof(PLpgSQL_stmt_if));
742 new->cmd_type = PLPGSQL_STMT_IF;
746 new->false_body = $5;
748 $$ = (PLpgSQL_stmt *)new;
756 | K_ELSIF lno expr_until_then proc_sect stmt_else
759 * Translate the structure: into:
761 * IF c1 THEN IF c1 THEN
771 PLpgSQL_stmt_if *new_if;
773 /* first create a new if-statement */
774 new_if = palloc0(sizeof(PLpgSQL_stmt_if));
775 new_if->cmd_type = PLPGSQL_STMT_IF;
778 new_if->true_body = $4;
779 new_if->false_body = $5;
781 /* wrap the if-statement in a "container" list */
782 $$ = list_make1(new_if);
791 stmt_loop : opt_block_label K_LOOP lno loop_body
793 PLpgSQL_stmt_loop *new;
795 new = palloc0(sizeof(PLpgSQL_stmt_loop));
796 new->cmd_type = PLPGSQL_STMT_LOOP;
799 new->body = $4.stmts;
801 check_labels($1, $4.end_label);
804 $$ = (PLpgSQL_stmt *)new;
808 stmt_while : opt_block_label K_WHILE lno expr_until_loop loop_body
810 PLpgSQL_stmt_while *new;
812 new = palloc0(sizeof(PLpgSQL_stmt_while));
813 new->cmd_type = PLPGSQL_STMT_WHILE;
817 new->body = $5.stmts;
819 check_labels($1, $5.end_label);
822 $$ = (PLpgSQL_stmt *)new;
826 stmt_for : opt_block_label K_FOR for_control loop_body
828 /* This runs after we've scanned the loop body */
829 if ($3->cmd_type == PLPGSQL_STMT_FORI)
831 PLpgSQL_stmt_fori *new;
833 new = (PLpgSQL_stmt_fori *) $3;
835 new->body = $4.stmts;
836 $$ = (PLpgSQL_stmt *) new;
838 else if ($3->cmd_type == PLPGSQL_STMT_FORS)
840 PLpgSQL_stmt_fors *new;
842 new = (PLpgSQL_stmt_fors *) $3;
844 new->body = $4.stmts;
845 $$ = (PLpgSQL_stmt *) new;
849 PLpgSQL_stmt_dynfors *new;
851 Assert($3->cmd_type == PLPGSQL_STMT_DYNFORS);
852 new = (PLpgSQL_stmt_dynfors *) $3;
854 new->body = $4.stmts;
855 $$ = (PLpgSQL_stmt *) new;
858 check_labels($1, $4.end_label);
859 /* close namespace started in opt_label */
865 lno for_variable K_IN
869 /* Simple case: EXECUTE is a dynamic FOR loop */
870 if (tok == K_EXECUTE)
872 PLpgSQL_stmt_dynfors *new;
875 expr = plpgsql_read_expression(K_LOOP, "LOOP");
877 new = palloc0(sizeof(PLpgSQL_stmt_dynfors));
878 new->cmd_type = PLPGSQL_STMT_DYNFORS;
886 plpgsql_error_lineno = $1;
887 yyerror("loop variable of loop over rows must be a record or row variable");
891 $$ = (PLpgSQL_stmt *) new;
896 bool reverse = false;
899 * We have to distinguish between two
900 * alternatives: FOR var IN a .. b and FOR
901 * var IN query. Unfortunately this is
902 * tricky, since the query in the second
903 * form needn't start with a SELECT
904 * keyword. We use the ugly hack of
905 * looking for two periods after the first
906 * token. We also check for the REVERSE
907 * keyword, which means it must be an
910 if (tok == K_REVERSE)
913 plpgsql_push_back_token(tok);
916 * Read tokens until we see either a ".."
917 * or a LOOP. The text we read may not
918 * necessarily be a well-formed SQL
919 * statement, so we need to invoke
920 * read_sql_construct directly.
922 expr1 = read_sql_construct(K_DOTDOT,
932 /* Saw "..", so it must be an integer loop */
935 PLpgSQL_stmt_fori *new;
937 /* First expression is well-formed */
938 check_sql_expr(expr1->query);
940 expr2 = plpgsql_read_expression(K_LOOP, "LOOP");
942 fvar = (PLpgSQL_var *)
943 plpgsql_build_variable($2.name,
945 plpgsql_build_datatype(INT4OID,
949 /* put the for-variable into the local block */
950 plpgsql_add_initdatums(NULL);
952 new = palloc0(sizeof(PLpgSQL_stmt_fori));
953 new->cmd_type = PLPGSQL_STMT_FORI;
956 new->reverse = reverse;
960 $$ = (PLpgSQL_stmt *) new;
965 * No "..", so it must be a query loop. We've prefixed an
966 * extra SELECT to the query text, so we need to remove that
967 * before performing syntax checking.
970 PLpgSQL_stmt_fors *new;
973 yyerror("cannot specify REVERSE in query FOR loop");
975 Assert(strncmp(expr1->query, "SELECT ", 7) == 0);
976 tmp_query = pstrdup(expr1->query + 7);
978 expr1->query = tmp_query;
980 check_sql_expr(expr1->query);
982 new = palloc0(sizeof(PLpgSQL_stmt_fors));
983 new->cmd_type = PLPGSQL_STMT_FORS;
991 plpgsql_error_lineno = $1;
992 yyerror("loop variable of loop over rows must be record or row variable");
996 $$ = (PLpgSQL_stmt *) new;
1002 for_variable : T_SCALAR
1006 plpgsql_convert_ident(yytext, &name, 1);
1008 $$.lineno = plpgsql_scanner_lineno();
1016 plpgsql_convert_ident(yytext, &name, 1);
1018 $$.lineno = plpgsql_scanner_lineno();
1026 plpgsql_convert_ident(yytext, &name, 1);
1028 $$.lineno = plpgsql_scanner_lineno();
1029 $$.rec = yylval.rec;
1036 plpgsql_convert_ident(yytext, &name, 1);
1038 $$.lineno = plpgsql_scanner_lineno();
1039 $$.row = yylval.row;
1044 stmt_select : K_SELECT lno
1046 $$ = make_select_stmt();
1051 stmt_exit : exit_type lno opt_label opt_exitcond
1053 PLpgSQL_stmt_exit *new;
1055 new = palloc0(sizeof(PLpgSQL_stmt_exit));
1056 new->cmd_type = PLPGSQL_STMT_EXIT;
1062 $$ = (PLpgSQL_stmt *)new;
1076 stmt_return : K_RETURN lno
1078 PLpgSQL_stmt_return *new;
1080 new = palloc0(sizeof(PLpgSQL_stmt_return));
1081 new->cmd_type = PLPGSQL_STMT_RETURN;
1086 if (plpgsql_curr_compile->fn_retset)
1089 yyerror("RETURN cannot have a parameter in function returning set; use RETURN NEXT");
1091 else if (plpgsql_curr_compile->out_param_varno >= 0)
1094 yyerror("RETURN cannot have a parameter in function with OUT parameters");
1095 new->retvarno = plpgsql_curr_compile->out_param_varno;
1097 else if (plpgsql_curr_compile->fn_rettype == VOIDOID)
1100 yyerror("RETURN cannot have a parameter in function returning void");
1102 else if (plpgsql_curr_compile->fn_retistuple)
1107 /* we allow this to support RETURN NULL in triggers */
1111 new->retvarno = yylval.row->rowno;
1115 new->retvarno = yylval.rec->recno;
1119 yyerror("RETURN must specify a record or row variable in function returning tuple");
1123 yyerror("RETURN must specify a record or row variable in function returning tuple");
1128 * Note that a well-formed expression is
1129 * _required_ here; anything else is a
1130 * compile-time error.
1132 new->expr = plpgsql_read_expression(';', ";");
1135 $$ = (PLpgSQL_stmt *)new;
1139 stmt_return_next: K_RETURN_NEXT lno
1141 PLpgSQL_stmt_return_next *new;
1143 if (!plpgsql_curr_compile->fn_retset)
1144 yyerror("cannot use RETURN NEXT in a non-SETOF function");
1146 new = palloc0(sizeof(PLpgSQL_stmt_return_next));
1147 new->cmd_type = PLPGSQL_STMT_RETURN_NEXT;
1152 if (plpgsql_curr_compile->out_param_varno >= 0)
1155 yyerror("RETURN NEXT cannot have a parameter in function with OUT parameters");
1156 new->retvarno = plpgsql_curr_compile->out_param_varno;
1158 else if (plpgsql_curr_compile->fn_retistuple)
1163 new->retvarno = yylval.row->rowno;
1167 new->retvarno = yylval.rec->recno;
1171 yyerror("RETURN NEXT must specify a record or row variable in function returning tuple");
1175 yyerror("RETURN NEXT must specify a record or row variable in function returning tuple");
1178 new->expr = plpgsql_read_expression(';', ";");
1180 $$ = (PLpgSQL_stmt *)new;
1184 stmt_raise : K_RAISE lno raise_level raise_msg
1186 PLpgSQL_stmt_raise *new;
1189 new = palloc(sizeof(PLpgSQL_stmt_raise));
1191 new->cmd_type = PLPGSQL_STMT_RAISE;
1193 new->elog_level = $3;
1200 * We expect either a semi-colon, which
1201 * indicates no parameters, or a comma that
1202 * begins the list of parameter expressions
1204 if (tok != ',' && tok != ';')
1205 yyerror("syntax error");
1214 expr = read_sql_construct(',', ';', ", or ;",
1217 new->params = lappend(new->params, expr);
1223 $$ = (PLpgSQL_stmt *)new;
1227 raise_msg : T_STRING
1229 $$ = plpgsql_get_string_value();
1233 raise_level : K_EXCEPTION
1259 loop_body : proc_sect K_END K_LOOP opt_label ';'
1266 stmt_execsql : execsql_start lno
1268 PLpgSQL_stmt_execsql *new;
1270 new = palloc(sizeof(PLpgSQL_stmt_execsql));
1271 new->cmd_type = PLPGSQL_STMT_EXECSQL;
1273 new->sqlstmt = read_sql_stmt($1);
1275 $$ = (PLpgSQL_stmt *)new;
1279 stmt_dynexecute : K_EXECUTE lno
1281 PLpgSQL_stmt_dynexecute *new;
1285 expr = read_sql_construct(K_INTO, ';', "INTO|;", "SELECT ",
1286 true, true, &endtoken);
1288 new = palloc(sizeof(PLpgSQL_stmt_dynexecute));
1289 new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
1296 * If we saw "INTO", look for a following row
1297 * var, record var, or list of scalars.
1299 if (endtoken == K_INTO)
1304 check_assignable((PLpgSQL_datum *) yylval.row);
1305 new->row = yylval.row;
1309 check_assignable((PLpgSQL_datum *) yylval.row);
1310 new->rec = yylval.rec;
1314 new->row = read_into_scalar_list(yytext, yylval.scalar);
1318 plpgsql_error_lineno = $2;
1320 (errcode(ERRCODE_SYNTAX_ERROR),
1321 errmsg("syntax error at \"%s\"", yytext),
1322 errdetail("Expected record variable, row variable, "
1323 "or list of scalar variables.")));
1326 yyerror("syntax error");
1329 $$ = (PLpgSQL_stmt *)new;
1334 stmt_open : K_OPEN lno cursor_varptr
1336 PLpgSQL_stmt_open *new;
1339 new = palloc0(sizeof(PLpgSQL_stmt_open));
1340 new->cmd_type = PLPGSQL_STMT_OPEN;
1342 new->curvar = $3->varno;
1344 if ($3->cursor_explicit_expr == NULL)
1349 plpgsql_error_lineno = $2;
1351 (errcode(ERRCODE_SYNTAX_ERROR),
1352 errmsg("syntax error at \"%s\"",
1354 errdetail("Expected FOR to open a reference cursor.")));
1358 if (tok == K_EXECUTE)
1360 new->dynquery = read_sql_stmt("SELECT ");
1364 plpgsql_push_back_token(tok);
1365 new->query = read_sql_stmt("");
1370 if ($3->cursor_explicit_argrow >= 0)
1377 plpgsql_error_lineno = plpgsql_scanner_lineno();
1379 (errcode(ERRCODE_SYNTAX_ERROR),
1380 errmsg("cursor \"%s\" has arguments",
1385 * Push back the '(', else read_sql_stmt
1386 * will complain about unbalanced parens.
1388 plpgsql_push_back_token(tok);
1390 new->argquery = read_sql_stmt("SELECT ");
1393 * Now remove the leading and trailing parens,
1394 * because we want "select 1, 2", not
1397 cp = new->argquery->query;
1399 if (strncmp(cp, "SELECT", 6) != 0)
1401 plpgsql_error_lineno = plpgsql_scanner_lineno();
1402 /* internal error */
1403 elog(ERROR, "expected \"SELECT (\", got \"%s\"",
1404 new->argquery->query);
1407 while (*cp == ' ') /* could be more than 1 space here */
1411 plpgsql_error_lineno = plpgsql_scanner_lineno();
1412 /* internal error */
1413 elog(ERROR, "expected \"SELECT (\", got \"%s\"",
1414 new->argquery->query);
1418 cp += strlen(cp) - 1;
1421 yyerror("expected \")\"");
1429 plpgsql_error_lineno = plpgsql_scanner_lineno();
1431 (errcode(ERRCODE_SYNTAX_ERROR),
1432 errmsg("cursor \"%s\" has no arguments",
1438 plpgsql_error_lineno = plpgsql_scanner_lineno();
1440 (errcode(ERRCODE_SYNTAX_ERROR),
1441 errmsg("syntax error at \"%s\"",
1447 $$ = (PLpgSQL_stmt *)new;
1451 stmt_fetch : K_FETCH lno cursor_variable K_INTO
1453 PLpgSQL_stmt_fetch *new;
1455 new = (PLpgSQL_stmt_fetch *)make_fetch_stmt();
1458 $$ = (PLpgSQL_stmt *)new;
1463 stmt_close : K_CLOSE lno cursor_variable ';'
1465 PLpgSQL_stmt_close *new;
1467 new = palloc(sizeof(PLpgSQL_stmt_close));
1468 new->cmd_type = PLPGSQL_STMT_CLOSE;
1472 $$ = (PLpgSQL_stmt *)new;
1476 stmt_null : K_NULL ';'
1478 /* We do not bother building a node for NULL */
1483 cursor_varptr : T_SCALAR
1485 if (yylval.scalar->dtype != PLPGSQL_DTYPE_VAR)
1486 yyerror("cursor variable must be a simple variable");
1488 if (((PLpgSQL_var *) yylval.scalar)->datatype->typoid != REFCURSOROID)
1490 plpgsql_error_lineno = plpgsql_scanner_lineno();
1492 (errcode(ERRCODE_DATATYPE_MISMATCH),
1493 errmsg("\"%s\" must be of type cursor or refcursor",
1494 ((PLpgSQL_var *) yylval.scalar)->refname)));
1496 $$ = (PLpgSQL_var *) yylval.scalar;
1500 cursor_variable : T_SCALAR
1502 if (yylval.scalar->dtype != PLPGSQL_DTYPE_VAR)
1503 yyerror("cursor variable must be a simple variable");
1505 if (((PLpgSQL_var *) yylval.scalar)->datatype->typoid != REFCURSOROID)
1507 plpgsql_error_lineno = plpgsql_scanner_lineno();
1509 (errcode(ERRCODE_DATATYPE_MISMATCH),
1510 errmsg("\"%s\" must be of type refcursor",
1511 ((PLpgSQL_var *) yylval.scalar)->refname)));
1513 $$ = yylval.scalar->dno;
1517 execsql_start : T_WORD
1518 { $$ = pstrdup(yytext); }
1520 { $$ = pstrdup(yytext); }
1528 * We use a mid-rule action to add these
1529 * special variables to the namespace before
1530 * parsing the WHEN clauses themselves.
1532 PLpgSQL_exception_block *new = palloc(sizeof(PLpgSQL_exception_block));
1533 PLpgSQL_variable *var;
1535 var = plpgsql_build_variable("sqlstate", $2,
1536 plpgsql_build_datatype(TEXTOID, -1),
1538 ((PLpgSQL_var *) var)->isconst = true;
1539 new->sqlstate_varno = var->dno;
1541 var = plpgsql_build_variable("sqlerrm", $2,
1542 plpgsql_build_datatype(TEXTOID, -1),
1544 ((PLpgSQL_var *) var)->isconst = true;
1545 new->sqlerrm_varno = var->dno;
1547 $<exception_block>$ = new;
1551 PLpgSQL_exception_block *new = $<exception_block>3;
1558 proc_exceptions : proc_exceptions proc_exception
1560 $$ = lappend($1, $2);
1564 $$ = list_make1($1);
1568 proc_exception : K_WHEN lno proc_conditions K_THEN proc_sect
1570 PLpgSQL_exception *new;
1572 new = palloc0(sizeof(PLpgSQL_exception));
1574 new->conditions = $3;
1581 proc_conditions : proc_conditions K_OR opt_lblname
1583 PLpgSQL_condition *old;
1585 for (old = $1; old->next != NULL; old = old->next)
1587 old->next = plpgsql_parse_err_condition($3);
1593 $$ = plpgsql_parse_err_condition($1);
1598 { $$ = plpgsql_read_expression(';', ";"); }
1601 expr_until_rightbracket :
1602 { $$ = plpgsql_read_expression(']', "]"); }
1606 { $$ = plpgsql_read_expression(K_THEN, "THEN"); }
1610 { $$ = plpgsql_read_expression(K_LOOP, "LOOP"); }
1615 plpgsql_ns_push(NULL);
1618 | '<' '<' opt_lblname '>' '>'
1620 plpgsql_ns_push($3);
1632 plpgsql_convert_ident(yytext, &label_name, 1);
1637 /* just to give a better error than "syntax error" */
1638 yyerror("no such label");
1644 | K_WHEN expr_until_semi
1648 opt_lblname : T_WORD
1652 plpgsql_convert_ident(yytext, &name, 1);
1659 $$ = plpgsql_error_lineno = plpgsql_scanner_lineno();
1667 plpgsql_read_expression(int until, const char *expected)
1669 return read_sql_construct(until, 0, expected, "SELECT ", true, true, NULL);
1672 static PLpgSQL_expr *
1673 read_sql_stmt(const char *sqlstart)
1675 return read_sql_construct(';', 0, ";", sqlstart, false, true, NULL);
1679 * Read a SQL construct and build a PLpgSQL_expr for it.
1681 * until: token code for expected terminator
1682 * until2: token code for alternate terminator (pass 0 if none)
1683 * expected: text to use in complaining that terminator was not found
1684 * sqlstart: text to prefix to the accumulated SQL text
1685 * isexpression: whether to say we're reading an "expression" or a "statement"
1686 * valid_sql: whether to check the syntax of the expr (prefixed with sqlstart)
1687 * endtoken: if not NULL, ending token is stored at *endtoken
1688 * (this is only interesting if until2 isn't zero)
1690 static PLpgSQL_expr *
1691 read_sql_construct(int until,
1693 const char *expected,
1694 const char *sqlstart,
1708 lno = plpgsql_scanner_lineno();
1709 plpgsql_dstring_init(&ds);
1710 plpgsql_dstring_append(&ds, sqlstart);
1715 if (tok == until && parenlevel == 0)
1717 if (tok == until2 && parenlevel == 0)
1719 if (tok == '(' || tok == '[')
1721 else if (tok == ')' || tok == ']')
1726 (errcode(ERRCODE_SYNTAX_ERROR),
1727 errmsg("mismatched parentheses")));
1730 * End of function definition is an error, and we don't expect to
1731 * hit a semicolon either (unless it's the until symbol, in which
1732 * case we should have fallen out above).
1734 if (tok == 0 || tok == ';')
1736 plpgsql_error_lineno = lno;
1737 if (parenlevel != 0)
1739 (errcode(ERRCODE_SYNTAX_ERROR),
1740 errmsg("mismatched parentheses")));
1743 (errcode(ERRCODE_SYNTAX_ERROR),
1744 errmsg("missing \"%s\" at end of SQL expression",
1748 (errcode(ERRCODE_SYNTAX_ERROR),
1749 errmsg("missing \"%s\" at end of SQL statement",
1753 if (plpgsql_SpaceScanned)
1754 plpgsql_dstring_append(&ds, " ");
1756 /* Check for array overflow */
1757 if (nparams >= 1024)
1759 plpgsql_error_lineno = lno;
1761 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1762 errmsg("too many variables specified in SQL statement")));
1768 params[nparams] = yylval.scalar->dno;
1769 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1770 plpgsql_dstring_append(&ds, buf);
1774 params[nparams] = yylval.row->rowno;
1775 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1776 plpgsql_dstring_append(&ds, buf);
1780 params[nparams] = yylval.rec->recno;
1781 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1782 plpgsql_dstring_append(&ds, buf);
1786 plpgsql_dstring_append(&ds, yytext);
1794 expr = palloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
1795 expr->dtype = PLPGSQL_DTYPE_EXPR;
1796 expr->query = pstrdup(plpgsql_dstring_get(&ds));
1798 expr->nparams = nparams;
1799 while(nparams-- > 0)
1800 expr->params[nparams] = params[nparams];
1801 plpgsql_dstring_free(&ds);
1804 check_sql_expr(expr->query);
1809 static PLpgSQL_type *
1810 read_datatype(int tok)
1814 PLpgSQL_type *result;
1815 bool needspace = false;
1818 lno = plpgsql_scanner_lineno();
1820 /* Often there will be a lookahead token, but if not, get one */
1826 /* lexer found word%TYPE and did its thing already */
1827 return yylval.dtype;
1830 plpgsql_dstring_init(&ds);
1836 plpgsql_error_lineno = lno;
1837 if (parenlevel != 0)
1839 (errcode(ERRCODE_SYNTAX_ERROR),
1840 errmsg("mismatched parentheses")));
1842 (errcode(ERRCODE_SYNTAX_ERROR),
1843 errmsg("incomplete datatype declaration")));
1845 /* Possible followers for datatype in a declaration */
1846 if (tok == K_NOT || tok == K_ASSIGN || tok == K_DEFAULT)
1848 /* Possible followers for datatype in a cursor_arg list */
1849 if ((tok == ',' || tok == ')') && parenlevel == 0)
1853 else if (tok == ')')
1856 plpgsql_dstring_append(&ds, " ");
1858 plpgsql_dstring_append(&ds, yytext);
1863 plpgsql_push_back_token(tok);
1865 plpgsql_error_lineno = lno; /* in case of error in parse_datatype */
1867 result = plpgsql_parse_datatype(plpgsql_dstring_get(&ds));
1869 plpgsql_dstring_free(&ds);
1874 static PLpgSQL_stmt *
1875 make_select_stmt(void)
1882 PLpgSQL_row *row = NULL;
1883 PLpgSQL_rec *rec = NULL;
1885 bool have_into = false;
1887 plpgsql_dstring_init(&ds);
1888 plpgsql_dstring_append(&ds, "SELECT ");
1898 plpgsql_error_lineno = plpgsql_scanner_lineno();
1900 (errcode(ERRCODE_SYNTAX_ERROR),
1901 errmsg("unexpected end of function definition")));
1907 plpgsql_error_lineno = plpgsql_scanner_lineno();
1909 (errcode(ERRCODE_SYNTAX_ERROR),
1910 errmsg("INTO specified more than once")));
1926 row = read_into_scalar_list(yytext, yylval.scalar);
1931 /* Treat the INTO as non-special */
1932 plpgsql_dstring_append(&ds, " INTO ");
1933 plpgsql_push_back_token(tok);
1939 if (plpgsql_SpaceScanned)
1940 plpgsql_dstring_append(&ds, " ");
1942 /* Check for array overflow */
1943 if (nparams >= 1024)
1945 plpgsql_error_lineno = plpgsql_scanner_lineno();
1947 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1948 errmsg("too many parameters specified in SQL statement")));
1954 params[nparams] = yylval.scalar->dno;
1955 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1956 plpgsql_dstring_append(&ds, buf);
1960 params[nparams] = yylval.row->rowno;
1961 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1962 plpgsql_dstring_append(&ds, buf);
1966 params[nparams] = yylval.rec->recno;
1967 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1968 plpgsql_dstring_append(&ds, buf);
1972 plpgsql_dstring_append(&ds, yytext);
1977 expr = palloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
1978 expr->dtype = PLPGSQL_DTYPE_EXPR;
1979 expr->query = pstrdup(plpgsql_dstring_get(&ds));
1981 expr->nparams = nparams;
1982 while(nparams-- > 0)
1983 expr->params[nparams] = params[nparams];
1984 plpgsql_dstring_free(&ds);
1988 PLpgSQL_stmt_select *select;
1990 select = palloc0(sizeof(PLpgSQL_stmt_select));
1991 select->cmd_type = PLPGSQL_STMT_SELECT;
1994 select->query = expr;
1996 return (PLpgSQL_stmt *)select;
2000 PLpgSQL_stmt_execsql *execsql;
2002 execsql = palloc(sizeof(PLpgSQL_stmt_execsql));
2003 execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
2004 execsql->sqlstmt = expr;
2006 return (PLpgSQL_stmt *)execsql;
2011 static PLpgSQL_stmt *
2012 make_fetch_stmt(void)
2015 PLpgSQL_row *row = NULL;
2016 PLpgSQL_rec *rec = NULL;
2017 PLpgSQL_stmt_fetch *fetch;
2019 /* We have already parsed everything through the INTO keyword */
2033 row = read_into_scalar_list(yytext, yylval.scalar);
2037 yyerror("syntax error");
2042 yyerror("syntax error");
2044 fetch = palloc0(sizeof(PLpgSQL_stmt_select));
2045 fetch->cmd_type = PLPGSQL_STMT_FETCH;
2049 return (PLpgSQL_stmt *)fetch;
2054 check_assignable(PLpgSQL_datum *datum)
2056 switch (datum->dtype)
2058 case PLPGSQL_DTYPE_VAR:
2059 if (((PLpgSQL_var *) datum)->isconst)
2061 plpgsql_error_lineno = plpgsql_scanner_lineno();
2063 (errcode(ERRCODE_ERROR_IN_ASSIGNMENT),
2064 errmsg("\"%s\" is declared CONSTANT",
2065 ((PLpgSQL_var *) datum)->refname)));
2068 case PLPGSQL_DTYPE_ROW:
2069 /* always assignable? */
2071 case PLPGSQL_DTYPE_REC:
2072 /* always assignable? What about NEW/OLD? */
2074 case PLPGSQL_DTYPE_RECFIELD:
2075 /* always assignable? */
2077 case PLPGSQL_DTYPE_ARRAYELEM:
2078 /* always assignable? */
2080 case PLPGSQL_DTYPE_TRIGARG:
2081 yyerror("cannot assign to tg_argv");
2084 elog(ERROR, "unrecognized dtype: %d", datum->dtype);
2090 * Given the first datum and name in the INTO list, continue to read
2091 * comma-separated scalar variables until we run out. Then construct
2092 * and return a fake "row" variable that represents the list of
2095 static PLpgSQL_row *
2096 read_into_scalar_list(const char *initial_name,
2097 PLpgSQL_datum *initial_datum)
2100 char *fieldnames[1024];
2105 check_assignable(initial_datum);
2106 fieldnames[0] = pstrdup(initial_name);
2107 varnos[0] = initial_datum->dno;
2110 while ((tok = yylex()) == ',')
2112 /* Check for array overflow */
2113 if (nfields >= 1024)
2115 plpgsql_error_lineno = plpgsql_scanner_lineno();
2117 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2118 errmsg("too many INTO variables specified")));
2125 check_assignable(yylval.scalar);
2126 fieldnames[nfields] = pstrdup(yytext);
2127 varnos[nfields++] = yylval.scalar->dno;
2131 plpgsql_error_lineno = plpgsql_scanner_lineno();
2133 (errcode(ERRCODE_SYNTAX_ERROR),
2134 errmsg("\"%s\" is not a variable",
2140 * We read an extra, non-comma character from yylex(), so push it
2141 * back onto the input stream
2143 plpgsql_push_back_token(tok);
2145 row = palloc(sizeof(PLpgSQL_row));
2146 row->dtype = PLPGSQL_DTYPE_ROW;
2147 row->refname = pstrdup("*internal*");
2148 row->lineno = plpgsql_scanner_lineno();
2149 row->rowtupdesc = NULL;
2150 row->nfields = nfields;
2151 row->fieldnames = palloc(sizeof(char *) * nfields);
2152 row->varnos = palloc(sizeof(int) * nfields);
2153 while (--nfields >= 0)
2155 row->fieldnames[nfields] = fieldnames[nfields];
2156 row->varnos[nfields] = varnos[nfields];
2159 plpgsql_adddatum((PLpgSQL_datum *)row);
2165 * When the PL/PgSQL parser expects to see a SQL statement, it is very
2166 * liberal in what it accepts; for example, we often assume an
2167 * unrecognized keyword is the beginning of a SQL statement. This
2168 * avoids the need to duplicate parts of the SQL grammar in the
2169 * PL/PgSQL grammar, but it means we can accept wildly malformed
2170 * input. To try and catch some of the more obviously invalid input,
2171 * we run the strings we expect to be SQL statements through the main
2174 * We only invoke the raw parser (not the analyzer); this doesn't do
2175 * any database access and does not check any semantic rules, it just
2176 * checks for basic syntactic correctness. We do this here, rather
2177 * than after parsing has finished, because a malformed SQL statement
2178 * may cause the PL/PgSQL parser to become confused about statement
2179 * borders. So it is best to bail out as early as we can.
2182 check_sql_expr(const char *stmt)
2184 ErrorContextCallback syntax_errcontext;
2185 ErrorContextCallback *previous_errcontext;
2186 MemoryContext oldCxt;
2188 if (!plpgsql_check_syntax)
2192 * Setup error traceback support for ereport(). The previous
2193 * ereport callback is installed by pl_comp.c, but we don't want
2194 * that to be invoked (since it will try to transpose the syntax
2195 * error to be relative to the CREATE FUNCTION), so temporarily
2196 * remove it from the list of callbacks.
2198 Assert(error_context_stack->callback == plpgsql_compile_error_callback);
2200 previous_errcontext = error_context_stack;
2201 syntax_errcontext.callback = plpgsql_sql_error_callback;
2202 syntax_errcontext.arg = (char *) stmt;
2203 syntax_errcontext.previous = error_context_stack->previous;
2204 error_context_stack = &syntax_errcontext;
2206 oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);
2207 (void) raw_parser(stmt);
2208 MemoryContextSwitchTo(oldCxt);
2210 /* Restore former ereport callback */
2211 error_context_stack = previous_errcontext;
2215 plpgsql_sql_error_callback(void *arg)
2217 char *sql_stmt = (char *) arg;
2219 Assert(plpgsql_error_funcname);
2221 errcontext("SQL statement in PL/PgSQL function \"%s\" near line %d",
2222 plpgsql_error_funcname, plpgsql_error_lineno);
2223 internalerrquery(sql_stmt);
2224 internalerrposition(geterrposition());
2229 check_labels(const char *start_label, const char *end_label)
2235 plpgsql_error_lineno = plpgsql_scanner_lineno();
2237 (errcode(ERRCODE_SYNTAX_ERROR),
2238 errmsg("end label \"%s\" specified for unlabelled block",
2242 if (strcmp(start_label, end_label) != 0)
2244 plpgsql_error_lineno = plpgsql_scanner_lineno();
2246 (errcode(ERRCODE_SYNTAX_ERROR),
2247 errmsg("end label \"%s\" differs from block's label \"%s\"",
2248 end_label, start_label)));
2253 #include "pl_scan.c"