rename check_constant() to less confusing name

This commit is contained in:
Jussi Saurio
2025-04-17 15:00:16 +03:00
parent 6ff5ff49b7
commit b36c898842

View File

@@ -479,7 +479,7 @@ fn rewrite_exprs_update(plan: &mut UpdatePlan) -> Result<()> {
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConstantPredicate {
pub enum AlwaysTrueOrFalse {
AlwaysTrue,
AlwaysFalse,
}
@@ -489,17 +489,18 @@ pub enum ConstantPredicate {
Implemented for ast::Expr
*/
pub trait Optimizable {
// if the expression is a constant expression e.g. '1', returns the constant condition
fn check_constant(&self) -> Result<Option<ConstantPredicate>>;
// if the expression is a constant expression that, when evaluated as a condition, is always true or false
// return a [ConstantPredicate].
fn check_always_true_or_false(&self) -> Result<Option<AlwaysTrueOrFalse>>;
fn is_always_true(&self) -> Result<bool> {
Ok(self
.check_constant()?
.map_or(false, |c| c == ConstantPredicate::AlwaysTrue))
.check_always_true_or_false()?
.map_or(false, |c| c == AlwaysTrueOrFalse::AlwaysTrue))
}
fn is_always_false(&self) -> Result<bool> {
Ok(self
.check_constant()?
.map_or(false, |c| c == ConstantPredicate::AlwaysFalse))
.check_always_true_or_false()?
.map_or(false, |c| c == AlwaysTrueOrFalse::AlwaysFalse))
}
fn is_rowid_alias_of(&self, table_index: usize) -> bool;
fn is_nonnull(&self, tables: &[TableReference]) -> bool;
@@ -599,22 +600,23 @@ impl Optimizable for ast::Expr {
Expr::Variable(..) => false,
}
}
fn check_constant(&self) -> Result<Option<ConstantPredicate>> {
/// Returns true if the expression is a constant expression that, when evaluated as a condition, is always true or false
fn check_always_true_or_false(&self) -> Result<Option<AlwaysTrueOrFalse>> {
match self {
Self::Literal(lit) => match lit {
ast::Literal::Numeric(b) => {
if let Ok(int_value) = b.parse::<i64>() {
return Ok(Some(if int_value == 0 {
ConstantPredicate::AlwaysFalse
AlwaysTrueOrFalse::AlwaysFalse
} else {
ConstantPredicate::AlwaysTrue
AlwaysTrueOrFalse::AlwaysTrue
}));
}
if let Ok(float_value) = b.parse::<f64>() {
return Ok(Some(if float_value == 0.0 {
ConstantPredicate::AlwaysFalse
AlwaysTrueOrFalse::AlwaysFalse
} else {
ConstantPredicate::AlwaysTrue
AlwaysTrueOrFalse::AlwaysTrue
}));
}
@@ -624,35 +626,35 @@ impl Optimizable for ast::Expr {
let without_quotes = s.trim_matches('\'');
if let Ok(int_value) = without_quotes.parse::<i64>() {
return Ok(Some(if int_value == 0 {
ConstantPredicate::AlwaysFalse
AlwaysTrueOrFalse::AlwaysFalse
} else {
ConstantPredicate::AlwaysTrue
AlwaysTrueOrFalse::AlwaysTrue
}));
}
if let Ok(float_value) = without_quotes.parse::<f64>() {
return Ok(Some(if float_value == 0.0 {
ConstantPredicate::AlwaysFalse
AlwaysTrueOrFalse::AlwaysFalse
} else {
ConstantPredicate::AlwaysTrue
AlwaysTrueOrFalse::AlwaysTrue
}));
}
Ok(Some(ConstantPredicate::AlwaysFalse))
Ok(Some(AlwaysTrueOrFalse::AlwaysFalse))
}
_ => Ok(None),
},
Self::Unary(op, expr) => {
if *op == ast::UnaryOperator::Not {
let trivial = expr.check_constant()?;
let trivial = expr.check_always_true_or_false()?;
return Ok(trivial.map(|t| match t {
ConstantPredicate::AlwaysTrue => ConstantPredicate::AlwaysFalse,
ConstantPredicate::AlwaysFalse => ConstantPredicate::AlwaysTrue,
AlwaysTrueOrFalse::AlwaysTrue => AlwaysTrueOrFalse::AlwaysFalse,
AlwaysTrueOrFalse::AlwaysFalse => AlwaysTrueOrFalse::AlwaysTrue,
}));
}
if *op == ast::UnaryOperator::Negative {
let trivial = expr.check_constant()?;
let trivial = expr.check_always_true_or_false()?;
return Ok(trivial);
}
@@ -661,50 +663,50 @@ impl Optimizable for ast::Expr {
Self::InList { lhs: _, not, rhs } => {
if rhs.is_none() {
return Ok(Some(if *not {
ConstantPredicate::AlwaysTrue
AlwaysTrueOrFalse::AlwaysTrue
} else {
ConstantPredicate::AlwaysFalse
AlwaysTrueOrFalse::AlwaysFalse
}));
}
let rhs = rhs.as_ref().unwrap();
if rhs.is_empty() {
return Ok(Some(if *not {
ConstantPredicate::AlwaysTrue
AlwaysTrueOrFalse::AlwaysTrue
} else {
ConstantPredicate::AlwaysFalse
AlwaysTrueOrFalse::AlwaysFalse
}));
}
Ok(None)
}
Self::Binary(lhs, op, rhs) => {
let lhs_trivial = lhs.check_constant()?;
let rhs_trivial = rhs.check_constant()?;
let lhs_trivial = lhs.check_always_true_or_false()?;
let rhs_trivial = rhs.check_always_true_or_false()?;
match op {
ast::Operator::And => {
if lhs_trivial == Some(ConstantPredicate::AlwaysFalse)
|| rhs_trivial == Some(ConstantPredicate::AlwaysFalse)
if lhs_trivial == Some(AlwaysTrueOrFalse::AlwaysFalse)
|| rhs_trivial == Some(AlwaysTrueOrFalse::AlwaysFalse)
{
return Ok(Some(ConstantPredicate::AlwaysFalse));
return Ok(Some(AlwaysTrueOrFalse::AlwaysFalse));
}
if lhs_trivial == Some(ConstantPredicate::AlwaysTrue)
&& rhs_trivial == Some(ConstantPredicate::AlwaysTrue)
if lhs_trivial == Some(AlwaysTrueOrFalse::AlwaysTrue)
&& rhs_trivial == Some(AlwaysTrueOrFalse::AlwaysTrue)
{
return Ok(Some(ConstantPredicate::AlwaysTrue));
return Ok(Some(AlwaysTrueOrFalse::AlwaysTrue));
}
Ok(None)
}
ast::Operator::Or => {
if lhs_trivial == Some(ConstantPredicate::AlwaysTrue)
|| rhs_trivial == Some(ConstantPredicate::AlwaysTrue)
if lhs_trivial == Some(AlwaysTrueOrFalse::AlwaysTrue)
|| rhs_trivial == Some(AlwaysTrueOrFalse::AlwaysTrue)
{
return Ok(Some(ConstantPredicate::AlwaysTrue));
return Ok(Some(AlwaysTrueOrFalse::AlwaysTrue));
}
if lhs_trivial == Some(ConstantPredicate::AlwaysFalse)
&& rhs_trivial == Some(ConstantPredicate::AlwaysFalse)
if lhs_trivial == Some(AlwaysTrueOrFalse::AlwaysFalse)
&& rhs_trivial == Some(AlwaysTrueOrFalse::AlwaysFalse)
{
return Ok(Some(ConstantPredicate::AlwaysFalse));
return Ok(Some(AlwaysTrueOrFalse::AlwaysFalse));
}
Ok(None)