-
Notifications
You must be signed in to change notification settings - Fork 766
Added support for parsing nested object in query for Snowflake #2359
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
cb33ca1
0c439b0
141df58
aebee46
c39397f
e8e783a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3657,6 +3657,32 @@ impl<'a> Parser<'a> { | |
| /// ``` | ||
| /// | ||
| /// [1]: https://duckdb.org/docs/sql/data_types/union.html | ||
| fn parse_object_data_type(&mut self) -> Result<DataType, ParserError> { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm this diff looks a bit off,does the comment above apply to this new function? it looks like it was rather meant for parse_union_type_def |
||
| self.expect_keyword_is(Keyword::OBJECT)?; | ||
| // Object type may have no fields: OBJECT or OBJECT() | ||
| if !self.peek_token_ref().token.eq(&Token::LParen) { | ||
| return Ok(DataType::Object { fields: None }); | ||
| } | ||
| self.expect_token(&Token::LParen)?; | ||
| let fields = if self.peek_token_ref().token == Token::RParen { | ||
| vec![] | ||
| } else { | ||
| self.parse_comma_separated(|parser| { | ||
| let field_name = parser.parse_identifier()?; | ||
| let field_type = parser.parse_data_type()?; | ||
| Ok(StructField { | ||
| field_name: Some(field_name), | ||
| field_type, | ||
| options: None, | ||
| }) | ||
| })? | ||
| }; | ||
| self.expect_token(&Token::RParen)?; | ||
| Ok(DataType::Object { | ||
| fields: Some(fields), | ||
| }) | ||
| } | ||
|
|
||
| fn parse_union_type_def(&mut self) -> Result<Vec<UnionField>, ParserError> { | ||
| self.expect_keyword_is(Keyword::UNION)?; | ||
|
|
||
|
|
@@ -13115,6 +13141,10 @@ impl<'a> Parser<'a> { | |
| let fields = self.parse_union_type_def()?; | ||
| Ok(DataType::Union(fields)) | ||
| } | ||
| Keyword::OBJECT if dialect_is!(dialect is SnowflakeDialect | GenericDialect) => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we change this to use a dialect method?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @iffyio, i dont understand what do you mean.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah so I meant to use instead a |
||
| self.prev_token(); | ||
| self.parse_object_data_type() | ||
| } | ||
| Keyword::NULLABLE if dialect_is!(dialect is ClickHouseDialect | GenericDialect) => { | ||
| Ok(self.parse_sub_type(DataType::Nullable)?) | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4912,3 +4912,21 @@ fn test_select_dollar_column_from_stage() { | |
| // With table function args, without alias | ||
| snowflake().verified_stmt("SELECT $1, $2 FROM @mystage1(file_format => 'myformat')"); | ||
| } | ||
|
|
||
| #[test] | ||
| fn parse_nested_object() { | ||
| // nested OBJECT with a single field | ||
| snowflake().verified_stmt("SELECT TRY_CAST(PARSE_JSON('{\"obj_field\":{\"field\":\"value\",}}') AS OBJECT(obj_field OBJECT(field VARCHAR)))"); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. heads up after switching to dialect method, these tests can use |
||
|
|
||
| // OBJECT with multiple fields | ||
| snowflake().verified_stmt("SELECT CAST(v AS OBJECT(a VARCHAR, b INT, c BOOLEAN))"); | ||
|
|
||
| // nested OBJECT with multiple fields at both levels | ||
| snowflake().verified_stmt("SELECT CAST(v AS OBJECT(x OBJECT(a INT, b VARCHAR), y NUMBER))"); | ||
|
|
||
| // OBJECT with zero fields (empty parentheses) | ||
| snowflake().verified_stmt("SELECT CAST(v AS OBJECT())"); | ||
|
|
||
| // bare OBJECT without parentheses round-trips as OBJECT | ||
| snowflake().verified_stmt("SELECT CAST(v AS OBJECT)"); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.