2 /**********************************************************************
3 * gram.y - Parser for the PL/pgSQL
7 * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.14 2001/02/10 22:42:01 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 **********************************************************************/
43 #include "pl_scan.c" /* GNU bison wants it here */
48 static PLpgSQL_expr *read_sqlstmt(int until, char *s, char *sqlstart);
49 static PLpgSQL_stmt *make_select_stmt(void);
50 static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
79 PLpgSQL_recfield *recfield;
80 PLpgSQL_trigarg *trigarg;
84 PLpgSQL_stmt_block *program;
85 PLpgSQL_nsitem *nsitem;
88 %type <declhdr> decl_sect
89 %type <varname> decl_varname
90 %type <str> decl_renname
91 %type <ival> decl_const, decl_notnull, decl_atttypmod, decl_atttypmodval
92 %type <expr> decl_defval
93 %type <dtype> decl_datatype, decl_dtypename
94 %type <row> decl_rowtype
95 %type <nsitem> decl_aliasitem
96 %type <str> decl_stmts, decl_stmt
98 %type <expr> expr_until_semi, expr_until_then, expr_until_loop
99 %type <expr> opt_exitcond
101 %type <ival> assign_var
103 %type <varname> fori_varname
104 %type <forilow> fori_lower
105 %type <rec> fors_target
107 %type <str> opt_lblname, opt_label
108 %type <str> opt_exitlabel
109 %type <str> execsql_start
111 %type <stmts> proc_sect, proc_stmts, stmt_else, loop_body
112 %type <stmt> proc_stmt, pl_block
113 %type <stmt> stmt_assign, stmt_if, stmt_loop, stmt_while, stmt_exit
114 %type <stmt> stmt_return, stmt_raise, stmt_execsql, stmt_fori
115 %type <stmt> stmt_fors, stmt_select, stmt_perform
116 %type <stmt> stmt_dynexecute, stmt_dynfors, stmt_getdiag
118 %type <dtlist> raise_params
119 %type <ival> raise_level, raise_param
120 %type <str> raise_msg
122 %type <dtlist> getdiag_items, getdiag_targets
123 %type <ival> getdiag_item, getdiag_target
195 pl_function : T_FUNCTION comp_optsect pl_block
197 yylval.program = (PLpgSQL_stmt_block *)$3;
199 | T_TRIGGER comp_optsect pl_block
201 yylval.program = (PLpgSQL_stmt_block *)$3;
209 comp_options : comp_options comp_option
213 comp_option : O_OPTION O_DUMP
215 plpgsql_DumpExecTree = 1;
219 pl_block : decl_sect K_BEGIN lno proc_sect K_END ';'
221 PLpgSQL_stmt_block *new;
223 new = malloc(sizeof(PLpgSQL_stmt_block));
224 memset(new, 0, sizeof(PLpgSQL_stmt_block));
226 new->cmd_type = PLPGSQL_STMT_BLOCK;
228 new->label = $1.label;
229 new->n_initvars = $1.n_initvars;
230 new->initvarnos = $1.initvarnos;
235 $$ = (PLpgSQL_stmt *)new;
240 decl_sect : opt_label
242 plpgsql_ns_setlocal(false);
245 $$.initvarnos = NULL;
246 plpgsql_add_initdatums(NULL);
248 | opt_label decl_start
250 plpgsql_ns_setlocal(false);
253 $$.initvarnos = NULL;
254 plpgsql_add_initdatums(NULL);
256 | opt_label decl_start decl_stmts
258 plpgsql_ns_setlocal(false);
264 $$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos));
268 decl_start : K_DECLARE
270 plpgsql_ns_setlocal(true);
274 decl_stmts : decl_stmts decl_stmt
284 decl_stmt : '<' '<' opt_lblname '>' '>'
298 decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
302 new = malloc(sizeof(PLpgSQL_var));
304 new->dtype = PLPGSQL_DTYPE_VAR;
305 new->refname = $1.name;
306 new->lineno = $1.lineno;
311 new->default_val = $5;
313 plpgsql_adddatum((PLpgSQL_datum *)new);
314 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
317 | decl_varname K_RECORD ';'
321 new = malloc(sizeof(PLpgSQL_var));
323 new->dtype = PLPGSQL_DTYPE_REC;
324 new->refname = $1.name;
325 new->lineno = $1.lineno;
327 plpgsql_adddatum((PLpgSQL_datum *)new);
328 plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, new->recno,
331 | decl_varname decl_rowtype ';'
333 $2->dtype = PLPGSQL_DTYPE_ROW;
334 $2->refname = $1.name;
335 $2->lineno = $1.lineno;
337 plpgsql_adddatum((PLpgSQL_datum *)$2);
338 plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, $2->rowno,
341 | decl_varname K_ALIAS K_FOR decl_aliasitem ';'
343 plpgsql_ns_additem($4->itemtype,
344 $4->itemno, $1.name);
346 | K_RENAME decl_renname K_TO decl_renname ';'
348 plpgsql_ns_rename($2, $4);
352 decl_aliasitem : T_WORD
357 plpgsql_ns_setlocal(false);
358 name = plpgsql_tolower(yytext);
359 if (name[0] != '$') {
360 elog(ERROR, "can only alias positional parameters");
362 nsi = plpgsql_ns_lookup(name, NULL);
364 elog(ERROR, "function has no parameter %s", name);
367 plpgsql_ns_setlocal(true);
379 decl_varname : T_WORD
381 /* name should be malloc'd for use as varname */
382 $$.name = strdup(plpgsql_tolower(yytext));
383 $$.lineno = yylineno;
387 decl_renname : T_WORD
389 /* the result must be palloc'd, see plpgsql_ns_rename */
390 $$ = plpgsql_tolower(yytext);
400 decl_datatype : decl_dtypename
406 decl_dtypename : T_DTYPE
410 | T_CHAR decl_atttypmod
413 plpgsql_parse_word("char");
416 plpgsql_parse_word("bpchar");
421 | T_VARCHAR decl_atttypmod
423 plpgsql_parse_word("varchar");
427 | T_BPCHAR '(' decl_atttypmodval ')'
429 plpgsql_parse_word("bpchar");
439 | '(' decl_atttypmodval ')'
445 decl_atttypmodval : T_NUMBER
447 $$ = pg_atoi(yytext, sizeof(int16), '\0') + VARHDRSZ;
467 expr = malloc(sizeof(PLpgSQL_expr));
468 plpgsql_dstring_init(&ds);
469 plpgsql_dstring_append(&ds, "SELECT ");
471 expr->dtype = PLPGSQL_DTYPE_EXPR;
478 plpgsql_error_lineno = lno;
479 plpgsql_comperrinfo();
480 elog(ERROR, "unexpected end of file");
482 if (yylex() != ';') {
483 plpgsql_error_lineno = lno;
484 plpgsql_comperrinfo();
485 elog(ERROR, "expectec ; after NULL");
488 plpgsql_dstring_free(&ds);
494 plpgsql_dstring_append(&ds, yytext);
495 while ((tok = yylex()) != ';') {
497 plpgsql_error_lineno = lno;
498 plpgsql_comperrinfo();
499 elog(ERROR, "unterminated default value");
501 if (plpgsql_SpaceScanned) {
502 plpgsql_dstring_append(&ds, " ");
504 plpgsql_dstring_append(&ds, yytext);
506 expr->query = strdup(plpgsql_dstring_get(&ds));
507 plpgsql_dstring_free(&ds);
515 decl_defkey : K_ASSIGN
522 new = malloc(sizeof(PLpgSQL_stmts));
523 memset(new, 0, sizeof(PLpgSQL_stmts));
532 proc_stmts : proc_stmts proc_stmt
534 if ($1->stmts_used == $1->stmts_alloc) {
535 $1->stmts_alloc *= 2;
536 $1->stmts = realloc($1->stmts, sizeof(PLpgSQL_stmt *) * $1->stmts_alloc);
538 $1->stmts[$1->stmts_used++] = (struct PLpgSQL_stmt *)$2;
546 new = malloc(sizeof(PLpgSQL_stmts));
547 memset(new, 0, sizeof(PLpgSQL_stmts));
549 new->stmts_alloc = 64;
551 new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
552 new->stmts[0] = (struct PLpgSQL_stmt *)$1;
592 stmt_perform : K_PERFORM lno expr_until_semi
594 PLpgSQL_stmt_assign *new;
596 new = malloc(sizeof(PLpgSQL_stmt_assign));
597 memset(new, 0, sizeof(PLpgSQL_stmt_assign));
599 new->cmd_type = PLPGSQL_STMT_ASSIGN;
604 $$ = (PLpgSQL_stmt *)new;
608 stmt_assign : assign_var lno K_ASSIGN expr_until_semi
610 PLpgSQL_stmt_assign *new;
612 new = malloc(sizeof(PLpgSQL_stmt_assign));
613 memset(new, 0, sizeof(PLpgSQL_stmt_assign));
615 new->cmd_type = PLPGSQL_STMT_ASSIGN;
620 $$ = (PLpgSQL_stmt *)new;
624 stmt_getdiag : K_GET K_DIAGNOSTICS lno K_SELECT getdiag_items K_INTO getdiag_targets ';'
626 PLpgSQL_stmt_getdiag *new;
628 new = malloc(sizeof(PLpgSQL_stmt_getdiag));
629 memset(new, 0, sizeof(PLpgSQL_stmt_getdiag));
631 new->cmd_type = PLPGSQL_STMT_GETDIAG;
633 new->nitems = $5.nused;
634 new->items = malloc(sizeof(int) * $5.nused);
635 new->ntargets = $7.nused;
636 new->targets = malloc(sizeof(int) * $7.nused);
637 memcpy(new->items, $5.dtnums, sizeof(int) * $5.nused);
638 memcpy(new->targets, $7.dtnums, sizeof(int) * $7.nused);
640 if (new->nitems != new->ntargets) {
641 plpgsql_error_lineno = new->lineno;
642 plpgsql_comperrinfo();
643 elog(ERROR, "number of diagnostic items does not match target list");
646 $$ = (PLpgSQL_stmt *)new;
650 getdiag_items : getdiag_items ',' getdiag_item
652 if ($1.nused == $1.nalloc) {
654 $1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
656 $1.dtnums[$1.nused++] = $3;
658 $$.nalloc = $1.nalloc;
660 $$.dtnums = $1.dtnums;
666 $$.dtnums = palloc(sizeof(int) * $$.nalloc);
671 getdiag_item : K_PROCESSED
673 $$ = PLPGSQL_GETDIAG_PROCESSED;
677 $$ = PLPGSQL_GETDIAG_RESULT;
681 getdiag_targets : getdiag_targets ',' getdiag_target
683 if ($1.nused == $1.nalloc) {
685 $1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
687 $1.dtnums[$1.nused++] = $3;
689 $$.nalloc = $1.nalloc;
691 $$.dtnums = $1.dtnums;
697 $$.dtnums = palloc(sizeof(int) * $$.nalloc);
703 getdiag_target : T_VARIABLE
705 if (yylval.var->isconst) {
706 plpgsql_comperrinfo();
707 elog(ERROR, "%s is declared CONSTANT; can not receive diagnostics", yylval.var->refname);
709 $$ = yylval.var->varno;
713 $$ = yylval.recfield->rfno;
718 assign_var : T_VARIABLE
720 if (yylval.var->isconst) {
721 plpgsql_comperrinfo();
722 elog(ERROR, "%s is declared CONSTANT", yylval.var->refname);
724 $$ = yylval.var->varno;
728 $$ = yylval.recfield->rfno;
732 stmt_if : K_IF lno expr_until_then proc_sect stmt_else K_END K_IF ';'
734 PLpgSQL_stmt_if *new;
736 new = malloc(sizeof(PLpgSQL_stmt_if));
737 memset(new, 0, sizeof(PLpgSQL_stmt_if));
739 new->cmd_type = PLPGSQL_STMT_IF;
743 new->false_body = $5;
745 $$ = (PLpgSQL_stmt *)new;
753 new = malloc(sizeof(PLpgSQL_stmts));
754 memset(new, 0, sizeof(PLpgSQL_stmts));
761 stmt_loop : opt_label K_LOOP lno loop_body
763 PLpgSQL_stmt_loop *new;
765 new = malloc(sizeof(PLpgSQL_stmt_loop));
766 memset(new, 0, sizeof(PLpgSQL_stmt_loop));
768 new->cmd_type = PLPGSQL_STMT_LOOP;
775 $$ = (PLpgSQL_stmt *)new;
779 stmt_while : opt_label K_WHILE lno expr_until_loop loop_body
781 PLpgSQL_stmt_while *new;
783 new = malloc(sizeof(PLpgSQL_stmt_while));
784 memset(new, 0, sizeof(PLpgSQL_stmt_while));
786 new->cmd_type = PLPGSQL_STMT_WHILE;
794 $$ = (PLpgSQL_stmt *)new;
798 stmt_fori : opt_label K_FOR lno fori_var K_IN fori_lower expr_until_loop loop_body
800 PLpgSQL_stmt_fori *new;
802 new = malloc(sizeof(PLpgSQL_stmt_fori));
803 memset(new, 0, sizeof(PLpgSQL_stmt_fori));
805 new->cmd_type = PLPGSQL_STMT_FORI;
809 new->reverse = $6.reverse;
810 new->lower = $6.expr;
816 $$ = (PLpgSQL_stmt *)new;
820 fori_var : fori_varname
824 new = malloc(sizeof(PLpgSQL_var));
826 new->dtype = PLPGSQL_DTYPE_VAR;
827 new->refname = $1.name;
828 new->lineno = $1.lineno;
830 plpgsql_parse_word("integer");
832 new->datatype = yylval.dtype;
833 new->isconst = false;
834 new->notnull = false;
835 new->default_val = NULL;
837 plpgsql_adddatum((PLpgSQL_datum *)new);
838 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
841 plpgsql_add_initdatums(NULL);
847 fori_varname : T_VARIABLE
849 $$.name = strdup(yytext);
850 $$.lineno = yylineno;
854 $$.name = strdup(yytext);
855 $$.lineno = yylineno;
871 plpgsql_dstring_init(&ds);
872 plpgsql_dstring_append(&ds, "SELECT ");
875 while((tok = yylex()) != K_DOTDOT) {
878 if (tok == K_REVERSE) {
883 if (tok == ';') break;
884 if (plpgsql_SpaceScanned) {
885 plpgsql_dstring_append(&ds, " ");
889 params[nparams] = yylval.var->varno;
890 sprintf(buf, " $%d ", ++nparams);
891 plpgsql_dstring_append(&ds, buf);
895 params[nparams] = yylval.recfield->rfno;
896 sprintf(buf, " $%d ", ++nparams);
897 plpgsql_dstring_append(&ds, buf);
901 params[nparams] = yylval.trigarg->dno;
902 sprintf(buf, " $%d ", ++nparams);
903 plpgsql_dstring_append(&ds, buf);
908 plpgsql_error_lineno = lno;
909 plpgsql_comperrinfo();
910 elog(ERROR, "missing .. to terminate lower bound of for loop");
912 plpgsql_dstring_append(&ds, yytext);
917 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
918 expr->dtype = PLPGSQL_DTYPE_EXPR;
919 expr->query = strdup(plpgsql_dstring_get(&ds));
921 expr->nparams = nparams;
922 while(nparams-- > 0) {
923 expr->params[nparams] = params[nparams];
925 plpgsql_dstring_free(&ds);
929 stmt_fors : opt_label K_FOR lno fors_target K_IN K_SELECT expr_until_loop loop_body
931 PLpgSQL_stmt_fors *new;
933 new = malloc(sizeof(PLpgSQL_stmt_fors));
934 memset(new, 0, sizeof(PLpgSQL_stmt_fors));
936 new->cmd_type = PLPGSQL_STMT_FORS;
940 case PLPGSQL_DTYPE_REC:
943 case PLPGSQL_DTYPE_ROW:
944 new->row = (PLpgSQL_row *)$4;
947 plpgsql_comperrinfo();
948 elog(ERROR, "unknown dtype %d in stmt_fors", $4->dtype);
955 $$ = (PLpgSQL_stmt *)new;
958 stmt_dynfors : opt_label K_FOR lno fors_target K_IN K_EXECUTE expr_until_loop loop_body
960 PLpgSQL_stmt_dynfors *new;
962 new = malloc(sizeof(PLpgSQL_stmt_dynfors));
963 memset(new, 0, sizeof(PLpgSQL_stmt_dynfors));
965 new->cmd_type = PLPGSQL_STMT_DYNFORS;
969 case PLPGSQL_DTYPE_REC:
972 case PLPGSQL_DTYPE_ROW:
973 new->row = (PLpgSQL_row *)$4;
976 plpgsql_comperrinfo();
977 elog(ERROR, "unknown dtype %d in stmt_dynfors", $4->dtype);
984 $$ = (PLpgSQL_stmt *)new;
987 fors_target : T_RECORD
993 $$ = (PLpgSQL_rec *)(yylval.row);
997 stmt_select : K_SELECT lno
999 $$ = make_select_stmt();
1004 stmt_exit : K_EXIT lno opt_exitlabel opt_exitcond
1006 PLpgSQL_stmt_exit *new;
1008 new = malloc(sizeof(PLpgSQL_stmt_exit));
1009 memset(new, 0, sizeof(PLpgSQL_stmt_exit));
1011 new->cmd_type = PLPGSQL_STMT_EXIT;
1016 $$ = (PLpgSQL_stmt *)new;
1020 stmt_return : K_RETURN lno
1022 PLpgSQL_stmt_return *new;
1023 PLpgSQL_expr *expr = NULL;
1026 new = malloc(sizeof(PLpgSQL_stmt_return));
1027 memset(new, 0, sizeof(PLpgSQL_stmt_return));
1029 if (plpgsql_curr_compile->fn_retistuple) {
1030 new->retistuple = true;
1032 switch (tok = yylex()) {
1038 expr = make_tupret_expr(yylval.row);
1042 new->retrecno = yylval.rec->recno;
1047 yyerror("return type mismatch in function returning table row");
1050 if (yylex() != ';') {
1051 yyerror("expected ';'");
1054 new->retistuple = false;
1055 expr = plpgsql_read_expression(';', ";");
1058 new->cmd_type = PLPGSQL_STMT_RETURN;
1062 $$ = (PLpgSQL_stmt *)new;
1066 stmt_raise : K_RAISE lno raise_level raise_msg raise_params ';'
1068 PLpgSQL_stmt_raise *new;
1070 new = malloc(sizeof(PLpgSQL_stmt_raise));
1072 new->cmd_type = PLPGSQL_STMT_RAISE;
1074 new->elog_level = $3;
1076 new->nparams = $5.nused;
1077 new->params = malloc(sizeof(int) * $5.nused);
1078 memcpy(new->params, $5.dtnums, sizeof(int) * $5.nused);
1080 $$ = (PLpgSQL_stmt *)new;
1082 | K_RAISE lno raise_level raise_msg ';'
1084 PLpgSQL_stmt_raise *new;
1086 new = malloc(sizeof(PLpgSQL_stmt_raise));
1088 new->cmd_type = PLPGSQL_STMT_RAISE;
1090 new->elog_level = $3;
1095 $$ = (PLpgSQL_stmt *)new;
1099 raise_msg : T_STRING
1101 $$ = strdup(yytext);
1105 raise_level : K_EXCEPTION
1119 raise_params : raise_params raise_param
1121 if ($1.nused == $1.nalloc) {
1123 $1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
1125 $1.dtnums[$1.nused++] = $2;
1127 $$.nalloc = $1.nalloc;
1128 $$.nused = $1.nused;
1129 $$.dtnums = $1.dtnums;
1135 $$.dtnums = palloc(sizeof(int) * $$.nalloc);
1140 raise_param : ',' T_VARIABLE
1142 $$ = yylval.var->varno;
1146 $$ = yylval.recfield->rfno;
1150 $$ = yylval.trigarg->dno;
1154 loop_body : proc_sect K_END K_LOOP ';'
1158 stmt_execsql : execsql_start lno
1160 PLpgSQL_stmt_execsql *new;
1162 new = malloc(sizeof(PLpgSQL_stmt_execsql));
1163 new->cmd_type = PLPGSQL_STMT_EXECSQL;
1165 new->sqlstmt = read_sqlstmt(';', ";", $1);
1167 $$ = (PLpgSQL_stmt *)new;
1171 stmt_dynexecute : K_EXECUTE lno expr_until_semi
1173 PLpgSQL_stmt_dynexecute *new;
1175 new = malloc(sizeof(PLpgSQL_stmt_dynexecute));
1176 new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
1180 $$ = (PLpgSQL_stmt *)new;
1184 execsql_start : T_WORD
1185 { $$ = strdup(yytext); }
1187 { $$ = strdup(yytext); }
1191 { $$ = plpgsql_read_expression(';', ";"); }
1195 { $$ = plpgsql_read_expression(K_THEN, "THEN"); }
1199 { $$ = plpgsql_read_expression(K_LOOP, "LOOP"); }
1204 plpgsql_ns_push(NULL);
1207 | '<' '<' opt_lblname '>' '>'
1209 plpgsql_ns_push($3);
1217 { $$ = strdup(yytext); }
1222 | K_WHEN expr_until_semi
1226 opt_lblname : T_WORD
1227 { $$ = strdup(yytext); }
1232 plpgsql_error_lineno = yylineno;
1240 #include "pl_scan.c" /* BSD yacc wants it here */
1245 plpgsql_read_expression (int until, char *s)
1247 return read_sqlstmt(until, s, "SELECT ");
1251 static PLpgSQL_expr *
1252 read_sqlstmt (int until, char *s, char *sqlstart)
1263 plpgsql_dstring_init(&ds);
1264 plpgsql_dstring_append(&ds, sqlstart);
1266 while((tok = yylex()) != until) {
1267 if (tok == ';') break;
1268 if (plpgsql_SpaceScanned) {
1269 plpgsql_dstring_append(&ds, " ");
1273 params[nparams] = yylval.var->varno;
1274 sprintf(buf, " $%d ", ++nparams);
1275 plpgsql_dstring_append(&ds, buf);
1279 params[nparams] = yylval.recfield->rfno;
1280 sprintf(buf, " $%d ", ++nparams);
1281 plpgsql_dstring_append(&ds, buf);
1285 params[nparams] = yylval.trigarg->dno;
1286 sprintf(buf, " $%d ", ++nparams);
1287 plpgsql_dstring_append(&ds, buf);
1292 plpgsql_error_lineno = lno;
1293 plpgsql_comperrinfo();
1294 elog(ERROR, "missing %s at end of SQL statement", s);
1296 plpgsql_dstring_append(&ds, yytext);
1301 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
1302 expr->dtype = PLPGSQL_DTYPE_EXPR;
1303 expr->query = strdup(plpgsql_dstring_get(&ds));
1305 expr->nparams = nparams;
1306 while(nparams-- > 0) {
1307 expr->params[nparams] = params[nparams];
1309 plpgsql_dstring_free(&ds);
1315 static PLpgSQL_stmt *
1325 PLpgSQL_row *row = NULL;
1326 PLpgSQL_rec *rec = NULL;
1327 PLpgSQL_stmt_select *select;
1328 int have_nexttok = 0;
1331 plpgsql_dstring_init(&ds);
1332 plpgsql_dstring_append(&ds, "SELECT ");
1334 while((tok = yylex()) != K_INTO) {
1336 PLpgSQL_stmt_execsql *execsql;
1338 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
1339 expr->dtype = PLPGSQL_DTYPE_EXPR;
1340 expr->query = strdup(plpgsql_dstring_get(&ds));
1342 expr->nparams = nparams;
1343 while(nparams-- > 0) {
1344 expr->params[nparams] = params[nparams];
1346 plpgsql_dstring_free(&ds);
1348 execsql = malloc(sizeof(PLpgSQL_stmt_execsql));
1349 execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
1350 execsql->sqlstmt = expr;
1352 return (PLpgSQL_stmt *)execsql;
1355 if (plpgsql_SpaceScanned) {
1356 plpgsql_dstring_append(&ds, " ");
1360 params[nparams] = yylval.var->varno;
1361 sprintf(buf, " $%d ", ++nparams);
1362 plpgsql_dstring_append(&ds, buf);
1366 params[nparams] = yylval.recfield->rfno;
1367 sprintf(buf, " $%d ", ++nparams);
1368 plpgsql_dstring_append(&ds, buf);
1372 params[nparams] = yylval.trigarg->dno;
1373 sprintf(buf, " $%d ", ++nparams);
1374 plpgsql_dstring_append(&ds, buf);
1379 plpgsql_error_lineno = yylineno;
1380 plpgsql_comperrinfo();
1381 elog(ERROR, "unexpected end of file");
1383 plpgsql_dstring_append(&ds, yytext);
1402 PLpgSQL_recfield *recfield;
1404 char *fieldnames[1024];
1410 fieldnames[0] = strdup(yytext);
1411 varnos[0] = var->varno;
1415 recfield = yylval.recfield;
1416 fieldnames[0] = strdup(yytext);
1417 varnos[0] = recfield->rfno;
1421 while ((tok = yylex()) == ',') {
1426 fieldnames[nfields] = strdup(yytext);
1427 varnos[nfields++] = var->varno;
1431 recfield = yylval.recfield;
1432 fieldnames[0] = strdup(yytext);
1433 varnos[0] = recfield->rfno;
1437 elog(ERROR, "plpgsql: %s is not a variable or record field", yytext);
1440 row = malloc(sizeof(PLpgSQL_row));
1441 row->dtype = PLPGSQL_DTYPE_ROW;
1442 row->refname = strdup("*internal*");
1443 row->lineno = yylineno;
1444 row->rowtypeclass = InvalidOid;
1445 row->nfields = nfields;
1446 row->fieldnames = malloc(sizeof(char *) * nfields);
1447 row->varnos = malloc(sizeof(int) * nfields);
1448 while (--nfields >= 0) {
1449 row->fieldnames[nfields] = fieldnames[nfields];
1450 row->varnos[nfields] = varnos[nfields];
1453 plpgsql_adddatum((PLpgSQL_datum *)row);
1461 if (plpgsql_SpaceScanned) {
1462 plpgsql_dstring_append(&ds, " ");
1464 plpgsql_dstring_append(&ds, yytext);
1469 PLpgSQL_stmt_execsql *execsql;
1471 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
1472 expr->dtype = PLPGSQL_DTYPE_EXPR;
1473 expr->query = strdup(plpgsql_dstring_get(&ds));
1475 expr->nparams = nparams;
1476 while(nparams-- > 0) {
1477 expr->params[nparams] = params[nparams];
1479 plpgsql_dstring_free(&ds);
1481 execsql = malloc(sizeof(PLpgSQL_stmt_execsql));
1482 execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
1483 execsql->sqlstmt = expr;
1485 return (PLpgSQL_stmt *)execsql;
1488 if (plpgsql_SpaceScanned) {
1489 plpgsql_dstring_append(&ds, " ");
1493 params[nparams] = yylval.var->varno;
1494 sprintf(buf, " $%d ", ++nparams);
1495 plpgsql_dstring_append(&ds, buf);
1499 params[nparams] = yylval.recfield->rfno;
1500 sprintf(buf, " $%d ", ++nparams);
1501 plpgsql_dstring_append(&ds, buf);
1505 params[nparams] = yylval.trigarg->dno;
1506 sprintf(buf, " $%d ", ++nparams);
1507 plpgsql_dstring_append(&ds, buf);
1512 plpgsql_error_lineno = yylineno;
1513 plpgsql_comperrinfo();
1514 elog(ERROR, "unexpected end of file");
1516 plpgsql_dstring_append(&ds, yytext);
1523 /************************************************************
1524 * Eat up the rest of the statement after the target fields
1525 ************************************************************/
1527 if (!have_nexttok) {
1535 if (plpgsql_SpaceScanned) {
1536 plpgsql_dstring_append(&ds, " ");
1540 params[nparams] = yylval.var->varno;
1541 sprintf(buf, " $%d ", ++nparams);
1542 plpgsql_dstring_append(&ds, buf);
1546 params[nparams] = yylval.recfield->rfno;
1547 sprintf(buf, " $%d ", ++nparams);
1548 plpgsql_dstring_append(&ds, buf);
1552 params[nparams] = yylval.trigarg->dno;
1553 sprintf(buf, " $%d ", ++nparams);
1554 plpgsql_dstring_append(&ds, buf);
1559 plpgsql_error_lineno = yylineno;
1560 plpgsql_comperrinfo();
1561 elog(ERROR, "unexpected end of file");
1563 plpgsql_dstring_append(&ds, yytext);
1568 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * (nparams - 1));
1569 expr->dtype = PLPGSQL_DTYPE_EXPR;
1570 expr->query = strdup(plpgsql_dstring_get(&ds));
1572 expr->nparams = nparams;
1573 while(nparams-- > 0) {
1574 expr->params[nparams] = params[nparams];
1576 plpgsql_dstring_free(&ds);
1578 select = malloc(sizeof(PLpgSQL_stmt_select));
1579 memset(select, 0, sizeof(PLpgSQL_stmt_select));
1580 select->cmd_type = PLPGSQL_STMT_SELECT;
1583 select->query = expr;
1585 return (PLpgSQL_stmt *)select;
1589 static PLpgSQL_expr *
1590 make_tupret_expr(PLpgSQL_row *row)
1597 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * (row->nfields - 1));
1598 expr->dtype = PLPGSQL_DTYPE_EXPR;
1600 plpgsql_dstring_init(&ds);
1601 plpgsql_dstring_append(&ds, "SELECT ");
1603 for (i = 0; i < row->nfields; i++) {
1604 sprintf(buf, "%s$%d", (i > 0) ? "," : "", i + 1);
1605 plpgsql_dstring_append(&ds, buf);
1606 expr->params[i] = row->varnos[i];
1609 expr->query = strdup(plpgsql_dstring_get(&ds));
1611 expr->plan_argtypes = NULL;
1612 expr->nparams = row->nfields;
1614 plpgsql_dstring_free(&ds);