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