mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-31 11:17:23 +00:00
Add support for arbitrary map access expr (#1179)
This commit is contained in:
parent
127be97369
commit
eda86d8ed7
5 changed files with 194 additions and 116 deletions
|
@ -1402,39 +1402,48 @@ fn bigquery_and_generic() -> TestedDialects {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn parse_map_access_offset() {
|
||||
let sql = "SELECT d[offset(0)]";
|
||||
let _select = bigquery().verified_only_select(sql);
|
||||
assert_eq!(
|
||||
_select.projection[0],
|
||||
SelectItem::UnnamedExpr(Expr::MapAccess {
|
||||
column: Box::new(Expr::Identifier(Ident {
|
||||
value: "d".to_string(),
|
||||
quote_style: None,
|
||||
})),
|
||||
keys: vec![Expr::Function(Function {
|
||||
name: ObjectName(vec!["offset".into()]),
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
|
||||
number("0")
|
||||
))),],
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
})],
|
||||
})
|
||||
);
|
||||
fn parse_map_access_expr() {
|
||||
let sql = "users[-1][safe_offset(2)].a.b";
|
||||
let expr = bigquery().verified_expr(sql);
|
||||
|
||||
// test other operators
|
||||
for sql in [
|
||||
"SELECT d[SAFE_OFFSET(0)]",
|
||||
"SELECT d[ORDINAL(0)]",
|
||||
"SELECT d[SAFE_ORDINAL(0)]",
|
||||
] {
|
||||
bigquery().verified_only_select(sql);
|
||||
fn map_access_key(key: Expr, syntax: MapAccessSyntax) -> MapAccessKey {
|
||||
MapAccessKey { key, syntax }
|
||||
}
|
||||
let expected = Expr::MapAccess {
|
||||
column: Expr::Identifier(Ident::new("users")).into(),
|
||||
keys: vec![
|
||||
map_access_key(
|
||||
Expr::UnaryOp {
|
||||
op: UnaryOperator::Minus,
|
||||
expr: Expr::Value(number("1")).into(),
|
||||
},
|
||||
MapAccessSyntax::Bracket,
|
||||
),
|
||||
map_access_key(
|
||||
Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("safe_offset")]),
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
|
||||
number("2"),
|
||||
)))],
|
||||
filter: None,
|
||||
null_treatment: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
}),
|
||||
MapAccessSyntax::Bracket,
|
||||
),
|
||||
map_access_key(
|
||||
Expr::CompoundIdentifier(vec![Ident::new("a"), Ident::new("b")]),
|
||||
MapAccessSyntax::Period,
|
||||
),
|
||||
],
|
||||
};
|
||||
assert_eq!(expr, expected);
|
||||
|
||||
let sql = "SELECT myfunc()[-1].a[SAFE_OFFSET(2)].b";
|
||||
bigquery().verified_only_select(sql);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -39,23 +39,26 @@ fn parse_map_access_expr() {
|
|||
value: "string_values".to_string(),
|
||||
quote_style: None,
|
||||
})),
|
||||
keys: vec![Expr::Function(Function {
|
||||
name: ObjectName(vec!["indexOf".into()]),
|
||||
args: vec![
|
||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier(Ident::new(
|
||||
"string_names"
|
||||
)))),
|
||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
|
||||
Value::SingleQuotedString("endpoint".to_string())
|
||||
))),
|
||||
],
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
})],
|
||||
keys: vec![MapAccessKey {
|
||||
key: Expr::Function(Function {
|
||||
name: ObjectName(vec!["indexOf".into()]),
|
||||
args: vec![
|
||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier(
|
||||
Ident::new("string_names")
|
||||
))),
|
||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
|
||||
Value::SingleQuotedString("endpoint".to_string())
|
||||
))),
|
||||
],
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
}),
|
||||
syntax: MapAccessSyntax::Bracket
|
||||
}],
|
||||
})],
|
||||
into: None,
|
||||
from: vec![TableWithJoins {
|
||||
|
@ -80,23 +83,26 @@ fn parse_map_access_expr() {
|
|||
right: Box::new(BinaryOp {
|
||||
left: Box::new(MapAccess {
|
||||
column: Box::new(Identifier(Ident::new("string_value"))),
|
||||
keys: vec![Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("indexOf")]),
|
||||
args: vec![
|
||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier(
|
||||
Ident::new("string_name")
|
||||
))),
|
||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
|
||||
Value::SingleQuotedString("app".to_string())
|
||||
))),
|
||||
],
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
})],
|
||||
keys: vec![MapAccessKey {
|
||||
key: Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("indexOf")]),
|
||||
args: vec![
|
||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier(
|
||||
Ident::new("string_name")
|
||||
))),
|
||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
|
||||
Value::SingleQuotedString("app".to_string())
|
||||
))),
|
||||
],
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
}),
|
||||
syntax: MapAccessSyntax::Bracket
|
||||
}],
|
||||
}),
|
||||
op: BinaryOperator::NotEq,
|
||||
right: Box::new(Expr::Value(Value::SingleQuotedString("foo".to_string()))),
|
||||
|
|
|
@ -8643,3 +8643,45 @@ fn test_buffer_reuse() {
|
|||
p.parse_statements().unwrap();
|
||||
let _ = p.into_tokens();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_map_access_expr() {
|
||||
let sql = "users[-1][safe_offset(2)]";
|
||||
let dialects = TestedDialects {
|
||||
dialects: vec![Box::new(BigQueryDialect {}), Box::new(ClickHouseDialect {})],
|
||||
options: None,
|
||||
};
|
||||
let expr = dialects.verified_expr(sql);
|
||||
let expected = Expr::MapAccess {
|
||||
column: Expr::Identifier(Ident::new("users")).into(),
|
||||
keys: vec![
|
||||
MapAccessKey {
|
||||
key: Expr::UnaryOp {
|
||||
op: UnaryOperator::Minus,
|
||||
expr: Expr::Value(number("1")).into(),
|
||||
},
|
||||
syntax: MapAccessSyntax::Bracket,
|
||||
},
|
||||
MapAccessKey {
|
||||
key: Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("safe_offset")]),
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
|
||||
number("2"),
|
||||
)))],
|
||||
filter: None,
|
||||
null_treatment: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
}),
|
||||
syntax: MapAccessSyntax::Bracket,
|
||||
},
|
||||
],
|
||||
};
|
||||
assert_eq!(expr, expected);
|
||||
|
||||
for sql in ["users[1]", "a[array_length(b) - 1 + 2][c + 3][d * 4]"] {
|
||||
let _ = dialects.verified_expr(sql);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue