diff --git a/core/translate/optimizer.rs b/core/translate/optimizer.rs index 6f4a164ec..3a16098d0 100644 --- a/core/translate/optimizer.rs +++ b/core/translate/optimizer.rs @@ -1896,6 +1896,26 @@ pub struct Constraints { constraints: Vec, } +fn as_binary_components( + expr: &ast::Expr, +) -> Result> { + match unwrap_parens(expr)? { + ast::Expr::Binary(lhs, operator, rhs) + if matches!( + operator, + ast::Operator::Equals + | ast::Operator::Greater + | ast::Operator::Less + | ast::Operator::GreaterEquals + | ast::Operator::LessEquals + ) => + { + Ok(Some((lhs.as_ref(), *operator, rhs.as_ref()))) + } + _ => Ok(None), + } +} + /// Precompute all potentially usable [Constraints] from a WHERE clause. /// The resulting list of [Constraints] is then used to evaluate the best access methods for various join orders. pub fn constraints_from_where_clause( @@ -1921,31 +1941,21 @@ pub fn constraints_from_where_clause( constraints: Vec::new(), }; for (i, term) in where_clause.iter().enumerate() { - let ast::Expr::Binary(lhs, operator, rhs) = unwrap_parens(&term.expr)? else { + let Some((lhs, operator, rhs)) = as_binary_components(&term.expr)? else { continue; }; - if !matches!( - operator, - ast::Operator::Equals - | ast::Operator::Greater - | ast::Operator::Less - | ast::Operator::GreaterEquals - | ast::Operator::LessEquals - ) { - continue; - } if let Some(outer_join_tbl) = term.from_outer_join { if outer_join_tbl != table_no { continue; } } - match lhs.as_ref() { + match lhs { ast::Expr::Column { table, column, .. } => { if *table == table_no { if rowid_alias_column.map_or(false, |idx| *column == idx) { cs.constraints.push(Constraint { where_clause_pos: (i, BinaryExprSide::Rhs), - operator: *operator, + operator, index_col_pos: 0, table_col_pos: rowid_alias_column.unwrap(), sort_order: SortOrder::Asc, @@ -1954,7 +1964,7 @@ pub fn constraints_from_where_clause( } else { cs_ephemeral.constraints.push(Constraint { where_clause_pos: (i, BinaryExprSide::Rhs), - operator: *operator, + operator, index_col_pos: 0, table_col_pos: *column, sort_order: SortOrder::Asc, @@ -1967,7 +1977,7 @@ pub fn constraints_from_where_clause( if *table == table_no && rowid_alias_column.is_some() { cs.constraints.push(Constraint { where_clause_pos: (i, BinaryExprSide::Rhs), - operator: *operator, + operator, index_col_pos: 0, table_col_pos: rowid_alias_column.unwrap(), sort_order: SortOrder::Asc, @@ -1977,13 +1987,13 @@ pub fn constraints_from_where_clause( } _ => {} }; - match rhs.as_ref() { + match rhs { ast::Expr::Column { table, column, .. } => { if *table == table_no { if rowid_alias_column.map_or(false, |idx| *column == idx) { cs.constraints.push(Constraint { where_clause_pos: (i, BinaryExprSide::Lhs), - operator: opposite_cmp_op(*operator), + operator: opposite_cmp_op(operator), index_col_pos: 0, table_col_pos: rowid_alias_column.unwrap(), sort_order: SortOrder::Asc, @@ -1992,7 +2002,7 @@ pub fn constraints_from_where_clause( } else { cs_ephemeral.constraints.push(Constraint { where_clause_pos: (i, BinaryExprSide::Lhs), - operator: opposite_cmp_op(*operator), + operator: opposite_cmp_op(operator), index_col_pos: 0, table_col_pos: *column, sort_order: SortOrder::Asc, @@ -2005,7 +2015,7 @@ pub fn constraints_from_where_clause( if *table == table_no && rowid_alias_column.is_some() { cs.constraints.push(Constraint { where_clause_pos: (i, BinaryExprSide::Lhs), - operator: opposite_cmp_op(*operator), + operator: opposite_cmp_op(operator), index_col_pos: 0, table_col_pos: rowid_alias_column.unwrap(), sort_order: SortOrder::Asc, @@ -2081,19 +2091,9 @@ pub fn constraints_from_where_clause( constraints: Vec::new(), }; for (i, term) in where_clause.iter().enumerate() { - let ast::Expr::Binary(lhs, operator, rhs) = unwrap_parens(&term.expr)? else { + let Some((lhs, operator, rhs)) = as_binary_components(&term.expr)? else { continue; }; - if !matches!( - operator, - ast::Operator::Equals - | ast::Operator::Greater - | ast::Operator::Less - | ast::Operator::GreaterEquals - | ast::Operator::LessEquals - ) { - continue; - } if let Some(outer_join_tbl) = term.from_outer_join { if outer_join_tbl != table_no { continue; @@ -2104,10 +2104,10 @@ pub fn constraints_from_where_clause( { cs.constraints.push(Constraint { where_clause_pos: (i, BinaryExprSide::Rhs), - operator: *operator, + operator, index_col_pos: position_in_index, table_col_pos: { - let ast::Expr::Column { column, .. } = lhs.as_ref() else { + let ast::Expr::Column { column, .. } = lhs else { crate::bail_parse_error!("expected column in index constraint"); }; *column @@ -2121,10 +2121,10 @@ pub fn constraints_from_where_clause( { cs.constraints.push(Constraint { where_clause_pos: (i, BinaryExprSide::Lhs), - operator: opposite_cmp_op(*operator), + operator: opposite_cmp_op(operator), index_col_pos: position_in_index, table_col_pos: { - let ast::Expr::Column { column, .. } = rhs.as_ref() else { + let ast::Expr::Column { column, .. } = rhs else { crate::bail_parse_error!("expected column in index constraint"); }; *column @@ -2261,20 +2261,9 @@ fn is_potential_index_constraint( return false; } // Skip terms that are not binary comparisons - let Ok(ast::Expr::Binary(lhs, operator, rhs)) = unwrap_parens(&term.expr) else { + let Ok(Some((lhs, _, rhs))) = as_binary_components(&term.expr) else { return false; }; - // Only consider index scans for binary ops that are comparisons - if !matches!( - *operator, - ast::Operator::Equals - | ast::Operator::Greater - | ast::Operator::GreaterEquals - | ast::Operator::Less - | ast::Operator::LessEquals - ) { - return false; - } // If both lhs and rhs refer to columns from this table, we can't use this constraint // because we can't use the index to satisfy the condition.