mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-23 15:34:09 +00:00
Extend lambda support for ClickHouse and DuckDB dialects (#1686)
This commit is contained in:
parent
94b2ff7191
commit
aeaafbe6e4
5 changed files with 78 additions and 64 deletions
|
@ -1045,7 +1045,9 @@ pub enum Expr {
|
||||||
/// param -> expr | (param1, ...) -> expr
|
/// param -> expr | (param1, ...) -> expr
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// See <https://docs.databricks.com/en/sql/language-manual/sql-ref-lambda-functions.html>.
|
/// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/functions#higher-order-functions---operator-and-lambdaparams-expr-function)
|
||||||
|
/// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-lambda-functions.html)
|
||||||
|
/// [DuckDb](https://duckdb.org/docs/sql/functions/lambda.html)
|
||||||
Lambda(LambdaFunction),
|
Lambda(LambdaFunction),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,4 +70,9 @@ impl Dialect for ClickHouseDialect {
|
||||||
fn supports_dictionary_syntax(&self) -> bool {
|
fn supports_dictionary_syntax(&self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// See <https://clickhouse.com/docs/en/sql-reference/functions#higher-order-functions---operator-and-lambdaparams-expr-function>
|
||||||
|
fn supports_lambda_functions(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,11 @@ impl Dialect for DuckDbDialect {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// See <https://duckdb.org/docs/sql/functions/lambda.html>
|
||||||
|
fn supports_lambda_functions(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
// DuckDB is compatible with PostgreSQL syntax for this statement,
|
// DuckDB is compatible with PostgreSQL syntax for this statement,
|
||||||
// although not all features may be implemented.
|
// although not all features may be implemented.
|
||||||
fn supports_explain_with_utility_options(&self) -> bool {
|
fn supports_explain_with_utility_options(&self) -> bool {
|
||||||
|
|
|
@ -13332,3 +13332,68 @@ fn test_trailing_commas_in_from() {
|
||||||
"SELECT 1, 2 FROM (SELECT * FROM t1), (SELECT * FROM t2)",
|
"SELECT 1, 2 FROM (SELECT * FROM t1), (SELECT * FROM t2)",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_lambdas() {
|
||||||
|
let dialects = all_dialects_where(|d| d.supports_lambda_functions());
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
let sql = concat!(
|
||||||
|
"SELECT array_sort(array('Hello', 'World'), ",
|
||||||
|
"(p1, p2) -> CASE WHEN p1 = p2 THEN 0 ",
|
||||||
|
"WHEN reverse(p1) < reverse(p2) THEN -1 ",
|
||||||
|
"ELSE 1 END)",
|
||||||
|
);
|
||||||
|
pretty_assertions::assert_eq!(
|
||||||
|
SelectItem::UnnamedExpr(call(
|
||||||
|
"array_sort",
|
||||||
|
[
|
||||||
|
call(
|
||||||
|
"array",
|
||||||
|
[
|
||||||
|
Expr::Value(Value::SingleQuotedString("Hello".to_owned())),
|
||||||
|
Expr::Value(Value::SingleQuotedString("World".to_owned()))
|
||||||
|
]
|
||||||
|
),
|
||||||
|
Expr::Lambda(LambdaFunction {
|
||||||
|
params: OneOrManyWithParens::Many(vec![Ident::new("p1"), Ident::new("p2")]),
|
||||||
|
body: Box::new(Expr::Case {
|
||||||
|
operand: None,
|
||||||
|
conditions: vec![
|
||||||
|
Expr::BinaryOp {
|
||||||
|
left: Box::new(Expr::Identifier(Ident::new("p1"))),
|
||||||
|
op: BinaryOperator::Eq,
|
||||||
|
right: Box::new(Expr::Identifier(Ident::new("p2")))
|
||||||
|
},
|
||||||
|
Expr::BinaryOp {
|
||||||
|
left: Box::new(call(
|
||||||
|
"reverse",
|
||||||
|
[Expr::Identifier(Ident::new("p1"))]
|
||||||
|
)),
|
||||||
|
op: BinaryOperator::Lt,
|
||||||
|
right: Box::new(call(
|
||||||
|
"reverse",
|
||||||
|
[Expr::Identifier(Ident::new("p2"))]
|
||||||
|
))
|
||||||
|
}
|
||||||
|
],
|
||||||
|
results: vec![
|
||||||
|
Expr::Value(number("0")),
|
||||||
|
Expr::UnaryOp {
|
||||||
|
op: UnaryOperator::Minus,
|
||||||
|
expr: Box::new(Expr::Value(number("1")))
|
||||||
|
}
|
||||||
|
],
|
||||||
|
else_result: Some(Box::new(Expr::Value(number("1"))))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
]
|
||||||
|
)),
|
||||||
|
dialects.verified_only_select(sql).projection[0]
|
||||||
|
);
|
||||||
|
|
||||||
|
dialects.verified_expr(
|
||||||
|
"map_zip_with(map(1, 'a', 2, 'b'), map(1, 'x', 2, 'y'), (k, v1, v2) -> concat(v1, v2))",
|
||||||
|
);
|
||||||
|
dialects.verified_expr("transform(array(1, 2, 3), x -> x + 1)");
|
||||||
|
}
|
||||||
|
|
|
@ -83,69 +83,6 @@ fn test_databricks_exists() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_databricks_lambdas() {
|
|
||||||
#[rustfmt::skip]
|
|
||||||
let sql = concat!(
|
|
||||||
"SELECT array_sort(array('Hello', 'World'), ",
|
|
||||||
"(p1, p2) -> CASE WHEN p1 = p2 THEN 0 ",
|
|
||||||
"WHEN reverse(p1) < reverse(p2) THEN -1 ",
|
|
||||||
"ELSE 1 END)",
|
|
||||||
);
|
|
||||||
pretty_assertions::assert_eq!(
|
|
||||||
SelectItem::UnnamedExpr(call(
|
|
||||||
"array_sort",
|
|
||||||
[
|
|
||||||
call(
|
|
||||||
"array",
|
|
||||||
[
|
|
||||||
Expr::Value(Value::SingleQuotedString("Hello".to_owned())),
|
|
||||||
Expr::Value(Value::SingleQuotedString("World".to_owned()))
|
|
||||||
]
|
|
||||||
),
|
|
||||||
Expr::Lambda(LambdaFunction {
|
|
||||||
params: OneOrManyWithParens::Many(vec![Ident::new("p1"), Ident::new("p2")]),
|
|
||||||
body: Box::new(Expr::Case {
|
|
||||||
operand: None,
|
|
||||||
conditions: vec![
|
|
||||||
Expr::BinaryOp {
|
|
||||||
left: Box::new(Expr::Identifier(Ident::new("p1"))),
|
|
||||||
op: BinaryOperator::Eq,
|
|
||||||
right: Box::new(Expr::Identifier(Ident::new("p2")))
|
|
||||||
},
|
|
||||||
Expr::BinaryOp {
|
|
||||||
left: Box::new(call(
|
|
||||||
"reverse",
|
|
||||||
[Expr::Identifier(Ident::new("p1"))]
|
|
||||||
)),
|
|
||||||
op: BinaryOperator::Lt,
|
|
||||||
right: Box::new(call(
|
|
||||||
"reverse",
|
|
||||||
[Expr::Identifier(Ident::new("p2"))]
|
|
||||||
))
|
|
||||||
}
|
|
||||||
],
|
|
||||||
results: vec![
|
|
||||||
Expr::Value(number("0")),
|
|
||||||
Expr::UnaryOp {
|
|
||||||
op: UnaryOperator::Minus,
|
|
||||||
expr: Box::new(Expr::Value(number("1")))
|
|
||||||
}
|
|
||||||
],
|
|
||||||
else_result: Some(Box::new(Expr::Value(number("1"))))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
]
|
|
||||||
)),
|
|
||||||
databricks().verified_only_select(sql).projection[0]
|
|
||||||
);
|
|
||||||
|
|
||||||
databricks().verified_expr(
|
|
||||||
"map_zip_with(map(1, 'a', 2, 'b'), map(1, 'x', 2, 'y'), (k, v1, v2) -> concat(v1, v2))",
|
|
||||||
);
|
|
||||||
databricks().verified_expr("transform(array(1, 2, 3), x -> x + 1)");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_values_clause() {
|
fn test_values_clause() {
|
||||||
let values = Values {
|
let values = Values {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue