Skip to content

Commit 2778211

Browse files
committed
handle the chain of the subscript and map accesses for generic and duckdb
1 parent 221b9dc commit 2778211

File tree

2 files changed

+68
-18
lines changed

2 files changed

+68
-18
lines changed

src/parser/mod.rs

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2919,12 +2919,23 @@ impl<'a> Parser<'a> {
29192919
})
29202920
} else if Token::LBracket == tok {
29212921
if dialect_of!(self is PostgreSqlDialect | DuckDbDialect | GenericDialect) {
2922-
self.parse_subscript(expr)
2922+
let expr = self.parse_multi_dim_subscript(expr)?;
2923+
if self.dialect.support_period_map_access_key() {
2924+
self.parse_map_access(expr, vec![])
2925+
} else {
2926+
Ok(expr)
2927+
}
29232928
} else if dialect_of!(self is SnowflakeDialect) {
29242929
self.prev_token();
29252930
self.parse_json_access(expr)
29262931
} else {
2927-
self.parse_map_access(expr)
2932+
let key = self.parse_expr()?;
2933+
self.expect_token(&Token::RBracket)?;
2934+
let keys = vec![MapAccessKey {
2935+
key,
2936+
syntax: MapAccessSyntax::Bracket,
2937+
}];
2938+
self.parse_map_access(expr, keys)
29282939
}
29292940
} else if dialect_of!(self is SnowflakeDialect | GenericDialect) && Token::Colon == tok {
29302941
self.prev_token();
@@ -3020,6 +3031,19 @@ impl<'a> Parser<'a> {
30203031
})
30213032
}
30223033

3034+
/// Parse an multi-dimension array accessing like '[1:3][1][1]'
3035+
///
3036+
/// Parser is right after the first `[`
3037+
pub fn parse_multi_dim_subscript(&mut self, mut expr: Expr) -> Result<Expr, ParserError> {
3038+
loop {
3039+
expr = self.parse_subscript(expr)?;
3040+
if !self.consume_token(&Token::LBracket) {
3041+
break;
3042+
}
3043+
}
3044+
Ok(expr)
3045+
}
3046+
30233047
/// Parses an array subscript like `[1:3]`
30243048
///
30253049
/// Parser is right after `[`
@@ -3085,14 +3109,15 @@ impl<'a> Parser<'a> {
30853109
})
30863110
}
30873111

3088-
pub fn parse_map_access(&mut self, expr: Expr) -> Result<Expr, ParserError> {
3089-
let key = self.parse_expr()?;
3090-
self.expect_token(&Token::RBracket)?;
3091-
3092-
let mut keys = vec![MapAccessKey {
3093-
key,
3094-
syntax: MapAccessSyntax::Bracket,
3095-
}];
3112+
/// Parse the map access like `[key]` or `.key` if [Dialect::support_period_map_access_key] is true
3113+
/// It could be an access-chain like `[key1][key2].key3`
3114+
///
3115+
/// The parameter `keys` is an initialized buffer that could contain some keys parsed from other places.
3116+
pub fn parse_map_access(
3117+
&mut self,
3118+
expr: Expr,
3119+
mut keys: Vec<MapAccessKey>,
3120+
) -> Result<Expr, ParserError> {
30963121
loop {
30973122
let key = match self.peek_token().token {
30983123
Token::LBracket => {
@@ -3104,10 +3129,7 @@ impl<'a> Parser<'a> {
31043129
syntax: MapAccessSyntax::Bracket,
31053130
}
31063131
}
3107-
// Access on BigQuery nested and repeated expressions can
3108-
// mix notations in the same expression.
3109-
// https://cloud.google.com/bigquery/docs/nested-repeated#query_nested_and_repeated_columns
3110-
Token::Period if dialect_of!(self is BigQueryDialect) => {
3132+
Token::Period if self.dialect.support_period_map_access_key() => {
31113133
self.next_token(); // consume `.`
31123134
MapAccessKey {
31133135
key: self.parse_expr()?,
@@ -3119,10 +3141,16 @@ impl<'a> Parser<'a> {
31193141
keys.push(key);
31203142
}
31213143

3122-
Ok(Expr::MapAccess {
3123-
column: Box::new(expr),
3124-
keys,
3125-
})
3144+
// If no any key be collected, it means the elements have been parsed to [Subscript]
3145+
// e.g. `select abc[1]` or `select abc[1][2]`
3146+
if keys.is_empty() {
3147+
Ok(expr)
3148+
} else {
3149+
Ok(Expr::MapAccess {
3150+
column: Box::new(expr),
3151+
keys,
3152+
})
3153+
}
31263154
}
31273155

31283156
/// Parses the parens following the `[ NOT ] IN` operator.

tests/sqlparser_common.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12013,3 +12013,25 @@ fn parse_create_table_select() {
1201312013
);
1201412014
}
1201512015
}
12016+
12017+
#[test]
12018+
fn test_period_map_access() {
12019+
let supported_dialects = TestedDialects::new(vec![
12020+
Box::new(GenericDialect {}),
12021+
Box::new(DuckDbDialect {}),
12022+
]);
12023+
let sqls = [
12024+
"SELECT abc[1] FROM t",
12025+
"SELECT abc[1].f1 FROM t",
12026+
"SELECT abc[1].f1.f2 FROM t",
12027+
"SELECT f1.abc[1] FROM t",
12028+
"SELECT f1.f2.abc[1] FROM t",
12029+
"SELECT f1.abc[1].f2 FROM t",
12030+
"SELECT abc['a'][1].f1 FROM t",
12031+
"SELECT abc['a'].f1[1].f2 FROM t",
12032+
"SELECT abc['a'].f1[1].f2[2] FROM t",
12033+
];
12034+
for sql in sqls {
12035+
supported_dialects.verified_stmt(sql);
12036+
}
12037+
}

0 commit comments

Comments
 (0)