2 /**********************************************************************
3 * gram.y - Parser for the PL/pgSQL
7 * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.56 2004/06/04 02:37:06 tgl Exp $
9 * This software is copyrighted by Jan Wieck - Hamburg.
11 * The author hereby grants permission to use, copy, modify,
12 * distribute, and license this software and its documentation
13 * for any purpose, provided that existing copyright notices are
14 * retained in all copies and that this notice is included
15 * verbatim in any distributions. No written agreement, license,
16 * or royalty fee is required for any of the authorized uses.
17 * Modifications to this software may be copyrighted by their
18 * author and need not follow the licensing terms described
19 * here, provided that the new terms are clearly indicated on
20 * the first page of each file where they apply.
22 * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
23 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
24 * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
25 * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
26 * IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
29 * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
30 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
32 * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
33 * AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
34 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
35 * ENHANCEMENTS, OR MODIFICATIONS.
37 **********************************************************************/
42 static PLpgSQL_expr *read_sql_construct(int until,
45 const char *sqlstart);
46 static PLpgSQL_expr *read_sql_stmt(const char *sqlstart);
47 static PLpgSQL_type *read_datatype(int tok);
48 static PLpgSQL_stmt *make_select_stmt(void);
49 static PLpgSQL_stmt *make_fetch_stmt(void);
50 static void check_assignable(PLpgSQL_datum *datum);
72 PLpgSQL_diag_item *dtitems;
86 PLpgSQL_datum *scalar; /* a VAR, RECFIELD, or TRIGARG */
87 PLpgSQL_variable *variable; /* a VAR, REC, or ROW */
94 PLpgSQL_stmt_block *program;
95 PLpgSQL_nsitem *nsitem;
98 %type <declhdr> decl_sect
99 %type <varname> decl_varname
100 %type <str> decl_renname
101 %type <ival> decl_const decl_notnull
102 %type <expr> decl_defval decl_cursor_query
103 %type <dtype> decl_datatype
104 %type <row> decl_cursor_args decl_cursor_arglist
105 %type <nsitem> decl_aliasitem
106 %type <str> decl_stmts decl_stmt
108 %type <expr> expr_until_semi expr_until_rightbracket
109 %type <expr> expr_until_then expr_until_loop
110 %type <expr> opt_exitcond
112 %type <ival> assign_var cursor_variable
113 %type <var> fori_var cursor_varptr
114 %type <variable> decl_cursor_arg
115 %type <varname> fori_varname
116 %type <forilow> fori_lower
117 %type <rec> fors_target
119 %type <str> opt_lblname opt_label
120 %type <str> opt_exitlabel
121 %type <str> execsql_start
123 %type <stmts> proc_sect proc_stmts stmt_else loop_body
124 %type <stmt> proc_stmt pl_block
125 %type <stmt> stmt_assign stmt_if stmt_loop stmt_while stmt_exit
126 %type <stmt> stmt_return stmt_return_next stmt_raise stmt_execsql
127 %type <stmt> stmt_fori stmt_fors stmt_select stmt_perform
128 %type <stmt> stmt_dynexecute stmt_dynfors stmt_getdiag
129 %type <stmt> stmt_open stmt_fetch stmt_close
131 %type <intlist> raise_params
132 %type <ival> raise_level raise_param
133 %type <str> raise_msg
135 %type <dtlist> getdiag_list
136 %type <ival> getdiag_item getdiag_target
199 %token T_SCALAR /* a VAR, RECFIELD, or TRIGARG */
212 pl_function : T_FUNCTION comp_optsect pl_block opt_semi
214 yylval.program = (PLpgSQL_stmt_block *)$3;
216 | T_TRIGGER comp_optsect pl_block opt_semi
218 yylval.program = (PLpgSQL_stmt_block *)$3;
226 comp_options : comp_options comp_option
230 comp_option : O_OPTION O_DUMP
232 plpgsql_DumpExecTree = 1;
240 pl_block : decl_sect K_BEGIN lno proc_sect K_END
242 PLpgSQL_stmt_block *new;
244 new = malloc(sizeof(PLpgSQL_stmt_block));
245 memset(new, 0, sizeof(PLpgSQL_stmt_block));
247 new->cmd_type = PLPGSQL_STMT_BLOCK;
249 new->label = $1.label;
250 new->n_initvars = $1.n_initvars;
251 new->initvarnos = $1.initvarnos;
256 $$ = (PLpgSQL_stmt *)new;
261 decl_sect : opt_label
263 plpgsql_ns_setlocal(false);
266 $$.initvarnos = NULL;
267 plpgsql_add_initdatums(NULL);
269 | opt_label decl_start
271 plpgsql_ns_setlocal(false);
274 $$.initvarnos = NULL;
275 plpgsql_add_initdatums(NULL);
277 | opt_label decl_start decl_stmts
279 plpgsql_ns_setlocal(false);
284 $$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos));
288 decl_start : K_DECLARE
290 plpgsql_ns_setlocal(true);
294 decl_stmts : decl_stmts decl_stmt
300 decl_stmt : '<' '<' opt_lblname '>' '>'
308 decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
310 PLpgSQL_variable *var;
312 var = plpgsql_build_variable($1.name, $1.lineno,
316 if (var->dtype == PLPGSQL_DTYPE_VAR)
317 ((PLpgSQL_var *) var)->isconst = $2;
320 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
321 errmsg("row or record variable cannot be CONSTANT")));
325 if (var->dtype == PLPGSQL_DTYPE_VAR)
326 ((PLpgSQL_var *) var)->notnull = $4;
329 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
330 errmsg("row or record variable cannot be NOT NULL")));
334 if (var->dtype == PLPGSQL_DTYPE_VAR)
335 ((PLpgSQL_var *) var)->default_val = $5;
338 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
339 errmsg("default value for row or record variable is not supported")));
342 | decl_varname K_ALIAS K_FOR decl_aliasitem ';'
344 plpgsql_ns_additem($4->itemtype,
345 $4->itemno, $1.name);
347 | K_RENAME decl_renname K_TO decl_renname ';'
349 plpgsql_ns_rename($2, $4);
351 | decl_varname K_CURSOR
352 { plpgsql_ns_push(NULL); }
353 decl_cursor_args decl_is_from decl_cursor_query
356 PLpgSQL_expr *curname_def;
361 /* pop local namespace for cursor args */
364 new = (PLpgSQL_var *)
365 plpgsql_build_variable($1.name, $1.lineno,
366 plpgsql_build_datatype(REFCURSOROID,
370 curname_def = malloc(sizeof(PLpgSQL_expr));
371 memset(curname_def, 0, sizeof(PLpgSQL_expr));
373 curname_def->dtype = PLPGSQL_DTYPE_EXPR;
374 strcpy(buf, "SELECT '");
376 cp2 = buf + strlen(buf);
379 if (*cp1 == '\\' || *cp1 == '\'')
383 strcpy(cp2, "'::refcursor");
384 curname_def->query = strdup(buf);
385 new->default_val = curname_def;
387 new->cursor_explicit_expr = $6;
389 new->cursor_explicit_argrow = -1;
391 new->cursor_explicit_argrow = $4->rowno;
399 plpgsql_ns_setlocal(false);
400 query = read_sql_stmt("");
401 plpgsql_ns_setlocal(true);
411 | '(' decl_cursor_arglist ')'
413 /* Copy the temp arrays to malloc'd storage */
414 int nfields = $2->nfields;
418 ftmp = malloc(nfields * sizeof(char *));
419 vtmp = malloc(nfields * sizeof(int));
420 memcpy(ftmp, $2->fieldnames, nfields * sizeof(char *));
421 memcpy(vtmp, $2->varnos, nfields * sizeof(int));
423 pfree((char *)($2->fieldnames));
424 pfree((char *)($2->varnos));
426 $2->fieldnames = ftmp;
429 plpgsql_adddatum((PLpgSQL_datum *)$2);
435 decl_cursor_arglist : decl_cursor_arg
439 new = malloc(sizeof(PLpgSQL_row));
440 memset(new, 0, sizeof(PLpgSQL_row));
442 new->dtype = PLPGSQL_DTYPE_ROW;
443 new->refname = strdup("*internal*");
444 new->lineno = plpgsql_scanner_lineno();
445 new->rowtupdesc = NULL;
447 * We make temporary fieldnames/varnos arrays that
448 * are much bigger than necessary. We will resize
449 * them to just the needed size in the
450 * decl_cursor_args production.
452 new->fieldnames = palloc(1024 * sizeof(char *));
453 new->varnos = palloc(1024 * sizeof(int));
456 new->fieldnames[0] = $1->refname;
457 new->varnos[0] = $1->dno;
461 | decl_cursor_arglist ',' decl_cursor_arg
463 int i = $1->nfields++;
465 $1->fieldnames[i] = $3->refname;
466 $1->varnos[i] = $3->dno;
472 decl_cursor_arg : decl_varname decl_datatype
474 $$ = plpgsql_build_variable($1.name, $1.lineno,
479 decl_is_from : K_IS | /* Oracle */
482 decl_aliasitem : T_WORD
487 plpgsql_convert_ident(yytext, &name, 1);
489 yyerror("only positional parameters may be aliased");
491 plpgsql_ns_setlocal(false);
492 nsi = plpgsql_ns_lookup(name, NULL);
495 plpgsql_error_lineno = plpgsql_scanner_lineno();
497 (errcode(ERRCODE_UNDEFINED_PARAMETER),
498 errmsg("function has no parameter \"%s\"",
502 plpgsql_ns_setlocal(true);
510 decl_varname : T_WORD
514 plpgsql_convert_ident(yytext, &name, 1);
515 /* name should be malloc'd for use as varname */
516 $$.name = strdup(name);
517 $$.lineno = plpgsql_scanner_lineno();
522 decl_renname : T_WORD
526 plpgsql_convert_ident(yytext, &name, 1);
527 /* the result must be palloc'd, see plpgsql_ns_rename */
541 * If there's a lookahead token, read_datatype
544 $$ = read_datatype(yychar);
559 plpgsql_ns_setlocal(false);
560 $$ = plpgsql_read_expression(';', ";");
561 plpgsql_ns_setlocal(true);
565 decl_defkey : K_ASSIGN
573 new = malloc(sizeof(PLpgSQL_stmts));
574 memset(new, 0, sizeof(PLpgSQL_stmts));
581 proc_stmts : proc_stmts proc_stmt
583 if ($1->stmts_used == $1->stmts_alloc)
585 $1->stmts_alloc *= 2;
586 $1->stmts = realloc($1->stmts, sizeof(PLpgSQL_stmt *) * $1->stmts_alloc);
588 $1->stmts[$1->stmts_used++] = (struct PLpgSQL_stmt *)$2;
596 new = malloc(sizeof(PLpgSQL_stmts));
597 memset(new, 0, sizeof(PLpgSQL_stmts));
599 new->stmts_alloc = 64;
601 new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
602 new->stmts[0] = (struct PLpgSQL_stmt *)$1;
609 proc_stmt : pl_block ';'
651 stmt_perform : K_PERFORM lno expr_until_semi
653 PLpgSQL_stmt_perform *new;
655 new = malloc(sizeof(PLpgSQL_stmt_perform));
656 memset(new, 0, sizeof(PLpgSQL_stmt_perform));
658 new->cmd_type = PLPGSQL_STMT_PERFORM;
662 $$ = (PLpgSQL_stmt *)new;
666 stmt_assign : assign_var lno K_ASSIGN expr_until_semi
668 PLpgSQL_stmt_assign *new;
670 new = malloc(sizeof(PLpgSQL_stmt_assign));
671 memset(new, 0, sizeof(PLpgSQL_stmt_assign));
673 new->cmd_type = PLPGSQL_STMT_ASSIGN;
678 $$ = (PLpgSQL_stmt *)new;
682 stmt_getdiag : K_GET K_DIAGNOSTICS lno getdiag_list ';'
684 PLpgSQL_stmt_getdiag *new;
686 new = malloc(sizeof(PLpgSQL_stmt_getdiag));
687 memset(new, 0, sizeof(PLpgSQL_stmt_getdiag));
689 new->cmd_type = PLPGSQL_STMT_GETDIAG;
691 new->ndtitems = $4.nused;
692 new->dtitems = malloc(sizeof(PLpgSQL_diag_item) * $4.nused);
693 memcpy(new->dtitems, $4.dtitems, sizeof(PLpgSQL_diag_item) * $4.nused);
695 $$ = (PLpgSQL_stmt *)new;
699 getdiag_list : getdiag_list ',' getdiag_target K_ASSIGN getdiag_item
701 if ($1.nused == $1.nalloc)
704 $1.dtitems = repalloc($1.dtitems, sizeof(PLpgSQL_diag_item) * $1.nalloc);
706 $1.dtitems[$1.nused].target = $3;
707 $1.dtitems[$1.nused].item = $5;
710 $$.nalloc = $1.nalloc;
712 $$.dtitems = $1.dtitems;
714 | getdiag_target K_ASSIGN getdiag_item
718 $$.dtitems = palloc(sizeof(PLpgSQL_diag_item) * $$.nalloc);
719 $$.dtitems[0].target = $1;
720 $$.dtitems[0].item = $3;
724 getdiag_item : K_ROW_COUNT
726 $$ = PLPGSQL_GETDIAG_ROW_COUNT;
730 $$ = PLPGSQL_GETDIAG_RESULT_OID;
734 getdiag_target : T_SCALAR
736 check_assignable(yylval.scalar);
737 $$ = yylval.scalar->dno;
742 assign_var : T_SCALAR
744 check_assignable(yylval.scalar);
745 $$ = yylval.scalar->dno;
749 check_assignable((PLpgSQL_datum *) yylval.row);
750 $$ = yylval.row->rowno;
754 check_assignable((PLpgSQL_datum *) yylval.rec);
755 $$ = yylval.rec->recno;
757 | assign_var '[' expr_until_rightbracket
759 PLpgSQL_arrayelem *new;
761 new = malloc(sizeof(PLpgSQL_arrayelem));
762 memset(new, 0, sizeof(PLpgSQL_arrayelem));
764 new->dtype = PLPGSQL_DTYPE_ARRAYELEM;
766 new->arrayparentno = $1;
768 plpgsql_adddatum((PLpgSQL_datum *)new);
774 stmt_if : K_IF lno expr_until_then proc_sect stmt_else K_END K_IF ';'
776 PLpgSQL_stmt_if *new;
778 new = malloc(sizeof(PLpgSQL_stmt_if));
779 memset(new, 0, sizeof(PLpgSQL_stmt_if));
781 new->cmd_type = PLPGSQL_STMT_IF;
785 new->false_body = $5;
787 $$ = (PLpgSQL_stmt *)new;
795 new = malloc(sizeof(PLpgSQL_stmts));
796 memset(new, 0, sizeof(PLpgSQL_stmts));
799 | K_ELSIF lno expr_until_then proc_sect stmt_else
802 * Translate the structure: into:
804 * IF c1 THEN IF c1 THEN
817 PLpgSQL_stmt_if *new_if;
819 /* first create a new if-statement */
820 new_if = malloc(sizeof(PLpgSQL_stmt_if));
821 memset(new_if, 0, sizeof(PLpgSQL_stmt_if));
823 new_if->cmd_type = PLPGSQL_STMT_IF;
826 new_if->true_body = $4;
827 new_if->false_body = $5;
829 /* this is a 'container' for the if-statement */
830 new = malloc(sizeof(PLpgSQL_stmts));
831 memset(new, 0, sizeof(PLpgSQL_stmts));
833 new->stmts_alloc = 64;
835 new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
836 new->stmts[0] = (struct PLpgSQL_stmt *)new_if;
848 stmt_loop : opt_label K_LOOP lno loop_body
850 PLpgSQL_stmt_loop *new;
852 new = malloc(sizeof(PLpgSQL_stmt_loop));
853 memset(new, 0, sizeof(PLpgSQL_stmt_loop));
855 new->cmd_type = PLPGSQL_STMT_LOOP;
862 $$ = (PLpgSQL_stmt *)new;
866 stmt_while : opt_label K_WHILE lno expr_until_loop loop_body
868 PLpgSQL_stmt_while *new;
870 new = malloc(sizeof(PLpgSQL_stmt_while));
871 memset(new, 0, sizeof(PLpgSQL_stmt_while));
873 new->cmd_type = PLPGSQL_STMT_WHILE;
881 $$ = (PLpgSQL_stmt *)new;
885 stmt_fori : opt_label K_FOR lno fori_var K_IN fori_lower expr_until_loop loop_body
887 PLpgSQL_stmt_fori *new;
889 new = malloc(sizeof(PLpgSQL_stmt_fori));
890 memset(new, 0, sizeof(PLpgSQL_stmt_fori));
892 new->cmd_type = PLPGSQL_STMT_FORI;
896 new->reverse = $6.reverse;
897 new->lower = $6.expr;
903 $$ = (PLpgSQL_stmt *)new;
907 fori_var : fori_varname
911 new = (PLpgSQL_var *)
912 plpgsql_build_variable($1.name, $1.lineno,
913 plpgsql_build_datatype(INT4OID,
917 plpgsql_add_initdatums(NULL);
923 fori_varname : T_SCALAR
927 plpgsql_convert_ident(yytext, &name, 1);
928 /* name should be malloc'd for use as varname */
929 $$.name = strdup(name);
930 $$.lineno = plpgsql_scanner_lineno();
937 plpgsql_convert_ident(yytext, &name, 1);
938 /* name should be malloc'd for use as varname */
939 $$.name = strdup(name);
940 $$.lineno = plpgsql_scanner_lineno();
950 if (tok == K_REVERSE)
957 plpgsql_push_back_token(tok);
960 $$.expr = plpgsql_read_expression(K_DOTDOT, "..");
964 stmt_fors : opt_label K_FOR lno fors_target K_IN K_SELECT expr_until_loop loop_body
966 PLpgSQL_stmt_fors *new;
968 new = malloc(sizeof(PLpgSQL_stmt_fors));
969 memset(new, 0, sizeof(PLpgSQL_stmt_fors));
971 new->cmd_type = PLPGSQL_STMT_FORS;
976 case PLPGSQL_DTYPE_REC:
979 case PLPGSQL_DTYPE_ROW:
980 new->row = (PLpgSQL_row *)$4;
983 elog(ERROR, "unrecognized dtype: %d",
991 $$ = (PLpgSQL_stmt *)new;
995 stmt_dynfors : opt_label K_FOR lno fors_target K_IN K_EXECUTE expr_until_loop loop_body
997 PLpgSQL_stmt_dynfors *new;
999 new = malloc(sizeof(PLpgSQL_stmt_dynfors));
1000 memset(new, 0, sizeof(PLpgSQL_stmt_dynfors));
1002 new->cmd_type = PLPGSQL_STMT_DYNFORS;
1007 case PLPGSQL_DTYPE_REC:
1010 case PLPGSQL_DTYPE_ROW:
1011 new->row = (PLpgSQL_row *)$4;
1014 elog(ERROR, "unrecognized dtype: %d",
1022 $$ = (PLpgSQL_stmt *)new;
1026 fors_target : T_RECORD
1027 { $$ = yylval.rec; }
1030 $$ = (PLpgSQL_rec *)(yylval.row);
1034 stmt_select : K_SELECT lno
1036 $$ = make_select_stmt();
1041 stmt_exit : K_EXIT lno opt_exitlabel opt_exitcond
1043 PLpgSQL_stmt_exit *new;
1045 new = malloc(sizeof(PLpgSQL_stmt_exit));
1046 memset(new, 0, sizeof(PLpgSQL_stmt_exit));
1048 new->cmd_type = PLPGSQL_STMT_EXIT;
1053 $$ = (PLpgSQL_stmt *)new;
1057 stmt_return : K_RETURN lno
1059 PLpgSQL_stmt_return *new;
1061 new = malloc(sizeof(PLpgSQL_stmt_return));
1062 memset(new, 0, sizeof(PLpgSQL_stmt_return));
1067 if (plpgsql_curr_compile->fn_retset)
1070 yyerror("RETURN cannot have a parameter in function returning set; use RETURN NEXT");
1072 else if (plpgsql_curr_compile->fn_retistuple)
1080 new->retrowno = yylval.row->rowno;
1084 new->retrecno = yylval.rec->recno;
1088 yyerror("RETURN must specify a record or row variable in function returning tuple");
1092 yyerror("RETURN must specify a record or row variable in function returning tuple");
1096 /* ordinary expression case */
1097 new->expr = plpgsql_read_expression(';', ";");
1100 new->cmd_type = PLPGSQL_STMT_RETURN;
1103 $$ = (PLpgSQL_stmt *)new;
1107 stmt_return_next: K_RETURN_NEXT lno
1109 PLpgSQL_stmt_return_next *new;
1111 if (!plpgsql_curr_compile->fn_retset)
1112 yyerror("cannot use RETURN NEXT in a non-SETOF function");
1114 new = malloc(sizeof(PLpgSQL_stmt_return_next));
1115 memset(new, 0, sizeof(PLpgSQL_stmt_return_next));
1117 new->cmd_type = PLPGSQL_STMT_RETURN_NEXT;
1120 if (plpgsql_curr_compile->fn_retistuple)
1124 if (tok == T_RECORD)
1125 new->rec = yylval.rec;
1126 else if (tok == T_ROW)
1127 new->row = yylval.row;
1129 yyerror("RETURN NEXT must specify a record or row variable in function returning tuple");
1132 yyerror("RETURN NEXT must specify a record or row variable in function returning tuple");
1135 new->expr = plpgsql_read_expression(';', ";");
1137 $$ = (PLpgSQL_stmt *)new;
1141 stmt_raise : K_RAISE lno raise_level raise_msg raise_params ';'
1143 PLpgSQL_stmt_raise *new;
1145 new = malloc(sizeof(PLpgSQL_stmt_raise));
1147 new->cmd_type = PLPGSQL_STMT_RAISE;
1149 new->elog_level = $3;
1151 new->nparams = $5.nused;
1152 new->params = malloc(sizeof(int) * $5.nused);
1153 memcpy(new->params, $5.nums, sizeof(int) * $5.nused);
1155 $$ = (PLpgSQL_stmt *)new;
1157 | K_RAISE lno raise_level raise_msg ';'
1159 PLpgSQL_stmt_raise *new;
1161 new = malloc(sizeof(PLpgSQL_stmt_raise));
1163 new->cmd_type = PLPGSQL_STMT_RAISE;
1165 new->elog_level = $3;
1170 $$ = (PLpgSQL_stmt *)new;
1174 raise_msg : T_STRING
1176 $$ = plpgsql_get_string_value();
1180 raise_level : K_EXCEPTION
1206 raise_params : raise_params raise_param
1208 if ($1.nused == $1.nalloc)
1211 $1.nums = repalloc($1.nums, sizeof(int) * $1.nalloc);
1213 $1.nums[$1.nused++] = $2;
1215 $$.nalloc = $1.nalloc;
1216 $$.nused = $1.nused;
1223 $$.nums = palloc(sizeof(int) * $$.nalloc);
1228 raise_param : ',' T_SCALAR
1230 $$ = yylval.scalar->dno;
1234 loop_body : proc_sect K_END K_LOOP ';'
1238 stmt_execsql : execsql_start lno
1240 PLpgSQL_stmt_execsql *new;
1242 new = malloc(sizeof(PLpgSQL_stmt_execsql));
1243 new->cmd_type = PLPGSQL_STMT_EXECSQL;
1245 new->sqlstmt = read_sql_stmt($1);
1247 $$ = (PLpgSQL_stmt *)new;
1251 stmt_dynexecute : K_EXECUTE lno expr_until_semi
1253 PLpgSQL_stmt_dynexecute *new;
1255 new = malloc(sizeof(PLpgSQL_stmt_dynexecute));
1256 new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
1260 $$ = (PLpgSQL_stmt *)new;
1264 stmt_open : K_OPEN lno cursor_varptr
1266 PLpgSQL_stmt_open *new;
1269 new = malloc(sizeof(PLpgSQL_stmt_open));
1270 memset(new, 0, sizeof(PLpgSQL_stmt_open));
1272 new->cmd_type = PLPGSQL_STMT_OPEN;
1274 new->curvar = $3->varno;
1276 if ($3->cursor_explicit_expr == NULL)
1282 plpgsql_error_lineno = $2;
1284 (errcode(ERRCODE_SYNTAX_ERROR),
1285 errmsg("syntax error at \"%s\"",
1287 errdetail("Expected FOR to open a reference cursor.")));
1295 plpgsql_push_back_token(tok);
1296 new->query = read_sql_stmt("");
1300 new->dynquery = read_sql_stmt("SELECT ");
1304 plpgsql_error_lineno = $2;
1306 (errcode(ERRCODE_SYNTAX_ERROR),
1307 errmsg("syntax error at \"%s\"",
1314 if ($3->cursor_explicit_argrow >= 0)
1322 plpgsql_error_lineno = plpgsql_scanner_lineno();
1324 (errcode(ERRCODE_SYNTAX_ERROR),
1325 errmsg("cursor \"%s\" has arguments",
1330 * Push back the '(', else read_sql_stmt
1331 * will complain about unbalanced parens.
1333 plpgsql_push_back_token(tok);
1335 new->argquery = read_sql_stmt("SELECT ");
1338 * Now remove the leading and trailing parens,
1339 * because we want "select 1, 2", not
1342 cp = new->argquery->query;
1344 if (strncmp(cp, "SELECT", 6) != 0)
1346 plpgsql_error_lineno = plpgsql_scanner_lineno();
1347 /* internal error */
1348 elog(ERROR, "expected \"SELECT (\", got \"%s\"",
1349 new->argquery->query);
1352 while (*cp == ' ') /* could be more than 1 space here */
1356 plpgsql_error_lineno = plpgsql_scanner_lineno();
1357 /* internal error */
1358 elog(ERROR, "expected \"SELECT (\", got \"%s\"",
1359 new->argquery->query);
1363 cp += strlen(cp) - 1;
1366 yyerror("expected \")\"");
1375 plpgsql_error_lineno = plpgsql_scanner_lineno();
1377 (errcode(ERRCODE_SYNTAX_ERROR),
1378 errmsg("cursor \"%s\" has no arguments",
1384 plpgsql_error_lineno = plpgsql_scanner_lineno();
1386 (errcode(ERRCODE_SYNTAX_ERROR),
1387 errmsg("syntax error at \"%s\"",
1393 $$ = (PLpgSQL_stmt *)new;
1397 stmt_fetch : K_FETCH lno cursor_variable K_INTO
1399 PLpgSQL_stmt_fetch *new;
1401 new = (PLpgSQL_stmt_fetch *)make_fetch_stmt();
1404 $$ = (PLpgSQL_stmt *)new;
1409 stmt_close : K_CLOSE lno cursor_variable ';'
1411 PLpgSQL_stmt_close *new;
1413 new = malloc(sizeof(PLpgSQL_stmt_close));
1414 new->cmd_type = PLPGSQL_STMT_CLOSE;
1418 $$ = (PLpgSQL_stmt *)new;
1422 cursor_varptr : T_SCALAR
1424 if (yylval.scalar->dtype != PLPGSQL_DTYPE_VAR)
1425 yyerror("cursor variable must be a simple variable");
1427 if (((PLpgSQL_var *) yylval.scalar)->datatype->typoid != REFCURSOROID)
1429 plpgsql_error_lineno = plpgsql_scanner_lineno();
1431 (errcode(ERRCODE_DATATYPE_MISMATCH),
1432 errmsg("\"%s\" must be of type cursor or refcursor",
1433 ((PLpgSQL_var *) yylval.scalar)->refname)));
1435 $$ = (PLpgSQL_var *) yylval.scalar;
1439 cursor_variable : T_SCALAR
1441 if (yylval.scalar->dtype != PLPGSQL_DTYPE_VAR)
1442 yyerror("cursor variable must be a simple variable");
1444 if (((PLpgSQL_var *) yylval.scalar)->datatype->typoid != REFCURSOROID)
1446 plpgsql_error_lineno = plpgsql_scanner_lineno();
1448 (errcode(ERRCODE_DATATYPE_MISMATCH),
1449 errmsg("\"%s\" must be of type refcursor",
1450 ((PLpgSQL_var *) yylval.scalar)->refname)));
1452 $$ = yylval.scalar->dno;
1456 execsql_start : T_WORD
1457 { $$ = strdup(yytext); }
1459 { $$ = strdup(yytext); }
1463 { $$ = plpgsql_read_expression(';', ";"); }
1466 expr_until_rightbracket :
1467 { $$ = plpgsql_read_expression(']', "]"); }
1471 { $$ = plpgsql_read_expression(K_THEN, "THEN"); }
1475 { $$ = plpgsql_read_expression(K_LOOP, "LOOP"); }
1480 plpgsql_ns_push(NULL);
1483 | '<' '<' opt_lblname '>' '>'
1485 plpgsql_ns_push($3);
1493 { $$ = strdup(yytext); }
1498 | K_WHEN expr_until_semi
1502 opt_lblname : T_WORD
1506 plpgsql_convert_ident(yytext, &name, 1);
1514 $$ = plpgsql_error_lineno = plpgsql_scanner_lineno();
1522 plpgsql_read_expression(int until, const char *expected)
1524 return read_sql_construct(until, expected, true, "SELECT ");
1527 static PLpgSQL_expr *
1528 read_sql_stmt(const char *sqlstart)
1530 return read_sql_construct(';', ";", false, sqlstart);
1533 static PLpgSQL_expr *
1534 read_sql_construct(int until,
1535 const char *expected,
1537 const char *sqlstart)
1548 lno = plpgsql_scanner_lineno();
1549 plpgsql_dstring_init(&ds);
1550 plpgsql_dstring_append(&ds, (char *) sqlstart);
1555 if (tok == until && parenlevel == 0)
1557 if (tok == '(' || tok == '[')
1559 else if (tok == ')' || tok == ']')
1564 (errcode(ERRCODE_SYNTAX_ERROR),
1565 errmsg("mismatched parentheses")));
1568 * End of function definition is an error, and we don't expect to
1569 * hit a semicolon either (unless it's the until symbol, in which
1570 * case we should have fallen out above).
1572 if (tok == 0 || tok == ';')
1574 plpgsql_error_lineno = lno;
1575 if (parenlevel != 0)
1577 (errcode(ERRCODE_SYNTAX_ERROR),
1578 errmsg("mismatched parentheses")));
1581 (errcode(ERRCODE_SYNTAX_ERROR),
1582 errmsg("missing \"%s\" at end of SQL expression",
1586 (errcode(ERRCODE_SYNTAX_ERROR),
1587 errmsg("missing \"%s\" at end of SQL statement",
1591 if (plpgsql_SpaceScanned)
1592 plpgsql_dstring_append(&ds, " ");
1596 params[nparams] = yylval.scalar->dno;
1597 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1598 plpgsql_dstring_append(&ds, buf);
1602 params[nparams] = yylval.row->rowno;
1603 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1604 plpgsql_dstring_append(&ds, buf);
1608 params[nparams] = yylval.rec->recno;
1609 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1610 plpgsql_dstring_append(&ds, buf);
1614 plpgsql_dstring_append(&ds, yytext);
1619 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
1620 expr->dtype = PLPGSQL_DTYPE_EXPR;
1621 expr->query = strdup(plpgsql_dstring_get(&ds));
1623 expr->nparams = nparams;
1624 while(nparams-- > 0)
1625 expr->params[nparams] = params[nparams];
1626 plpgsql_dstring_free(&ds);
1631 static PLpgSQL_type *
1632 read_datatype(int tok)
1636 PLpgSQL_type *result;
1637 bool needspace = false;
1640 lno = plpgsql_scanner_lineno();
1642 /* Often there will be a lookahead token, but if not, get one */
1648 /* lexer found word%TYPE and did its thing already */
1649 return yylval.dtype;
1652 plpgsql_dstring_init(&ds);
1658 plpgsql_error_lineno = lno;
1659 if (parenlevel != 0)
1661 (errcode(ERRCODE_SYNTAX_ERROR),
1662 errmsg("mismatched parentheses")));
1664 (errcode(ERRCODE_SYNTAX_ERROR),
1665 errmsg("incomplete datatype declaration")));
1667 /* Possible followers for datatype in a declaration */
1668 if (tok == K_NOT || tok == K_ASSIGN || tok == K_DEFAULT)
1670 /* Possible followers for datatype in a cursor_arg list */
1671 if ((tok == ',' || tok == ')') && parenlevel == 0)
1675 else if (tok == ')')
1678 plpgsql_dstring_append(&ds, " ");
1680 plpgsql_dstring_append(&ds, yytext);
1685 plpgsql_push_back_token(tok);
1687 plpgsql_error_lineno = lno; /* in case of error in parse_datatype */
1689 result = plpgsql_parse_datatype(plpgsql_dstring_get(&ds));
1691 plpgsql_dstring_free(&ds);
1697 static PLpgSQL_stmt *
1698 make_select_stmt(void)
1705 PLpgSQL_row *row = NULL;
1706 PLpgSQL_rec *rec = NULL;
1708 int have_nexttok = 0;
1711 plpgsql_dstring_init(&ds);
1712 plpgsql_dstring_append(&ds, "SELECT ");
1723 plpgsql_error_lineno = plpgsql_scanner_lineno();
1725 (errcode(ERRCODE_SYNTAX_ERROR),
1726 errmsg("unexpected end of function definition")));
1732 plpgsql_error_lineno = plpgsql_scanner_lineno();
1734 (errcode(ERRCODE_SYNTAX_ERROR),
1735 errmsg("INTO specified more than once")));
1753 char *fieldnames[1024];
1756 check_assignable(yylval.scalar);
1757 fieldnames[0] = strdup(yytext);
1758 varnos[0] = yylval.scalar->dno;
1760 while ((tok = yylex()) == ',')
1766 check_assignable(yylval.scalar);
1767 fieldnames[nfields] = strdup(yytext);
1768 varnos[nfields++] = yylval.scalar->dno;
1772 plpgsql_error_lineno = plpgsql_scanner_lineno();
1774 (errcode(ERRCODE_SYNTAX_ERROR),
1775 errmsg("\"%s\" is not a variable",
1781 row = malloc(sizeof(PLpgSQL_row));
1782 row->dtype = PLPGSQL_DTYPE_ROW;
1783 row->refname = strdup("*internal*");
1784 row->lineno = plpgsql_scanner_lineno();
1785 row->rowtupdesc = NULL;
1786 row->nfields = nfields;
1787 row->fieldnames = malloc(sizeof(char *) * nfields);
1788 row->varnos = malloc(sizeof(int) * nfields);
1789 while (--nfields >= 0)
1791 row->fieldnames[nfields] = fieldnames[nfields];
1792 row->varnos[nfields] = varnos[nfields];
1795 plpgsql_adddatum((PLpgSQL_datum *)row);
1802 /* Treat the INTO as non-special */
1803 plpgsql_dstring_append(&ds, " INTO ");
1810 if (plpgsql_SpaceScanned)
1811 plpgsql_dstring_append(&ds, " ");
1815 params[nparams] = yylval.scalar->dno;
1816 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1817 plpgsql_dstring_append(&ds, buf);
1821 params[nparams] = yylval.row->rowno;
1822 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1823 plpgsql_dstring_append(&ds, buf);
1827 params[nparams] = yylval.rec->recno;
1828 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1829 plpgsql_dstring_append(&ds, buf);
1833 plpgsql_dstring_append(&ds, yytext);
1838 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
1839 expr->dtype = PLPGSQL_DTYPE_EXPR;
1840 expr->query = strdup(plpgsql_dstring_get(&ds));
1842 expr->nparams = nparams;
1843 while(nparams-- > 0)
1844 expr->params[nparams] = params[nparams];
1845 plpgsql_dstring_free(&ds);
1849 PLpgSQL_stmt_select *select;
1851 select = malloc(sizeof(PLpgSQL_stmt_select));
1852 memset(select, 0, sizeof(PLpgSQL_stmt_select));
1853 select->cmd_type = PLPGSQL_STMT_SELECT;
1856 select->query = expr;
1858 return (PLpgSQL_stmt *)select;
1862 PLpgSQL_stmt_execsql *execsql;
1864 execsql = malloc(sizeof(PLpgSQL_stmt_execsql));
1865 execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
1866 execsql->sqlstmt = expr;
1868 return (PLpgSQL_stmt *)execsql;
1873 static PLpgSQL_stmt *
1874 make_fetch_stmt(void)
1877 PLpgSQL_row *row = NULL;
1878 PLpgSQL_rec *rec = NULL;
1879 PLpgSQL_stmt_fetch *fetch;
1880 int have_nexttok = 0;
1882 /* We have already parsed everything through the INTO keyword */
1898 char *fieldnames[1024];
1901 check_assignable(yylval.scalar);
1902 fieldnames[0] = strdup(yytext);
1903 varnos[0] = yylval.scalar->dno;
1905 while ((tok = yylex()) == ',')
1911 check_assignable(yylval.scalar);
1912 fieldnames[nfields] = strdup(yytext);
1913 varnos[nfields++] = yylval.scalar->dno;
1917 plpgsql_error_lineno = plpgsql_scanner_lineno();
1919 (errcode(ERRCODE_SYNTAX_ERROR),
1920 errmsg("\"%s\" is not a variable",
1926 row = malloc(sizeof(PLpgSQL_row));
1927 row->dtype = PLPGSQL_DTYPE_ROW;
1928 row->refname = strdup("*internal*");
1929 row->lineno = plpgsql_scanner_lineno();
1930 row->rowtupdesc = NULL;
1931 row->nfields = nfields;
1932 row->fieldnames = malloc(sizeof(char *) * nfields);
1933 row->varnos = malloc(sizeof(int) * nfields);
1934 while (--nfields >= 0)
1936 row->fieldnames[nfields] = fieldnames[nfields];
1937 row->varnos[nfields] = varnos[nfields];
1940 plpgsql_adddatum((PLpgSQL_datum *)row);
1945 yyerror("syntax error");
1952 yyerror("syntax error");
1954 fetch = malloc(sizeof(PLpgSQL_stmt_select));
1955 memset(fetch, 0, sizeof(PLpgSQL_stmt_fetch));
1956 fetch->cmd_type = PLPGSQL_STMT_FETCH;
1960 return (PLpgSQL_stmt *)fetch;
1965 check_assignable(PLpgSQL_datum *datum)
1967 switch (datum->dtype)
1969 case PLPGSQL_DTYPE_VAR:
1970 if (((PLpgSQL_var *) datum)->isconst)
1972 plpgsql_error_lineno = plpgsql_scanner_lineno();
1974 (errcode(ERRCODE_ERROR_IN_ASSIGNMENT),
1975 errmsg("\"%s\" is declared CONSTANT",
1976 ((PLpgSQL_var *) datum)->refname)));
1979 case PLPGSQL_DTYPE_ROW:
1980 /* always assignable? */
1982 case PLPGSQL_DTYPE_REC:
1983 /* always assignable? What about NEW/OLD? */
1985 case PLPGSQL_DTYPE_RECFIELD:
1986 /* always assignable? */
1988 case PLPGSQL_DTYPE_ARRAYELEM:
1989 /* always assignable? */
1991 case PLPGSQL_DTYPE_TRIGARG:
1992 yyerror("cannot assign to tg_argv");
1995 elog(ERROR, "unrecognized dtype: %d", datum->dtype);
2000 #include "pl_scan.c"