Skip to content
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

chore(query): fix filter reorder check #15613

Merged
merged 6 commits into from
May 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 24 additions & 7 deletions src/query/expression/src/filter/select_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,14 @@ impl SelectExprBuilder {
let select_op =
SelectOp::try_from_func_name(&function.signature.name).unwrap();
let select_op = if not { select_op.not() } else { select_op };
let can_reorder =
Self::can_reorder(&args[0]) && Self::can_reorder(&args[1]);
SelectExprBuildResult::new(SelectExpr::Compare((
select_op,
args.clone(),
generics.clone(),
)))
.can_reorder(can_reorder)
}
"not" => {
self.not_function = Some((id.clone(), function.clone()));
Expand Down Expand Up @@ -158,6 +161,7 @@ impl SelectExprBuilder {
.can_push_down_not(false);
}
};
let can_reorder = Self::can_reorder(column);
if matches!(column_data_type, DataType::String | DataType::Nullable(box DataType::String))
&& let Scalar::String(like_str) = scalar
{
Expand All @@ -168,15 +172,17 @@ impl SelectExprBuilder {
like_str.clone(),
not,
)))
.can_reorder(can_reorder)
} else {
SelectExprBuildResult::new(SelectExpr::Others(expr.clone()))
.can_push_down_not(false)
.can_reorder(can_reorder)
}
}
"is_true" => self.build_select_expr(&args[0], not),
_ => self
.other_select_expr(expr, not)
.can_reorder(Self::can_reorder(func_name)),
.can_reorder(Self::can_reorder(expr)),
}
}
}
Expand Down Expand Up @@ -207,13 +213,24 @@ impl SelectExprBuilder {
// If a function may be use for filter short-circuiting, we can not perform filter reorder,
// for example, for predicates `a != 0 and 3 / a > 1`,if we swap `a != 0` and `3 / a > 1`,
// there will be a divide by zero error.
fn can_reorder(func_name: &str) -> bool {
// There may be other functions that can be used for filter short-circuiting.
if matches!(func_name, "cast" | "div" | "divide" | "modulo") || func_name.starts_with("to_")
{
return false;
pub fn can_reorder(expr: &Expr) -> bool {
match expr {
Expr::FunctionCall { function, args, .. } => {
let func_name = function.signature.name.as_str();
// There may be other functions that can be used for filter short-circuiting.
let mut can_reorder = !matches!(func_name, "cast" | "div" | "divide" | "modulo")
&& !func_name.starts_with("to_");
if can_reorder {
for arg in args {
can_reorder &= Self::can_reorder(arg);
}
}
can_reorder
}
Expr::ColumnRef { .. } | Expr::Constant { .. } => true,
Expr::Cast { is_try, .. } if *is_try => true,
_ => false,
}
true
}

fn other_select_expr(&self, expr: &Expr, not: bool) -> SelectExprBuildResult {
Expand Down
15 changes: 15 additions & 0 deletions tests/sqllogictests/suites/query/filter.test
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,21 @@ select a from t where a = 0 or 3 / a > 2 order by a
statement ok
drop table if exists t;

# AND filter short circuit
statement ok
create table t(a varchar);

statement ok
insert into t values('null'), ('202405');

query I
SELECT count(1) FROM t WHERE a <> 'null' AND a IS NOT NULL AND to_date(a || '01', '%Y%m%d') > add_years(today(), - 100);
----
1

statement ok
drop table if exists t;

# Boolean comparison
statement ok
drop table if exists t;
Expand Down
Loading