Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/binder/aggregate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ use std::collections::HashSet;
use super::{Binder, QueryBindStep};
use crate::errors::DatabaseError;
use crate::expression::function::scala::ScalarFunction;
use crate::expression::visitor::{walk_expr, Visitor};
use crate::expression::visitor_mut::{walk_mut_expr, VisitorMut};
use crate::expression::visitor::{walk_expr, ExprVisitor};
use crate::expression::visitor_mut::{walk_mut_expr, ExprVisitorMut};
use crate::planner::LogicalPlan;
use crate::storage::Transaction;
use crate::types::value::DataValue;
Expand Down Expand Up @@ -269,7 +269,7 @@ impl<T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'_, '_, T, A>
HashSet::from_iter(group_raw_exprs.iter().copied());

for expr in select_items {
if expr.has_agg_call() {
if expr.has_agg_call()? {
continue;
}
group_raw_set.remove(expr);
Expand Down Expand Up @@ -347,7 +347,7 @@ impl<'a> HavingOrderByValidator<'a> {
}
}

impl<'expr> Visitor<'expr> for HavingOrderByValidator<'_> {
impl<'expr> ExprVisitor<'expr> for HavingOrderByValidator<'_> {
fn visit(&mut self, expr: &'expr ScalarExpression) -> Result<(), DatabaseError> {
match expr {
ScalarExpression::AggCall { .. } => {
Expand Down Expand Up @@ -427,7 +427,7 @@ impl<'a, 'p> AggregateOutputBinder<'a, 'p> {
}
}

impl<'a> VisitorMut<'a> for AggregateOutputBinder<'_, '_> {
impl<'a> ExprVisitorMut<'a> for AggregateOutputBinder<'_, '_> {
fn visit(&mut self, expr: &'a mut ScalarExpression) -> Result<(), DatabaseError> {
if let ScalarExpression::Alias {
expr: inner_expr,
Expand All @@ -453,7 +453,7 @@ mod tests {
use crate::catalog::{ColumnCatalog, ColumnDesc, ColumnRef};
use crate::errors::DatabaseError;
use crate::expression::agg::AggKind;
use crate::expression::visitor_mut::VisitorMut;
use crate::expression::visitor_mut::ExprVisitorMut;
use crate::expression::{AliasType, BinaryOperator, ScalarExpression};
use crate::planner::PlanArena;
use crate::storage::Storage;
Expand Down
6 changes: 3 additions & 3 deletions src/binder/distinct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

use crate::binder::{Binder, QueryBindStep};
use crate::errors::DatabaseError;
use crate::expression::visitor_mut::{walk_mut_expr, VisitorMut};
use crate::expression::visitor_mut::{walk_mut_expr, ExprVisitorMut};
use crate::expression::ScalarExpression;
use crate::planner::operator::aggregate::AggregateOperator;
use crate::planner::operator::sort::SortField;
Expand Down Expand Up @@ -101,7 +101,7 @@ impl<'a, 'p> DistinctOutputBinder<'a, 'p> {
}
}

impl<'a> VisitorMut<'a> for DistinctOutputBinder<'_, '_> {
impl<'a> ExprVisitorMut<'a> for DistinctOutputBinder<'_, '_> {
fn visit(&mut self, expr: &'a mut ScalarExpression) -> Result<(), DatabaseError> {
if let ScalarExpression::Alias {
expr: inner_expr,
Expand All @@ -124,7 +124,7 @@ mod tests {
use super::DistinctOutputBinder;
use crate::catalog::{ColumnCatalog, ColumnDesc, ColumnRef};
use crate::errors::DatabaseError;
use crate::expression::visitor_mut::VisitorMut;
use crate::expression::visitor_mut::ExprVisitorMut;
use crate::expression::{AliasType, ScalarExpression};
use crate::planner::PlanArena;
use crate::types::LogicalType;
Expand Down
8 changes: 4 additions & 4 deletions src/binder/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::db::{BindSource, DBTransaction, Database, DatabaseIter, TransactionIt
use crate::errors::{DatabaseError, SqlErrorSpan};
use crate::expression;
use crate::expression::simplify::ConstantCalculator;
use crate::expression::visitor_mut::VisitorMut;
use crate::expression::visitor_mut::ExprVisitorMut;
use crate::expression::{AliasType, ScalarExpression};
use crate::iter_ext::Itertools;
use crate::parser::parse_sql;
Expand Down Expand Up @@ -338,7 +338,7 @@ struct UpdateExprTargetRemapper<'a, 'p> {
arena: &'a PlanArena<'p>,
}

impl VisitorMut<'_> for UpdateExprTargetRemapper<'_, '_> {
impl ExprVisitorMut<'_> for UpdateExprTargetRemapper<'_, '_> {
fn visit_column_ref(
&mut self,
column: &mut ColumnRef,
Expand Down Expand Up @@ -669,7 +669,7 @@ where
) -> Result<ScalarExpression, DatabaseError> {
let mut expr = self.binder.bind_expr(&expr, self.arena)?;

if expr.any_referenced_column(self.arena, |_, _| true) {
if expr.any_referenced_column(self.arena, |_, _| true)? {
return Err(DatabaseError::UnsupportedStmt(
"column is not allowed to exist in default".to_string(),
));
Expand Down Expand Up @@ -783,7 +783,7 @@ where
ColumnOption::Default(expr) => {
let mut expr = self.binder.bind_expr(&expr, self.arena)?;

if expr.any_referenced_column(self.arena, |_, _| true) {
if expr.any_referenced_column(self.arena, |_, _| true)? {
return Err(DatabaseError::UnsupportedStmt(
"column is not allowed to exist in `default`".to_string(),
));
Expand Down
114 changes: 62 additions & 52 deletions src/binder/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use super::{Binder, BinderContext, QueryBindStep, SetOperatorKind, Source, SubQu
use crate::catalog::{ColumnRef, ColumnRelation, TableName};
use crate::errors::DatabaseError;
use crate::execution::dql::join::joins_nullable;
use crate::expression::visitor_mut::{walk_mut_expr, PositionShift, VisitorMut};
use crate::expression::visitor_mut::{walk_mut_expr, ExprVisitorMut, PositionShift};
use crate::expression::{AliasType, BinaryOperator};
use crate::iter_ext::Itertools;
use crate::planner::operator::function_scan::FunctionScanOperator;
Expand All @@ -51,7 +51,7 @@ struct RightSidePositionGlobalizer<'a, 'p> {
arena: &'a crate::planner::PlanArena<'p>,
}

impl<'a> VisitorMut<'a> for RightSidePositionGlobalizer<'_, '_> {
impl<'a> ExprVisitorMut<'a> for RightSidePositionGlobalizer<'_, '_> {
fn visit_column_ref(
&mut self,
column: &'a mut ColumnRef,
Expand Down Expand Up @@ -80,7 +80,7 @@ struct SplitScopePositionRebinder<'a, 'p> {
arena: &'a crate::planner::PlanArena<'p>,
}

impl VisitorMut<'_> for SplitScopePositionRebinder<'_, '_> {
impl ExprVisitorMut<'_> for SplitScopePositionRebinder<'_, '_> {
fn visit_column_ref(
&mut self,
column: &mut ColumnRef,
Expand Down Expand Up @@ -109,7 +109,7 @@ struct MarkerPositionGlobalizer<'a, 'p> {
arena: &'a crate::planner::PlanArena<'p>,
}

impl VisitorMut<'_> for MarkerPositionGlobalizer<'_, '_> {
impl ExprVisitorMut<'_> for MarkerPositionGlobalizer<'_, '_> {
fn visit_column_ref(
&mut self,
column: &mut ColumnRef,
Expand Down Expand Up @@ -154,7 +154,7 @@ impl<'a, 'p> ProjectionOutputBinder<'a, 'p> {
}
}

impl<'a> VisitorMut<'a> for ProjectionOutputBinder<'_, '_> {
impl<'a> ExprVisitorMut<'a> for ProjectionOutputBinder<'_, '_> {
fn visit(&mut self, expr: &'a mut ScalarExpression) -> Result<(), DatabaseError> {
if let Some(output_ref) = self.output_ref(expr) {
*expr = output_ref;
Expand Down Expand Up @@ -432,8 +432,10 @@ where

#[cfg(feature = "orm")]
pub fn finish(self) -> Result<LogicalPlan, DatabaseError> {
if self.select_list.iter().any(ScalarExpression::has_agg_call) {
return self.aggregate_without_group()?.finish();
for expr in &self.select_list {
if expr.has_agg_call()? {
return self.aggregate_without_group()?.finish();
}
}
self.binder
.bind_project(self.plan, self.select_list, self.arena)
Expand Down Expand Up @@ -801,7 +803,7 @@ impl<'a: 'b, 'b, T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'
arena: &'a crate::planner::PlanArena<'p>,
}

impl VisitorMut<'_> for AppendedRightOutputBinder<'_, '_> {
impl ExprVisitorMut<'_> for AppendedRightOutputBinder<'_, '_> {
fn visit_column_ref(
&mut self,
column: &mut ColumnRef,
Expand Down Expand Up @@ -1495,7 +1497,7 @@ impl<'a: 'b, 'b, T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'
plan: &mut LogicalPlan,
predicates: &[ScalarExpression],
arena: &mut crate::planner::PlanArena,
) -> Vec<AppendedRightOutput> {
) -> Result<Vec<AppendedRightOutput>, DatabaseError> {
let output_schema = plan.output_schema(arena).clone();
let output_len = output_schema.len();
if let LogicalPlan {
Expand All @@ -1505,36 +1507,38 @@ impl<'a: 'b, 'b, T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'
} = plan
{
let Childrens::Only(child) = childrens.as_mut() else {
return Vec::new();
return Ok(Vec::new());
};
let child_schema = child.output_schema(arena);
let mut appended_outputs = Vec::new();
op.exprs.extend(
child_schema
.iter()
.enumerate()
.filter(|(_, column)| {
!output_schema.contains(column)
&& predicates.iter().any(|expr| {
expr.any_referenced_column(arena, |arena, candidate| {
arena.same_column(*candidate, **column)
})
})
})
.map(|(position, column)| {
appended_outputs.push(AppendedRightOutput {
column: *column,
child_position: position,
output_position: output_len + appended_outputs.len(),
});
ScalarExpression::column_expr(*column, position)
}),
);
for (position, column) in child_schema.iter().enumerate() {
if output_schema.contains(column) {
continue;
}
let mut referenced = false;
for expr in predicates {
if expr.any_referenced_column(arena, |arena, candidate| {
arena.same_column(*candidate, *column)
})? {
referenced = true;
break;
}
}
if referenced {
op.exprs
.push(ScalarExpression::column_expr(*column, position));
appended_outputs.push(AppendedRightOutput {
column: *column,
child_position: position,
output_position: output_len + appended_outputs.len(),
});
}
}
plan.reset_output_schema_cache();
return appended_outputs;
return Ok(appended_outputs);
}

Vec::new()
Ok(Vec::new())
}

#[allow(clippy::too_many_arguments)]
Expand Down Expand Up @@ -1565,7 +1569,7 @@ impl<'a: 'b, 'b, T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'

if correlated {
let appended_right_outputs =
Self::ensure_mark_apply_right_outputs(&mut plan, &apply_predicates, arena);
Self::ensure_mark_apply_right_outputs(&mut plan, &apply_predicates, arena)?;
if !appended_right_outputs.is_empty() {
Self::localize_appended_right_outputs(
apply_predicates.iter_mut(),
Expand Down Expand Up @@ -1618,33 +1622,36 @@ impl<'a: 'b, 'b, T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'
plan: &LogicalPlan,
left_schema: &Schema,
arena: &mut crate::planner::PlanArena,
) -> bool {
) -> Result<bool, DatabaseError> {
if !plan
.operator
.visit_referenced_columns(arena, &mut |arena, column| {
!left_schema
.iter()
.any(|left| arena.same_column(*left, *column))
})
})?
{
return true;
return Ok(true);
}

match plan.childrens.as_ref() {
Childrens::Only(child) => Self::plan_has_correlated_refs(child, left_schema, arena),
Childrens::Twins { left, right } => {
Self::plan_has_correlated_refs(left, left_schema, arena)
|| Self::plan_has_correlated_refs(right, left_schema, arena)
if Self::plan_has_correlated_refs(left, left_schema, arena)? {
Ok(true)
} else {
Self::plan_has_correlated_refs(right, left_schema, arena)
}
}
Childrens::None => false,
Childrens::None => Ok(false),
}
}

fn expr_has_correlated_refs(
expr: &ScalarExpression,
left_schema: &Schema,
arena: &mut crate::planner::PlanArena,
) -> bool {
) -> Result<bool, DatabaseError> {
expr.any_referenced_column(arena, |arena, column| {
left_schema
.iter()
Expand Down Expand Up @@ -1688,7 +1695,7 @@ impl<'a: 'b, 'b, T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'
match plan.childrens.as_ref() {
Childrens::Only(_) => {}
Childrens::Twins { .. } => {
if Self::plan_has_correlated_refs(&plan, left_schema, arena) {
if Self::plan_has_correlated_refs(&plan, left_schema, arena)? {
return Err(DatabaseError::UnsupportedStmt(
"correlated EXISTS/NOT EXISTS does not support set or join subqueries"
.to_string(),
Expand All @@ -1715,7 +1722,7 @@ impl<'a: 'b, 'b, T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'
let mut predicates = Vec::new();
Self::split_conjuncts(op.predicate, &mut predicates);
for predicate in predicates {
if Self::expr_has_correlated_refs(&predicate, left_schema, arena) {
if Self::expr_has_correlated_refs(&predicate, left_schema, arena)? {
correlated_filters.push(predicate);
} else {
local_filters.push(predicate);
Expand Down Expand Up @@ -1775,7 +1782,7 @@ impl<'a: 'b, 'b, T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'
arena,
),
plan => {
if Self::plan_has_correlated_refs(&plan, left_schema, arena) {
if Self::plan_has_correlated_refs(&plan, left_schema, arena)? {
Err(DatabaseError::UnsupportedStmt(
"correlated EXISTS/NOT EXISTS only supports filter-based subqueries"
.to_string(),
Expand Down Expand Up @@ -2142,9 +2149,11 @@ impl<'a: 'b, 'b, T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'
// example: baz > 1
if left_expr.all_referenced_columns(arena, |_, column| {
fn_or_contains(*column)
}) && right_expr.all_referenced_columns(arena, |_, column| {
fn_or_contains(*column)
}) {
})? && right_expr
.all_referenced_columns(arena, |_, column| {
fn_or_contains(*column)
})?
{
accum_filter.push(ScalarExpression::Binary {
left_expr,
right_expr,
Expand Down Expand Up @@ -2186,9 +2195,10 @@ impl<'a: 'b, 'b, T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'
}
_ => {
if left_expr
.all_referenced_columns(arena, |_, column| fn_or_contains(*column))
&& right_expr
.all_referenced_columns(arena, |_, column| fn_or_contains(*column))
.all_referenced_columns(arena, |_, column| fn_or_contains(*column))?
&& right_expr.all_referenced_columns(arena, |_, column| {
fn_or_contains(*column)
})?
{
accum_filter.push(ScalarExpression::Binary {
left_expr,
Expand All @@ -2202,7 +2212,7 @@ impl<'a: 'b, 'b, T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'
}
}
expr => {
if expr.all_referenced_columns(arena, |_, column| fn_or_contains(*column)) {
if expr.all_referenced_columns(arena, |_, column| fn_or_contains(*column))? {
// example: baz > 1
accum_filter.push(expr);
}
Expand All @@ -2219,7 +2229,7 @@ mod tests {
use crate::binder::test::build_t1_table;
use crate::catalog::{ColumnCatalog, ColumnDesc};
use crate::errors::DatabaseError;
use crate::expression::visitor_mut::VisitorMut;
use crate::expression::visitor_mut::ExprVisitorMut;
use crate::expression::{AliasType, ScalarExpression};
use crate::planner::operator::join::{JoinCondition, JoinType};
use crate::planner::operator::mark_apply::{
Expand Down
2 changes: 1 addition & 1 deletion src/catalog/column.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ impl ColumnDesc {
if let Some(expr) = &default {
let table_arena = crate::planner::TableArenaCell::default();
let plan_arena = crate::planner::PlanArena::new(&table_arena);
if expr.has_table_ref_column(&plan_arena) {
if expr.has_table_ref_column(&plan_arena)? {
return Err(DatabaseError::DefaultNotColumnRef);
}
}
Expand Down
Loading
Loading