use std::collections::HashSet;
use std::hash::Hash;
use std::sync::LazyLock;
use egg::{rewrite as rw, *};
use super::{EGraph, Expr, Pattern, RecExpr, Rewrite};
use crate::catalog::RootCatalogRef;
use crate::types::F32;
mod agg;
mod expr;
mod plan;
mod rows;
mod schema;
mod type_;
pub use self::schema::ColumnIndexResolver;
pub use self::type_::TypeError;
pub static STAGE1_RULES: LazyLock<Vec<Rewrite>> = LazyLock::new(|| {
let mut rules = vec![];
rules.append(&mut plan::column_prune_rules());
rules.append(&mut schema::rules());
rules
});
pub static STAGE2_RULES: LazyLock<Vec<Rewrite>> = LazyLock::new(|| {
let mut rules = vec![];
rules.append(&mut expr::rules());
rules.append(&mut plan::always_better_rules());
rules
});
pub static STAGE3_RULES: LazyLock<Vec<Rewrite>> = LazyLock::new(|| {
let mut rules = vec![];
rules.append(&mut expr::rules());
rules.append(&mut plan::join_rules());
rules
});
#[derive(Default)]
pub struct ExprAnalysis;
#[derive(Debug)]
pub struct Data {
pub constant: expr::ConstValue,
pub columns: plan::ColumnSet,
pub schema: schema::Schema,
pub rows: rows::Rows,
}
impl Analysis<Expr> for ExprAnalysis {
type Data = Data;
fn make(egraph: &EGraph, enode: &Expr) -> Self::Data {
Data {
constant: expr::eval_constant(egraph, enode),
columns: plan::analyze_columns(egraph, enode),
schema: schema::analyze_schema(enode, |i| egraph[*i].data.schema.clone()),
rows: rows::analyze_rows(egraph, enode),
}
}
fn merge(&mut self, to: &mut Self::Data, from: Self::Data) -> DidMerge {
let merge_const = egg::merge_max(&mut to.constant, from.constant);
let merge_columns = merge_small_set(&mut to.columns, from.columns);
let merge_schema = egg::merge_max(&mut to.schema, from.schema);
let merge_rows = egg::merge_min(
unsafe { std::mem::transmute(&mut to.rows) },
F32::from(from.rows),
);
merge_const | merge_columns | merge_schema | merge_rows
}
fn modify(egraph: &mut EGraph, id: Id) {
expr::union_constant(egraph, id);
}
}
#[derive(Default)]
pub struct TypeSchemaAnalysis {
pub catalog: RootCatalogRef,
}
#[derive(Debug)]
pub struct TypeSchema {
pub type_: type_::Type,
pub schema: schema::Schema,
pub aggs: agg::AggSet,
}
impl Analysis<Expr> for TypeSchemaAnalysis {
type Data = TypeSchema;
fn make(egraph: &egg::EGraph<Expr, Self>, enode: &Expr) -> Self::Data {
TypeSchema {
type_: type_::analyze_type(
enode,
|i| egraph[*i].data.type_.clone(),
&egraph.analysis.catalog,
),
schema: schema::analyze_schema(enode, |i| egraph[*i].data.schema.clone()),
aggs: agg::analyze_aggs(enode, |i| egraph[*i].data.aggs.clone()),
}
}
fn merge(&mut self, to: &mut Self::Data, from: Self::Data) -> DidMerge {
let merge_type = egg::merge_max(&mut to.type_, from.type_);
let merge_schema = egg::merge_max(&mut to.schema, from.schema);
let merge_aggs = egg::merge_max(&mut to.aggs, from.aggs);
merge_type | merge_schema | merge_aggs
}
}
fn merge_small_set<T: Eq + Hash>(to: &mut HashSet<T>, from: HashSet<T>) -> DidMerge {
if from.len() < to.len() {
*to = from;
DidMerge(true, false)
} else {
DidMerge(false, true)
}
}
fn var(s: &str) -> Var {
s.parse().expect("invalid variable")
}
fn pattern(s: &str) -> Pattern {
s.parse().expect("invalid pattern")
}