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


##########
src/parser/mod.rs:
##########
@@ -11679,14 +11679,21 @@ impl<'a> Parser<'a> {
     pub fn parse_update(&mut self) -> Result<Statement, ParserError> {
         let or = self.parse_conflict_clause();
         let table = self.parse_table_and_joins()?;
+        let from_before_set = if self.parse_keyword(Keyword::FROM)
+            && dialect_of!(self is GenericDialect | PostgreSqlDialect | 
DuckDbDialect | BigQueryDialect | SnowflakeDialect | RedshiftSqlDialect | 
MsSqlDialect | SQLiteDialect )

Review Comment:
   I'm thinking since the functionality does not conflict with other dialects 
we can skip the dialect guards and parse the `FROM (SELECT ...)` as long as it 
exists?



##########
src/parser/mod.rs:
##########
@@ -11679,14 +11679,21 @@ impl<'a> Parser<'a> {
     pub fn parse_update(&mut self) -> Result<Statement, ParserError> {
         let or = self.parse_conflict_clause();
         let table = self.parse_table_and_joins()?;
+        let from_before_set = if self.parse_keyword(Keyword::FROM)
+            && dialect_of!(self is GenericDialect | PostgreSqlDialect | 
DuckDbDialect | BigQueryDialect | SnowflakeDialect | RedshiftSqlDialect | 
MsSqlDialect | SQLiteDialect )
+        {
+            Some(self.parse_table_and_joins()?)
+        } else {
+            None
+        };
         self.expect_keyword(Keyword::SET)?;
         let assignments = 
self.parse_comma_separated(Parser::parse_assignment)?;
         let from = if self.parse_keyword(Keyword::FROM)
             && dialect_of!(self is GenericDialect | PostgreSqlDialect | 
DuckDbDialect | BigQueryDialect | SnowflakeDialect | RedshiftSqlDialect | 
MsSqlDialect | SQLiteDialect )
         {
             Some(self.parse_table_and_joins()?)
         } else {
-            None
+            from_before_set

Review Comment:
   Could we instead introduce a wrapper type to encode the position information?
   Something like
   ```rust
   enum UpdateTableFromKind {
        BeforeSet(TableWithJoins),
        AfterSet(TableWithJoins)
   }
   ...
   Statement::Update {... from: Option<UpdateTableFromKind> }
   ```
   See 
[TableSampleKind](https://github.com/yoavcloud/datafusion-sqlparser-rs/blob/eae5629fb86f5e262063c0bc99ff628a5855168f/src/ast/query.rs#L1157-L1162)
 for an example on this approach.
   
   That would ensure that we can produce the same sql as in the input.



##########
tests/sqlparser_snowflake.rs:
##########
@@ -2974,3 +2974,10 @@ fn test_table_sample() {
     snowflake_and_generic().verified_stmt("SELECT id FROM mytable TABLESAMPLE 
(10) REPEATABLE (1)");
     snowflake_and_generic().verified_stmt("SELECT id FROM mytable TABLESAMPLE 
(10) SEED (1)");
 }
+
+#[test]
+fn parse_update_from_before_select() {

Review Comment:
   note if we drop the dialect guard, we can move the tests to 
sqlparser_common.rs to cover all dialects.
   
   Also could we add a test case demonstrating the behavior mentioned above 
where we have two `FROM` clauses? e.g.
   ```sql
   UPDATE t1 FROM (SELECT ... ) AS t2 SET name = t2.name FROM (SELECT ...) AS 
t2;
   ``` 



##########
src/parser/mod.rs:
##########
@@ -11679,14 +11679,21 @@ impl<'a> Parser<'a> {
     pub fn parse_update(&mut self) -> Result<Statement, ParserError> {
         let or = self.parse_conflict_clause();
         let table = self.parse_table_and_joins()?;
+        let from_before_set = if self.parse_keyword(Keyword::FROM)
+            && dialect_of!(self is GenericDialect | PostgreSqlDialect | 
DuckDbDialect | BigQueryDialect | SnowflakeDialect | RedshiftSqlDialect | 
MsSqlDialect | SQLiteDialect )
+        {
+            Some(self.parse_table_and_joins()?)
+        } else {
+            None
+        };
         self.expect_keyword(Keyword::SET)?;
         let assignments = 
self.parse_comma_separated(Parser::parse_assignment)?;
         let from = if self.parse_keyword(Keyword::FROM)

Review Comment:
   thinking here in order to be correct we might need to check `if 
from_before_set.is_none() && self.parse_keyword(FROM) ...`? I'm assuming that 
the intention is that it is invalid sql to provide both?



-- 
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