2 /**********************************************************************
3 * gram.y - Parser for the PL/pgSQL
7 * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.70 2005/05/26 00:16:31 momjian Exp $
9 * This software is copyrighted by Jan Wieck - Hamburg.
11 * The author hereby grants permission to use, copy, modify,
12 * distribute, and license this software and its documentation
13 * for any purpose, provided that existing copyright notices are
14 * retained in all copies and that this notice is included
15 * verbatim in any distributions. No written agreement, license,
16 * or royalty fee is required for any of the authorized uses.
17 * Modifications to this software may be copyrighted by their
18 * author and need not follow the licensing terms described
19 * here, provided that the new terms are clearly indicated on
20 * the first page of each file where they apply.
22 * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
23 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
24 * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
25 * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
26 * IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
29 * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
30 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
32 * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
33 * AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
34 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
35 * ENHANCEMENTS, OR MODIFICATIONS.
37 **********************************************************************/
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);
90 PLpgSQL_datum *scalar; /* a VAR, RECFIELD, or TRIGARG */
91 PLpgSQL_variable *variable; /* a VAR, REC, or ROW */
97 PLpgSQL_stmt_block *program;
98 PLpgSQL_condition *condition;
99 PLpgSQL_exception *exception;
100 PLpgSQL_nsitem *nsitem;
101 PLpgSQL_diag_item *diagitem;
104 %type <fict_vars> fict_vars_sect
105 %type <declhdr> decl_sect
106 %type <varname> decl_varname
107 %type <str> decl_renname
108 %type <ival> decl_const decl_notnull
109 %type <expr> decl_defval decl_cursor_query
110 %type <dtype> decl_datatype
111 %type <row> decl_cursor_args
112 %type <list> decl_cursor_arglist
113 %type <nsitem> decl_aliasitem
114 %type <str> decl_stmts decl_stmt
116 %type <expr> expr_until_semi expr_until_rightbracket
117 %type <expr> expr_until_then expr_until_loop
118 %type <expr> opt_exitcond
120 %type <ival> assign_var cursor_variable
121 %type <var> cursor_varptr
122 %type <variable> decl_cursor_arg
123 %type <forvariable> for_variable
124 %type <stmt> for_control
126 %type <str> opt_lblname opt_label
127 %type <str> opt_exitlabel
128 %type <str> execsql_start
130 %type <list> proc_sect proc_stmts stmt_else loop_body
131 %type <stmt> proc_stmt pl_block
132 %type <stmt> stmt_assign stmt_if stmt_loop stmt_while stmt_exit
133 %type <stmt> stmt_return stmt_return_next stmt_raise stmt_execsql
134 %type <stmt> stmt_for stmt_select stmt_perform
135 %type <stmt> stmt_dynexecute stmt_getdiag
136 %type <stmt> stmt_open stmt_fetch stmt_close stmt_null
138 %type <list> exception_sect proc_exceptions
139 %type <exception> proc_exception
140 %type <condition> proc_conditions
142 %type <list> raise_params
143 %type <ival> raise_level raise_param
144 %type <str> raise_msg
146 %type <list> getdiag_list
147 %type <diagitem> getdiag_list_item
148 %type <ival> getdiag_kind getdiag_target
212 %token T_SCALAR /* a VAR, RECFIELD, or TRIGARG */
225 pl_function : T_FUNCTION comp_optsect pl_block opt_semi
227 yylval.program = (PLpgSQL_stmt_block *)$3;
229 | T_TRIGGER comp_optsect pl_block opt_semi
231 yylval.program = (PLpgSQL_stmt_block *)$3;
239 comp_options : comp_options comp_option
243 comp_option : O_OPTION O_DUMP
245 plpgsql_DumpExecTree = true;
253 pl_block : decl_sect fict_vars_sect K_BEGIN lno proc_sect exception_sect K_END
255 PLpgSQL_stmt_block *new;
257 new = palloc0(sizeof(PLpgSQL_stmt_block));
259 new->cmd_type = PLPGSQL_STMT_BLOCK;
261 new->label = $1.label;
262 new->n_initvars = $1.n_initvars;
263 new->initvarnos = $1.initvarnos;
265 new->exceptions = $6;
267 new->sqlstate_varno = $2.sqlstate_varno;
268 new->sqlerrm_varno = $2.sqlerrm_varno;
272 $$ = (PLpgSQL_stmt *)new;
278 PLpgSQL_variable *var;
280 plpgsql_ns_setlocal(false);
281 var = plpgsql_build_variable("sqlstate", 0,
282 plpgsql_build_datatype(TEXTOID, -1), true);
283 $$.sqlstate_varno = var->dno;
284 var = plpgsql_build_variable("sqlerrm", 0,
285 plpgsql_build_datatype(TEXTOID, -1), true);
286 $$.sqlerrm_varno = var->dno;
287 plpgsql_add_initdatums(NULL);
290 decl_sect : opt_label
292 plpgsql_ns_setlocal(false);
295 $$.initvarnos = NULL;
296 plpgsql_add_initdatums(NULL);
298 | opt_label decl_start
300 plpgsql_ns_setlocal(false);
303 $$.initvarnos = NULL;
304 plpgsql_add_initdatums(NULL);
306 | opt_label decl_start decl_stmts
308 plpgsql_ns_setlocal(false);
313 $$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos));
317 decl_start : K_DECLARE
319 plpgsql_ns_setlocal(true);
323 decl_stmts : decl_stmts decl_stmt
329 decl_stmt : '<' '<' opt_lblname '>' '>'
337 decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
339 PLpgSQL_variable *var;
341 var = plpgsql_build_variable($1.name, $1.lineno,
345 if (var->dtype == PLPGSQL_DTYPE_VAR)
346 ((PLpgSQL_var *) var)->isconst = $2;
349 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
350 errmsg("row or record variable cannot be CONSTANT")));
354 if (var->dtype == PLPGSQL_DTYPE_VAR)
355 ((PLpgSQL_var *) var)->notnull = $4;
358 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
359 errmsg("row or record variable cannot be NOT NULL")));
363 if (var->dtype == PLPGSQL_DTYPE_VAR)
364 ((PLpgSQL_var *) var)->default_val = $5;
367 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
368 errmsg("default value for row or record variable is not supported")));
371 | decl_varname K_ALIAS K_FOR decl_aliasitem ';'
373 plpgsql_ns_additem($4->itemtype,
374 $4->itemno, $1.name);
376 | K_RENAME decl_renname K_TO decl_renname ';'
378 plpgsql_ns_rename($2, $4);
380 | decl_varname K_CURSOR
381 { plpgsql_ns_push(NULL); }
382 decl_cursor_args decl_is_from decl_cursor_query
385 PLpgSQL_expr *curname_def;
390 /* pop local namespace for cursor args */
393 new = (PLpgSQL_var *)
394 plpgsql_build_variable($1.name, $1.lineno,
395 plpgsql_build_datatype(REFCURSOROID,
399 curname_def = palloc0(sizeof(PLpgSQL_expr));
401 curname_def->dtype = PLPGSQL_DTYPE_EXPR;
402 strcpy(buf, "SELECT '");
404 cp2 = buf + strlen(buf);
407 if (*cp1 == '\\' || *cp1 == '\'')
411 strcpy(cp2, "'::refcursor");
412 curname_def->query = pstrdup(buf);
413 new->default_val = curname_def;
415 new->cursor_explicit_expr = $6;
417 new->cursor_explicit_argrow = -1;
419 new->cursor_explicit_argrow = $4->rowno;
427 plpgsql_ns_setlocal(false);
428 query = read_sql_stmt("");
429 plpgsql_ns_setlocal(true);
439 | '(' decl_cursor_arglist ')'
445 new = palloc0(sizeof(PLpgSQL_row));
446 new->dtype = PLPGSQL_DTYPE_ROW;
447 new->lineno = plpgsql_scanner_lineno();
448 new->rowtupdesc = NULL;
449 new->nfields = list_length($2);
450 new->fieldnames = palloc(new->nfields * sizeof(char *));
451 new->varnos = palloc(new->nfields * sizeof(int));
456 PLpgSQL_variable *arg = (PLpgSQL_variable *) lfirst(l);
457 new->fieldnames[i] = arg->refname;
458 new->varnos[i] = arg->dno;
463 plpgsql_adddatum((PLpgSQL_datum *) new);
468 decl_cursor_arglist : decl_cursor_arglist decl_cursor_arg
470 $$ = lappend($1, $2);
478 decl_cursor_arg : decl_varname decl_datatype
480 $$ = plpgsql_build_variable($1.name, $1.lineno,
485 decl_is_from : K_IS | /* Oracle */
488 decl_aliasitem : T_WORD
493 plpgsql_convert_ident(yytext, &name, 1);
495 yyerror("only positional parameters may be aliased");
497 plpgsql_ns_setlocal(false);
498 nsi = plpgsql_ns_lookup(name, NULL);
501 plpgsql_error_lineno = plpgsql_scanner_lineno();
503 (errcode(ERRCODE_UNDEFINED_PARAMETER),
504 errmsg("function has no parameter \"%s\"",
508 plpgsql_ns_setlocal(true);
516 decl_varname : T_WORD
520 plpgsql_convert_ident(yytext, &name, 1);
522 $$.lineno = plpgsql_scanner_lineno();
526 decl_renname : T_WORD
530 plpgsql_convert_ident(yytext, &name, 1);
531 /* the result must be palloc'd, see plpgsql_ns_rename */
545 * If there's a lookahead token, read_datatype
548 $$ = read_datatype(yychar);
563 plpgsql_ns_setlocal(false);
564 $$ = plpgsql_read_expression(';', ";");
565 plpgsql_ns_setlocal(true);
569 decl_defkey : K_ASSIGN
581 proc_stmts : proc_stmts proc_stmt
586 $$ = lappend($1, $2);
597 proc_stmt : pl_block ';'
637 stmt_perform : K_PERFORM lno expr_until_semi
639 PLpgSQL_stmt_perform *new;
641 new = palloc0(sizeof(PLpgSQL_stmt_perform));
642 new->cmd_type = PLPGSQL_STMT_PERFORM;
646 $$ = (PLpgSQL_stmt *)new;
650 stmt_assign : assign_var lno K_ASSIGN expr_until_semi
652 PLpgSQL_stmt_assign *new;
654 new = palloc0(sizeof(PLpgSQL_stmt_assign));
655 new->cmd_type = PLPGSQL_STMT_ASSIGN;
660 $$ = (PLpgSQL_stmt *)new;
664 stmt_getdiag : K_GET K_DIAGNOSTICS lno getdiag_list ';'
666 PLpgSQL_stmt_getdiag *new;
668 new = palloc0(sizeof(PLpgSQL_stmt_getdiag));
669 new->cmd_type = PLPGSQL_STMT_GETDIAG;
671 new->diag_items = $4;
673 $$ = (PLpgSQL_stmt *)new;
677 getdiag_list : getdiag_list ',' getdiag_list_item
679 $$ = lappend($1, $3);
687 getdiag_list_item : getdiag_target K_ASSIGN getdiag_kind
689 PLpgSQL_diag_item *new;
691 new = palloc(sizeof(PLpgSQL_diag_item));
699 getdiag_kind : K_ROW_COUNT
701 $$ = PLPGSQL_GETDIAG_ROW_COUNT;
705 $$ = PLPGSQL_GETDIAG_RESULT_OID;
709 getdiag_target : T_SCALAR
711 check_assignable(yylval.scalar);
712 $$ = yylval.scalar->dno;
717 assign_var : T_SCALAR
719 check_assignable(yylval.scalar);
720 $$ = yylval.scalar->dno;
724 check_assignable((PLpgSQL_datum *) yylval.row);
725 $$ = yylval.row->rowno;
729 check_assignable((PLpgSQL_datum *) yylval.rec);
730 $$ = yylval.rec->recno;
732 | assign_var '[' expr_until_rightbracket
734 PLpgSQL_arrayelem *new;
736 new = palloc0(sizeof(PLpgSQL_arrayelem));
737 new->dtype = PLPGSQL_DTYPE_ARRAYELEM;
739 new->arrayparentno = $1;
741 plpgsql_adddatum((PLpgSQL_datum *)new);
747 stmt_if : K_IF lno expr_until_then proc_sect stmt_else K_END K_IF ';'
749 PLpgSQL_stmt_if *new;
751 new = palloc0(sizeof(PLpgSQL_stmt_if));
752 new->cmd_type = PLPGSQL_STMT_IF;
756 new->false_body = $5;
758 $$ = (PLpgSQL_stmt *)new;
766 | K_ELSIF lno expr_until_then proc_sect stmt_else
769 * Translate the structure: into:
771 * IF c1 THEN IF c1 THEN
781 PLpgSQL_stmt_if *new_if;
783 /* first create a new if-statement */
784 new_if = palloc0(sizeof(PLpgSQL_stmt_if));
785 new_if->cmd_type = PLPGSQL_STMT_IF;
788 new_if->true_body = $4;
789 new_if->false_body = $5;
791 /* wrap the if-statement in a "container" list */
792 $$ = list_make1(new_if);
801 stmt_loop : opt_label K_LOOP lno loop_body
803 PLpgSQL_stmt_loop *new;
805 new = palloc0(sizeof(PLpgSQL_stmt_loop));
806 new->cmd_type = PLPGSQL_STMT_LOOP;
813 $$ = (PLpgSQL_stmt *)new;
817 stmt_while : opt_label K_WHILE lno expr_until_loop loop_body
819 PLpgSQL_stmt_while *new;
821 new = palloc0(sizeof(PLpgSQL_stmt_while));
822 new->cmd_type = PLPGSQL_STMT_WHILE;
830 $$ = (PLpgSQL_stmt *)new;
834 stmt_for : opt_label K_FOR for_control loop_body
836 /* This runs after we've scanned the loop body */
837 if ($3->cmd_type == PLPGSQL_STMT_FORI)
839 PLpgSQL_stmt_fori *new;
841 new = (PLpgSQL_stmt_fori *) $3;
844 $$ = (PLpgSQL_stmt *) new;
846 else if ($3->cmd_type == PLPGSQL_STMT_FORS)
848 PLpgSQL_stmt_fors *new;
850 new = (PLpgSQL_stmt_fors *) $3;
853 $$ = (PLpgSQL_stmt *) new;
857 PLpgSQL_stmt_dynfors *new;
859 Assert($3->cmd_type == PLPGSQL_STMT_DYNFORS);
860 new = (PLpgSQL_stmt_dynfors *) $3;
863 $$ = (PLpgSQL_stmt *) new;
866 /* close namespace started in opt_label */
872 lno for_variable K_IN
876 /* Simple case: EXECUTE is a dynamic FOR loop */
877 if (tok == K_EXECUTE)
879 PLpgSQL_stmt_dynfors *new;
882 expr = plpgsql_read_expression(K_LOOP, "LOOP");
884 new = palloc0(sizeof(PLpgSQL_stmt_dynfors));
885 new->cmd_type = PLPGSQL_STMT_DYNFORS;
893 plpgsql_error_lineno = $1;
894 yyerror("loop variable of loop over rows must be a record or row variable");
898 $$ = (PLpgSQL_stmt *) new;
903 bool reverse = false;
906 * We have to distinguish between two
907 * alternatives: FOR var IN a .. b and FOR
908 * var IN query. Unfortunately this is
909 * tricky, since the query in the second
910 * form needn't start with a SELECT
911 * keyword. We use the ugly hack of
912 * looking for two periods after the first
913 * token. We also check for the REVERSE
914 * keyword, which means it must be an
917 if (tok == K_REVERSE)
920 plpgsql_push_back_token(tok);
923 * Read tokens until we see either a ".."
924 * or a LOOP. The text we read may not
925 * necessarily be a well-formed SQL
926 * statement, so we need to invoke
927 * read_sql_construct directly.
929 expr1 = read_sql_construct(K_DOTDOT,
939 /* Saw "..", so it must be an integer loop */
942 PLpgSQL_stmt_fori *new;
944 /* First expression is well-formed */
945 check_sql_expr(expr1->query);
947 expr2 = plpgsql_read_expression(K_LOOP, "LOOP");
949 fvar = (PLpgSQL_var *)
950 plpgsql_build_variable($2.name,
952 plpgsql_build_datatype(INT4OID,
956 /* put the for-variable into the local block */
957 plpgsql_add_initdatums(NULL);
959 new = palloc0(sizeof(PLpgSQL_stmt_fori));
960 new->cmd_type = PLPGSQL_STMT_FORI;
963 new->reverse = reverse;
967 $$ = (PLpgSQL_stmt *) new;
972 * No "..", so it must be a query loop. We've prefixed an
973 * extra SELECT to the query text, so we need to remove that
974 * before performing syntax checking.
977 PLpgSQL_stmt_fors *new;
980 yyerror("cannot specify REVERSE in query FOR loop");
982 Assert(strncmp(expr1->query, "SELECT ", 7) == 0);
983 tmp_query = pstrdup(expr1->query + 7);
985 expr1->query = tmp_query;
987 check_sql_expr(expr1->query);
989 new = palloc0(sizeof(PLpgSQL_stmt_fors));
990 new->cmd_type = PLPGSQL_STMT_FORS;
998 plpgsql_error_lineno = $1;
999 yyerror("loop variable of loop over rows must be record or row variable");
1003 $$ = (PLpgSQL_stmt *) new;
1009 for_variable : T_SCALAR
1013 plpgsql_convert_ident(yytext, &name, 1);
1015 $$.lineno = plpgsql_scanner_lineno();
1023 plpgsql_convert_ident(yytext, &name, 1);
1025 $$.lineno = plpgsql_scanner_lineno();
1033 plpgsql_convert_ident(yytext, &name, 1);
1035 $$.lineno = plpgsql_scanner_lineno();
1036 $$.rec = yylval.rec;
1043 plpgsql_convert_ident(yytext, &name, 1);
1045 $$.lineno = plpgsql_scanner_lineno();
1046 $$.row = yylval.row;
1051 stmt_select : K_SELECT lno
1053 $$ = make_select_stmt();
1058 stmt_exit : K_EXIT lno opt_exitlabel opt_exitcond
1060 PLpgSQL_stmt_exit *new;
1062 new = palloc0(sizeof(PLpgSQL_stmt_exit));
1063 new->cmd_type = PLPGSQL_STMT_EXIT;
1068 $$ = (PLpgSQL_stmt *)new;
1072 stmt_return : K_RETURN lno
1074 PLpgSQL_stmt_return *new;
1076 new = palloc0(sizeof(PLpgSQL_stmt_return));
1077 new->cmd_type = PLPGSQL_STMT_RETURN;
1082 if (plpgsql_curr_compile->fn_retset)
1085 yyerror("RETURN cannot have a parameter in function returning set; use RETURN NEXT");
1087 else if (plpgsql_curr_compile->out_param_varno >= 0)
1090 yyerror("RETURN cannot have a parameter in function with OUT parameters");
1091 new->retvarno = plpgsql_curr_compile->out_param_varno;
1093 else if (plpgsql_curr_compile->fn_rettype == VOIDOID)
1096 yyerror("RETURN cannot have a parameter in function returning void");
1098 else if (plpgsql_curr_compile->fn_retistuple)
1103 /* we allow this to support RETURN NULL in triggers */
1107 new->retvarno = yylval.row->rowno;
1111 new->retvarno = yylval.rec->recno;
1115 yyerror("RETURN must specify a record or row variable in function returning tuple");
1119 yyerror("RETURN must specify a record or row variable in function returning tuple");
1124 * Note that a well-formed expression is
1125 * _required_ here; anything else is a
1126 * compile-time error.
1128 new->expr = plpgsql_read_expression(';', ";");
1131 $$ = (PLpgSQL_stmt *)new;
1135 stmt_return_next: K_RETURN_NEXT lno
1137 PLpgSQL_stmt_return_next *new;
1139 if (!plpgsql_curr_compile->fn_retset)
1140 yyerror("cannot use RETURN NEXT in a non-SETOF function");
1142 new = palloc0(sizeof(PLpgSQL_stmt_return_next));
1143 new->cmd_type = PLPGSQL_STMT_RETURN_NEXT;
1148 if (plpgsql_curr_compile->out_param_varno >= 0)
1151 yyerror("RETURN NEXT cannot have a parameter in function with OUT parameters");
1152 new->retvarno = plpgsql_curr_compile->out_param_varno;
1154 else if (plpgsql_curr_compile->fn_retistuple)
1159 new->retvarno = yylval.row->rowno;
1163 new->retvarno = yylval.rec->recno;
1167 yyerror("RETURN NEXT must specify a record or row variable in function returning tuple");
1171 yyerror("RETURN NEXT must specify a record or row variable in function returning tuple");
1174 new->expr = plpgsql_read_expression(';', ";");
1176 $$ = (PLpgSQL_stmt *)new;
1180 stmt_raise : K_RAISE lno raise_level raise_msg raise_params ';'
1182 PLpgSQL_stmt_raise *new;
1184 new = palloc(sizeof(PLpgSQL_stmt_raise));
1186 new->cmd_type = PLPGSQL_STMT_RAISE;
1188 new->elog_level = $3;
1192 $$ = (PLpgSQL_stmt *)new;
1194 | K_RAISE lno raise_level raise_msg ';'
1196 PLpgSQL_stmt_raise *new;
1198 new = palloc(sizeof(PLpgSQL_stmt_raise));
1200 new->cmd_type = PLPGSQL_STMT_RAISE;
1202 new->elog_level = $3;
1206 $$ = (PLpgSQL_stmt *)new;
1210 raise_msg : T_STRING
1212 $$ = plpgsql_get_string_value();
1216 raise_level : K_EXCEPTION
1242 raise_params : raise_params raise_param
1244 $$ = lappend_int($1, $2);
1248 $$ = list_make1_int($1);
1252 raise_param : ',' T_SCALAR
1254 $$ = yylval.scalar->dno;
1258 loop_body : proc_sect K_END K_LOOP ';'
1262 stmt_execsql : execsql_start lno
1264 PLpgSQL_stmt_execsql *new;
1266 new = palloc(sizeof(PLpgSQL_stmt_execsql));
1267 new->cmd_type = PLPGSQL_STMT_EXECSQL;
1269 new->sqlstmt = read_sql_stmt($1);
1271 $$ = (PLpgSQL_stmt *)new;
1275 stmt_dynexecute : K_EXECUTE lno expr_until_semi
1277 PLpgSQL_stmt_dynexecute *new;
1279 new = palloc(sizeof(PLpgSQL_stmt_dynexecute));
1280 new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
1284 $$ = (PLpgSQL_stmt *)new;
1288 stmt_open : K_OPEN lno cursor_varptr
1290 PLpgSQL_stmt_open *new;
1293 new = palloc0(sizeof(PLpgSQL_stmt_open));
1294 new->cmd_type = PLPGSQL_STMT_OPEN;
1296 new->curvar = $3->varno;
1298 if ($3->cursor_explicit_expr == NULL)
1303 plpgsql_error_lineno = $2;
1305 (errcode(ERRCODE_SYNTAX_ERROR),
1306 errmsg("syntax error at \"%s\"",
1308 errdetail("Expected FOR to open a reference cursor.")));
1312 if (tok == K_EXECUTE)
1314 new->dynquery = read_sql_stmt("SELECT ");
1318 plpgsql_push_back_token(tok);
1319 new->query = read_sql_stmt("");
1324 if ($3->cursor_explicit_argrow >= 0)
1331 plpgsql_error_lineno = plpgsql_scanner_lineno();
1333 (errcode(ERRCODE_SYNTAX_ERROR),
1334 errmsg("cursor \"%s\" has arguments",
1339 * Push back the '(', else read_sql_stmt
1340 * will complain about unbalanced parens.
1342 plpgsql_push_back_token(tok);
1344 new->argquery = read_sql_stmt("SELECT ");
1347 * Now remove the leading and trailing parens,
1348 * because we want "select 1, 2", not
1351 cp = new->argquery->query;
1353 if (strncmp(cp, "SELECT", 6) != 0)
1355 plpgsql_error_lineno = plpgsql_scanner_lineno();
1356 /* internal error */
1357 elog(ERROR, "expected \"SELECT (\", got \"%s\"",
1358 new->argquery->query);
1361 while (*cp == ' ') /* could be more than 1 space here */
1365 plpgsql_error_lineno = plpgsql_scanner_lineno();
1366 /* internal error */
1367 elog(ERROR, "expected \"SELECT (\", got \"%s\"",
1368 new->argquery->query);
1372 cp += strlen(cp) - 1;
1375 yyerror("expected \")\"");
1383 plpgsql_error_lineno = plpgsql_scanner_lineno();
1385 (errcode(ERRCODE_SYNTAX_ERROR),
1386 errmsg("cursor \"%s\" has no arguments",
1392 plpgsql_error_lineno = plpgsql_scanner_lineno();
1394 (errcode(ERRCODE_SYNTAX_ERROR),
1395 errmsg("syntax error at \"%s\"",
1401 $$ = (PLpgSQL_stmt *)new;
1405 stmt_fetch : K_FETCH lno cursor_variable K_INTO
1407 PLpgSQL_stmt_fetch *new;
1409 new = (PLpgSQL_stmt_fetch *)make_fetch_stmt();
1412 $$ = (PLpgSQL_stmt *)new;
1417 stmt_close : K_CLOSE lno cursor_variable ';'
1419 PLpgSQL_stmt_close *new;
1421 new = palloc(sizeof(PLpgSQL_stmt_close));
1422 new->cmd_type = PLPGSQL_STMT_CLOSE;
1426 $$ = (PLpgSQL_stmt *)new;
1430 stmt_null : K_NULL ';'
1432 /* We do not bother building a node for NULL */
1437 cursor_varptr : T_SCALAR
1439 if (yylval.scalar->dtype != PLPGSQL_DTYPE_VAR)
1440 yyerror("cursor variable must be a simple variable");
1442 if (((PLpgSQL_var *) yylval.scalar)->datatype->typoid != REFCURSOROID)
1444 plpgsql_error_lineno = plpgsql_scanner_lineno();
1446 (errcode(ERRCODE_DATATYPE_MISMATCH),
1447 errmsg("\"%s\" must be of type cursor or refcursor",
1448 ((PLpgSQL_var *) yylval.scalar)->refname)));
1450 $$ = (PLpgSQL_var *) yylval.scalar;
1454 cursor_variable : T_SCALAR
1456 if (yylval.scalar->dtype != PLPGSQL_DTYPE_VAR)
1457 yyerror("cursor variable must be a simple variable");
1459 if (((PLpgSQL_var *) yylval.scalar)->datatype->typoid != REFCURSOROID)
1461 plpgsql_error_lineno = plpgsql_scanner_lineno();
1463 (errcode(ERRCODE_DATATYPE_MISMATCH),
1464 errmsg("\"%s\" must be of type refcursor",
1465 ((PLpgSQL_var *) yylval.scalar)->refname)));
1467 $$ = yylval.scalar->dno;
1471 execsql_start : T_WORD
1472 { $$ = pstrdup(yytext); }
1474 { $$ = pstrdup(yytext); }
1479 | K_EXCEPTION proc_exceptions
1483 proc_exceptions : proc_exceptions proc_exception
1485 $$ = lappend($1, $2);
1489 $$ = list_make1($1);
1493 proc_exception : K_WHEN lno proc_conditions K_THEN proc_sect
1495 PLpgSQL_exception *new;
1497 new = palloc0(sizeof(PLpgSQL_exception));
1499 new->conditions = $3;
1506 proc_conditions : proc_conditions K_OR opt_lblname
1508 PLpgSQL_condition *old;
1510 for (old = $1; old->next != NULL; old = old->next)
1512 old->next = plpgsql_parse_err_condition($3);
1518 $$ = plpgsql_parse_err_condition($1);
1523 { $$ = plpgsql_read_expression(';', ";"); }
1526 expr_until_rightbracket :
1527 { $$ = plpgsql_read_expression(']', "]"); }
1531 { $$ = plpgsql_read_expression(K_THEN, "THEN"); }
1535 { $$ = plpgsql_read_expression(K_LOOP, "LOOP"); }
1540 plpgsql_ns_push(NULL);
1543 | '<' '<' opt_lblname '>' '>'
1545 plpgsql_ns_push($3);
1556 plpgsql_convert_ident(yytext, &name, 1);
1561 /* just to give a better error than "syntax error" */
1562 yyerror("no such label");
1568 | K_WHEN expr_until_semi
1572 opt_lblname : T_WORD
1576 plpgsql_convert_ident(yytext, &name, 1);
1583 $$ = plpgsql_error_lineno = plpgsql_scanner_lineno();
1591 plpgsql_read_expression(int until, const char *expected)
1593 return read_sql_construct(until, 0, expected, "SELECT ", true, true, NULL);
1596 static PLpgSQL_expr *
1597 read_sql_stmt(const char *sqlstart)
1599 return read_sql_construct(';', 0, ";", sqlstart, false, true, NULL);
1603 * Read a SQL construct and build a PLpgSQL_expr for it.
1605 * until: token code for expected terminator
1606 * until2: token code for alternate terminator (pass 0 if none)
1607 * expected: text to use in complaining that terminator was not found
1608 * sqlstart: text to prefix to the accumulated SQL text
1609 * isexpression: whether to say we're reading an "expression" or a "statement"
1610 * valid_sql: whether to check the syntax of the expression (plus sqlstart)
1611 * endtoken: if not NULL, ending token is stored at *endtoken
1612 * (this is only interesting if until2 isn't zero)
1614 static PLpgSQL_expr *
1615 read_sql_construct(int until,
1617 const char *expected,
1618 const char *sqlstart,
1632 lno = plpgsql_scanner_lineno();
1633 plpgsql_dstring_init(&ds);
1634 plpgsql_dstring_append(&ds, sqlstart);
1639 if (tok == until && parenlevel == 0)
1641 if (tok == until2 && parenlevel == 0)
1643 if (tok == '(' || tok == '[')
1645 else if (tok == ')' || tok == ']')
1650 (errcode(ERRCODE_SYNTAX_ERROR),
1651 errmsg("mismatched parentheses")));
1654 * End of function definition is an error, and we don't expect to
1655 * hit a semicolon either (unless it's the until symbol, in which
1656 * case we should have fallen out above).
1658 if (tok == 0 || tok == ';')
1660 plpgsql_error_lineno = lno;
1661 if (parenlevel != 0)
1663 (errcode(ERRCODE_SYNTAX_ERROR),
1664 errmsg("mismatched parentheses")));
1667 (errcode(ERRCODE_SYNTAX_ERROR),
1668 errmsg("missing \"%s\" at end of SQL expression",
1672 (errcode(ERRCODE_SYNTAX_ERROR),
1673 errmsg("missing \"%s\" at end of SQL statement",
1677 if (plpgsql_SpaceScanned)
1678 plpgsql_dstring_append(&ds, " ");
1680 /* Check for array overflow */
1681 if (nparams >= 1024)
1683 plpgsql_error_lineno = lno;
1685 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1686 errmsg("too many variables specified in SQL statement")));
1692 params[nparams] = yylval.scalar->dno;
1693 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1694 plpgsql_dstring_append(&ds, buf);
1698 params[nparams] = yylval.row->rowno;
1699 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1700 plpgsql_dstring_append(&ds, buf);
1704 params[nparams] = yylval.rec->recno;
1705 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1706 plpgsql_dstring_append(&ds, buf);
1710 plpgsql_dstring_append(&ds, yytext);
1718 expr = palloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
1719 expr->dtype = PLPGSQL_DTYPE_EXPR;
1720 expr->query = pstrdup(plpgsql_dstring_get(&ds));
1722 expr->nparams = nparams;
1723 while(nparams-- > 0)
1724 expr->params[nparams] = params[nparams];
1725 plpgsql_dstring_free(&ds);
1728 check_sql_expr(expr->query);
1733 static PLpgSQL_type *
1734 read_datatype(int tok)
1738 PLpgSQL_type *result;
1739 bool needspace = false;
1742 lno = plpgsql_scanner_lineno();
1744 /* Often there will be a lookahead token, but if not, get one */
1750 /* lexer found word%TYPE and did its thing already */
1751 return yylval.dtype;
1754 plpgsql_dstring_init(&ds);
1760 plpgsql_error_lineno = lno;
1761 if (parenlevel != 0)
1763 (errcode(ERRCODE_SYNTAX_ERROR),
1764 errmsg("mismatched parentheses")));
1766 (errcode(ERRCODE_SYNTAX_ERROR),
1767 errmsg("incomplete datatype declaration")));
1769 /* Possible followers for datatype in a declaration */
1770 if (tok == K_NOT || tok == K_ASSIGN || tok == K_DEFAULT)
1772 /* Possible followers for datatype in a cursor_arg list */
1773 if ((tok == ',' || tok == ')') && parenlevel == 0)
1777 else if (tok == ')')
1780 plpgsql_dstring_append(&ds, " ");
1782 plpgsql_dstring_append(&ds, yytext);
1787 plpgsql_push_back_token(tok);
1789 plpgsql_error_lineno = lno; /* in case of error in parse_datatype */
1791 result = plpgsql_parse_datatype(plpgsql_dstring_get(&ds));
1793 plpgsql_dstring_free(&ds);
1798 static PLpgSQL_stmt *
1799 make_select_stmt(void)
1806 PLpgSQL_row *row = NULL;
1807 PLpgSQL_rec *rec = NULL;
1809 bool have_into = false;
1811 plpgsql_dstring_init(&ds);
1812 plpgsql_dstring_append(&ds, "SELECT ");
1822 plpgsql_error_lineno = plpgsql_scanner_lineno();
1824 (errcode(ERRCODE_SYNTAX_ERROR),
1825 errmsg("unexpected end of function definition")));
1831 plpgsql_error_lineno = plpgsql_scanner_lineno();
1833 (errcode(ERRCODE_SYNTAX_ERROR),
1834 errmsg("INTO specified more than once")));
1850 row = read_into_scalar_list(yytext, yylval.scalar);
1855 /* Treat the INTO as non-special */
1856 plpgsql_dstring_append(&ds, " INTO ");
1857 plpgsql_push_back_token(tok);
1863 if (plpgsql_SpaceScanned)
1864 plpgsql_dstring_append(&ds, " ");
1866 /* Check for array overflow */
1867 if (nparams >= 1024)
1869 plpgsql_error_lineno = plpgsql_scanner_lineno();
1871 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1872 errmsg("too many parameters specified in SQL statement")));
1878 params[nparams] = yylval.scalar->dno;
1879 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1880 plpgsql_dstring_append(&ds, buf);
1884 params[nparams] = yylval.row->rowno;
1885 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1886 plpgsql_dstring_append(&ds, buf);
1890 params[nparams] = yylval.rec->recno;
1891 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1892 plpgsql_dstring_append(&ds, buf);
1896 plpgsql_dstring_append(&ds, yytext);
1901 expr = palloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
1902 expr->dtype = PLPGSQL_DTYPE_EXPR;
1903 expr->query = pstrdup(plpgsql_dstring_get(&ds));
1905 expr->nparams = nparams;
1906 while(nparams-- > 0)
1907 expr->params[nparams] = params[nparams];
1908 plpgsql_dstring_free(&ds);
1912 PLpgSQL_stmt_select *select;
1914 select = palloc0(sizeof(PLpgSQL_stmt_select));
1915 select->cmd_type = PLPGSQL_STMT_SELECT;
1918 select->query = expr;
1920 return (PLpgSQL_stmt *)select;
1924 PLpgSQL_stmt_execsql *execsql;
1926 execsql = palloc(sizeof(PLpgSQL_stmt_execsql));
1927 execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
1928 execsql->sqlstmt = expr;
1930 return (PLpgSQL_stmt *)execsql;
1935 static PLpgSQL_stmt *
1936 make_fetch_stmt(void)
1939 PLpgSQL_row *row = NULL;
1940 PLpgSQL_rec *rec = NULL;
1941 PLpgSQL_stmt_fetch *fetch;
1943 /* We have already parsed everything through the INTO keyword */
1957 row = read_into_scalar_list(yytext, yylval.scalar);
1961 yyerror("syntax error");
1966 yyerror("syntax error");
1968 fetch = palloc0(sizeof(PLpgSQL_stmt_select));
1969 fetch->cmd_type = PLPGSQL_STMT_FETCH;
1973 return (PLpgSQL_stmt *)fetch;
1978 check_assignable(PLpgSQL_datum *datum)
1980 switch (datum->dtype)
1982 case PLPGSQL_DTYPE_VAR:
1983 if (((PLpgSQL_var *) datum)->isconst)
1985 plpgsql_error_lineno = plpgsql_scanner_lineno();
1987 (errcode(ERRCODE_ERROR_IN_ASSIGNMENT),
1988 errmsg("\"%s\" is declared CONSTANT",
1989 ((PLpgSQL_var *) datum)->refname)));
1992 case PLPGSQL_DTYPE_ROW:
1993 /* always assignable? */
1995 case PLPGSQL_DTYPE_REC:
1996 /* always assignable? What about NEW/OLD? */
1998 case PLPGSQL_DTYPE_RECFIELD:
1999 /* always assignable? */
2001 case PLPGSQL_DTYPE_ARRAYELEM:
2002 /* always assignable? */
2004 case PLPGSQL_DTYPE_TRIGARG:
2005 yyerror("cannot assign to tg_argv");
2008 elog(ERROR, "unrecognized dtype: %d", datum->dtype);
2014 * Given the first datum and name in the INTO list, continue to read
2015 * comma-separated scalar variables until we run out. Then construct
2016 * and return a fake "row" variable that represents the list of
2019 static PLpgSQL_row *
2020 read_into_scalar_list(const char *initial_name,
2021 PLpgSQL_datum *initial_datum)
2024 char *fieldnames[1024];
2029 check_assignable(initial_datum);
2030 fieldnames[0] = pstrdup(initial_name);
2031 varnos[0] = initial_datum->dno;
2034 while ((tok = yylex()) == ',')
2036 /* Check for array overflow */
2037 if (nfields >= 1024)
2039 plpgsql_error_lineno = plpgsql_scanner_lineno();
2041 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2042 errmsg("too many INTO variables specified")));
2049 check_assignable(yylval.scalar);
2050 fieldnames[nfields] = pstrdup(yytext);
2051 varnos[nfields++] = yylval.scalar->dno;
2055 plpgsql_error_lineno = plpgsql_scanner_lineno();
2057 (errcode(ERRCODE_SYNTAX_ERROR),
2058 errmsg("\"%s\" is not a variable",
2064 * We read an extra, non-comma character from yylex(), so push it
2065 * back onto the input stream
2067 plpgsql_push_back_token(tok);
2069 row = palloc(sizeof(PLpgSQL_row));
2070 row->dtype = PLPGSQL_DTYPE_ROW;
2071 row->refname = pstrdup("*internal*");
2072 row->lineno = plpgsql_scanner_lineno();
2073 row->rowtupdesc = NULL;
2074 row->nfields = nfields;
2075 row->fieldnames = palloc(sizeof(char *) * nfields);
2076 row->varnos = palloc(sizeof(int) * nfields);
2077 while (--nfields >= 0)
2079 row->fieldnames[nfields] = fieldnames[nfields];
2080 row->varnos[nfields] = varnos[nfields];
2083 plpgsql_adddatum((PLpgSQL_datum *)row);
2089 * When the PL/PgSQL parser expects to see a SQL statement, it is very
2090 * liberal in what it accepts; for example, we often assume an
2091 * unrecognized keyword is the beginning of a SQL statement. This
2092 * avoids the need to duplicate parts of the SQL grammar in the
2093 * PL/PgSQL grammar, but it means we can accept wildly malformed
2094 * input. To try and catch some of the more obviously invalid input,
2095 * we run the strings we expect to be SQL statements through the main
2098 * We only invoke the raw parser (not the analyzer); this doesn't do
2099 * any database access and does not check any semantic rules, it just
2100 * checks for basic syntactic correctness. We do this here, rather
2101 * than after parsing has finished, because a malformed SQL statement
2102 * may cause the PL/PgSQL parser to become confused about statement
2103 * borders. So it is best to bail out as early as we can.
2106 check_sql_expr(const char *stmt)
2108 ErrorContextCallback syntax_errcontext;
2109 ErrorContextCallback *previous_errcontext;
2110 MemoryContext oldCxt;
2112 if (!plpgsql_check_syntax)
2116 * Setup error traceback support for ereport(). The previous
2117 * ereport callback is installed by pl_comp.c, but we don't want
2118 * that to be invoked (since it will try to transpose the syntax
2119 * error to be relative to the CREATE FUNCTION), so temporarily
2120 * remove it from the list of callbacks.
2122 Assert(error_context_stack->callback == plpgsql_compile_error_callback);
2124 previous_errcontext = error_context_stack;
2125 syntax_errcontext.callback = plpgsql_sql_error_callback;
2126 syntax_errcontext.arg = (char *) stmt;
2127 syntax_errcontext.previous = error_context_stack->previous;
2128 error_context_stack = &syntax_errcontext;
2130 oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);
2131 (void) raw_parser(stmt);
2132 MemoryContextSwitchTo(oldCxt);
2134 /* Restore former ereport callback */
2135 error_context_stack = previous_errcontext;
2139 plpgsql_sql_error_callback(void *arg)
2141 char *sql_stmt = (char *) arg;
2143 Assert(plpgsql_error_funcname);
2145 errcontext("SQL statement in PL/PgSQL function \"%s\" near line %d",
2146 plpgsql_error_funcname, plpgsql_error_lineno);
2147 internalerrquery(sql_stmt);
2148 internalerrposition(geterrposition());
2152 #include "pl_scan.c"