Dont store available_indexes on plan; only used in optimize_plan()

This commit is contained in:
Jussi Saurio
2025-02-03 09:45:33 +02:00
parent 61a007fb29
commit 40f536fabb
5 changed files with 45 additions and 45 deletions

View File

@@ -331,7 +331,7 @@ impl Connection {
*select,
&self.db.syms.borrow(),
)?;
optimize_plan(&mut plan)?;
optimize_plan(&mut plan, &self.schema.borrow())?;
println!("{}", plan);
}
_ => todo!(),

View File

@@ -18,7 +18,7 @@ pub fn translate_delete(
syms: &SymbolTable,
) -> Result<()> {
let mut delete_plan = prepare_delete_plan(schema, tbl_name, where_clause, limit)?;
optimize_plan(&mut delete_plan)?;
optimize_plan(&mut delete_plan, schema)?;
emit_program(program, delete_plan, syms)
}
@@ -55,7 +55,6 @@ pub fn prepare_delete_plan(
order_by: None,
limit: resolved_limit,
offset: resolved_offset,
available_indexes: vec![],
contains_constant_false_condition: false,
};

View File

@@ -1,18 +1,21 @@
use std::rc::Rc;
use std::{collections::HashMap, rc::Rc};
use sqlite3_parser::ast;
use crate::{schema::Index, Result};
use crate::{
schema::{Index, Schema},
Result,
};
use super::plan::{
DeletePlan, Direction, IterationDirection, Operation, Plan, Search, SelectPlan, TableReference,
WhereTerm,
};
pub fn optimize_plan(plan: &mut Plan) -> Result<()> {
pub fn optimize_plan(plan: &mut Plan, schema: &Schema) -> Result<()> {
match plan {
Plan::Select(plan) => optimize_select_plan(plan),
Plan::Delete(plan) => optimize_delete_plan(plan),
Plan::Select(plan) => optimize_select_plan(plan, schema),
Plan::Delete(plan) => optimize_delete_plan(plan, schema),
}
}
@@ -21,8 +24,8 @@ pub fn optimize_plan(plan: &mut Plan) -> Result<()> {
* TODO: these could probably be done in less passes,
* but having them separate makes them easier to understand
*/
fn optimize_select_plan(plan: &mut SelectPlan) -> Result<()> {
optimize_subqueries(plan)?;
fn optimize_select_plan(plan: &mut SelectPlan, schema: &Schema) -> Result<()> {
optimize_subqueries(plan, schema)?;
rewrite_exprs_select(plan)?;
if let ConstantConditionEliminationResult::ImpossibleCondition =
eliminate_constant_conditions(&mut plan.where_clause)?
@@ -33,16 +36,16 @@ fn optimize_select_plan(plan: &mut SelectPlan) -> Result<()> {
use_indexes(
&mut plan.table_references,
&plan.available_indexes,
&schema.indexes,
&mut plan.where_clause,
)?;
eliminate_unnecessary_orderby(plan)?;
eliminate_unnecessary_orderby(plan, schema)?;
Ok(())
}
fn optimize_delete_plan(plan: &mut DeletePlan) -> Result<()> {
fn optimize_delete_plan(plan: &mut DeletePlan, schema: &Schema) -> Result<()> {
rewrite_exprs_delete(plan)?;
if let ConstantConditionEliminationResult::ImpossibleCondition =
eliminate_constant_conditions(&mut plan.where_clause)?
@@ -53,17 +56,17 @@ fn optimize_delete_plan(plan: &mut DeletePlan) -> Result<()> {
use_indexes(
&mut plan.table_references,
&plan.available_indexes,
&schema.indexes,
&mut plan.where_clause,
)?;
Ok(())
}
fn optimize_subqueries(plan: &mut SelectPlan) -> Result<()> {
fn optimize_subqueries(plan: &mut SelectPlan, schema: &Schema) -> Result<()> {
for table in plan.table_references.iter_mut() {
if let Operation::Subquery { plan, .. } = &mut table.op {
optimize_select_plan(&mut *plan)?;
optimize_select_plan(&mut *plan, schema)?;
}
}
@@ -73,7 +76,7 @@ fn optimize_subqueries(plan: &mut SelectPlan) -> Result<()> {
fn query_is_already_ordered_by(
table_references: &[TableReference],
key: &mut ast::Expr,
available_indexes: &Vec<Rc<Index>>,
available_indexes: &HashMap<String, Vec<Rc<Index>>>,
) -> Result<bool> {
let first_table = table_references.first();
if first_table.is_none() {
@@ -86,10 +89,9 @@ fn query_is_already_ordered_by(
Search::RowidEq { .. } => Ok(key.is_rowid_alias_of(0)),
Search::RowidSearch { .. } => Ok(key.is_rowid_alias_of(0)),
Search::IndexSearch { index, .. } => {
let index_idx = key.check_index_scan(0, &table_reference, available_indexes)?;
let index_is_the_same = index_idx
.map(|i| Rc::ptr_eq(&available_indexes[i], index))
.unwrap_or(false);
let index_rc = key.check_index_scan(0, &table_reference, available_indexes)?;
let index_is_the_same =
index_rc.map(|irc| Rc::ptr_eq(index, &irc)).unwrap_or(false);
Ok(index_is_the_same)
}
},
@@ -97,7 +99,7 @@ fn query_is_already_ordered_by(
}
}
fn eliminate_unnecessary_orderby(plan: &mut SelectPlan) -> Result<()> {
fn eliminate_unnecessary_orderby(plan: &mut SelectPlan, schema: &Schema) -> Result<()> {
if plan.order_by.is_none() {
return Ok(());
}
@@ -115,7 +117,7 @@ fn eliminate_unnecessary_orderby(plan: &mut SelectPlan) -> Result<()> {
let (key, direction) = o.first_mut().unwrap();
let already_ordered =
query_is_already_ordered_by(&plan.table_references, key, &plan.available_indexes)?;
query_is_already_ordered_by(&plan.table_references, key, &schema.indexes)?;
if already_ordered {
push_scan_direction(&mut plan.table_references[0], direction);
@@ -136,7 +138,7 @@ fn eliminate_unnecessary_orderby(plan: &mut SelectPlan) -> Result<()> {
*/
fn use_indexes(
table_references: &mut [TableReference],
available_indexes: &Vec<Rc<Index>>,
available_indexes: &HashMap<String, Vec<Rc<Index>>>,
where_clause: &mut Vec<WhereTerm>,
) -> Result<()> {
if where_clause.is_empty() {
@@ -274,8 +276,8 @@ pub trait Optimizable {
&mut self,
table_index: usize,
table_reference: &TableReference,
available_indexes: &[Rc<Index>],
) -> Result<Option<usize>>;
available_indexes: &HashMap<String, Vec<Rc<Index>>>,
) -> Result<Option<Rc<Index>>>;
}
impl Optimizable for ast::Expr {
@@ -293,19 +295,23 @@ impl Optimizable for ast::Expr {
&mut self,
table_index: usize,
table_reference: &TableReference,
available_indexes: &[Rc<Index>],
) -> Result<Option<usize>> {
available_indexes: &HashMap<String, Vec<Rc<Index>>>,
) -> Result<Option<Rc<Index>>> {
match self {
Self::Column { table, column, .. } => {
if *table != table_index {
return Ok(None);
}
for (idx, index) in available_indexes.iter().enumerate() {
if index.table_name == table_reference.table.get_name() {
let column = table_reference.table.get_column_at(*column);
if index.columns.first().unwrap().name == column.name {
return Ok(Some(idx));
}
let available_indexes_for_table =
available_indexes.get(table_reference.table.get_name());
if available_indexes_for_table.is_none() {
return Ok(None);
}
let available_indexes_for_table = available_indexes_for_table.unwrap();
for index in available_indexes_for_table.iter() {
let column = table_reference.table.get_column_at(*column);
if index.columns.first().unwrap().name == column.name {
return Ok(Some(index.clone()));
}
}
Ok(None)
@@ -489,7 +495,7 @@ pub fn try_extract_index_search_expression(
cond: &mut WhereTerm,
table_index: usize,
table_reference: &TableReference,
available_indexes: &[Rc<Index>],
available_indexes: &HashMap<String, Vec<Rc<Index>>>,
) -> Result<Option<Search>> {
if cond.eval_at_loop != table_index {
return Ok(None);
@@ -556,7 +562,7 @@ pub fn try_extract_index_search_expression(
}
}
if let Some(index_index) =
if let Some(index_rc) =
lhs.check_index_scan(table_index, &table_reference, available_indexes)?
{
match operator {
@@ -567,7 +573,7 @@ pub fn try_extract_index_search_expression(
| ast::Operator::LessEquals => {
let rhs_owned = rhs.take_ownership();
return Ok(Some(Search::IndexSearch {
index: available_indexes[index_index].clone(),
index: index_rc,
cmp_op: *operator,
cmp_expr: WhereTerm {
expr: rhs_owned,
@@ -580,7 +586,7 @@ pub fn try_extract_index_search_expression(
}
}
if let Some(index_index) =
if let Some(index_rc) =
rhs.check_index_scan(table_index, &table_reference, available_indexes)?
{
match operator {
@@ -591,7 +597,7 @@ pub fn try_extract_index_search_expression(
| ast::Operator::LessEquals => {
let lhs_owned = lhs.take_ownership();
return Ok(Some(Search::IndexSearch {
index: available_indexes[index_index].clone(),
index: index_rc,
cmp_op: opposite_cmp_op(*operator),
cmp_expr: WhereTerm {
expr: lhs_owned,

View File

@@ -89,8 +89,6 @@ pub struct SelectPlan {
pub limit: Option<isize>,
/// offset clause
pub offset: Option<isize>,
/// all the indexes available
pub available_indexes: Vec<Rc<Index>>,
/// query contains a constant condition that is always false
pub contains_constant_false_condition: bool,
/// query type (top level or subquery)
@@ -112,8 +110,6 @@ pub struct DeletePlan {
pub limit: Option<isize>,
/// offset clause
pub offset: Option<isize>,
/// all the indexes available
pub available_indexes: Vec<Rc<Index>>,
/// query contains a constant condition that is always false
pub contains_constant_false_condition: bool,
}

View File

@@ -21,7 +21,7 @@ pub fn translate_select(
syms: &SymbolTable,
) -> Result<()> {
let mut select_plan = prepare_select_plan(schema, select, syms)?;
optimize_plan(&mut select_plan)?;
optimize_plan(&mut select_plan, schema)?;
emit_program(program, select_plan, syms)
}
@@ -78,7 +78,6 @@ pub fn prepare_select_plan(
aggregates: vec![],
limit: None,
offset: None,
available_indexes: schema.indexes.clone().into_values().flatten().collect(),
contains_constant_false_condition: false,
query_type: SelectQueryType::TopLevel,
};