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,
2828 int *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 @@ static void 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 @@ static void 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 }
12121170 else
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{
19961897 PLpgSQL_dstring ds;
19971898 int nparams = 0 ;
@@ -2112,6 +2013,7 @@ make_select_stmt(void)
21122013
21132014 select = palloc0 (sizeof (PLpgSQL_stmt_select));
21142015 select->cmd_type = PLPGSQL_STMT_SELECT;
2016+ select->lineno = lineno;
21152017 select->rec = rec;
21162018 select->row = row;
21172019 select->query = expr;
@@ -2125,6 +2027,7 @@ make_select_stmt(void)
21252027
21262028 execsql = palloc (sizeof (PLpgSQL_stmt_execsql));
21272029 execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
2030+ execsql->lineno = lineno;
21282031 execsql->sqlstmt = expr;
21292032
21302033 return (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{
21382041 int tok;
21392042 PLpgSQL_row *row = NULL ;
@@ -2172,12 +2075,124 @@ make_fetch_stmt(void)
21722075 if (tok != ' ;' )
21732076 yyerror (" syntax error" );
21742077
2175- fetch = palloc0 (sizeof (PLpgSQL_stmt_select ));
2078+ fetch = palloc0 (sizeof (PLpgSQL_stmt_fetch ));
21762079 fetch->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
0 commit comments