iffyio commented on code in PR #1765:
URL: 
https://github.com/apache/datafusion-sqlparser-rs/pull/1765#discussion_r1990717603

##########
src/parser/mod.rs:
##########
@@ -10272,20 +10269,33 @@ impl<'a> Parser<'a> {
                 {
                     // MySQL style LIMIT x,y => LIMIT y OFFSET x.
                     // Check 
<https://dev.mysql.com/doc/refman/8.0/en/select.html> for more details.
-                    offset = Some(Offset {
-                        value: limit.unwrap(),
-                        rows: OffsetRows::None,
-                    });
+                    limit_comma_offset = limit.take();
                     limit = Some(self.parse_expr()?);
                 }
             }
 
-            let limit_by = if dialect_of!(self is ClickHouseDialect | 
GenericDialect)
+            let limit_by = if limit_comma_offset.is_none()

Review Comment:
   should this condition rather be `if limit.is_some()`? it looks like `SELECT 
* FROM T BY abc` would parse successfully but the `BY clause` will be dropped, 
since all the limit/offset options above will be None whereas here we will 
parse the `BY` without using it



##########
src/parser/mod.rs:
##########
@@ -10272,20 +10269,33 @@ impl<'a> Parser<'a> {
                 {
                     // MySQL style LIMIT x,y => LIMIT y OFFSET x.
                     // Check 
<https://dev.mysql.com/doc/refman/8.0/en/select.html> for more details.
-                    offset = Some(Offset {
-                        value: limit.unwrap(),
-                        rows: OffsetRows::None,
-                    });
+                    limit_comma_offset = limit.take();
                     limit = Some(self.parse_expr()?);
                 }
             }
 
-            let limit_by = if dialect_of!(self is ClickHouseDialect | 
GenericDialect)
+            let limit_by = if limit_comma_offset.is_none()
+                && dialect_of!(self is ClickHouseDialect | GenericDialect)
                 && self.parse_keyword(Keyword::BY)
             {
-                self.parse_comma_separated(Parser::parse_expr)?
+                Some(self.parse_comma_separated(Parser::parse_expr)?)
             } else {
-                vec![]
+                None
+            };
+
+            let limit_clause = if let Some(offset) = limit_comma_offset {
+                Some(LimitClause::OffsetCommaLimit {
+                    offset,
+                    limit: limit.expect("Expected <limit> expression for LIMIT 
<offset>, <limit>"),
+                })
+            } else if limit.is_some() || offset.is_some() || 
limit_by.is_some() {

Review Comment:
   for the full flow, thinking the post processing could be combined with the 
loop in order to avoid the is_some() checks and would make a few currently 
invalid syntax be rejected, thinking something like this?
   
   ```rust
   let limit_clause = None;
   let limit = None;
   let offset = None;
   
   for _ in 0..3 {
     if offset.is_none() && self.parse_keyword(OFFSET) {
       offset = Some(self.parse_offset()?);
       continue
     }
   
     if limit.is_none() && self.parse_keyword(LIMIT) {
       let expr = self.parse_limit()?;
       if offset.is_none() && self.dialect.supports_limit_comma() && 
self.consume_token(Comma) {
         limit_clause = Some(LimitClause::OffsetCommLimit {
           offset: expr,
           limit: self.parse_expr()?;
         });
         break
       }
       continue
     }
   
     if limit.is_some() && dialect_of!(self is ClickHouseDialect | 
GenericDialect) && self.parse_keyword(BY) {
       limit_clause = Some(LimitClause::LimitOffset{
         limit: limit.take(),
         offset: offset.take(),
         limit_by: Some(self.parse_comma_separated(Parser::parse_expr)?)
       })
       break
     }
   
     limit_clause = if limit.is_some() || offset_is_some() {
         limit_clause = Some(LimitClause::LimitOffset{
           limit: limit,
           offset: offset,
           limit_by: None
         });
     };
     break
   }
   ```
   
   atm looks like there are some queries like `SELECT * FROM T OFFSET 5 BY foo` 
which look like they'd be accepted but aren't valid, figured it might be 
clearer to make those terminal states visible in the code with above snippet



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscr...@datafusion.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: github-unsubscr...@datafusion.apache.org
For additional commands, e-mail: github-h...@datafusion.apache.org

Reply via email to