2 /**********************************************************************
3 * gram.y - Parser for the PL/pgSQL
7 * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.65 2005/02/13 01:25:50 momjian Exp $
9 * This software is copyrighted by Jan Wieck - Hamburg.
11 * The author hereby grants permission to use, copy, modify,
12 * distribute, and license this software and its documentation
13 * for any purpose, provided that existing copyright notices are
14 * retained in all copies and that this notice is included
15 * verbatim in any distributions. No written agreement, license,
16 * or royalty fee is required for any of the authorized uses.
17 * Modifications to this software may be copyrighted by their
18 * author and need not follow the licensing terms described
19 * here, provided that the new terms are clearly indicated on
20 * the first page of each file where they apply.
22 * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
23 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
24 * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
25 * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
26 * IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
29 * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
30 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
32 * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
33 * AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
34 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
35 * ENHANCEMENTS, OR MODIFICATIONS.
37 **********************************************************************/
42 static PLpgSQL_expr *read_sql_construct(int until,
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_condition *condition;
100 PLpgSQL_exception *exception;
101 PLpgSQL_exceptions *exceptions;
102 PLpgSQL_nsitem *nsitem;
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 decl_cursor_arglist
112 %type <nsitem> decl_aliasitem
113 %type <str> decl_stmts decl_stmt
115 %type <expr> expr_until_semi expr_until_rightbracket
116 %type <expr> expr_until_then expr_until_loop
117 %type <expr> opt_exitcond
119 %type <ival> assign_var cursor_variable
120 %type <var> cursor_varptr
121 %type <variable> decl_cursor_arg
122 %type <forvariable> for_variable
123 %type <stmt> for_control
125 %type <str> opt_lblname opt_label
126 %type <str> opt_exitlabel
127 %type <str> execsql_start
129 %type <stmts> proc_sect proc_stmts stmt_else loop_body
130 %type <stmt> proc_stmt pl_block
131 %type <stmt> stmt_assign stmt_if stmt_loop stmt_while stmt_exit
132 %type <stmt> stmt_return stmt_return_next stmt_raise stmt_execsql
133 %type <stmt> stmt_for stmt_select stmt_perform
134 %type <stmt> stmt_dynexecute stmt_getdiag
135 %type <stmt> stmt_open stmt_fetch stmt_close stmt_null
137 %type <exceptions> exception_sect proc_exceptions
138 %type <exception> proc_exception
139 %type <condition> proc_conditions
141 %type <intlist> raise_params
142 %type <ival> raise_level raise_param
143 %type <str> raise_msg
145 %type <dtlist> getdiag_list
146 %type <ival> getdiag_item getdiag_target
210 %token T_SCALAR /* a VAR, RECFIELD, or TRIGARG */
223 pl_function : T_FUNCTION comp_optsect pl_block opt_semi
225 yylval.program = (PLpgSQL_stmt_block *)$3;
227 | T_TRIGGER comp_optsect pl_block opt_semi
229 yylval.program = (PLpgSQL_stmt_block *)$3;
237 comp_options : comp_options comp_option
241 comp_option : O_OPTION O_DUMP
243 plpgsql_DumpExecTree = 1;
251 pl_block : decl_sect K_BEGIN lno proc_sect exception_sect K_END
253 PLpgSQL_stmt_block *new;
255 new = malloc(sizeof(PLpgSQL_stmt_block));
256 memset(new, 0, sizeof(PLpgSQL_stmt_block));
258 new->cmd_type = PLPGSQL_STMT_BLOCK;
260 new->label = $1.label;
261 new->n_initvars = $1.n_initvars;
262 new->initvarnos = $1.initvarnos;
264 new->exceptions = $5;
268 $$ = (PLpgSQL_stmt *)new;
273 decl_sect : opt_label
275 plpgsql_ns_setlocal(false);
278 $$.initvarnos = NULL;
279 plpgsql_add_initdatums(NULL);
281 | opt_label decl_start
283 plpgsql_ns_setlocal(false);
286 $$.initvarnos = NULL;
287 plpgsql_add_initdatums(NULL);
289 | opt_label decl_start decl_stmts
291 plpgsql_ns_setlocal(false);
296 $$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos));
300 decl_start : K_DECLARE
302 plpgsql_ns_setlocal(true);
306 decl_stmts : decl_stmts decl_stmt
312 decl_stmt : '<' '<' opt_lblname '>' '>'
320 decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
322 PLpgSQL_variable *var;
324 var = plpgsql_build_variable($1.name, $1.lineno,
328 if (var->dtype == PLPGSQL_DTYPE_VAR)
329 ((PLpgSQL_var *) var)->isconst = $2;
332 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
333 errmsg("row or record variable cannot be CONSTANT")));
337 if (var->dtype == PLPGSQL_DTYPE_VAR)
338 ((PLpgSQL_var *) var)->notnull = $4;
341 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
342 errmsg("row or record variable cannot be NOT NULL")));
346 if (var->dtype == PLPGSQL_DTYPE_VAR)
347 ((PLpgSQL_var *) var)->default_val = $5;
350 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
351 errmsg("default value for row or record variable is not supported")));
354 | decl_varname K_ALIAS K_FOR decl_aliasitem ';'
356 plpgsql_ns_additem($4->itemtype,
357 $4->itemno, $1.name);
359 | K_RENAME decl_renname K_TO decl_renname ';'
361 plpgsql_ns_rename($2, $4);
363 | decl_varname K_CURSOR
364 { plpgsql_ns_push(NULL); }
365 decl_cursor_args decl_is_from decl_cursor_query
368 PLpgSQL_expr *curname_def;
373 /* pop local namespace for cursor args */
376 new = (PLpgSQL_var *)
377 plpgsql_build_variable($1.name, $1.lineno,
378 plpgsql_build_datatype(REFCURSOROID,
382 curname_def = malloc(sizeof(PLpgSQL_expr));
383 memset(curname_def, 0, sizeof(PLpgSQL_expr));
385 curname_def->dtype = PLPGSQL_DTYPE_EXPR;
386 strcpy(buf, "SELECT '");
388 cp2 = buf + strlen(buf);
391 if (*cp1 == '\\' || *cp1 == '\'')
395 strcpy(cp2, "'::refcursor");
396 curname_def->query = strdup(buf);
397 new->default_val = curname_def;
399 new->cursor_explicit_expr = $6;
401 new->cursor_explicit_argrow = -1;
403 new->cursor_explicit_argrow = $4->rowno;
411 plpgsql_ns_setlocal(false);
412 query = read_sql_stmt("");
413 plpgsql_ns_setlocal(true);
423 | '(' decl_cursor_arglist ')'
425 /* Copy the temp arrays to malloc'd storage */
426 int nfields = $2->nfields;
430 ftmp = malloc(nfields * sizeof(char *));
431 vtmp = malloc(nfields * sizeof(int));
432 memcpy(ftmp, $2->fieldnames, nfields * sizeof(char *));
433 memcpy(vtmp, $2->varnos, nfields * sizeof(int));
435 pfree($2->fieldnames);
438 $2->fieldnames = ftmp;
441 plpgsql_adddatum((PLpgSQL_datum *)$2);
447 decl_cursor_arglist : decl_cursor_arg
451 new = malloc(sizeof(PLpgSQL_row));
452 memset(new, 0, sizeof(PLpgSQL_row));
454 new->dtype = PLPGSQL_DTYPE_ROW;
455 new->refname = strdup("*internal*");
456 new->lineno = plpgsql_scanner_lineno();
457 new->rowtupdesc = NULL;
459 * We make temporary fieldnames/varnos arrays that
460 * are much bigger than necessary. We will resize
461 * them to just the needed size in the
462 * decl_cursor_args production.
464 new->fieldnames = palloc(1024 * sizeof(char *));
465 new->varnos = palloc(1024 * sizeof(int));
468 new->fieldnames[0] = $1->refname;
469 new->varnos[0] = $1->dno;
473 | decl_cursor_arglist ',' decl_cursor_arg
475 int i = $1->nfields++;
477 $1->fieldnames[i] = $3->refname;
478 $1->varnos[i] = $3->dno;
484 decl_cursor_arg : decl_varname decl_datatype
486 $$ = plpgsql_build_variable($1.name, $1.lineno,
491 decl_is_from : K_IS | /* Oracle */
494 decl_aliasitem : T_WORD
499 plpgsql_convert_ident(yytext, &name, 1);
501 yyerror("only positional parameters may be aliased");
503 plpgsql_ns_setlocal(false);
504 nsi = plpgsql_ns_lookup(name, NULL);
507 plpgsql_error_lineno = plpgsql_scanner_lineno();
509 (errcode(ERRCODE_UNDEFINED_PARAMETER),
510 errmsg("function has no parameter \"%s\"",
514 plpgsql_ns_setlocal(true);
522 decl_varname : T_WORD
526 plpgsql_convert_ident(yytext, &name, 1);
527 /* name should be malloc'd for use as varname */
528 $$.name = strdup(name);
529 $$.lineno = plpgsql_scanner_lineno();
534 decl_renname : T_WORD
538 plpgsql_convert_ident(yytext, &name, 1);
539 /* the result must be palloc'd, see plpgsql_ns_rename */
553 * If there's a lookahead token, read_datatype
556 $$ = read_datatype(yychar);
571 plpgsql_ns_setlocal(false);
572 $$ = plpgsql_read_expression(';', ";");
573 plpgsql_ns_setlocal(true);
577 decl_defkey : K_ASSIGN
585 new = malloc(sizeof(PLpgSQL_stmts));
586 memset(new, 0, sizeof(PLpgSQL_stmts));
593 proc_stmts : proc_stmts proc_stmt
597 if ($1->stmts_used == $1->stmts_alloc)
599 $1->stmts_alloc *= 2;
600 $1->stmts = realloc($1->stmts, sizeof(PLpgSQL_stmt *) * $1->stmts_alloc);
602 $1->stmts[$1->stmts_used++] = $2;
610 new = malloc(sizeof(PLpgSQL_stmts));
611 memset(new, 0, sizeof(PLpgSQL_stmts));
613 new->stmts_alloc = 32;
614 new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
617 new->stmts[new->stmts_used++] = $1;
623 proc_stmt : pl_block ';'
663 stmt_perform : K_PERFORM lno expr_until_semi
665 PLpgSQL_stmt_perform *new;
667 new = malloc(sizeof(PLpgSQL_stmt_perform));
668 memset(new, 0, sizeof(PLpgSQL_stmt_perform));
670 new->cmd_type = PLPGSQL_STMT_PERFORM;
674 $$ = (PLpgSQL_stmt *)new;
678 stmt_assign : assign_var lno K_ASSIGN expr_until_semi
680 PLpgSQL_stmt_assign *new;
682 new = malloc(sizeof(PLpgSQL_stmt_assign));
683 memset(new, 0, sizeof(PLpgSQL_stmt_assign));
685 new->cmd_type = PLPGSQL_STMT_ASSIGN;
690 $$ = (PLpgSQL_stmt *)new;
694 stmt_getdiag : K_GET K_DIAGNOSTICS lno getdiag_list ';'
696 PLpgSQL_stmt_getdiag *new;
698 new = malloc(sizeof(PLpgSQL_stmt_getdiag));
699 memset(new, 0, sizeof(PLpgSQL_stmt_getdiag));
701 new->cmd_type = PLPGSQL_STMT_GETDIAG;
703 new->ndtitems = $4.nused;
704 new->dtitems = malloc(sizeof(PLpgSQL_diag_item) * $4.nused);
705 memcpy(new->dtitems, $4.dtitems, sizeof(PLpgSQL_diag_item) * $4.nused);
707 $$ = (PLpgSQL_stmt *)new;
711 getdiag_list : getdiag_list ',' getdiag_target K_ASSIGN getdiag_item
713 if ($1.nused == $1.nalloc)
716 $1.dtitems = repalloc($1.dtitems, sizeof(PLpgSQL_diag_item) * $1.nalloc);
718 $1.dtitems[$1.nused].target = $3;
719 $1.dtitems[$1.nused].item = $5;
722 $$.nalloc = $1.nalloc;
724 $$.dtitems = $1.dtitems;
726 | getdiag_target K_ASSIGN getdiag_item
730 $$.dtitems = palloc(sizeof(PLpgSQL_diag_item) * $$.nalloc);
731 $$.dtitems[0].target = $1;
732 $$.dtitems[0].item = $3;
736 getdiag_item : K_ROW_COUNT
738 $$ = PLPGSQL_GETDIAG_ROW_COUNT;
742 $$ = PLPGSQL_GETDIAG_RESULT_OID;
746 getdiag_target : T_SCALAR
748 check_assignable(yylval.scalar);
749 $$ = yylval.scalar->dno;
754 assign_var : T_SCALAR
756 check_assignable(yylval.scalar);
757 $$ = yylval.scalar->dno;
761 check_assignable((PLpgSQL_datum *) yylval.row);
762 $$ = yylval.row->rowno;
766 check_assignable((PLpgSQL_datum *) yylval.rec);
767 $$ = yylval.rec->recno;
769 | assign_var '[' expr_until_rightbracket
771 PLpgSQL_arrayelem *new;
773 new = malloc(sizeof(PLpgSQL_arrayelem));
774 memset(new, 0, sizeof(PLpgSQL_arrayelem));
776 new->dtype = PLPGSQL_DTYPE_ARRAYELEM;
778 new->arrayparentno = $1;
780 plpgsql_adddatum((PLpgSQL_datum *)new);
786 stmt_if : K_IF lno expr_until_then proc_sect stmt_else K_END K_IF ';'
788 PLpgSQL_stmt_if *new;
790 new = malloc(sizeof(PLpgSQL_stmt_if));
791 memset(new, 0, sizeof(PLpgSQL_stmt_if));
793 new->cmd_type = PLPGSQL_STMT_IF;
797 new->false_body = $5;
799 $$ = (PLpgSQL_stmt *)new;
807 new = malloc(sizeof(PLpgSQL_stmts));
808 memset(new, 0, sizeof(PLpgSQL_stmts));
811 | K_ELSIF lno expr_until_then proc_sect stmt_else
814 * Translate the structure: into:
816 * IF c1 THEN IF c1 THEN
829 PLpgSQL_stmt_if *new_if;
831 /* first create a new if-statement */
832 new_if = malloc(sizeof(PLpgSQL_stmt_if));
833 memset(new_if, 0, sizeof(PLpgSQL_stmt_if));
835 new_if->cmd_type = PLPGSQL_STMT_IF;
838 new_if->true_body = $4;
839 new_if->false_body = $5;
841 /* this is a 'container' for the if-statement */
842 new = malloc(sizeof(PLpgSQL_stmts));
843 memset(new, 0, sizeof(PLpgSQL_stmts));
845 new->stmts_alloc = 64;
847 new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
848 new->stmts[0] = (PLpgSQL_stmt *) new_if;
860 stmt_loop : opt_label K_LOOP lno loop_body
862 PLpgSQL_stmt_loop *new;
864 new = malloc(sizeof(PLpgSQL_stmt_loop));
865 memset(new, 0, sizeof(PLpgSQL_stmt_loop));
867 new->cmd_type = PLPGSQL_STMT_LOOP;
874 $$ = (PLpgSQL_stmt *)new;
878 stmt_while : opt_label K_WHILE lno expr_until_loop loop_body
880 PLpgSQL_stmt_while *new;
882 new = malloc(sizeof(PLpgSQL_stmt_while));
883 memset(new, 0, sizeof(PLpgSQL_stmt_while));
885 new->cmd_type = PLPGSQL_STMT_WHILE;
893 $$ = (PLpgSQL_stmt *)new;
897 stmt_for : opt_label K_FOR for_control loop_body
899 /* This runs after we've scanned the loop body */
900 if ($3->cmd_type == PLPGSQL_STMT_FORI)
902 PLpgSQL_stmt_fori *new;
904 new = (PLpgSQL_stmt_fori *) $3;
907 $$ = (PLpgSQL_stmt *) new;
909 else if ($3->cmd_type == PLPGSQL_STMT_FORS)
911 PLpgSQL_stmt_fors *new;
913 new = (PLpgSQL_stmt_fors *) $3;
916 $$ = (PLpgSQL_stmt *) new;
920 PLpgSQL_stmt_dynfors *new;
922 Assert($3->cmd_type == PLPGSQL_STMT_DYNFORS);
923 new = (PLpgSQL_stmt_dynfors *) $3;
926 $$ = (PLpgSQL_stmt *) new;
929 /* close namespace started in opt_label */
934 for_control : lno for_variable K_IN
937 bool reverse = false;
938 bool execute = false;
941 /* check for REVERSE and EXECUTE */
943 if (tok == K_REVERSE)
949 if (tok == K_EXECUTE)
952 plpgsql_push_back_token(tok);
954 /* Collect one or two expressions */
955 expr1 = read_sql_construct(K_DOTDOT,
964 /* Found .., so it must be an integer loop */
965 PLpgSQL_stmt_fori *new;
969 expr2 = plpgsql_read_expression(K_LOOP, "LOOP");
973 plpgsql_error_lineno = $1;
974 yyerror("cannot specify EXECUTE in integer for-loop");
977 /* name should be malloc'd for use as varname */
978 fvar = (PLpgSQL_var *)
979 plpgsql_build_variable(strdup($2.name),
981 plpgsql_build_datatype(INT4OID,
985 /* put the for-variable into the local block */
986 plpgsql_add_initdatums(NULL);
988 new = malloc(sizeof(PLpgSQL_stmt_fori));
989 memset(new, 0, sizeof(PLpgSQL_stmt_fori));
991 new->cmd_type = PLPGSQL_STMT_FORI;
994 new->reverse = reverse;
998 $$ = (PLpgSQL_stmt *) new;
1002 /* No .., so it must be a loop over rows */
1003 PLpgSQL_stmt_dynfors *new;
1007 plpgsql_error_lineno = $1;
1008 yyerror("cannot specify REVERSE in loop over rows");
1011 new = malloc(sizeof(PLpgSQL_stmt_dynfors));
1012 memset(new, 0, sizeof(PLpgSQL_stmt_dynfors));
1014 new->cmd_type = PLPGSQL_STMT_DYNFORS;
1022 plpgsql_error_lineno = $1;
1023 yyerror("loop variable of loop over rows must be a record or row variable");
1027 $$ = (PLpgSQL_stmt *) new;
1031 /* No .., so it must be a loop over rows */
1032 PLpgSQL_stmt_fors *new;
1037 plpgsql_error_lineno = $1;
1038 yyerror("cannot specify REVERSE in loop over rows");
1041 new = malloc(sizeof(PLpgSQL_stmt_fors));
1042 memset(new, 0, sizeof(PLpgSQL_stmt_fors));
1044 new->cmd_type = PLPGSQL_STMT_FORS;
1052 plpgsql_error_lineno = $1;
1053 yyerror("loop variable of loop over rows must be a record or row variable");
1056 * Must get rid of the "SELECT " we prepended
1059 newquery = strdup(expr1->query + 7);
1061 expr1->query = newquery;
1065 $$ = (PLpgSQL_stmt *) new;
1070 for_variable : T_SCALAR
1074 plpgsql_convert_ident(yytext, &name, 1);
1076 $$.lineno = plpgsql_scanner_lineno();
1084 plpgsql_convert_ident(yytext, &name, 1);
1086 $$.lineno = plpgsql_scanner_lineno();
1094 plpgsql_convert_ident(yytext, &name, 1);
1096 $$.lineno = plpgsql_scanner_lineno();
1097 $$.rec = yylval.rec;
1104 plpgsql_convert_ident(yytext, &name, 1);
1106 $$.lineno = plpgsql_scanner_lineno();
1107 $$.row = yylval.row;
1112 stmt_select : K_SELECT lno
1114 $$ = make_select_stmt();
1119 stmt_exit : K_EXIT lno opt_exitlabel opt_exitcond
1121 PLpgSQL_stmt_exit *new;
1123 new = malloc(sizeof(PLpgSQL_stmt_exit));
1124 memset(new, 0, sizeof(PLpgSQL_stmt_exit));
1126 new->cmd_type = PLPGSQL_STMT_EXIT;
1131 $$ = (PLpgSQL_stmt *)new;
1135 stmt_return : K_RETURN lno
1137 PLpgSQL_stmt_return *new;
1139 new = malloc(sizeof(PLpgSQL_stmt_return));
1140 memset(new, 0, sizeof(PLpgSQL_stmt_return));
1145 if (plpgsql_curr_compile->fn_retset)
1148 yyerror("RETURN cannot have a parameter in function returning set; use RETURN NEXT");
1150 else if (plpgsql_curr_compile->fn_retistuple)
1158 new->retrowno = yylval.row->rowno;
1162 new->retrecno = yylval.rec->recno;
1166 yyerror("RETURN must specify a record or row variable in function returning tuple");
1170 yyerror("RETURN must specify a record or row variable in function returning tuple");
1174 /* ordinary expression case */
1175 new->expr = plpgsql_read_expression(';', ";");
1178 new->cmd_type = PLPGSQL_STMT_RETURN;
1181 $$ = (PLpgSQL_stmt *)new;
1185 stmt_return_next: K_RETURN_NEXT lno
1187 PLpgSQL_stmt_return_next *new;
1189 if (!plpgsql_curr_compile->fn_retset)
1190 yyerror("cannot use RETURN NEXT in a non-SETOF function");
1192 new = malloc(sizeof(PLpgSQL_stmt_return_next));
1193 memset(new, 0, sizeof(PLpgSQL_stmt_return_next));
1195 new->cmd_type = PLPGSQL_STMT_RETURN_NEXT;
1198 if (plpgsql_curr_compile->fn_retistuple)
1202 if (tok == T_RECORD)
1203 new->rec = yylval.rec;
1204 else if (tok == T_ROW)
1205 new->row = yylval.row;
1207 yyerror("RETURN NEXT must specify a record or row variable in function returning tuple");
1210 yyerror("RETURN NEXT must specify a record or row variable in function returning tuple");
1213 new->expr = plpgsql_read_expression(';', ";");
1215 $$ = (PLpgSQL_stmt *)new;
1219 stmt_raise : K_RAISE lno raise_level raise_msg raise_params ';'
1221 PLpgSQL_stmt_raise *new;
1223 new = malloc(sizeof(PLpgSQL_stmt_raise));
1225 new->cmd_type = PLPGSQL_STMT_RAISE;
1227 new->elog_level = $3;
1229 new->nparams = $5.nused;
1230 new->params = malloc(sizeof(int) * $5.nused);
1231 memcpy(new->params, $5.nums, sizeof(int) * $5.nused);
1233 $$ = (PLpgSQL_stmt *)new;
1235 | K_RAISE lno raise_level raise_msg ';'
1237 PLpgSQL_stmt_raise *new;
1239 new = malloc(sizeof(PLpgSQL_stmt_raise));
1241 new->cmd_type = PLPGSQL_STMT_RAISE;
1243 new->elog_level = $3;
1248 $$ = (PLpgSQL_stmt *)new;
1252 raise_msg : T_STRING
1254 $$ = plpgsql_get_string_value();
1258 raise_level : K_EXCEPTION
1284 raise_params : raise_params raise_param
1286 if ($1.nused == $1.nalloc)
1289 $1.nums = repalloc($1.nums, sizeof(int) * $1.nalloc);
1291 $1.nums[$1.nused++] = $2;
1293 $$.nalloc = $1.nalloc;
1294 $$.nused = $1.nused;
1301 $$.nums = palloc(sizeof(int) * $$.nalloc);
1306 raise_param : ',' T_SCALAR
1308 $$ = yylval.scalar->dno;
1312 loop_body : proc_sect K_END K_LOOP ';'
1316 stmt_execsql : execsql_start lno
1318 PLpgSQL_stmt_execsql *new;
1320 new = malloc(sizeof(PLpgSQL_stmt_execsql));
1321 new->cmd_type = PLPGSQL_STMT_EXECSQL;
1323 new->sqlstmt = read_sql_stmt($1);
1325 $$ = (PLpgSQL_stmt *)new;
1329 stmt_dynexecute : K_EXECUTE lno expr_until_semi
1331 PLpgSQL_stmt_dynexecute *new;
1333 new = malloc(sizeof(PLpgSQL_stmt_dynexecute));
1334 new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
1338 $$ = (PLpgSQL_stmt *)new;
1342 stmt_open : K_OPEN lno cursor_varptr
1344 PLpgSQL_stmt_open *new;
1347 new = malloc(sizeof(PLpgSQL_stmt_open));
1348 memset(new, 0, sizeof(PLpgSQL_stmt_open));
1350 new->cmd_type = PLPGSQL_STMT_OPEN;
1352 new->curvar = $3->varno;
1354 if ($3->cursor_explicit_expr == NULL)
1360 plpgsql_error_lineno = $2;
1362 (errcode(ERRCODE_SYNTAX_ERROR),
1363 errmsg("syntax error at \"%s\"",
1365 errdetail("Expected FOR to open a reference cursor.")));
1373 plpgsql_push_back_token(tok);
1374 new->query = read_sql_stmt("");
1378 new->dynquery = read_sql_stmt("SELECT ");
1382 plpgsql_error_lineno = $2;
1384 (errcode(ERRCODE_SYNTAX_ERROR),
1385 errmsg("syntax error at \"%s\"",
1392 if ($3->cursor_explicit_argrow >= 0)
1400 plpgsql_error_lineno = plpgsql_scanner_lineno();
1402 (errcode(ERRCODE_SYNTAX_ERROR),
1403 errmsg("cursor \"%s\" has arguments",
1408 * Push back the '(', else read_sql_stmt
1409 * will complain about unbalanced parens.
1411 plpgsql_push_back_token(tok);
1413 new->argquery = read_sql_stmt("SELECT ");
1416 * Now remove the leading and trailing parens,
1417 * because we want "select 1, 2", not
1420 cp = new->argquery->query;
1422 if (strncmp(cp, "SELECT", 6) != 0)
1424 plpgsql_error_lineno = plpgsql_scanner_lineno();
1425 /* internal error */
1426 elog(ERROR, "expected \"SELECT (\", got \"%s\"",
1427 new->argquery->query);
1430 while (*cp == ' ') /* could be more than 1 space here */
1434 plpgsql_error_lineno = plpgsql_scanner_lineno();
1435 /* internal error */
1436 elog(ERROR, "expected \"SELECT (\", got \"%s\"",
1437 new->argquery->query);
1441 cp += strlen(cp) - 1;
1444 yyerror("expected \")\"");
1453 plpgsql_error_lineno = plpgsql_scanner_lineno();
1455 (errcode(ERRCODE_SYNTAX_ERROR),
1456 errmsg("cursor \"%s\" has no arguments",
1462 plpgsql_error_lineno = plpgsql_scanner_lineno();
1464 (errcode(ERRCODE_SYNTAX_ERROR),
1465 errmsg("syntax error at \"%s\"",
1471 $$ = (PLpgSQL_stmt *)new;
1475 stmt_fetch : K_FETCH lno cursor_variable K_INTO
1477 PLpgSQL_stmt_fetch *new;
1479 new = (PLpgSQL_stmt_fetch *)make_fetch_stmt();
1482 $$ = (PLpgSQL_stmt *)new;
1487 stmt_close : K_CLOSE lno cursor_variable ';'
1489 PLpgSQL_stmt_close *new;
1491 new = malloc(sizeof(PLpgSQL_stmt_close));
1492 new->cmd_type = PLPGSQL_STMT_CLOSE;
1496 $$ = (PLpgSQL_stmt *)new;
1500 stmt_null : K_NULL ';'
1502 /* We do not bother building a node for NULL */
1507 cursor_varptr : T_SCALAR
1509 if (yylval.scalar->dtype != PLPGSQL_DTYPE_VAR)
1510 yyerror("cursor variable must be a simple variable");
1512 if (((PLpgSQL_var *) yylval.scalar)->datatype->typoid != REFCURSOROID)
1514 plpgsql_error_lineno = plpgsql_scanner_lineno();
1516 (errcode(ERRCODE_DATATYPE_MISMATCH),
1517 errmsg("\"%s\" must be of type cursor or refcursor",
1518 ((PLpgSQL_var *) yylval.scalar)->refname)));
1520 $$ = (PLpgSQL_var *) yylval.scalar;
1524 cursor_variable : T_SCALAR
1526 if (yylval.scalar->dtype != PLPGSQL_DTYPE_VAR)
1527 yyerror("cursor variable must be a simple variable");
1529 if (((PLpgSQL_var *) yylval.scalar)->datatype->typoid != REFCURSOROID)
1531 plpgsql_error_lineno = plpgsql_scanner_lineno();
1533 (errcode(ERRCODE_DATATYPE_MISMATCH),
1534 errmsg("\"%s\" must be of type refcursor",
1535 ((PLpgSQL_var *) yylval.scalar)->refname)));
1537 $$ = yylval.scalar->dno;
1541 execsql_start : T_WORD
1542 { $$ = strdup(yytext); }
1544 { $$ = strdup(yytext); }
1549 | K_EXCEPTION proc_exceptions
1553 proc_exceptions : proc_exceptions proc_exception
1555 if ($1->exceptions_used == $1->exceptions_alloc)
1557 $1->exceptions_alloc *= 2;
1558 $1->exceptions = realloc($1->exceptions, sizeof(PLpgSQL_exception *) * $1->exceptions_alloc);
1560 $1->exceptions[$1->exceptions_used++] = $2;
1566 PLpgSQL_exceptions *new;
1568 new = malloc(sizeof(PLpgSQL_exceptions));
1569 memset(new, 0, sizeof(PLpgSQL_exceptions));
1571 new->exceptions_alloc = 16;
1572 new->exceptions_used = 1;
1573 new->exceptions = malloc(sizeof(PLpgSQL_exception *) * new->exceptions_alloc);
1574 new->exceptions[0] = $1;
1580 proc_exception : K_WHEN lno proc_conditions K_THEN proc_sect
1582 PLpgSQL_exception *new;
1584 new = malloc(sizeof(PLpgSQL_exception));
1585 memset(new, 0, sizeof(PLpgSQL_exception));
1588 new->conditions = $3;
1595 proc_conditions : proc_conditions K_OR opt_lblname
1597 PLpgSQL_condition *old;
1599 for (old = $1; old->next != NULL; old = old->next)
1601 old->next = plpgsql_parse_err_condition($3);
1607 $$ = plpgsql_parse_err_condition($1);
1612 { $$ = plpgsql_read_expression(';', ";"); }
1615 expr_until_rightbracket :
1616 { $$ = plpgsql_read_expression(']', "]"); }
1620 { $$ = plpgsql_read_expression(K_THEN, "THEN"); }
1624 { $$ = plpgsql_read_expression(K_LOOP, "LOOP"); }
1629 plpgsql_ns_push(NULL);
1632 | '<' '<' opt_lblname '>' '>'
1634 plpgsql_ns_push($3);
1645 plpgsql_convert_ident(yytext, &name, 1);
1651 /* just to give a better error than "syntax error" */
1652 yyerror("no such label");
1658 | K_WHEN expr_until_semi
1662 opt_lblname : T_WORD
1666 plpgsql_convert_ident(yytext, &name, 1);
1674 $$ = plpgsql_error_lineno = plpgsql_scanner_lineno();
1682 plpgsql_read_expression(int until, const char *expected)
1684 return read_sql_construct(until, 0, expected, true, "SELECT ", NULL);
1687 static PLpgSQL_expr *
1688 read_sql_stmt(const char *sqlstart)
1690 return read_sql_construct(';', 0, ";", false, sqlstart, NULL);
1694 * Read a SQL construct and build a PLpgSQL_expr for it.
1696 * until: token code for expected terminator
1697 * until2: token code for alternate terminator (pass 0 if none)
1698 * expected: text to use in complaining that terminator was not found
1699 * isexpression: whether to say we're reading an "expression" or a "statement"
1700 * sqlstart: text to prefix to the accumulated SQL text
1701 * endtoken: if not NULL, ending token is stored at *endtoken
1702 * (this is only interesting if until2 isn't zero)
1704 static PLpgSQL_expr *
1705 read_sql_construct(int until,
1707 const char *expected,
1709 const char *sqlstart,
1721 lno = plpgsql_scanner_lineno();
1722 plpgsql_dstring_init(&ds);
1723 plpgsql_dstring_append(&ds, sqlstart);
1728 if (tok == until && parenlevel == 0)
1730 if (tok == until2 && parenlevel == 0)
1732 if (tok == '(' || tok == '[')
1734 else if (tok == ')' || tok == ']')
1739 (errcode(ERRCODE_SYNTAX_ERROR),
1740 errmsg("mismatched parentheses")));
1743 * End of function definition is an error, and we don't expect to
1744 * hit a semicolon either (unless it's the until symbol, in which
1745 * case we should have fallen out above).
1747 if (tok == 0 || tok == ';')
1749 plpgsql_error_lineno = lno;
1750 if (parenlevel != 0)
1752 (errcode(ERRCODE_SYNTAX_ERROR),
1753 errmsg("mismatched parentheses")));
1756 (errcode(ERRCODE_SYNTAX_ERROR),
1757 errmsg("missing \"%s\" at end of SQL expression",
1761 (errcode(ERRCODE_SYNTAX_ERROR),
1762 errmsg("missing \"%s\" at end of SQL statement",
1765 if (plpgsql_SpaceScanned)
1766 plpgsql_dstring_append(&ds, " ");
1770 params[nparams] = yylval.scalar->dno;
1771 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1772 plpgsql_dstring_append(&ds, buf);
1776 params[nparams] = yylval.row->rowno;
1777 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1778 plpgsql_dstring_append(&ds, buf);
1782 params[nparams] = yylval.rec->recno;
1783 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1784 plpgsql_dstring_append(&ds, buf);
1788 plpgsql_dstring_append(&ds, yytext);
1796 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
1797 expr->dtype = PLPGSQL_DTYPE_EXPR;
1798 expr->query = strdup(plpgsql_dstring_get(&ds));
1800 expr->nparams = nparams;
1801 while(nparams-- > 0)
1802 expr->params[nparams] = params[nparams];
1803 plpgsql_dstring_free(&ds);
1808 static PLpgSQL_type *
1809 read_datatype(int tok)
1813 PLpgSQL_type *result;
1814 bool needspace = false;
1817 lno = plpgsql_scanner_lineno();
1819 /* Often there will be a lookahead token, but if not, get one */
1825 /* lexer found word%TYPE and did its thing already */
1826 return yylval.dtype;
1829 plpgsql_dstring_init(&ds);
1835 plpgsql_error_lineno = lno;
1836 if (parenlevel != 0)
1838 (errcode(ERRCODE_SYNTAX_ERROR),
1839 errmsg("mismatched parentheses")));
1841 (errcode(ERRCODE_SYNTAX_ERROR),
1842 errmsg("incomplete datatype declaration")));
1844 /* Possible followers for datatype in a declaration */
1845 if (tok == K_NOT || tok == K_ASSIGN || tok == K_DEFAULT)
1847 /* Possible followers for datatype in a cursor_arg list */
1848 if ((tok == ',' || tok == ')') && parenlevel == 0)
1852 else if (tok == ')')
1855 plpgsql_dstring_append(&ds, " ");
1857 plpgsql_dstring_append(&ds, yytext);
1862 plpgsql_push_back_token(tok);
1864 plpgsql_error_lineno = lno; /* in case of error in parse_datatype */
1866 result = plpgsql_parse_datatype(plpgsql_dstring_get(&ds));
1868 plpgsql_dstring_free(&ds);
1874 static PLpgSQL_stmt *
1875 make_select_stmt(void)
1882 PLpgSQL_row *row = NULL;
1883 PLpgSQL_rec *rec = NULL;
1885 int have_nexttok = 0;
1888 plpgsql_dstring_init(&ds);
1889 plpgsql_dstring_append(&ds, "SELECT ");
1900 plpgsql_error_lineno = plpgsql_scanner_lineno();
1902 (errcode(ERRCODE_SYNTAX_ERROR),
1903 errmsg("unexpected end of function definition")));
1909 plpgsql_error_lineno = plpgsql_scanner_lineno();
1911 (errcode(ERRCODE_SYNTAX_ERROR),
1912 errmsg("INTO specified more than once")));
1930 char *fieldnames[1024];
1933 check_assignable(yylval.scalar);
1934 fieldnames[0] = strdup(yytext);
1935 varnos[0] = yylval.scalar->dno;
1937 while ((tok = yylex()) == ',')
1943 check_assignable(yylval.scalar);
1944 fieldnames[nfields] = strdup(yytext);
1945 varnos[nfields++] = yylval.scalar->dno;
1949 plpgsql_error_lineno = plpgsql_scanner_lineno();
1951 (errcode(ERRCODE_SYNTAX_ERROR),
1952 errmsg("\"%s\" is not a variable",
1958 row = malloc(sizeof(PLpgSQL_row));
1959 row->dtype = PLPGSQL_DTYPE_ROW;
1960 row->refname = strdup("*internal*");
1961 row->lineno = plpgsql_scanner_lineno();
1962 row->rowtupdesc = NULL;
1963 row->nfields = nfields;
1964 row->fieldnames = malloc(sizeof(char *) * nfields);
1965 row->varnos = malloc(sizeof(int) * nfields);
1966 while (--nfields >= 0)
1968 row->fieldnames[nfields] = fieldnames[nfields];
1969 row->varnos[nfields] = varnos[nfields];
1972 plpgsql_adddatum((PLpgSQL_datum *)row);
1979 /* Treat the INTO as non-special */
1980 plpgsql_dstring_append(&ds, " INTO ");
1987 if (plpgsql_SpaceScanned)
1988 plpgsql_dstring_append(&ds, " ");
1992 params[nparams] = yylval.scalar->dno;
1993 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1994 plpgsql_dstring_append(&ds, buf);
1998 params[nparams] = yylval.row->rowno;
1999 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
2000 plpgsql_dstring_append(&ds, buf);
2004 params[nparams] = yylval.rec->recno;
2005 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
2006 plpgsql_dstring_append(&ds, buf);
2010 plpgsql_dstring_append(&ds, yytext);
2015 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
2016 expr->dtype = PLPGSQL_DTYPE_EXPR;
2017 expr->query = strdup(plpgsql_dstring_get(&ds));
2019 expr->nparams = nparams;
2020 while(nparams-- > 0)
2021 expr->params[nparams] = params[nparams];
2022 plpgsql_dstring_free(&ds);
2026 PLpgSQL_stmt_select *select;
2028 select = malloc(sizeof(PLpgSQL_stmt_select));
2029 memset(select, 0, sizeof(PLpgSQL_stmt_select));
2030 select->cmd_type = PLPGSQL_STMT_SELECT;
2033 select->query = expr;
2035 return (PLpgSQL_stmt *)select;
2039 PLpgSQL_stmt_execsql *execsql;
2041 execsql = malloc(sizeof(PLpgSQL_stmt_execsql));
2042 execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
2043 execsql->sqlstmt = expr;
2045 return (PLpgSQL_stmt *)execsql;
2050 static PLpgSQL_stmt *
2051 make_fetch_stmt(void)
2054 PLpgSQL_row *row = NULL;
2055 PLpgSQL_rec *rec = NULL;
2056 PLpgSQL_stmt_fetch *fetch;
2057 int have_nexttok = 0;
2059 /* We have already parsed everything through the INTO keyword */
2075 char *fieldnames[1024];
2078 check_assignable(yylval.scalar);
2079 fieldnames[0] = strdup(yytext);
2080 varnos[0] = yylval.scalar->dno;
2082 while ((tok = yylex()) == ',')
2088 check_assignable(yylval.scalar);
2089 fieldnames[nfields] = strdup(yytext);
2090 varnos[nfields++] = yylval.scalar->dno;
2094 plpgsql_error_lineno = plpgsql_scanner_lineno();
2096 (errcode(ERRCODE_SYNTAX_ERROR),
2097 errmsg("\"%s\" is not a variable",
2103 row = malloc(sizeof(PLpgSQL_row));
2104 row->dtype = PLPGSQL_DTYPE_ROW;
2105 row->refname = strdup("*internal*");
2106 row->lineno = plpgsql_scanner_lineno();
2107 row->rowtupdesc = NULL;
2108 row->nfields = nfields;
2109 row->fieldnames = malloc(sizeof(char *) * nfields);
2110 row->varnos = malloc(sizeof(int) * nfields);
2111 while (--nfields >= 0)
2113 row->fieldnames[nfields] = fieldnames[nfields];
2114 row->varnos[nfields] = varnos[nfields];
2117 plpgsql_adddatum((PLpgSQL_datum *)row);
2122 yyerror("syntax error");
2129 yyerror("syntax error");
2131 fetch = malloc(sizeof(PLpgSQL_stmt_select));
2132 memset(fetch, 0, sizeof(PLpgSQL_stmt_fetch));
2133 fetch->cmd_type = PLPGSQL_STMT_FETCH;
2137 return (PLpgSQL_stmt *)fetch;
2142 check_assignable(PLpgSQL_datum *datum)
2144 switch (datum->dtype)
2146 case PLPGSQL_DTYPE_VAR:
2147 if (((PLpgSQL_var *) datum)->isconst)
2149 plpgsql_error_lineno = plpgsql_scanner_lineno();
2151 (errcode(ERRCODE_ERROR_IN_ASSIGNMENT),
2152 errmsg("\"%s\" is declared CONSTANT",
2153 ((PLpgSQL_var *) datum)->refname)));
2156 case PLPGSQL_DTYPE_ROW:
2157 /* always assignable? */
2159 case PLPGSQL_DTYPE_REC:
2160 /* always assignable? What about NEW/OLD? */
2162 case PLPGSQL_DTYPE_RECFIELD:
2163 /* always assignable? */
2165 case PLPGSQL_DTYPE_ARRAYELEM:
2166 /* always assignable? */
2168 case PLPGSQL_DTYPE_TRIGARG:
2169 yyerror("cannot assign to tg_argv");
2172 elog(ERROR, "unrecognized dtype: %d", datum->dtype);
2177 #include "pl_scan.c"