diff --git a/qurious/src/logical/expr/mod.rs b/qurious/src/logical/expr/mod.rs index 3e84593..60c5f62 100644 --- a/qurious/src/logical/expr/mod.rs +++ b/qurious/src/logical/expr/mod.rs @@ -309,3 +309,9 @@ pub struct Like { pub expr: Box, pub pattern: Box, } + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct SubQuery { + pub subquery: Arc, + pub outer_ref_columns: Vec, +} diff --git a/qurious/src/optimizer/mod.rs b/qurious/src/optimizer/mod.rs index 012a245..f13b86b 100644 --- a/qurious/src/optimizer/mod.rs +++ b/qurious/src/optimizer/mod.rs @@ -1,6 +1,6 @@ mod count_wildcard_rule; mod pushdown_filter_inner_join; -// mod scalar_subquery_to_join; +mod scalar_subquery_to_join; mod type_coercion; use crate::{error::Result, logical::plan::LogicalPlan}; diff --git a/qurious/src/optimizer/scalar_subquery_to_join.rs b/qurious/src/optimizer/scalar_subquery_to_join.rs index 624b29a..86f59ca 100644 --- a/qurious/src/optimizer/scalar_subquery_to_join.rs +++ b/qurious/src/optimizer/scalar_subquery_to_join.rs @@ -1,7 +1,9 @@ +use arrow::ipc::Binary; + use super::OptimizerRule; use crate::common::transformed::{TransformNode, Transformed, TransformedResult, TreeNodeRecursion}; use crate::error::Result; -use crate::logical::expr::LogicalExpr; +use crate::logical::expr::{BinaryExpr, LogicalExpr}; use crate::logical::plan::LogicalPlan; use crate::logical::LogicalPlanBuilder; @@ -27,14 +29,18 @@ impl OptimizerRule for ScalarSubqueryToJoin { plan.transform(|plan| match plan { LogicalPlan::Filter(filter) => { if !contains_scalar_subquery(&filter.expr) { - return Ok(Transformed::no(plan)); + return Ok(Transformed::no(LogicalPlan::Filter(filter))); } - let (aliases, rewritten_subquery) = extract_scalar_subquery(&filter.expr)?; + let cur_input = filter.input; + let subqueries = extract_scalar_subquery(filter.expr); + // iterate through all subqueries in predicate, turning each into a left join + for subquery in subqueries { + let rewritten_child_subquery = self.optimize(subquery)?; - let alias_subquery = LogicalPlanBuilder::from(*filter.input) - .join_on(aliases) - .build()?; + let (join_conditions, rewritten_expr) = + self.extract_correlation_conditions(&rewritten_child_subquery)?; + } todo!() } @@ -44,6 +50,10 @@ impl OptimizerRule for ScalarSubqueryToJoin { } } +fn extract_correlation_conditions(expr: &LogicalExpr) -> Result<(LogicalPlan, LogicalExpr)> { + todo!() +} + fn contains_scalar_subquery(expr: &LogicalExpr) -> bool { let mut contains = false; expr.apply(|expr| { @@ -57,8 +67,16 @@ fn contains_scalar_subquery(expr: &LogicalExpr) -> bool { contains } -fn extract_scalar_subquery(expr: &LogicalExpr) -> Result<(Vec<(LogicalExpr, String)>, LogicalExpr)> { - todo!() +fn extract_scalar_subquery(expr: LogicalExpr) -> Vec { + match expr { + LogicalExpr::SubQuery(subquery) => vec![*subquery], + LogicalExpr::BinaryExpr(BinaryExpr { left, right, .. }) => { + let mut plans = extract_scalar_subquery(*left); + plans.extend(extract_scalar_subquery(*right)); + plans + } + _ => vec![], + } } #[cfg(test)] mod tests {