2 /**********************************************************************
3 * gram.y - Parser for the PL/pgSQL
7 * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.5 1999/08/07 04:25:02 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 **********************************************************************/
44 static PLpgSQL_expr *read_sqlstmt(int until, char *s, char *sqlstart);
45 static PLpgSQL_stmt *make_select_stmt(void);
46 static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
75 PLpgSQL_recfield *recfield;
76 PLpgSQL_trigarg *trigarg;
80 PLpgSQL_stmt_block *program;
81 PLpgSQL_nsitem *nsitem;
84 %type <declhdr> decl_sect
85 %type <varname> decl_varname
86 %type <str> decl_renname
87 %type <ival> decl_const, decl_notnull, decl_atttypmod, decl_atttypmodval
88 %type <expr> decl_defval
89 %type <dtype> decl_datatype, decl_dtypename
90 %type <row> decl_rowtype
91 %type <nsitem> decl_aliasitem
92 %type <str> decl_stmts, decl_stmt
94 %type <expr> expr_until_semi, expr_until_then, expr_until_loop
95 %type <expr> opt_exitcond
97 %type <ival> assign_var
99 %type <varname> fori_varname
100 %type <forilow> fori_lower
101 %type <rec> fors_target
103 %type <str> opt_lblname, opt_label
104 %type <str> opt_exitlabel
105 %type <str> execsql_start
107 %type <stmts> proc_sect, proc_stmts, stmt_else, loop_body
108 %type <stmt> proc_stmt, pl_block
109 %type <stmt> stmt_assign, stmt_if, stmt_loop, stmt_while, stmt_exit
110 %type <stmt> stmt_return, stmt_raise, stmt_execsql, stmt_fori
111 %type <stmt> stmt_fors, stmt_select, stmt_perform
113 %type <dtlist> raise_params
114 %type <ival> raise_level, raise_param
115 %type <str> raise_msg
182 pl_function : T_FUNCTION comp_optsect pl_block
184 yylval.program = (PLpgSQL_stmt_block *)$3;
186 | T_TRIGGER comp_optsect pl_block
188 yylval.program = (PLpgSQL_stmt_block *)$3;
196 comp_options : comp_options comp_option
200 comp_option : O_OPTION O_DUMP
202 plpgsql_DumpExecTree = 1;
206 pl_block : decl_sect K_BEGIN lno proc_sect K_END ';'
208 PLpgSQL_stmt_block *new;
210 new = malloc(sizeof(PLpgSQL_stmt_block));
211 memset(new, 0, sizeof(PLpgSQL_stmt_block));
213 new->cmd_type = PLPGSQL_STMT_BLOCK;
215 new->label = $1.label;
216 new->n_initvars = $1.n_initvars;
217 new->initvarnos = $1.initvarnos;
222 $$ = (PLpgSQL_stmt *)new;
227 decl_sect : opt_label
229 plpgsql_ns_setlocal(false);
232 $$.initvarnos = NULL;
233 plpgsql_add_initdatums(NULL);
235 | opt_label decl_start
237 plpgsql_ns_setlocal(false);
240 $$.initvarnos = NULL;
241 plpgsql_add_initdatums(NULL);
243 | opt_label decl_start decl_stmts
245 plpgsql_ns_setlocal(false);
251 $$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos));
255 decl_start : K_DECLARE
257 plpgsql_ns_setlocal(true);
261 decl_stmts : decl_stmts decl_stmt
271 decl_stmt : '<' '<' opt_lblname '>' '>'
285 decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
289 new = malloc(sizeof(PLpgSQL_var));
291 new->dtype = PLPGSQL_DTYPE_VAR;
292 new->refname = $1.name;
293 new->lineno = $1.lineno;
298 new->default_val = $5;
300 plpgsql_adddatum((PLpgSQL_datum *)new);
301 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
304 | decl_varname K_RECORD ';'
308 new = malloc(sizeof(PLpgSQL_var));
310 new->dtype = PLPGSQL_DTYPE_REC;
311 new->refname = $1.name;
312 new->lineno = $1.lineno;
314 plpgsql_adddatum((PLpgSQL_datum *)new);
315 plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, new->recno,
318 | decl_varname decl_rowtype ';'
320 $2->dtype = PLPGSQL_DTYPE_ROW;
321 $2->refname = $1.name;
322 $2->lineno = $1.lineno;
324 plpgsql_adddatum((PLpgSQL_datum *)$2);
325 plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, $2->rowno,
328 | decl_varname K_ALIAS K_FOR decl_aliasitem ';'
330 plpgsql_ns_additem($4->itemtype,
331 $4->itemno, $1.name);
333 | K_RENAME decl_renname K_TO decl_renname ';'
335 plpgsql_ns_rename($2, $4);
339 decl_aliasitem : T_WORD
344 plpgsql_ns_setlocal(false);
345 name = plpgsql_tolower(yytext);
346 if (name[0] != '$') {
347 elog(ERROR, "can only alias positional parameters");
349 nsi = plpgsql_ns_lookup(name, NULL);
351 elog(ERROR, "function has no parameter %s", name);
354 plpgsql_ns_setlocal(true);
366 decl_varname : T_WORD
368 $$.name = strdup(yytext);
369 $$.lineno = yylineno;
373 decl_renname : T_WORD
375 $$ = plpgsql_tolower(yytext);
385 decl_datatype : decl_dtypename
391 decl_dtypename : T_DTYPE
395 | T_CHAR decl_atttypmod
398 plpgsql_parse_word("char");
401 plpgsql_parse_word("bpchar");
406 | T_VARCHAR decl_atttypmod
408 plpgsql_parse_word("varchar");
412 | T_BPCHAR '(' decl_atttypmodval ')'
414 plpgsql_parse_word("bpchar");
424 | '(' decl_atttypmodval ')'
430 decl_atttypmodval : T_NUMBER
432 $$ = int2in(yytext) + VARHDRSZ;
452 expr = malloc(sizeof(PLpgSQL_expr));
453 plpgsql_dstring_init(&ds);
454 plpgsql_dstring_append(&ds, "SELECT ");
456 expr->dtype = PLPGSQL_DTYPE_EXPR;
463 plpgsql_error_lineno = lno;
464 plpgsql_comperrinfo();
465 elog(ERROR, "unexpected end of file");
467 if (yylex() != ';') {
468 plpgsql_error_lineno = lno;
469 plpgsql_comperrinfo();
470 elog(ERROR, "expectec ; after NULL");
473 plpgsql_dstring_free(&ds);
479 plpgsql_dstring_append(&ds, yytext);
480 while ((tok = yylex()) != ';') {
482 plpgsql_error_lineno = lno;
483 plpgsql_comperrinfo();
484 elog(ERROR, "unterminated default value");
486 if (plpgsql_SpaceScanned) {
487 plpgsql_dstring_append(&ds, " ");
489 plpgsql_dstring_append(&ds, yytext);
491 expr->query = strdup(plpgsql_dstring_get(&ds));
492 plpgsql_dstring_free(&ds);
500 decl_defkey : K_ASSIGN
507 new = malloc(sizeof(PLpgSQL_stmts));
508 memset(new, 0, sizeof(PLpgSQL_stmts));
517 proc_stmts : proc_stmts proc_stmt
519 if ($1->stmts_used == $1->stmts_alloc) {
520 $1->stmts_alloc *= 2;
521 $1->stmts = realloc($1->stmts, sizeof(PLpgSQL_stmt *) * $1->stmts_alloc);
523 $1->stmts[$1->stmts_used++] = (struct PLpgSQL_stmt *)$2;
531 new = malloc(sizeof(PLpgSQL_stmts));
532 memset(new, 0, sizeof(PLpgSQL_stmts));
534 new->stmts_alloc = 64;
536 new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
537 new->stmts[0] = (struct PLpgSQL_stmt *)$1;
571 stmt_perform : K_PERFORM lno expr_until_semi
573 PLpgSQL_stmt_assign *new;
575 new = malloc(sizeof(PLpgSQL_stmt_assign));
576 memset(new, 0, sizeof(PLpgSQL_stmt_assign));
578 new->cmd_type = PLPGSQL_STMT_ASSIGN;
583 $$ = (PLpgSQL_stmt *)new;
587 stmt_assign : assign_var lno K_ASSIGN expr_until_semi
589 PLpgSQL_stmt_assign *new;
591 new = malloc(sizeof(PLpgSQL_stmt_assign));
592 memset(new, 0, sizeof(PLpgSQL_stmt_assign));
594 new->cmd_type = PLPGSQL_STMT_ASSIGN;
599 $$ = (PLpgSQL_stmt *)new;
603 assign_var : T_VARIABLE
605 if (yylval.var->isconst) {
606 plpgsql_comperrinfo();
607 elog(ERROR, "%s is declared CONSTANT", yylval.var->refname);
609 $$ = yylval.var->varno;
613 $$ = yylval.recfield->rfno;
617 stmt_if : K_IF lno expr_until_then proc_sect stmt_else K_END K_IF ';'
619 PLpgSQL_stmt_if *new;
621 new = malloc(sizeof(PLpgSQL_stmt_if));
622 memset(new, 0, sizeof(PLpgSQL_stmt_if));
624 new->cmd_type = PLPGSQL_STMT_IF;
628 new->false_body = $5;
630 $$ = (PLpgSQL_stmt *)new;
638 new = malloc(sizeof(PLpgSQL_stmts));
639 memset(new, 0, sizeof(PLpgSQL_stmts));
646 stmt_loop : opt_label K_LOOP lno loop_body
648 PLpgSQL_stmt_loop *new;
650 new = malloc(sizeof(PLpgSQL_stmt_loop));
651 memset(new, 0, sizeof(PLpgSQL_stmt_loop));
653 new->cmd_type = PLPGSQL_STMT_LOOP;
660 $$ = (PLpgSQL_stmt *)new;
664 stmt_while : opt_label K_WHILE lno expr_until_loop loop_body
666 PLpgSQL_stmt_while *new;
668 new = malloc(sizeof(PLpgSQL_stmt_while));
669 memset(new, 0, sizeof(PLpgSQL_stmt_while));
671 new->cmd_type = PLPGSQL_STMT_WHILE;
679 $$ = (PLpgSQL_stmt *)new;
683 stmt_fori : opt_label K_FOR lno fori_var K_IN fori_lower expr_until_loop loop_body
685 PLpgSQL_stmt_fori *new;
687 new = malloc(sizeof(PLpgSQL_stmt_fori));
688 memset(new, 0, sizeof(PLpgSQL_stmt_fori));
690 new->cmd_type = PLPGSQL_STMT_FORI;
694 new->reverse = $6.reverse;
695 new->lower = $6.expr;
701 $$ = (PLpgSQL_stmt *)new;
705 fori_var : fori_varname
709 new = malloc(sizeof(PLpgSQL_var));
711 new->dtype = PLPGSQL_DTYPE_VAR;
712 new->refname = $1.name;
713 new->lineno = $1.lineno;
715 plpgsql_parse_word("integer");
717 new->datatype = yylval.dtype;
718 new->isconst = false;
719 new->notnull = false;
720 new->default_val = NULL;
722 plpgsql_adddatum((PLpgSQL_datum *)new);
723 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
726 plpgsql_add_initdatums(NULL);
732 fori_varname : T_VARIABLE
734 $$.name = strdup(yytext);
735 $$.lineno = yylineno;
739 $$.name = strdup(yytext);
740 $$.lineno = yylineno;
756 plpgsql_dstring_init(&ds);
757 plpgsql_dstring_append(&ds, "SELECT ");
760 while((tok = yylex()) != K_DOTDOT) {
763 if (tok == K_REVERSE) {
768 if (tok == ';') break;
769 if (plpgsql_SpaceScanned) {
770 plpgsql_dstring_append(&ds, " ");
774 params[nparams] = yylval.var->varno;
775 sprintf(buf, "$%d", ++nparams);
776 plpgsql_dstring_append(&ds, buf);
780 params[nparams] = yylval.recfield->rfno;
781 sprintf(buf, "$%d", ++nparams);
782 plpgsql_dstring_append(&ds, buf);
786 params[nparams] = yylval.trigarg->dno;
787 sprintf(buf, "$%d", ++nparams);
788 plpgsql_dstring_append(&ds, buf);
793 plpgsql_error_lineno = lno;
794 plpgsql_comperrinfo();
795 elog(ERROR, "missing .. to terminate lower bound of for loop");
797 plpgsql_dstring_append(&ds, yytext);
802 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
803 expr->dtype = PLPGSQL_DTYPE_EXPR;
804 expr->query = strdup(plpgsql_dstring_get(&ds));
806 expr->nparams = nparams;
807 while(nparams-- > 0) {
808 expr->params[nparams] = params[nparams];
810 plpgsql_dstring_free(&ds);
814 stmt_fors : opt_label K_FOR lno fors_target K_IN K_SELECT expr_until_loop loop_body
816 PLpgSQL_stmt_fors *new;
818 new = malloc(sizeof(PLpgSQL_stmt_fors));
819 memset(new, 0, sizeof(PLpgSQL_stmt_fors));
821 new->cmd_type = PLPGSQL_STMT_FORS;
825 case PLPGSQL_DTYPE_REC:
828 case PLPGSQL_DTYPE_ROW:
829 new->row = (PLpgSQL_row *)$4;
832 plpgsql_comperrinfo();
833 elog(ERROR, "unknown dtype %d in stmt_fors", $4->dtype);
840 $$ = (PLpgSQL_stmt *)new;
843 fors_target : T_RECORD
849 $$ = (PLpgSQL_rec *)(yylval.row);
853 stmt_select : K_SELECT lno
855 $$ = make_select_stmt();
860 stmt_exit : K_EXIT lno opt_exitlabel opt_exitcond
862 PLpgSQL_stmt_exit *new;
864 new = malloc(sizeof(PLpgSQL_stmt_exit));
865 memset(new, 0, sizeof(PLpgSQL_stmt_exit));
867 new->cmd_type = PLPGSQL_STMT_EXIT;
872 $$ = (PLpgSQL_stmt *)new;
876 stmt_return : K_RETURN lno
878 PLpgSQL_stmt_return *new;
879 PLpgSQL_expr *expr = NULL;
882 new = malloc(sizeof(PLpgSQL_stmt_return));
883 memset(new, 0, sizeof(PLpgSQL_stmt_return));
885 if (plpgsql_curr_compile->fn_retistuple) {
886 new->retistuple = true;
888 switch (tok = yylex()) {
894 expr = make_tupret_expr(yylval.row);
898 new->retrecno = yylval.rec->recno;
903 yyerror("return type mismatch in function returning table row");
906 if (yylex() != ';') {
907 yyerror("expected ';'");
910 new->retistuple = false;
911 expr = plpgsql_read_expression(';', ";");
914 new->cmd_type = PLPGSQL_STMT_RETURN;
918 $$ = (PLpgSQL_stmt *)new;
922 stmt_raise : K_RAISE lno raise_level raise_msg raise_params ';'
924 PLpgSQL_stmt_raise *new;
926 new = malloc(sizeof(PLpgSQL_stmt_raise));
928 new->cmd_type = PLPGSQL_STMT_RAISE;
930 new->elog_level = $3;
932 new->nparams = $5.nused;
933 new->params = malloc(sizeof(int) * $5.nused);
934 memcpy(new->params, $5.dtnums, sizeof(int) * $5.nused);
936 $$ = (PLpgSQL_stmt *)new;
938 | K_RAISE lno raise_level raise_msg ';'
940 PLpgSQL_stmt_raise *new;
942 new = malloc(sizeof(PLpgSQL_stmt_raise));
944 new->cmd_type = PLPGSQL_STMT_RAISE;
946 new->elog_level = $3;
951 $$ = (PLpgSQL_stmt *)new;
961 raise_level : K_EXCEPTION
975 raise_params : raise_params raise_param
977 if ($1.nused == $1.nalloc) {
979 $1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
981 $1.dtnums[$1.nused++] = $2;
983 $$.nalloc = $1.nalloc;
985 $$.dtnums = $1.dtnums;
991 $$.dtnums = palloc(sizeof(int) * $$.nalloc);
996 raise_param : ',' T_VARIABLE
998 $$ = yylval.var->varno;
1002 $$ = yylval.recfield->rfno;
1006 $$ = yylval.trigarg->dno;
1010 loop_body : proc_sect K_END K_LOOP ';'
1014 stmt_execsql : execsql_start lno
1016 PLpgSQL_stmt_execsql *new;
1018 new = malloc(sizeof(PLpgSQL_stmt_execsql));
1019 new->cmd_type = PLPGSQL_STMT_EXECSQL;
1021 new->sqlstmt = read_sqlstmt(';', ";", $1);
1023 $$ = (PLpgSQL_stmt *)new;
1027 execsql_start : T_WORD
1028 { $$ = strdup(yytext); }
1030 { $$ = strdup(yytext); }
1034 { $$ = plpgsql_read_expression(';', ";"); }
1038 { $$ = plpgsql_read_expression(K_THEN, "THEN"); }
1042 { $$ = plpgsql_read_expression(K_LOOP, "LOOP"); }
1047 plpgsql_ns_push(NULL);
1050 | '<' '<' opt_lblname '>' '>'
1052 plpgsql_ns_push($3);
1060 { $$ = strdup(yytext); }
1065 | K_WHEN expr_until_semi
1069 opt_lblname : T_WORD
1070 { $$ = strdup(yytext); }
1075 plpgsql_error_lineno = yylineno;
1082 #include "pl_scan.c"
1085 plpgsql_read_expression (int until, char *s)
1087 return read_sqlstmt(until, s, "SELECT ");
1091 static PLpgSQL_expr *
1092 read_sqlstmt (int until, char *s, char *sqlstart)
1103 plpgsql_dstring_init(&ds);
1104 plpgsql_dstring_append(&ds, sqlstart);
1106 while((tok = yylex()) != until) {
1107 if (tok == ';') break;
1108 if (plpgsql_SpaceScanned) {
1109 plpgsql_dstring_append(&ds, " ");
1113 params[nparams] = yylval.var->varno;
1114 sprintf(buf, "$%d", ++nparams);
1115 plpgsql_dstring_append(&ds, buf);
1119 params[nparams] = yylval.recfield->rfno;
1120 sprintf(buf, "$%d", ++nparams);
1121 plpgsql_dstring_append(&ds, buf);
1125 params[nparams] = yylval.trigarg->dno;
1126 sprintf(buf, "$%d", ++nparams);
1127 plpgsql_dstring_append(&ds, buf);
1132 plpgsql_error_lineno = lno;
1133 plpgsql_comperrinfo();
1134 elog(ERROR, "missing %s at end of SQL statement", s);
1136 plpgsql_dstring_append(&ds, yytext);
1141 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
1142 expr->dtype = PLPGSQL_DTYPE_EXPR;
1143 expr->query = strdup(plpgsql_dstring_get(&ds));
1145 expr->nparams = nparams;
1146 while(nparams-- > 0) {
1147 expr->params[nparams] = params[nparams];
1149 plpgsql_dstring_free(&ds);
1155 static PLpgSQL_stmt *
1165 PLpgSQL_row *row = NULL;
1166 PLpgSQL_rec *rec = NULL;
1167 PLpgSQL_stmt_select *select;
1168 int have_nexttok = 0;
1171 plpgsql_dstring_init(&ds);
1172 plpgsql_dstring_append(&ds, "SELECT ");
1174 while((tok = yylex()) != K_INTO) {
1176 PLpgSQL_stmt_execsql *execsql;
1178 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
1179 expr->dtype = PLPGSQL_DTYPE_EXPR;
1180 expr->query = strdup(plpgsql_dstring_get(&ds));
1182 expr->nparams = nparams;
1183 while(nparams-- > 0) {
1184 expr->params[nparams] = params[nparams];
1186 plpgsql_dstring_free(&ds);
1188 execsql = malloc(sizeof(PLpgSQL_stmt_execsql));
1189 execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
1190 execsql->sqlstmt = expr;
1192 return (PLpgSQL_stmt *)execsql;
1195 if (plpgsql_SpaceScanned) {
1196 plpgsql_dstring_append(&ds, " ");
1200 params[nparams] = yylval.var->varno;
1201 sprintf(buf, "$%d", ++nparams);
1202 plpgsql_dstring_append(&ds, buf);
1206 params[nparams] = yylval.recfield->rfno;
1207 sprintf(buf, "$%d", ++nparams);
1208 plpgsql_dstring_append(&ds, buf);
1212 params[nparams] = yylval.trigarg->dno;
1213 sprintf(buf, "$%d", ++nparams);
1214 plpgsql_dstring_append(&ds, buf);
1219 plpgsql_error_lineno = yylineno;
1220 plpgsql_comperrinfo();
1221 elog(ERROR, "unexpected end of file");
1223 plpgsql_dstring_append(&ds, yytext);
1242 PLpgSQL_recfield *recfield;
1244 char *fieldnames[1024];
1250 fieldnames[0] = strdup(yytext);
1251 varnos[0] = var->varno;
1255 recfield = yylval.recfield;
1256 fieldnames[0] = strdup(yytext);
1257 varnos[0] = recfield->rfno;
1261 while ((tok = yylex()) == ',') {
1266 fieldnames[nfields] = strdup(yytext);
1267 varnos[nfields++] = var->varno;
1271 recfield = yylval.recfield;
1272 fieldnames[0] = strdup(yytext);
1273 varnos[0] = recfield->rfno;
1277 elog(ERROR, "plpgsql: %s is not a variable or record field", yytext);
1280 row = malloc(sizeof(PLpgSQL_row));
1281 row->dtype = PLPGSQL_DTYPE_ROW;
1282 row->refname = strdup("*internal*");
1283 row->lineno = yylineno;
1284 row->rowtypeclass = InvalidOid;
1285 row->nfields = nfields;
1286 row->fieldnames = malloc(sizeof(char *) * nfields);
1287 row->varnos = malloc(sizeof(int) * nfields);
1288 while (--nfields >= 0) {
1289 row->fieldnames[nfields] = fieldnames[nfields];
1290 row->varnos[nfields] = varnos[nfields];
1293 plpgsql_adddatum((PLpgSQL_datum *)row);
1301 if (plpgsql_SpaceScanned) {
1302 plpgsql_dstring_append(&ds, " ");
1304 plpgsql_dstring_append(&ds, yytext);
1309 PLpgSQL_stmt_execsql *execsql;
1311 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
1312 expr->dtype = PLPGSQL_DTYPE_EXPR;
1313 expr->query = strdup(plpgsql_dstring_get(&ds));
1315 expr->nparams = nparams;
1316 while(nparams-- > 0) {
1317 expr->params[nparams] = params[nparams];
1319 plpgsql_dstring_free(&ds);
1321 execsql = malloc(sizeof(PLpgSQL_stmt_execsql));
1322 execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
1323 execsql->sqlstmt = expr;
1325 return (PLpgSQL_stmt *)execsql;
1328 if (plpgsql_SpaceScanned) {
1329 plpgsql_dstring_append(&ds, " ");
1333 params[nparams] = yylval.var->varno;
1334 sprintf(buf, "$%d", ++nparams);
1335 plpgsql_dstring_append(&ds, buf);
1339 params[nparams] = yylval.recfield->rfno;
1340 sprintf(buf, "$%d", ++nparams);
1341 plpgsql_dstring_append(&ds, buf);
1345 params[nparams] = yylval.trigarg->dno;
1346 sprintf(buf, "$%d", ++nparams);
1347 plpgsql_dstring_append(&ds, buf);
1352 plpgsql_error_lineno = yylineno;
1353 plpgsql_comperrinfo();
1354 elog(ERROR, "unexpected end of file");
1356 plpgsql_dstring_append(&ds, yytext);
1363 /************************************************************
1364 * Eat up the rest of the statement after the target fields
1365 ************************************************************/
1367 if (!have_nexttok) {
1375 if (plpgsql_SpaceScanned) {
1376 plpgsql_dstring_append(&ds, " ");
1380 params[nparams] = yylval.var->varno;
1381 sprintf(buf, "$%d", ++nparams);
1382 plpgsql_dstring_append(&ds, buf);
1386 params[nparams] = yylval.recfield->rfno;
1387 sprintf(buf, "$%d", ++nparams);
1388 plpgsql_dstring_append(&ds, buf);
1392 params[nparams] = yylval.trigarg->dno;
1393 sprintf(buf, "$%d", ++nparams);
1394 plpgsql_dstring_append(&ds, buf);
1399 plpgsql_error_lineno = yylineno;
1400 plpgsql_comperrinfo();
1401 elog(ERROR, "unexpected end of file");
1403 plpgsql_dstring_append(&ds, yytext);
1408 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * (nparams - 1));
1409 expr->dtype = PLPGSQL_DTYPE_EXPR;
1410 expr->query = strdup(plpgsql_dstring_get(&ds));
1412 expr->nparams = nparams;
1413 while(nparams-- > 0) {
1414 expr->params[nparams] = params[nparams];
1416 plpgsql_dstring_free(&ds);
1418 select = malloc(sizeof(PLpgSQL_stmt_select));
1419 memset(select, 0, sizeof(PLpgSQL_stmt_select));
1420 select->cmd_type = PLPGSQL_STMT_SELECT;
1423 select->query = expr;
1425 return (PLpgSQL_stmt *)select;
1429 static PLpgSQL_expr *
1430 make_tupret_expr(PLpgSQL_row *row)
1437 expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * (row->nfields - 1));
1438 expr->dtype = PLPGSQL_DTYPE_EXPR;
1440 plpgsql_dstring_init(&ds);
1441 plpgsql_dstring_append(&ds, "SELECT ");
1443 for (i = 0; i < row->nfields; i++) {
1444 sprintf(buf, "%s$%d", (i > 0) ? "," : "", i + 1);
1445 plpgsql_dstring_append(&ds, buf);
1446 expr->params[i] = row->varnos[i];
1449 expr->query = strdup(plpgsql_dstring_get(&ds));
1451 expr->plan_argtypes = NULL;
1452 expr->nparams = row->nfields;
1454 plpgsql_dstring_free(&ds);