99 *
1010 *
1111 * IDENTIFICATION
12- * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.93 2006/06/16 23:29:26 tgl Exp $
12+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.94 2006/08/14 00:46:53 tgl Exp $
1313 *
1414 *-------------------------------------------------------------------------
1515*/
@@ -28,8 +28,10 @@ static PLpgSQL_expr*read_sql_construct(int until,
2828int *endtoken);
2929static PLpgSQL_expr*read_sql_stmt (const char *sqlstart);
3030static PLpgSQL_type*read_datatype (int tok);
31- static PLpgSQL_stmt*make_select_stmt (void );
32- static PLpgSQL_stmt*make_fetch_stmt (void );
31+ static PLpgSQL_stmt*make_select_stmt (int lineno);
32+ static PLpgSQL_stmt*make_fetch_stmt (int lineno,int curvar);
33+ static PLpgSQL_stmt*make_return_stmt (int lineno);
34+ static PLpgSQL_stmt*make_return_next_stmt (int lineno);
3335static void check_assignable (PLpgSQL_datum *datum);
3436static PLpgSQL_row*read_into_scalar_list (const char *initial_name,
3537 PLpgSQL_datum *initial_datum);
@@ -118,7 +120,7 @@ staticvoid check_labels(const char *start_label,
118120%type <loop_body> loop_body
119121%type <stmt> proc_stmt pl_block
120122%type <stmt> stmt_assign stmt_if stmt_loop stmt_while stmt_exit
121- %type <stmt> stmt_return stmt_return_next stmt_raise stmt_execsql
123+ %type <stmt> stmt_return stmt_raise stmt_execsql
122124%type <stmt> stmt_for stmt_select stmt_perform
123125%type <stmt> stmt_dynexecute stmt_getdiag
124126%type <stmt> stmt_open stmt_fetch stmt_close stmt_null
@@ -183,7 +185,6 @@ staticvoid check_labels(const char *start_label,
183185%token K_RENAME
184186%token K_RESULT_OID
185187%token K_RETURN
186- %token K_RETURN_NEXT
187188%token K_REVERSE
188189%token K_SELECT
189190%token K_STRICT
@@ -596,8 +597,6 @@ proc_stmt: pl_block ';'
596597{$$ =$1 ; }
597598| stmt_return
598599{$$ =$1 ; }
599- | stmt_return_next
600- {$$ =$1 ; }
601600| stmt_raise
602601{$$ =$1 ; }
603602| stmt_execsql
@@ -1130,8 +1129,7 @@ for_variable: T_SCALAR
11301129
11311130stmt_select :K_SELECT lno
11321131{
1133- $$ = make_select_stmt();
1134- $$ ->lineno =$2 ;
1132+ $$ = make_select_stmt($2 );
11351133}
11361134;
11371135
@@ -1162,109 +1160,18 @@ exit_type: K_EXIT
11621160
11631161stmt_return :K_RETURN lno
11641162{
1165- PLpgSQL_stmt_return *new ;
1166-
1167- new = palloc0(sizeof (PLpgSQL_stmt_return));
1168- new ->cmd_type = PLPGSQL_STMT_RETURN;
1169- new ->lineno =$2 ;
1170- new ->expr =NULL ;
1171- new ->retvarno = -1 ;
1163+ int tok;
11721164
1173- if (plpgsql_curr_compile->fn_retset)
1174- {
1175- if (yylex () !=' ;' )
1176- yyerror (" RETURN cannot have a parameter in function returning set; use RETURN NEXT" );
1177- }
1178- else if (plpgsql_curr_compile->out_param_varno >=0 )
1179- {
1180- if (yylex () !=' ;' )
1181- yyerror (" RETURN cannot have a parameter in function with OUT parameters" );
1182- new ->retvarno = plpgsql_curr_compile->out_param_varno;
1183- }
1184- else if (plpgsql_curr_compile->fn_rettype == VOIDOID)
1165+ tok =yylex ();
1166+ if (tok == K_NEXT)
11851167{
1186- if (yylex () !=' ;' )
1187- yyerror (" RETURN cannot have a parameter in function returning void" );
1188- }
1189- else if (plpgsql_curr_compile->fn_retistuple)
1190- {
1191- switch (yylex ())
1192- {
1193- case K_NULL:
1194- /* we allow this to support RETURN NULL in triggers*/
1195- break ;
1196-
1197- case T_ROW:
1198- new ->retvarno = yylval.row->rowno;
1199- break ;
1200-
1201- case T_RECORD:
1202- new ->retvarno = yylval.rec->recno;
1203- break ;
1204-
1205- default :
1206- yyerror (" RETURN must specify a record or row variable in function returning tuple" );
1207- break ;
1208- }
1209- if (yylex () !=' ;' )
1210- yyerror (" RETURN must specify a record or row variable in function returning tuple" );
1168+ $$ = make_return_next_stmt($2 );
12111169}
12121170else
12131171{
1214- /*
1215- * Note that a well-formed expression is
1216- * _required_ here; anything else is a
1217- * compile-time error.
1218- */
1219- new ->expr = plpgsql_read_expression(' ;' ," ;" );
1172+ plpgsql_push_back_token (tok);
1173+ $$ = make_return_stmt($2 );
12201174}
1221-
1222- $$ = (PLpgSQL_stmt *)new ;
1223- }
1224- ;
1225-
1226- stmt_return_next :K_RETURN_NEXT lno
1227- {
1228- PLpgSQL_stmt_return_next *new ;
1229-
1230- if (!plpgsql_curr_compile->fn_retset)
1231- yyerror (" cannot use RETURN NEXT in a non-SETOF function" );
1232-
1233- new = palloc0(sizeof (PLpgSQL_stmt_return_next));
1234- new ->cmd_type= PLPGSQL_STMT_RETURN_NEXT;
1235- new ->lineno=$2 ;
1236- new ->expr =NULL ;
1237- new ->retvarno= -1 ;
1238-
1239- if (plpgsql_curr_compile->out_param_varno >=0 )
1240- {
1241- if (yylex () !=' ;' )
1242- yyerror (" RETURN NEXT cannot have a parameter in function with OUT parameters" );
1243- new ->retvarno = plpgsql_curr_compile->out_param_varno;
1244- }
1245- else if (plpgsql_curr_compile->fn_retistuple)
1246- {
1247- switch (yylex ())
1248- {
1249- case T_ROW:
1250- new ->retvarno = yylval.row->rowno;
1251- break ;
1252-
1253- case T_RECORD:
1254- new ->retvarno = yylval.rec->recno;
1255- break ;
1256-
1257- default :
1258- yyerror (" RETURN NEXT must specify a record or row variable in function returning tuple" );
1259- break ;
1260- }
1261- if (yylex () !=' ;' )
1262- yyerror (" RETURN NEXT must specify a record or row variable in function returning tuple" );
1263- }
1264- else
1265- new ->expr = plpgsql_read_expression(' ;' ," ;" );
1266-
1267- $$ = (PLpgSQL_stmt *)new ;
12681175}
12691176;
12701177
@@ -1537,13 +1444,7 @@ stmt_open: K_OPEN lno cursor_varptr
15371444
15381445stmt_fetch :K_FETCH lno cursor_variable K_INTO
15391446{
1540- PLpgSQL_stmt_fetch *new ;
1541-
1542- new = (PLpgSQL_stmt_fetch *)make_fetch_stmt();
1543- new ->curvar =$3 ;
1544-
1545- $$ = (PLpgSQL_stmt *)new ;
1546- $$ ->lineno =$2 ;
1447+ $$ = make_fetch_stmt($2 ,$3 );
15471448}
15481449;
15491450
@@ -1991,7 +1892,7 @@ read_datatype(int tok)
19911892}
19921893
19931894static PLpgSQL_stmt *
1994- make_select_stmt (void )
1895+ make_select_stmt (int lineno )
19951896{
19961897PLpgSQL_dstringds;
19971898int nparams =0 ;
@@ -2112,6 +2013,7 @@ make_select_stmt(void)
21122013
21132014select =palloc0 (sizeof (PLpgSQL_stmt_select));
21142015select->cmd_type = PLPGSQL_STMT_SELECT;
2016+ select->lineno = lineno;
21152017select->rec = rec;
21162018select->row = row;
21172019select->query = expr;
@@ -2125,6 +2027,7 @@ make_select_stmt(void)
21252027
21262028execsql =palloc (sizeof (PLpgSQL_stmt_execsql));
21272029execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
2030+ execsql->lineno = lineno;
21282031execsql->sqlstmt = expr;
21292032
21302033return (PLpgSQL_stmt *)execsql;
@@ -2133,7 +2036,7 @@ make_select_stmt(void)
21332036
21342037
21352038static PLpgSQL_stmt *
2136- make_fetch_stmt (void )
2039+ make_fetch_stmt (int lineno, int curvar )
21372040{
21382041int tok;
21392042PLpgSQL_row *row =NULL ;
@@ -2172,12 +2075,124 @@ make_fetch_stmt(void)
21722075if (tok !=' ;' )
21732076yyerror (" syntax error" );
21742077
2175- fetch =palloc0 (sizeof (PLpgSQL_stmt_select ));
2078+ fetch =palloc0 (sizeof (PLpgSQL_stmt_fetch ));
21762079fetch->cmd_type = PLPGSQL_STMT_FETCH;
2177- fetch->rec = rec;
2178- fetch->row = row;
2080+ fetch->lineno = lineno;
2081+ fetch->rec = rec;
2082+ fetch->row = row;
2083+ fetch->curvar = curvar;
2084+
2085+ return (PLpgSQL_stmt *) fetch;
2086+ }
2087+
2088+
2089+ static PLpgSQL_stmt *
2090+ make_return_stmt (int lineno)
2091+ {
2092+ PLpgSQL_stmt_return *new ;
2093+
2094+ new =palloc0 (sizeof (PLpgSQL_stmt_return));
2095+ new ->cmd_type = PLPGSQL_STMT_RETURN;
2096+ new ->lineno = lineno;
2097+ new ->expr =NULL ;
2098+ new ->retvarno = -1 ;
2099+
2100+ if (plpgsql_curr_compile->fn_retset )
2101+ {
2102+ if (yylex () !=' ;' )
2103+ yyerror (" RETURN cannot have a parameter in function returning set; use RETURN NEXT" );
2104+ }
2105+ else if (plpgsql_curr_compile->out_param_varno >=0 )
2106+ {
2107+ if (yylex () !=' ;' )
2108+ yyerror (" RETURN cannot have a parameter in function with OUT parameters" );
2109+ new ->retvarno = plpgsql_curr_compile->out_param_varno ;
2110+ }
2111+ else if (plpgsql_curr_compile->fn_rettype == VOIDOID)
2112+ {
2113+ if (yylex () !=' ;' )
2114+ yyerror (" RETURN cannot have a parameter in function returning void" );
2115+ }
2116+ else if (plpgsql_curr_compile->fn_retistuple )
2117+ {
2118+ switch (yylex ())
2119+ {
2120+ case K_NULL:
2121+ /* we allow this to support RETURN NULL in triggers*/
2122+ break ;
2123+
2124+ case T_ROW:
2125+ new ->retvarno = yylval.row ->rowno ;
2126+ break ;
2127+
2128+ case T_RECORD:
2129+ new ->retvarno = yylval.rec ->recno ;
2130+ break ;
2131+
2132+ default :
2133+ yyerror (" RETURN must specify a record or row variable in function returning tuple" );
2134+ break ;
2135+ }
2136+ if (yylex () !=' ;' )
2137+ yyerror (" RETURN must specify a record or row variable in function returning tuple" );
2138+ }
2139+ else
2140+ {
2141+ /*
2142+ * Note that a well-formed expression is
2143+ * _required_ here; anything else is a
2144+ * compile-time error.
2145+ */
2146+ new ->expr =plpgsql_read_expression (' ;' ," ;" );
2147+ }
2148+
2149+ return (PLpgSQL_stmt *)new ;
2150+ }
2151+
2152+
2153+ static PLpgSQL_stmt *
2154+ make_return_next_stmt (int lineno)
2155+ {
2156+ PLpgSQL_stmt_return_next *new ;
2157+
2158+ if (!plpgsql_curr_compile->fn_retset )
2159+ yyerror (" cannot use RETURN NEXT in a non-SETOF function" );
2160+
2161+ new =palloc0 (sizeof (PLpgSQL_stmt_return_next));
2162+ new ->cmd_type = PLPGSQL_STMT_RETURN_NEXT;
2163+ new ->lineno = lineno;
2164+ new ->expr =NULL ;
2165+ new ->retvarno = -1 ;
2166+
2167+ if (plpgsql_curr_compile->out_param_varno >=0 )
2168+ {
2169+ if (yylex () !=' ;' )
2170+ yyerror (" RETURN NEXT cannot have a parameter in function with OUT parameters" );
2171+ new ->retvarno = plpgsql_curr_compile->out_param_varno ;
2172+ }
2173+ else if (plpgsql_curr_compile->fn_retistuple )
2174+ {
2175+ switch (yylex ())
2176+ {
2177+ case T_ROW:
2178+ new ->retvarno = yylval.row ->rowno ;
2179+ break ;
2180+
2181+ case T_RECORD:
2182+ new ->retvarno = yylval.rec ->recno ;
2183+ break ;
2184+
2185+ default :
2186+ yyerror (" RETURN NEXT must specify a record or row variable in function returning tuple" );
2187+ break ;
2188+ }
2189+ if (yylex () !=' ;' )
2190+ yyerror (" RETURN NEXT must specify a record or row variable in function returning tuple" );
2191+ }
2192+ else
2193+ new ->expr =plpgsql_read_expression (' ;' ," ;" );
21792194
2180- return (PLpgSQL_stmt *)fetch ;
2195+ return (PLpgSQL_stmt *)new ;
21812196}
21822197
21832198