From e05417a3e3009b0ee9e5579b904431f712857542 Mon Sep 17 00:00:00 2001 From: Adrian Garcia Badaracco <1755071+adriangb@users.noreply.github.com> Date: Sun, 3 Nov 2024 16:59:57 -0600 Subject: [PATCH] Simplify `EXPR LIKE 'constant'` to `expr = 'constant'` --- .../simplify_expressions/expr_simplifier.rs | 24 +++++++++++++++++++ .../test_files/string/string_view.slt | 5 ++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/datafusion/optimizer/src/simplify_expressions/expr_simplifier.rs b/datafusion/optimizer/src/simplify_expressions/expr_simplifier.rs index 57c59146f77a..f2e52be1b880 100644 --- a/datafusion/optimizer/src/simplify_expressions/expr_simplifier.rs +++ b/datafusion/optimizer/src/simplify_expressions/expr_simplifier.rs @@ -1514,6 +1514,19 @@ impl<'a, S: SimplifyInfo> TreeNodeRewriter for Simplifier<'a, S> { ..like })) } + Some(pattern_str) + if like.escape_char.is_none() + && !pattern_str.contains(['%', '_'].as_ref()) => + { + // If the pattern does not contain any wildcards, we can simplify the like expression to an equality expression + // TODO: handle escape characters + Transformed::yes(Expr::BinaryExpr(BinaryExpr { + left: like.expr.clone(), + op: if like.negated { NotEq } else { Eq }, + right: like.pattern.clone(), + })) + } + Some(_pattern_str) => Transformed::no(Expr::Like(like)), } } @@ -3791,6 +3804,16 @@ mod tests { let expr = not_ilike(null, lit("a%")); assert_eq!(simplify(expr), lit_bool_null()); + + // expr [NOT] [I]LIKE with pattern without wildcards + let expr = like(col("c1"), lit("a")); + assert_eq!(simplify(expr), col("c1").eq(lit("a"))); + let expr = not_like(col("c1"), lit("a")); + assert_eq!(simplify(expr), col("c1").not_eq(lit("a"))); + let expr = like(col("c1"), lit("a_")); + assert_eq!(simplify(expr), col("c1").like(lit("a_"))); + let expr = not_like(col("c1"), lit("a_")); + assert_eq!(simplify(expr), col("c1").not_like(lit("a_"))); } #[test] @@ -4166,6 +4189,7 @@ mod tests { Ok(DataType::Int16) } } + #[test] fn test_optimize_volatile_conditions() { let fun = Arc::new(ScalarUDF::new_from_impl(VolatileUdf::new())); diff --git a/datafusion/sqllogictest/test_files/string/string_view.slt b/datafusion/sqllogictest/test_files/string/string_view.slt index 43b08cb25f3f..f432b3e8d77f 100644 --- a/datafusion/sqllogictest/test_files/string/string_view.slt +++ b/datafusion/sqllogictest/test_files/string/string_view.slt @@ -396,8 +396,9 @@ EXPLAIN SELECT FROM test; ---- logical_plan -01)Projection: test.column1_utf8view LIKE Utf8View("foo") AS like, test.column1_utf8view ILIKE Utf8View("foo") AS ilike -02)--TableScan: test projection=[column1_utf8view] +01)Projection: __common_expr_1 AS like, __common_expr_1 AS ilike +02)--Projection: test.column1_utf8view = Utf8View("foo") AS __common_expr_1 +03)----TableScan: test projection=[column1_utf8view] query TT