1111 *
1212 *
1313 * IDENTIFICATION
14- * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.676 2009/08/02 22:14:52 tgl Exp $
14+ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.677 2009/08/18 23:40:20 tgl Exp $
1515 *
1616 * HISTORY
1717 * AUTHORDATEMAJOR EVENT
@@ -331,7 +331,8 @@ static TypeName *TableFuncTypeName(List *columns);
331331%type <ival> opt_column event cursor_options opt_hold opt_set_data
332332%type <objtype> reindex_type drop_type comment_type
333333
334- %type <node> fetch_direction select_limit_value select_offset_value
334+ %type <node> fetch_direction limit_clause select_limit_value
335+ offset_clause select_offset_value
335336select_offset_value2 opt_select_fetch_first_value
336337%type <ival> row_or_rows first_or_next
337338
@@ -7228,14 +7229,20 @@ sortby:a_expr USING qual_all_Op opt_nulls_order
72287229
72297230
72307231select_limit:
7231- LIMIT select_limit_value OFFSET select_offset_value
7232- {$$ = list_make2($4 ,$2 ); }
7233- | OFFSET select_offset_value LIMIT select_limit_value
7234- {$$ = list_make2($2 ,$4 ); }
7235- | LIMIT select_limit_value
7236- {$$ = list_make2(NULL ,$2 ); }
7237- | OFFSET select_offset_value
7238- {$$ = list_make2($2 ,NULL ); }
7232+ limit_clause offset_clause{$$ = list_make2($2 ,$1 ); }
7233+ | offset_clause limit_clause{$$ = list_make2($1 ,$2 ); }
7234+ | limit_clause{$$ = list_make2(NULL ,$1 ); }
7235+ | offset_clause{$$ = list_make2($1 ,NULL ); }
7236+ ;
7237+
7238+ opt_select_limit:
7239+ select_limit{$$ =$1 ; }
7240+ |/* EMPTY*/ {$$ = list_make2(NULL ,NULL ); }
7241+ ;
7242+
7243+ limit_clause:
7244+ LIMIT select_limit_value
7245+ {$$ =$2 ; }
72397246| LIMIT select_limit_value' ,' select_offset_value
72407247{
72417248/* Disabled because it was too confusing, bjm 2002-02-18*/
@@ -7245,19 +7252,17 @@ select_limit:
72457252 errhint(" Use separate LIMIT and OFFSET clauses." ),
72467253 parser_errposition(@1 )));
72477254}
7248- /* SQL:2008 syntax variants*/
7249- | OFFSET select_offset_value2 row_or_rows
7250- {$$ = list_make2($2 ,NULL ); }
7255+ /* SQL:2008 syntax*/
72517256| FETCH first_or_next opt_select_fetch_first_value row_or_rows ONLY
7252- {$$ = list_make2(NULL ,$3 ); }
7253- | OFFSET select_offset_value2 row_or_rows FETCH first_or_next opt_select_fetch_first_value row_or_rows ONLY
7254- {$$ = list_make2($2 ,$6 ); }
7257+ {$$ =$3 ; }
72557258;
72567259
7257- opt_select_limit:
7258- select_limit{$$ =$1 ; }
7259- |/* EMPTY*/
7260- {$$ = list_make2(NULL ,NULL ); }
7260+ offset_clause:
7261+ OFFSET select_offset_value
7262+ {$$ =$2 ; }
7263+ /* SQL:2008 syntax*/
7264+ | OFFSET select_offset_value2 row_or_rows
7265+ {$$ =$2 ; }
72617266;
72627267
72637268select_limit_value:
@@ -7269,19 +7274,20 @@ select_limit_value:
72697274}
72707275;
72717276
7277+ select_offset_value:
7278+ a_expr{$$ =$1 ; }
7279+ ;
7280+
72727281/*
72737282 * Allowing full expressions without parentheses causes various parsing
72747283 * problems with the trailing ROW/ROWS key words. SQL only calls for
7275- * constants, so we allow the rest only with parentheses.
7284+ * constants, so we allow the rest only with parentheses. If omitted,
7285+ * default to 1.
72767286*/
72777287opt_select_fetch_first_value:
7278- SignedIconst{$$ = makeIntConst($1 ,@1 ); }
7279- |' (' a_expr' )' {$$ =$2 ; }
7280- |/* EMPTY*/ {$$ = makeIntConst(1 , -1 ); }
7281- ;
7282-
7283- select_offset_value:
7284- a_expr{$$ =$1 ; }
7288+ SignedIconst{$$ = makeIntConst($1 ,@1 ); }
7289+ |' (' a_expr' )' {$$ =$2 ; }
7290+ |/* EMPTY*/ {$$ = makeIntConst(1 , -1 ); }
72857291;
72867292
72877293/*
@@ -7293,16 +7299,14 @@ select_offset_value2:
72937299;
72947300
72957301/* noise words*/
7296- row_or_rows:
7297- ROW{$$ =0 ; }
7298- | ROWS{$$ =0 ; }
7299- ;
7302+ row_or_rows: ROW{$$ =0 ; }
7303+ | ROWS{$$ =0 ; }
7304+ ;
7305+
7306+ first_or_next: FIRST_P{$$ =0 ; }
7307+ | NEXT{$$ =0 ; }
7308+ ;
73007309
7301- /* noise words*/
7302- first_or_next:
7303- FIRST_P{$$ =0 ; }
7304- | NEXT{$$ =0 ; }
7305- ;
73067310
73077311group_clause:
73087312GROUP_P BY expr_list{$$ =$3 ; }