From 530de62a0f8faa2ca338ae23d8de7118653bcd8d Mon Sep 17 00:00:00 2001 From: "xudong.w" Date: Wed, 9 Oct 2024 22:15:58 +0800 Subject: [PATCH] fix: window in scalar subquery returns wrong results (#16567) * fix: window in scalar subquery returns wrong results * fix cluster --- .../optimizer/decorrelate/decorrelate.rs | 2 +- .../decorrelate/subquery_rewriter.rs | 237 ++++------------- .../rewrite/rule_push_down_filter_join.rs | 8 +- .../planner/semantic/distinct_to_groupby.rs | 4 + .../mode/standalone/explain/explain.test | 248 +++++++++--------- .../suites/mode/standalone/explain/limit.test | 138 +++++----- .../mode/standalone/explain/prune_column.test | 109 ++++---- .../mode/standalone/explain/subquery.test | 181 ++++++------- .../mode/standalone/explain_native/limit.test | 138 +++++----- .../explain_native/prune_column.test | 109 ++++---- .../standalone/explain_native/subquery.test | 181 ++++++------- .../window_function/window_with_subquery.test | 20 ++ 12 files changed, 577 insertions(+), 798 deletions(-) create mode 100644 tests/sqllogictests/suites/query/window_function/window_with_subquery.test diff --git a/src/query/sql/src/planner/optimizer/decorrelate/decorrelate.rs b/src/query/sql/src/planner/optimizer/decorrelate/decorrelate.rs index 3daf61a1ca24..e5c222ceec42 100644 --- a/src/query/sql/src/planner/optimizer/decorrelate/decorrelate.rs +++ b/src/query/sql/src/planner/optimizer/decorrelate/decorrelate.rs @@ -306,7 +306,7 @@ impl SubqueryRewriter { Arc::new(left.clone()), Arc::new(flatten_plan), ); - Ok((s_expr, UnnestResult::SingleJoin { output_index: None })) + Ok((s_expr, UnnestResult::SingleJoin)) } SubqueryType::Exists | SubqueryType::NotExists => { if is_conjunctive_predicate { diff --git a/src/query/sql/src/planner/optimizer/decorrelate/subquery_rewriter.rs b/src/query/sql/src/planner/optimizer/decorrelate/subquery_rewriter.rs index f4170a0fcd2e..c0b1662befb6 100644 --- a/src/query/sql/src/planner/optimizer/decorrelate/subquery_rewriter.rs +++ b/src/query/sql/src/planner/optimizer/decorrelate/subquery_rewriter.rs @@ -32,7 +32,6 @@ use crate::optimizer::RelExpr; use crate::optimizer::SExpr; use crate::plans::Aggregate; use crate::plans::AggregateFunction; -use crate::plans::AggregateMode; use crate::plans::BoundColumnRef; use crate::plans::CastExpr; use crate::plans::ComparisonOp; @@ -61,7 +60,7 @@ pub enum UnnestResult { // Semi/Anti Join, Cross join for EXISTS SimpleJoin { output_index: Option }, MarkJoin { marker_index: IndexType }, - SingleJoin { output_index: Option }, + SingleJoin, } pub struct FlattenInfo { @@ -164,6 +163,17 @@ impl SubqueryRewriter { Ok(SExpr::create_unary(Arc::new(plan.into()), Arc::new(input))) } + RelOperator::Sort(mut sort) => { + let mut input = self.rewrite(s_expr.child(0)?)?; + for item in sort.window_partition.iter_mut() { + let res = self.try_rewrite_subquery(&item.scalar, &input, false)?; + input = res.1; + item.scalar = res.0; + } + + Ok(SExpr::create_unary(Arc::new(sort.into()), Arc::new(input))) + } + RelOperator::Join(_) | RelOperator::UnionAll(_) | RelOperator::MaterializedCte(_) => { Ok(SExpr::create_binary( Arc::new(s_expr.plan().clone()), @@ -172,13 +182,12 @@ impl SubqueryRewriter { )) } - RelOperator::Limit(_) - | RelOperator::Sort(_) - | RelOperator::Udf(_) - | RelOperator::AsyncFunction(_) => Ok(SExpr::create_unary( - Arc::new(s_expr.plan().clone()), - Arc::new(self.rewrite(s_expr.child(0)?)?), - )), + RelOperator::Limit(_) | RelOperator::Udf(_) | RelOperator::AsyncFunction(_) => { + Ok(SExpr::create_unary( + Arc::new(s_expr.plan().clone()), + Arc::new(self.rewrite(s_expr.child(0)?)?), + )) + } RelOperator::DummyTableScan(_) | RelOperator::Scan(_) @@ -294,20 +303,15 @@ impl SubqueryRewriter { } let (index, name) = if let UnnestResult::MarkJoin { marker_index } = result { (marker_index, marker_index.to_string()) - } else if let UnnestResult::SingleJoin { output_index } = result { - if let Some(output_idx) = output_index { - // uncorrelated scalar subquery - (output_idx, "_if_scalar_subquery".to_string()) - } else { - let mut output_column = subquery.output_column; - if let Some(index) = self.derived_columns.get(&output_column.index) { - output_column.index = *index; - } - ( - output_column.index, - format!("scalar_subquery_{:?}", output_column.index), - ) + } else if let UnnestResult::SingleJoin = result { + let mut output_column = subquery.output_column; + if let Some(index) = self.derived_columns.get(&output_column.index) { + output_column.index = *index; } + ( + output_column.index, + format!("scalar_subquery_{:?}", output_column.index), + ) } else { let index = subquery.output_column.index; (index, format!("subquery_{}", index)) @@ -423,7 +427,26 @@ impl SubqueryRewriter { is_conjunctive_predicate: bool, ) -> Result<(SExpr, UnnestResult)> { match subquery.typ { - SubqueryType::Scalar => self.rewrite_uncorrelated_scalar_subquery(left, subquery), + SubqueryType::Scalar => { + let join_plan = Join { + non_equi_conditions: vec![], + join_type: JoinType::LeftSingle, + marker_index: None, + from_correlated_subquery: false, + equi_conditions: vec![], + need_hold_hash_table: false, + is_lateral: false, + single_to_inner: None, + build_side_cache_info: None, + } + .into(); + let s_expr = SExpr::create_binary( + Arc::new(join_plan), + Arc::new(left.clone()), + Arc::new(*subquery.subquery.clone()), + ); + Ok((s_expr, UnnestResult::SingleJoin)) + } SubqueryType::Exists | SubqueryType::NotExists => { let mut subquery_expr = *subquery.subquery.clone(); // Wrap Limit to current subquery @@ -617,174 +640,6 @@ impl SubqueryRewriter { _ => unreachable!(), } } - - fn rewrite_uncorrelated_scalar_subquery( - &mut self, - left: &SExpr, - subquery: &SubqueryExpr, - ) -> Result<(SExpr, UnnestResult)> { - // Use cross join which brings chance to push down filter under cross join. - // Such as `SELECT * FROM c WHERE c_id=(SELECT max(c_id) FROM o WHERE ship='WA');` - // We can push down `c_id = max(c_id)` to cross join then make it as inner join. - let join_plan = Join { - equi_conditions: JoinEquiCondition::new_conditions(vec![], vec![], vec![]), - non_equi_conditions: vec![], - join_type: JoinType::Cross, - marker_index: None, - from_correlated_subquery: false, - need_hold_hash_table: false, - is_lateral: false, - single_to_inner: None, - build_side_cache_info: None, - } - .into(); - - // For some cases, empty result set will be occur, we should return null instead of empty set. - // So let wrap an expression: `if(count()=0, null, any(subquery.output_column)` - let count_func = ScalarExpr::AggregateFunction(AggregateFunction { - span: subquery.span, - func_name: "count".to_string(), - distinct: false, - params: vec![], - args: vec![ScalarExpr::BoundColumnRef(BoundColumnRef { - span: None, - column: subquery.output_column.clone(), - })], - return_type: Box::new(DataType::Number(NumberDataType::UInt64)), - display_name: "count".to_string(), - }); - let any_func = ScalarExpr::AggregateFunction(AggregateFunction { - span: subquery.span, - func_name: "any".to_string(), - distinct: false, - params: vec![], - return_type: subquery.output_column.data_type.clone(), - args: vec![ScalarExpr::BoundColumnRef(BoundColumnRef { - span: None, - column: subquery.output_column.clone(), - })], - display_name: "any".to_string(), - }); - // Add `count_func` and `any_func` to metadata - let count_idx = self.metadata.write().add_derived_column( - "_count_scalar_subquery".to_string(), - DataType::Number(NumberDataType::UInt64), - None, - ); - let any_idx = self.metadata.write().add_derived_column( - "_any_scalar_subquery".to_string(), - *subquery.output_column.data_type.clone(), - None, - ); - // Aggregate operator - let agg = SExpr::create_unary( - Arc::new( - Aggregate { - mode: AggregateMode::Initial, - group_items: vec![], - aggregate_functions: vec![ - ScalarItem { - scalar: count_func, - index: count_idx, - }, - ScalarItem { - scalar: any_func, - index: any_idx, - }, - ], - ..Default::default() - } - .into(), - ), - Arc::new(*subquery.subquery.clone()), - ); - - let limit = SExpr::create_unary( - Arc::new( - Limit { - limit: Some(1), - offset: 0, - before_exchange: false, - } - .into(), - ), - Arc::new(agg), - ); - - // Wrap expression - let count_col_ref = ScalarExpr::BoundColumnRef(BoundColumnRef { - span: None, - column: ColumnBindingBuilder::new( - "_count_scalar_subquery".to_string(), - count_idx, - Box::new(DataType::Number(NumberDataType::UInt64)), - Visibility::Visible, - ) - .build(), - }); - let any_col_ref = ScalarExpr::BoundColumnRef(BoundColumnRef { - span: None, - column: ColumnBindingBuilder::new( - "_any_scalar_subquery".to_string(), - any_idx, - subquery.output_column.data_type.clone(), - Visibility::Visible, - ) - .build(), - }); - let eq_func = ScalarExpr::FunctionCall(FunctionCall { - span: None, - func_name: "eq".to_string(), - params: vec![], - arguments: vec![ - count_col_ref, - ScalarExpr::ConstantExpr(ConstantExpr { - span: None, - value: Scalar::Number(NumberScalar::UInt8(0)), - }), - ], - }); - // If function - let if_func = ScalarExpr::FunctionCall(FunctionCall { - span: None, - func_name: "if".to_string(), - params: vec![], - arguments: vec![ - eq_func, - ScalarExpr::ConstantExpr(ConstantExpr { - span: None, - value: Scalar::Null, - }), - any_col_ref, - ], - }); - let if_func_idx = self.metadata.write().add_derived_column( - "_if_scalar_subquery".to_string(), - *subquery.output_column.data_type.clone(), - None, - ); - let scalar_expr = SExpr::create_unary( - Arc::new( - EvalScalar { - items: vec![ScalarItem { - scalar: if_func, - index: if_func_idx, - }], - } - .into(), - ), - Arc::new(limit), - ); - - let s_expr = SExpr::create_binary( - Arc::new(join_plan), - Arc::new(left.clone()), - Arc::new(scalar_expr), - ); - Ok((s_expr, UnnestResult::SingleJoin { - output_index: Some(if_func_idx), - })) - } } pub fn check_child_expr_in_subquery( diff --git a/src/query/sql/src/planner/optimizer/rule/rewrite/rule_push_down_filter_join.rs b/src/query/sql/src/planner/optimizer/rule/rewrite/rule_push_down_filter_join.rs index 57c354e910da..b806f3e4e1b4 100644 --- a/src/query/sql/src/planner/optimizer/rule/rewrite/rule_push_down_filter_join.rs +++ b/src/query/sql/src/planner/optimizer/rule/rewrite/rule_push_down_filter_join.rs @@ -178,13 +178,17 @@ pub fn try_push_down_filter_join(s_expr: &SExpr, metadata: MetadataRef) -> Resul } JoinPredicate::Other(_) => original_predicates.push(predicate), JoinPredicate::Both { is_equal_op, .. } => { - if matches!(join.join_type, JoinType::Inner | JoinType::Cross) { + if matches!(join.join_type, JoinType::Inner | JoinType::Cross) + || join.single_to_inner.is_some() + { if is_equal_op { push_down_predicates.push(predicate); } else { non_equi_predicates.push(predicate); } - join.join_type = JoinType::Inner; + if join.join_type == JoinType::Cross { + join.join_type = JoinType::Inner; + } } else { original_predicates.push(predicate); } diff --git a/src/query/sql/src/planner/semantic/distinct_to_groupby.rs b/src/query/sql/src/planner/semantic/distinct_to_groupby.rs index 84af6ef6ceb9..cb20b812b55f 100644 --- a/src/query/sql/src/planner/semantic/distinct_to_groupby.rs +++ b/src/query/sql/src/planner/semantic/distinct_to_groupby.rs @@ -53,12 +53,16 @@ impl DistinctToGroupBy { distinct, name, args, + window, .. }, }, alias, } = &select_list[0] { + if window.is_some() { + return; + } let sub_query_name = "_distinct_group_by_subquery"; if ((name.name.to_ascii_lowercase() == "count" && *distinct) || name.name.to_ascii_lowercase() == "count_distinct") diff --git a/tests/sqllogictests/suites/mode/standalone/explain/explain.test b/tests/sqllogictests/suites/mode/standalone/explain/explain.test index 9f19dc078761..36fbdfdeb958 100644 --- a/tests/sqllogictests/suites/mode/standalone/explain/explain.test +++ b/tests/sqllogictests/suites/mode/standalone/explain/explain.test @@ -1098,41 +1098,37 @@ insert into b values (1, 5), (4, 8) query T explain select * from a where a.id = (select id from b where a.id = b.id); ---- -Filter +HashJoin ├── output columns: [a.id (#0), a.c1 (#1)] -├── filters: [is_true(a.id (#0) = scalar_subquery_2 (#2))] -├── estimated rows: 0.08 -└── HashJoin - ├── output columns: [a.id (#0), a.c1 (#1), b.id (#2)] - ├── join type: INNER - ├── build keys: [id (#2)] - ├── probe keys: [id (#0)] - ├── filters: [] - ├── estimated rows: 0.40 - ├── Filter(Build) - │ ├── output columns: [b.id (#2)] - │ ├── filters: [is_true(b.id (#2) = b.id (#2))] - │ ├── estimated rows: 0.40 - │ └── TableScan - │ ├── table: default.default.b - │ ├── output columns: [id (#2)] - │ ├── read rows: 2 - │ ├── read size: < 1 KiB - │ ├── partitions total: 1 - │ ├── partitions scanned: 1 - │ ├── pruning stats: [segments: , blocks: ] - │ ├── push downs: [filters: [is_true(b.id (#2) = b.id (#2))], limit: NONE] - │ └── estimated rows: 2.00 - └── TableScan(Probe) - ├── table: default.default.a - ├── output columns: [id (#0), c1 (#1)] - ├── read rows: 3 - ├── read size: < 1 KiB - ├── partitions total: 1 - ├── partitions scanned: 1 - ├── pruning stats: [segments: , blocks: ] - ├── push downs: [filters: [], limit: NONE] - └── estimated rows: 3.00 +├── join type: INNER +├── build keys: [scalar_subquery_2 (#2), id (#2)] +├── probe keys: [a.id (#0), a.id (#0)] +├── filters: [] +├── estimated rows: 0.40 +├── Filter(Build) +│ ├── output columns: [b.id (#2)] +│ ├── filters: [is_true(b.id (#2) = b.id (#2))] +│ ├── estimated rows: 0.40 +│ └── TableScan +│ ├── table: default.default.b +│ ├── output columns: [id (#2)] +│ ├── read rows: 2 +│ ├── read size: < 1 KiB +│ ├── partitions total: 1 +│ ├── partitions scanned: 1 +│ ├── pruning stats: [segments: , blocks: ] +│ ├── push downs: [filters: [and_filters(b.id (#2) = b.id (#2), b.id (#2) = b.id (#2))], limit: NONE] +│ └── estimated rows: 2.00 +└── TableScan(Probe) + ├── table: default.default.a + ├── output columns: [id (#0), c1 (#1)] + ├── read rows: 3 + ├── read size: < 1 KiB + ├── partitions total: 1 + ├── partitions scanned: 1 + ├── pruning stats: [segments: , blocks: ] + ├── push downs: [filters: [], limit: NONE] + └── estimated rows: 3.00 statement ok drop table a; @@ -1507,110 +1503,102 @@ create table t2(a int, b int, c varchar(20)); query T explain select * from t2 where c > (select c from t1 where t1.a = t2.a group by c order by count(a)); ---- -Filter +HashJoin ├── output columns: [t2.a (#0), t2.b (#1), t2.c (#2)] -├── filters: [is_true(t2.c (#2) > scalar_subquery_5 (#5))] +├── join type: INNER +├── build keys: [a (#3)] +├── probe keys: [a (#0)] +├── filters: [t2.c (#2) > scalar_subquery_5 (#5)] ├── estimated rows: 0.00 -└── HashJoin - ├── output columns: [t2.a (#0), t2.b (#1), t2.c (#2), t1.c (#5)] - ├── join type: INNER - ├── build keys: [a (#3)] - ├── probe keys: [a (#0)] - ├── filters: [] - ├── estimated rows: 0.00 - ├── Sort(Build) - │ ├── output columns: [t1.c (#5), t1.a (#3), count(a) (#7)] - │ ├── sort keys: [count(a) ASC NULLS LAST] - │ ├── estimated rows: 0.00 - │ └── EvalScalar - │ ├── output columns: [t1.c (#5), t1.a (#3), count(a) (#7)] - │ ├── expressions: [count(a) (#6)] - │ ├── estimated rows: 0.00 - │ └── AggregateFinal - │ ├── output columns: [count(a) (#6), t1.c (#5), t1.a (#3)] - │ ├── group by: [c, a] - │ ├── aggregate functions: [count(a)] - │ ├── estimated rows: 0.00 - │ └── AggregatePartial - │ ├── group by: [c, a] - │ ├── aggregate functions: [count(a)] - │ ├── estimated rows: 0.00 - │ └── Filter - │ ├── output columns: [t1.a (#3), t1.c (#5)] - │ ├── filters: [is_true(t1.a (#3) = t1.a (#3))] - │ ├── estimated rows: 0.00 - │ └── TableScan - │ ├── table: default.default.t1 - │ ├── output columns: [a (#3), c (#5)] - │ ├── read rows: 0 - │ ├── read size: 0 - │ ├── partitions total: 0 - │ ├── partitions scanned: 0 - │ ├── push downs: [filters: [is_true(t1.a (#3) = t1.a (#3))], limit: NONE] - │ └── estimated rows: 0.00 - └── TableScan(Probe) - ├── table: default.default.t2 - ├── output columns: [a (#0), b (#1), c (#2)] - ├── read rows: 0 - ├── read size: 0 - ├── partitions total: 0 - ├── partitions scanned: 0 - ├── push downs: [filters: [], limit: NONE] - └── estimated rows: 0.00 +├── Sort(Build) +│ ├── output columns: [t1.c (#5), t1.a (#3), count(a) (#7)] +│ ├── sort keys: [count(a) ASC NULLS LAST] +│ ├── estimated rows: 0.00 +│ └── EvalScalar +│ ├── output columns: [t1.c (#5), t1.a (#3), count(a) (#7)] +│ ├── expressions: [count(a) (#6)] +│ ├── estimated rows: 0.00 +│ └── AggregateFinal +│ ├── output columns: [count(a) (#6), t1.c (#5), t1.a (#3)] +│ ├── group by: [c, a] +│ ├── aggregate functions: [count(a)] +│ ├── estimated rows: 0.00 +│ └── AggregatePartial +│ ├── group by: [c, a] +│ ├── aggregate functions: [count(a)] +│ ├── estimated rows: 0.00 +│ └── Filter +│ ├── output columns: [t1.a (#3), t1.c (#5)] +│ ├── filters: [is_true(t1.a (#3) = t1.a (#3))] +│ ├── estimated rows: 0.00 +│ └── TableScan +│ ├── table: default.default.t1 +│ ├── output columns: [a (#3), c (#5)] +│ ├── read rows: 0 +│ ├── read size: 0 +│ ├── partitions total: 0 +│ ├── partitions scanned: 0 +│ ├── push downs: [filters: [is_true(t1.a (#3) = t1.a (#3))], limit: NONE] +│ └── estimated rows: 0.00 +└── TableScan(Probe) + ├── table: default.default.t2 + ├── output columns: [a (#0), b (#1), c (#2)] + ├── read rows: 0 + ├── read size: 0 + ├── partitions total: 0 + ├── partitions scanned: 0 + ├── push downs: [filters: [], limit: NONE] + └── estimated rows: 0.00 query T explain select * from t2 where c > (select c from t1 where t1.a = t2.a group by c order by count(*)); ---- -Filter +HashJoin ├── output columns: [t2.a (#0), t2.b (#1), t2.c (#2)] -├── filters: [is_true(t2.c (#2) > scalar_subquery_5 (#5))] +├── join type: INNER +├── build keys: [a (#3)] +├── probe keys: [a (#0)] +├── filters: [t2.c (#2) > scalar_subquery_5 (#5)] ├── estimated rows: 0.00 -└── HashJoin - ├── output columns: [t2.a (#0), t2.b (#1), t2.c (#2), t1.c (#5)] - ├── join type: INNER - ├── build keys: [a (#3)] - ├── probe keys: [a (#0)] - ├── filters: [] - ├── estimated rows: 0.00 - ├── Sort(Build) - │ ├── output columns: [t1.c (#5), t1.a (#3), COUNT(*) (#7)] - │ ├── sort keys: [COUNT(*) ASC NULLS LAST] - │ ├── estimated rows: 0.00 - │ └── EvalScalar - │ ├── output columns: [t1.c (#5), t1.a (#3), COUNT(*) (#7)] - │ ├── expressions: [COUNT(*) (#6)] - │ ├── estimated rows: 0.00 - │ └── AggregateFinal - │ ├── output columns: [COUNT(*) (#6), t1.c (#5), t1.a (#3)] - │ ├── group by: [c, a] - │ ├── aggregate functions: [count()] - │ ├── estimated rows: 0.00 - │ └── AggregatePartial - │ ├── group by: [c, a] - │ ├── aggregate functions: [count()] - │ ├── estimated rows: 0.00 - │ └── Filter - │ ├── output columns: [t1.a (#3), t1.c (#5)] - │ ├── filters: [is_true(a (#3) = a (#3))] - │ ├── estimated rows: 0.00 - │ └── TableScan - │ ├── table: default.default.t1 - │ ├── output columns: [a (#3), c (#5)] - │ ├── read rows: 0 - │ ├── read size: 0 - │ ├── partitions total: 0 - │ ├── partitions scanned: 0 - │ ├── push downs: [filters: [is_true(t1.a (#3) = t1.a (#3))], limit: NONE] - │ └── estimated rows: 0.00 - └── TableScan(Probe) - ├── table: default.default.t2 - ├── output columns: [a (#0), b (#1), c (#2)] - ├── read rows: 0 - ├── read size: 0 - ├── partitions total: 0 - ├── partitions scanned: 0 - ├── push downs: [filters: [], limit: NONE] - └── estimated rows: 0.00 +├── Sort(Build) +│ ├── output columns: [t1.c (#5), t1.a (#3), COUNT(*) (#7)] +│ ├── sort keys: [COUNT(*) ASC NULLS LAST] +│ ├── estimated rows: 0.00 +│ └── EvalScalar +│ ├── output columns: [t1.c (#5), t1.a (#3), COUNT(*) (#7)] +│ ├── expressions: [COUNT(*) (#6)] +│ ├── estimated rows: 0.00 +│ └── AggregateFinal +│ ├── output columns: [COUNT(*) (#6), t1.c (#5), t1.a (#3)] +│ ├── group by: [c, a] +│ ├── aggregate functions: [count()] +│ ├── estimated rows: 0.00 +│ └── AggregatePartial +│ ├── group by: [c, a] +│ ├── aggregate functions: [count()] +│ ├── estimated rows: 0.00 +│ └── Filter +│ ├── output columns: [t1.a (#3), t1.c (#5)] +│ ├── filters: [is_true(a (#3) = a (#3))] +│ ├── estimated rows: 0.00 +│ └── TableScan +│ ├── table: default.default.t1 +│ ├── output columns: [a (#3), c (#5)] +│ ├── read rows: 0 +│ ├── read size: 0 +│ ├── partitions total: 0 +│ ├── partitions scanned: 0 +│ ├── push downs: [filters: [is_true(t1.a (#3) = t1.a (#3))], limit: NONE] +│ └── estimated rows: 0.00 +└── TableScan(Probe) + ├── table: default.default.t2 + ├── output columns: [a (#0), b (#1), c (#2)] + ├── read rows: 0 + ├── read size: 0 + ├── partitions total: 0 + ├── partitions scanned: 0 + ├── push downs: [filters: [], limit: NONE] + └── estimated rows: 0.00 query T explain insert into t2 select * from t1; diff --git a/tests/sqllogictests/suites/mode/standalone/explain/limit.test b/tests/sqllogictests/suites/mode/standalone/explain/limit.test index 0fe71b4a5d92..3b1ee5bb12cf 100644 --- a/tests/sqllogictests/suites/mode/standalone/explain/limit.test +++ b/tests/sqllogictests/suites/mode/standalone/explain/limit.test @@ -80,91 +80,87 @@ Limit ├── output columns: [t.number (#0)] ├── limit: 3 ├── offset: 0 -├── estimated rows: 0.20 +├── estimated rows: 1.00 └── Sort ├── output columns: [t.number (#0)] ├── sort keys: [number DESC NULLS LAST] - ├── estimated rows: 0.20 + ├── estimated rows: 1.00 └── AggregateFinal ├── output columns: [t.number (#0)] ├── group by: [number] ├── aggregate functions: [] - ├── estimated rows: 0.20 + ├── estimated rows: 1.00 └── AggregatePartial ├── group by: [number] ├── aggregate functions: [] - ├── estimated rows: 0.20 + ├── estimated rows: 1.00 ├── rank limit: 3 - └── Filter + └── HashJoin ├── output columns: [t.number (#0)] - ├── filters: [is_true(CAST(t.number (#0) AS UInt64 NULL) = if(true, TRY_CAST(scalar_subquery_4 (#4) AS UInt64 NULL), 0))] - ├── estimated rows: 0.20 - └── HashJoin - ├── output columns: [t.number (#0), COUNT(*) (#4)] - ├── join type: INNER - ├── build keys: [number (#2)] - ├── probe keys: [number (#0)] + ├── join type: INNER + ├── build keys: [number (#2), if(true, TRY_CAST(scalar_subquery_4 (#4) AS UInt64 NULL), 0)] + ├── probe keys: [number (#0), CAST(t.number (#0) AS UInt64 NULL)] + ├── filters: [] + ├── estimated rows: 1.00 + ├── AggregateFinal(Build) + │ ├── output columns: [COUNT(*) (#4), t2.number (#2)] + │ ├── group by: [number] + │ ├── aggregate functions: [count()] + │ ├── estimated rows: 1.00 + │ └── AggregatePartial + │ ├── group by: [number] + │ ├── aggregate functions: [count()] + │ ├── estimated rows: 1.00 + │ └── HashJoin + │ ├── output columns: [t2.number (#2)] + │ ├── join type: CROSS + │ ├── build keys: [] + │ ├── probe keys: [] + │ ├── filters: [] + │ ├── estimated rows: 1.00 + │ ├── TableScan(Build) + │ │ ├── table: default.system.numbers + │ │ ├── output columns: [] + │ │ ├── read rows: 1 + │ │ ├── read size: < 1 KiB + │ │ ├── partitions total: 1 + │ │ ├── partitions scanned: 1 + │ │ ├── push downs: [filters: [], limit: NONE] + │ │ └── estimated rows: 1.00 + │ └── TableScan(Probe) + │ ├── table: default.system.numbers + │ ├── output columns: [number (#2)] + │ ├── read rows: 1 + │ ├── read size: < 1 KiB + │ ├── partitions total: 1 + │ ├── partitions scanned: 1 + │ ├── push downs: [filters: [], limit: NONE] + │ └── estimated rows: 1.00 + └── HashJoin(Probe) + ├── output columns: [t.number (#0)] + ├── join type: CROSS + ├── build keys: [] + ├── probe keys: [] ├── filters: [] ├── estimated rows: 1.00 - ├── AggregateFinal(Build) - │ ├── output columns: [COUNT(*) (#4), t2.number (#2)] - │ ├── group by: [number] - │ ├── aggregate functions: [count()] - │ ├── estimated rows: 1.00 - │ └── AggregatePartial - │ ├── group by: [number] - │ ├── aggregate functions: [count()] - │ ├── estimated rows: 1.00 - │ └── HashJoin - │ ├── output columns: [t2.number (#2)] - │ ├── join type: CROSS - │ ├── build keys: [] - │ ├── probe keys: [] - │ ├── filters: [] - │ ├── estimated rows: 1.00 - │ ├── TableScan(Build) - │ │ ├── table: default.system.numbers - │ │ ├── output columns: [] - │ │ ├── read rows: 1 - │ │ ├── read size: < 1 KiB - │ │ ├── partitions total: 1 - │ │ ├── partitions scanned: 1 - │ │ ├── push downs: [filters: [], limit: NONE] - │ │ └── estimated rows: 1.00 - │ └── TableScan(Probe) - │ ├── table: default.system.numbers - │ ├── output columns: [number (#2)] - │ ├── read rows: 1 - │ ├── read size: < 1 KiB - │ ├── partitions total: 1 - │ ├── partitions scanned: 1 - │ ├── push downs: [filters: [], limit: NONE] - │ └── estimated rows: 1.00 - └── HashJoin(Probe) - ├── output columns: [t.number (#0)] - ├── join type: CROSS - ├── build keys: [] - ├── probe keys: [] - ├── filters: [] - ├── estimated rows: 1.00 - ├── TableScan(Build) - │ ├── table: default.system.numbers - │ ├── output columns: [] - │ ├── read rows: 1 - │ ├── read size: < 1 KiB - │ ├── partitions total: 1 - │ ├── partitions scanned: 1 - │ ├── push downs: [filters: [], limit: NONE] - │ └── estimated rows: 1.00 - └── TableScan(Probe) - ├── table: default.system.numbers - ├── output columns: [number (#0)] - ├── read rows: 1 - ├── read size: < 1 KiB - ├── partitions total: 1 - ├── partitions scanned: 1 - ├── push downs: [filters: [], limit: NONE] - └── estimated rows: 1.00 + ├── TableScan(Build) + │ ├── table: default.system.numbers + │ ├── output columns: [] + │ ├── read rows: 1 + │ ├── read size: < 1 KiB + │ ├── partitions total: 1 + │ ├── partitions scanned: 1 + │ ├── push downs: [filters: [], limit: NONE] + │ └── estimated rows: 1.00 + └── TableScan(Probe) + ├── table: default.system.numbers + ├── output columns: [number (#0)] + ├── read rows: 1 + ├── read size: < 1 KiB + ├── partitions total: 1 + ├── partitions scanned: 1 + ├── push downs: [filters: [], limit: NONE] + └── estimated rows: 1.00 query T explain select * from (select count(t1.number) as c1 from numbers(1) as t1 group by number) as t3 left join (select count(t.number) as c from numbers(2) as t group by number) as t4 on t3.c1=t4.c order by t3.c1 limit 1 diff --git a/tests/sqllogictests/suites/mode/standalone/explain/prune_column.test b/tests/sqllogictests/suites/mode/standalone/explain/prune_column.test index 91b532ed9e7d..80f7b07f2777 100644 --- a/tests/sqllogictests/suites/mode/standalone/explain/prune_column.test +++ b/tests/sqllogictests/suites/mode/standalone/explain/prune_column.test @@ -116,75 +116,56 @@ explain select t1.a from (select number + 1 as a, number + 1 as b from numbers(2 HashJoin ├── output columns: [a (#1)] ├── join type: INNER -├── build keys: [_if_scalar_subquery (#15)] -├── probe keys: [CAST(t1.a (#1) AS UInt64 NULL)] +├── build keys: [scalar_subquery_12 (#12)] +├── probe keys: [t1.a (#1)] ├── filters: [] ├── estimated rows: 2.00 -├── EvalScalar(Build) -│ ├── output columns: [_if_scalar_subquery (#15)] -│ ├── expressions: [if(CAST(_count_scalar_subquery (#13) = 0 AS Boolean NULL), NULL, _any_scalar_subquery (#14))] +├── AggregateFinal(Build) +│ ├── output columns: [COUNT(*) (#12)] +│ ├── group by: [] +│ ├── aggregate functions: [count()] │ ├── estimated rows: 1.00 -│ └── Limit -│ ├── output columns: [_count_scalar_subquery (#13), _any_scalar_subquery (#14)] -│ ├── limit: 1 -│ ├── offset: 0 +│ └── AggregatePartial +│ ├── group by: [] +│ ├── aggregate functions: [count()] │ ├── estimated rows: 1.00 -│ └── AggregateFinal -│ ├── output columns: [_count_scalar_subquery (#13), _any_scalar_subquery (#14)] -│ ├── group by: [] -│ ├── aggregate functions: [count(), any(COUNT(*))] -│ ├── estimated rows: 1.00 -│ └── AggregatePartial -│ ├── group by: [] -│ ├── aggregate functions: [count(), any(COUNT(*))] +│ └── HashJoin +│ ├── output columns: [] +│ ├── join type: INNER +│ ├── build keys: [t2.b (#5)] +│ ├── probe keys: [t3.b (#10)] +│ ├── filters: [] +│ ├── estimated rows: 0.20 +│ ├── EvalScalar(Build) +│ │ ├── output columns: [b (#5)] +│ │ ├── expressions: [numbers.number (#3) + 1] +│ │ ├── estimated rows: 0.20 +│ │ └── Filter +│ │ ├── output columns: [numbers.number (#3)] +│ │ ├── filters: [numbers.number (#3) + 1 = 1] +│ │ ├── estimated rows: 0.20 +│ │ └── TableScan +│ │ ├── table: default.system.numbers +│ │ ├── output columns: [number (#3)] +│ │ ├── read rows: 1 +│ │ ├── read size: < 1 KiB +│ │ ├── partitions total: 1 +│ │ ├── partitions scanned: 1 +│ │ ├── push downs: [filters: [numbers.number (#3) + 1 = 1], limit: NONE] +│ │ └── estimated rows: 1.00 +│ └── EvalScalar(Probe) +│ ├── output columns: [b (#10)] +│ ├── expressions: [numbers.number (#8) + 1] │ ├── estimated rows: 1.00 -│ ├── rank limit: 1 -│ └── AggregateFinal -│ ├── output columns: [COUNT(*) (#12)] -│ ├── group by: [] -│ ├── aggregate functions: [count()] -│ ├── estimated rows: 1.00 -│ └── AggregatePartial -│ ├── group by: [] -│ ├── aggregate functions: [count()] -│ ├── estimated rows: 1.00 -│ └── HashJoin -│ ├── output columns: [] -│ ├── join type: INNER -│ ├── build keys: [t2.b (#5)] -│ ├── probe keys: [t3.b (#10)] -│ ├── filters: [] -│ ├── estimated rows: 0.20 -│ ├── EvalScalar(Build) -│ │ ├── output columns: [b (#5)] -│ │ ├── expressions: [numbers.number (#3) + 1] -│ │ ├── estimated rows: 0.20 -│ │ └── Filter -│ │ ├── output columns: [numbers.number (#3)] -│ │ ├── filters: [numbers.number (#3) + 1 = 1] -│ │ ├── estimated rows: 0.20 -│ │ └── TableScan -│ │ ├── table: default.system.numbers -│ │ ├── output columns: [number (#3)] -│ │ ├── read rows: 1 -│ │ ├── read size: < 1 KiB -│ │ ├── partitions total: 1 -│ │ ├── partitions scanned: 1 -│ │ ├── push downs: [filters: [numbers.number (#3) + 1 = 1], limit: NONE] -│ │ └── estimated rows: 1.00 -│ └── EvalScalar(Probe) -│ ├── output columns: [b (#10)] -│ ├── expressions: [numbers.number (#8) + 1] -│ ├── estimated rows: 1.00 -│ └── TableScan -│ ├── table: default.system.numbers -│ ├── output columns: [number (#8)] -│ ├── read rows: 1 -│ ├── read size: < 1 KiB -│ ├── partitions total: 1 -│ ├── partitions scanned: 1 -│ ├── push downs: [filters: [], limit: NONE] -│ └── estimated rows: 1.00 +│ └── TableScan +│ ├── table: default.system.numbers +│ ├── output columns: [number (#8)] +│ ├── read rows: 1 +│ ├── read size: < 1 KiB +│ ├── partitions total: 1 +│ ├── partitions scanned: 1 +│ ├── push downs: [filters: [], limit: NONE] +│ └── estimated rows: 1.00 └── EvalScalar(Probe) ├── output columns: [a (#1)] ├── expressions: [numbers.number (#0) + 1] diff --git a/tests/sqllogictests/suites/mode/standalone/explain/subquery.test b/tests/sqllogictests/suites/mode/standalone/explain/subquery.test index 91d05787655f..c135363fe27d 100644 --- a/tests/sqllogictests/suites/mode/standalone/explain/subquery.test +++ b/tests/sqllogictests/suites/mode/standalone/explain/subquery.test @@ -1,76 +1,72 @@ query T explain select t.number from numbers(1) as t, numbers(1) as t1 where t.number = (select count(*) from numbers(1) as t2, numbers(1) as t3 where t.number = t2.number) ---- -Filter +HashJoin ├── output columns: [t.number (#0)] -├── filters: [is_true(CAST(t.number (#0) AS UInt64 NULL) = if(true, TRY_CAST(scalar_subquery_4 (#4) AS UInt64 NULL), 0))] -├── estimated rows: 0.20 -└── HashJoin - ├── output columns: [t.number (#0), COUNT(*) (#4)] - ├── join type: INNER - ├── build keys: [number (#2)] - ├── probe keys: [number (#0)] +├── join type: INNER +├── build keys: [number (#2), if(true, TRY_CAST(scalar_subquery_4 (#4) AS UInt64 NULL), 0)] +├── probe keys: [number (#0), CAST(t.number (#0) AS UInt64 NULL)] +├── filters: [] +├── estimated rows: 1.00 +├── AggregateFinal(Build) +│ ├── output columns: [COUNT(*) (#4), t2.number (#2)] +│ ├── group by: [number] +│ ├── aggregate functions: [count()] +│ ├── estimated rows: 1.00 +│ └── AggregatePartial +│ ├── group by: [number] +│ ├── aggregate functions: [count()] +│ ├── estimated rows: 1.00 +│ └── HashJoin +│ ├── output columns: [t2.number (#2)] +│ ├── join type: CROSS +│ ├── build keys: [] +│ ├── probe keys: [] +│ ├── filters: [] +│ ├── estimated rows: 1.00 +│ ├── TableScan(Build) +│ │ ├── table: default.system.numbers +│ │ ├── output columns: [] +│ │ ├── read rows: 1 +│ │ ├── read size: < 1 KiB +│ │ ├── partitions total: 1 +│ │ ├── partitions scanned: 1 +│ │ ├── push downs: [filters: [], limit: NONE] +│ │ └── estimated rows: 1.00 +│ └── TableScan(Probe) +│ ├── table: default.system.numbers +│ ├── output columns: [number (#2)] +│ ├── read rows: 1 +│ ├── read size: < 1 KiB +│ ├── partitions total: 1 +│ ├── partitions scanned: 1 +│ ├── push downs: [filters: [], limit: NONE] +│ └── estimated rows: 1.00 +└── HashJoin(Probe) + ├── output columns: [t.number (#0)] + ├── join type: CROSS + ├── build keys: [] + ├── probe keys: [] ├── filters: [] ├── estimated rows: 1.00 - ├── AggregateFinal(Build) - │ ├── output columns: [COUNT(*) (#4), t2.number (#2)] - │ ├── group by: [number] - │ ├── aggregate functions: [count()] - │ ├── estimated rows: 1.00 - │ └── AggregatePartial - │ ├── group by: [number] - │ ├── aggregate functions: [count()] - │ ├── estimated rows: 1.00 - │ └── HashJoin - │ ├── output columns: [t2.number (#2)] - │ ├── join type: CROSS - │ ├── build keys: [] - │ ├── probe keys: [] - │ ├── filters: [] - │ ├── estimated rows: 1.00 - │ ├── TableScan(Build) - │ │ ├── table: default.system.numbers - │ │ ├── output columns: [] - │ │ ├── read rows: 1 - │ │ ├── read size: < 1 KiB - │ │ ├── partitions total: 1 - │ │ ├── partitions scanned: 1 - │ │ ├── push downs: [filters: [], limit: NONE] - │ │ └── estimated rows: 1.00 - │ └── TableScan(Probe) - │ ├── table: default.system.numbers - │ ├── output columns: [number (#2)] - │ ├── read rows: 1 - │ ├── read size: < 1 KiB - │ ├── partitions total: 1 - │ ├── partitions scanned: 1 - │ ├── push downs: [filters: [], limit: NONE] - │ └── estimated rows: 1.00 - └── HashJoin(Probe) - ├── output columns: [t.number (#0)] - ├── join type: CROSS - ├── build keys: [] - ├── probe keys: [] - ├── filters: [] - ├── estimated rows: 1.00 - ├── TableScan(Build) - │ ├── table: default.system.numbers - │ ├── output columns: [] - │ ├── read rows: 1 - │ ├── read size: < 1 KiB - │ ├── partitions total: 1 - │ ├── partitions scanned: 1 - │ ├── push downs: [filters: [], limit: NONE] - │ └── estimated rows: 1.00 - └── TableScan(Probe) - ├── table: default.system.numbers - ├── output columns: [number (#0)] - ├── read rows: 1 - ├── read size: < 1 KiB - ├── partitions total: 1 - ├── partitions scanned: 1 - ├── push downs: [filters: [], limit: NONE] - └── estimated rows: 1.00 + ├── TableScan(Build) + │ ├── table: default.system.numbers + │ ├── output columns: [] + │ ├── read rows: 1 + │ ├── read size: < 1 KiB + │ ├── partitions total: 1 + │ ├── partitions scanned: 1 + │ ├── push downs: [filters: [], limit: NONE] + │ └── estimated rows: 1.00 + └── TableScan(Probe) + ├── table: default.system.numbers + ├── output columns: [number (#0)] + ├── read rows: 1 + ├── read size: < 1 KiB + ├── partitions total: 1 + ├── partitions scanned: 1 + ├── push downs: [filters: [], limit: NONE] + └── estimated rows: 1.00 query T explain select t.number from numbers(1) as t where exists (select t1.number from numbers(1) as t1 where t.number = t1.number) or t.number > 1 @@ -162,42 +158,23 @@ explain select t.number from numbers(2) as t where number = (select * from numbe HashJoin ├── output columns: [t.number (#0)] ├── join type: INNER -├── build keys: [_if_scalar_subquery (#4)] -├── probe keys: [CAST(t.number (#0) AS UInt64 NULL)] +├── build keys: [scalar_subquery_1 (#1)] +├── probe keys: [t.number (#0)] ├── filters: [] -├── estimated rows: 2.00 -├── EvalScalar(Build) -│ ├── output columns: [_if_scalar_subquery (#4)] -│ ├── expressions: [if(CAST(_count_scalar_subquery (#2) = 0 AS Boolean NULL), NULL, _any_scalar_subquery (#3))] -│ ├── estimated rows: 1.00 -│ └── Limit -│ ├── output columns: [_count_scalar_subquery (#2), _any_scalar_subquery (#3)] -│ ├── limit: 1 -│ ├── offset: 0 -│ ├── estimated rows: 1.00 -│ └── AggregateFinal -│ ├── output columns: [_count_scalar_subquery (#2), _any_scalar_subquery (#3)] -│ ├── group by: [] -│ ├── aggregate functions: [count(), any(number)] -│ ├── estimated rows: 1.00 -│ └── AggregatePartial -│ ├── group by: [] -│ ├── aggregate functions: [count(), any(number)] -│ ├── estimated rows: 1.00 -│ ├── rank limit: 1 -│ └── Filter -│ ├── output columns: [numbers.number (#1)] -│ ├── filters: [numbers.number (#1) = 0] -│ ├── estimated rows: 0.00 -│ └── TableScan -│ ├── table: default.system.numbers -│ ├── output columns: [number (#1)] -│ ├── read rows: 1 -│ ├── read size: < 1 KiB -│ ├── partitions total: 1 -│ ├── partitions scanned: 1 -│ ├── push downs: [filters: [numbers.number (#1) = 0], limit: NONE] -│ └── estimated rows: 1.00 +├── estimated rows: 0.00 +├── Filter(Build) +│ ├── output columns: [numbers.number (#1)] +│ ├── filters: [numbers.number (#1) = 0] +│ ├── estimated rows: 0.00 +│ └── TableScan +│ ├── table: default.system.numbers +│ ├── output columns: [number (#1)] +│ ├── read rows: 1 +│ ├── read size: < 1 KiB +│ ├── partitions total: 1 +│ ├── partitions scanned: 1 +│ ├── push downs: [filters: [numbers.number (#1) = 0], limit: NONE] +│ └── estimated rows: 1.00 └── TableScan(Probe) ├── table: default.system.numbers ├── output columns: [number (#0)] diff --git a/tests/sqllogictests/suites/mode/standalone/explain_native/limit.test b/tests/sqllogictests/suites/mode/standalone/explain_native/limit.test index 651e7a5cae7c..341a70a18a06 100644 --- a/tests/sqllogictests/suites/mode/standalone/explain_native/limit.test +++ b/tests/sqllogictests/suites/mode/standalone/explain_native/limit.test @@ -80,91 +80,87 @@ Limit ├── output columns: [t.number (#0)] ├── limit: 3 ├── offset: 0 -├── estimated rows: 0.20 +├── estimated rows: 1.00 └── Sort ├── output columns: [t.number (#0)] ├── sort keys: [number DESC NULLS LAST] - ├── estimated rows: 0.20 + ├── estimated rows: 1.00 └── AggregateFinal ├── output columns: [t.number (#0)] ├── group by: [number] ├── aggregate functions: [] - ├── estimated rows: 0.20 + ├── estimated rows: 1.00 └── AggregatePartial ├── group by: [number] ├── aggregate functions: [] - ├── estimated rows: 0.20 + ├── estimated rows: 1.00 ├── rank limit: 3 - └── Filter + └── HashJoin ├── output columns: [t.number (#0)] - ├── filters: [is_true(CAST(t.number (#0) AS UInt64 NULL) = if(true, TRY_CAST(scalar_subquery_4 (#4) AS UInt64 NULL), 0))] - ├── estimated rows: 0.20 - └── HashJoin - ├── output columns: [t.number (#0), COUNT(*) (#4)] - ├── join type: INNER - ├── build keys: [number (#2)] - ├── probe keys: [number (#0)] + ├── join type: INNER + ├── build keys: [number (#2), if(true, TRY_CAST(scalar_subquery_4 (#4) AS UInt64 NULL), 0)] + ├── probe keys: [number (#0), CAST(t.number (#0) AS UInt64 NULL)] + ├── filters: [] + ├── estimated rows: 1.00 + ├── AggregateFinal(Build) + │ ├── output columns: [COUNT(*) (#4), t2.number (#2)] + │ ├── group by: [number] + │ ├── aggregate functions: [count()] + │ ├── estimated rows: 1.00 + │ └── AggregatePartial + │ ├── group by: [number] + │ ├── aggregate functions: [count()] + │ ├── estimated rows: 1.00 + │ └── HashJoin + │ ├── output columns: [t2.number (#2)] + │ ├── join type: CROSS + │ ├── build keys: [] + │ ├── probe keys: [] + │ ├── filters: [] + │ ├── estimated rows: 1.00 + │ ├── TableScan(Build) + │ │ ├── table: default.system.numbers + │ │ ├── output columns: [] + │ │ ├── read rows: 1 + │ │ ├── read size: < 1 KiB + │ │ ├── partitions total: 1 + │ │ ├── partitions scanned: 1 + │ │ ├── push downs: [filters: [], limit: NONE] + │ │ └── estimated rows: 1.00 + │ └── TableScan(Probe) + │ ├── table: default.system.numbers + │ ├── output columns: [number (#2)] + │ ├── read rows: 1 + │ ├── read size: < 1 KiB + │ ├── partitions total: 1 + │ ├── partitions scanned: 1 + │ ├── push downs: [filters: [], limit: NONE] + │ └── estimated rows: 1.00 + └── HashJoin(Probe) + ├── output columns: [t.number (#0)] + ├── join type: CROSS + ├── build keys: [] + ├── probe keys: [] ├── filters: [] ├── estimated rows: 1.00 - ├── AggregateFinal(Build) - │ ├── output columns: [COUNT(*) (#4), t2.number (#2)] - │ ├── group by: [number] - │ ├── aggregate functions: [count()] - │ ├── estimated rows: 1.00 - │ └── AggregatePartial - │ ├── group by: [number] - │ ├── aggregate functions: [count()] - │ ├── estimated rows: 1.00 - │ └── HashJoin - │ ├── output columns: [t2.number (#2)] - │ ├── join type: CROSS - │ ├── build keys: [] - │ ├── probe keys: [] - │ ├── filters: [] - │ ├── estimated rows: 1.00 - │ ├── TableScan(Build) - │ │ ├── table: default.system.numbers - │ │ ├── output columns: [] - │ │ ├── read rows: 1 - │ │ ├── read size: < 1 KiB - │ │ ├── partitions total: 1 - │ │ ├── partitions scanned: 1 - │ │ ├── push downs: [filters: [], limit: NONE] - │ │ └── estimated rows: 1.00 - │ └── TableScan(Probe) - │ ├── table: default.system.numbers - │ ├── output columns: [number (#2)] - │ ├── read rows: 1 - │ ├── read size: < 1 KiB - │ ├── partitions total: 1 - │ ├── partitions scanned: 1 - │ ├── push downs: [filters: [], limit: NONE] - │ └── estimated rows: 1.00 - └── HashJoin(Probe) - ├── output columns: [t.number (#0)] - ├── join type: CROSS - ├── build keys: [] - ├── probe keys: [] - ├── filters: [] - ├── estimated rows: 1.00 - ├── TableScan(Build) - │ ├── table: default.system.numbers - │ ├── output columns: [] - │ ├── read rows: 1 - │ ├── read size: < 1 KiB - │ ├── partitions total: 1 - │ ├── partitions scanned: 1 - │ ├── push downs: [filters: [], limit: NONE] - │ └── estimated rows: 1.00 - └── TableScan(Probe) - ├── table: default.system.numbers - ├── output columns: [number (#0)] - ├── read rows: 1 - ├── read size: < 1 KiB - ├── partitions total: 1 - ├── partitions scanned: 1 - ├── push downs: [filters: [], limit: NONE] - └── estimated rows: 1.00 + ├── TableScan(Build) + │ ├── table: default.system.numbers + │ ├── output columns: [] + │ ├── read rows: 1 + │ ├── read size: < 1 KiB + │ ├── partitions total: 1 + │ ├── partitions scanned: 1 + │ ├── push downs: [filters: [], limit: NONE] + │ └── estimated rows: 1.00 + └── TableScan(Probe) + ├── table: default.system.numbers + ├── output columns: [number (#0)] + ├── read rows: 1 + ├── read size: < 1 KiB + ├── partitions total: 1 + ├── partitions scanned: 1 + ├── push downs: [filters: [], limit: NONE] + └── estimated rows: 1.00 query T explain select * from (select count(t1.number) as c1 from numbers(1) as t1 group by number) as t3 left join (select count(t.number) as c from numbers(2) as t group by number) as t4 on t3.c1=t4.c order by t3.c1 limit 1 diff --git a/tests/sqllogictests/suites/mode/standalone/explain_native/prune_column.test b/tests/sqllogictests/suites/mode/standalone/explain_native/prune_column.test index 7766a562e3dc..f0f749081574 100644 --- a/tests/sqllogictests/suites/mode/standalone/explain_native/prune_column.test +++ b/tests/sqllogictests/suites/mode/standalone/explain_native/prune_column.test @@ -116,75 +116,56 @@ explain select t1.a from (select number + 1 as a, number + 1 as b from numbers(2 HashJoin ├── output columns: [a (#1)] ├── join type: INNER -├── build keys: [_if_scalar_subquery (#15)] -├── probe keys: [CAST(t1.a (#1) AS UInt64 NULL)] +├── build keys: [scalar_subquery_12 (#12)] +├── probe keys: [t1.a (#1)] ├── filters: [] ├── estimated rows: 2.00 -├── EvalScalar(Build) -│ ├── output columns: [_if_scalar_subquery (#15)] -│ ├── expressions: [if(CAST(_count_scalar_subquery (#13) = 0 AS Boolean NULL), NULL, _any_scalar_subquery (#14))] +├── AggregateFinal(Build) +│ ├── output columns: [COUNT(*) (#12)] +│ ├── group by: [] +│ ├── aggregate functions: [count()] │ ├── estimated rows: 1.00 -│ └── Limit -│ ├── output columns: [_count_scalar_subquery (#13), _any_scalar_subquery (#14)] -│ ├── limit: 1 -│ ├── offset: 0 +│ └── AggregatePartial +│ ├── group by: [] +│ ├── aggregate functions: [count()] │ ├── estimated rows: 1.00 -│ └── AggregateFinal -│ ├── output columns: [_count_scalar_subquery (#13), _any_scalar_subquery (#14)] -│ ├── group by: [] -│ ├── aggregate functions: [count(), any(COUNT(*))] -│ ├── estimated rows: 1.00 -│ └── AggregatePartial -│ ├── group by: [] -│ ├── aggregate functions: [count(), any(COUNT(*))] +│ └── HashJoin +│ ├── output columns: [] +│ ├── join type: INNER +│ ├── build keys: [t2.b (#5)] +│ ├── probe keys: [t3.b (#10)] +│ ├── filters: [] +│ ├── estimated rows: 0.20 +│ ├── EvalScalar(Build) +│ │ ├── output columns: [b (#5)] +│ │ ├── expressions: [numbers.number (#3) + 1] +│ │ ├── estimated rows: 0.20 +│ │ └── Filter +│ │ ├── output columns: [numbers.number (#3)] +│ │ ├── filters: [numbers.number (#3) + 1 = 1] +│ │ ├── estimated rows: 0.20 +│ │ └── TableScan +│ │ ├── table: default.system.numbers +│ │ ├── output columns: [number (#3)] +│ │ ├── read rows: 1 +│ │ ├── read size: < 1 KiB +│ │ ├── partitions total: 1 +│ │ ├── partitions scanned: 1 +│ │ ├── push downs: [filters: [numbers.number (#3) + 1 = 1], limit: NONE] +│ │ └── estimated rows: 1.00 +│ └── EvalScalar(Probe) +│ ├── output columns: [b (#10)] +│ ├── expressions: [numbers.number (#8) + 1] │ ├── estimated rows: 1.00 -│ ├── rank limit: 1 -│ └── AggregateFinal -│ ├── output columns: [COUNT(*) (#12)] -│ ├── group by: [] -│ ├── aggregate functions: [count()] -│ ├── estimated rows: 1.00 -│ └── AggregatePartial -│ ├── group by: [] -│ ├── aggregate functions: [count()] -│ ├── estimated rows: 1.00 -│ └── HashJoin -│ ├── output columns: [] -│ ├── join type: INNER -│ ├── build keys: [t2.b (#5)] -│ ├── probe keys: [t3.b (#10)] -│ ├── filters: [] -│ ├── estimated rows: 0.20 -│ ├── EvalScalar(Build) -│ │ ├── output columns: [b (#5)] -│ │ ├── expressions: [numbers.number (#3) + 1] -│ │ ├── estimated rows: 0.20 -│ │ └── Filter -│ │ ├── output columns: [numbers.number (#3)] -│ │ ├── filters: [numbers.number (#3) + 1 = 1] -│ │ ├── estimated rows: 0.20 -│ │ └── TableScan -│ │ ├── table: default.system.numbers -│ │ ├── output columns: [number (#3)] -│ │ ├── read rows: 1 -│ │ ├── read size: < 1 KiB -│ │ ├── partitions total: 1 -│ │ ├── partitions scanned: 1 -│ │ ├── push downs: [filters: [numbers.number (#3) + 1 = 1], limit: NONE] -│ │ └── estimated rows: 1.00 -│ └── EvalScalar(Probe) -│ ├── output columns: [b (#10)] -│ ├── expressions: [numbers.number (#8) + 1] -│ ├── estimated rows: 1.00 -│ └── TableScan -│ ├── table: default.system.numbers -│ ├── output columns: [number (#8)] -│ ├── read rows: 1 -│ ├── read size: < 1 KiB -│ ├── partitions total: 1 -│ ├── partitions scanned: 1 -│ ├── push downs: [filters: [], limit: NONE] -│ └── estimated rows: 1.00 +│ └── TableScan +│ ├── table: default.system.numbers +│ ├── output columns: [number (#8)] +│ ├── read rows: 1 +│ ├── read size: < 1 KiB +│ ├── partitions total: 1 +│ ├── partitions scanned: 1 +│ ├── push downs: [filters: [], limit: NONE] +│ └── estimated rows: 1.00 └── EvalScalar(Probe) ├── output columns: [a (#1)] ├── expressions: [numbers.number (#0) + 1] diff --git a/tests/sqllogictests/suites/mode/standalone/explain_native/subquery.test b/tests/sqllogictests/suites/mode/standalone/explain_native/subquery.test index eee114fd8135..3be20bbd5cc0 100644 --- a/tests/sqllogictests/suites/mode/standalone/explain_native/subquery.test +++ b/tests/sqllogictests/suites/mode/standalone/explain_native/subquery.test @@ -1,76 +1,72 @@ query T explain select t.number from numbers(1) as t, numbers(1) as t1 where t.number = (select count(*) from numbers(1) as t2, numbers(1) as t3 where t.number = t2.number) ---- -Filter +HashJoin ├── output columns: [t.number (#0)] -├── filters: [is_true(CAST(t.number (#0) AS UInt64 NULL) = if(true, TRY_CAST(scalar_subquery_4 (#4) AS UInt64 NULL), 0))] -├── estimated rows: 0.20 -└── HashJoin - ├── output columns: [t.number (#0), COUNT(*) (#4)] - ├── join type: INNER - ├── build keys: [number (#2)] - ├── probe keys: [number (#0)] +├── join type: INNER +├── build keys: [number (#2), if(true, TRY_CAST(scalar_subquery_4 (#4) AS UInt64 NULL), 0)] +├── probe keys: [number (#0), CAST(t.number (#0) AS UInt64 NULL)] +├── filters: [] +├── estimated rows: 1.00 +├── AggregateFinal(Build) +│ ├── output columns: [COUNT(*) (#4), t2.number (#2)] +│ ├── group by: [number] +│ ├── aggregate functions: [count()] +│ ├── estimated rows: 1.00 +│ └── AggregatePartial +│ ├── group by: [number] +│ ├── aggregate functions: [count()] +│ ├── estimated rows: 1.00 +│ └── HashJoin +│ ├── output columns: [t2.number (#2)] +│ ├── join type: CROSS +│ ├── build keys: [] +│ ├── probe keys: [] +│ ├── filters: [] +│ ├── estimated rows: 1.00 +│ ├── TableScan(Build) +│ │ ├── table: default.system.numbers +│ │ ├── output columns: [] +│ │ ├── read rows: 1 +│ │ ├── read size: < 1 KiB +│ │ ├── partitions total: 1 +│ │ ├── partitions scanned: 1 +│ │ ├── push downs: [filters: [], limit: NONE] +│ │ └── estimated rows: 1.00 +│ └── TableScan(Probe) +│ ├── table: default.system.numbers +│ ├── output columns: [number (#2)] +│ ├── read rows: 1 +│ ├── read size: < 1 KiB +│ ├── partitions total: 1 +│ ├── partitions scanned: 1 +│ ├── push downs: [filters: [], limit: NONE] +│ └── estimated rows: 1.00 +└── HashJoin(Probe) + ├── output columns: [t.number (#0)] + ├── join type: CROSS + ├── build keys: [] + ├── probe keys: [] ├── filters: [] ├── estimated rows: 1.00 - ├── AggregateFinal(Build) - │ ├── output columns: [COUNT(*) (#4), t2.number (#2)] - │ ├── group by: [number] - │ ├── aggregate functions: [count()] - │ ├── estimated rows: 1.00 - │ └── AggregatePartial - │ ├── group by: [number] - │ ├── aggregate functions: [count()] - │ ├── estimated rows: 1.00 - │ └── HashJoin - │ ├── output columns: [t2.number (#2)] - │ ├── join type: CROSS - │ ├── build keys: [] - │ ├── probe keys: [] - │ ├── filters: [] - │ ├── estimated rows: 1.00 - │ ├── TableScan(Build) - │ │ ├── table: default.system.numbers - │ │ ├── output columns: [] - │ │ ├── read rows: 1 - │ │ ├── read size: < 1 KiB - │ │ ├── partitions total: 1 - │ │ ├── partitions scanned: 1 - │ │ ├── push downs: [filters: [], limit: NONE] - │ │ └── estimated rows: 1.00 - │ └── TableScan(Probe) - │ ├── table: default.system.numbers - │ ├── output columns: [number (#2)] - │ ├── read rows: 1 - │ ├── read size: < 1 KiB - │ ├── partitions total: 1 - │ ├── partitions scanned: 1 - │ ├── push downs: [filters: [], limit: NONE] - │ └── estimated rows: 1.00 - └── HashJoin(Probe) - ├── output columns: [t.number (#0)] - ├── join type: CROSS - ├── build keys: [] - ├── probe keys: [] - ├── filters: [] - ├── estimated rows: 1.00 - ├── TableScan(Build) - │ ├── table: default.system.numbers - │ ├── output columns: [] - │ ├── read rows: 1 - │ ├── read size: < 1 KiB - │ ├── partitions total: 1 - │ ├── partitions scanned: 1 - │ ├── push downs: [filters: [], limit: NONE] - │ └── estimated rows: 1.00 - └── TableScan(Probe) - ├── table: default.system.numbers - ├── output columns: [number (#0)] - ├── read rows: 1 - ├── read size: < 1 KiB - ├── partitions total: 1 - ├── partitions scanned: 1 - ├── push downs: [filters: [], limit: NONE] - └── estimated rows: 1.00 + ├── TableScan(Build) + │ ├── table: default.system.numbers + │ ├── output columns: [] + │ ├── read rows: 1 + │ ├── read size: < 1 KiB + │ ├── partitions total: 1 + │ ├── partitions scanned: 1 + │ ├── push downs: [filters: [], limit: NONE] + │ └── estimated rows: 1.00 + └── TableScan(Probe) + ├── table: default.system.numbers + ├── output columns: [number (#0)] + ├── read rows: 1 + ├── read size: < 1 KiB + ├── partitions total: 1 + ├── partitions scanned: 1 + ├── push downs: [filters: [], limit: NONE] + └── estimated rows: 1.00 query T explain select t.number from numbers(1) as t where exists (select t1.number from numbers(1) as t1 where t.number = t1.number) or t.number > 1 @@ -162,42 +158,23 @@ explain select t.number from numbers(2) as t where number = (select * from numbe HashJoin ├── output columns: [t.number (#0)] ├── join type: INNER -├── build keys: [_if_scalar_subquery (#4)] -├── probe keys: [CAST(t.number (#0) AS UInt64 NULL)] +├── build keys: [scalar_subquery_1 (#1)] +├── probe keys: [t.number (#0)] ├── filters: [] -├── estimated rows: 2.00 -├── EvalScalar(Build) -│ ├── output columns: [_if_scalar_subquery (#4)] -│ ├── expressions: [if(CAST(_count_scalar_subquery (#2) = 0 AS Boolean NULL), NULL, _any_scalar_subquery (#3))] -│ ├── estimated rows: 1.00 -│ └── Limit -│ ├── output columns: [_count_scalar_subquery (#2), _any_scalar_subquery (#3)] -│ ├── limit: 1 -│ ├── offset: 0 -│ ├── estimated rows: 1.00 -│ └── AggregateFinal -│ ├── output columns: [_count_scalar_subquery (#2), _any_scalar_subquery (#3)] -│ ├── group by: [] -│ ├── aggregate functions: [count(), any(number)] -│ ├── estimated rows: 1.00 -│ └── AggregatePartial -│ ├── group by: [] -│ ├── aggregate functions: [count(), any(number)] -│ ├── estimated rows: 1.00 -│ ├── rank limit: 1 -│ └── Filter -│ ├── output columns: [numbers.number (#1)] -│ ├── filters: [numbers.number (#1) = 0] -│ ├── estimated rows: 0.00 -│ └── TableScan -│ ├── table: default.system.numbers -│ ├── output columns: [number (#1)] -│ ├── read rows: 1 -│ ├── read size: < 1 KiB -│ ├── partitions total: 1 -│ ├── partitions scanned: 1 -│ ├── push downs: [filters: [numbers.number (#1) = 0], limit: NONE] -│ └── estimated rows: 1.00 +├── estimated rows: 0.00 +├── Filter(Build) +│ ├── output columns: [numbers.number (#1)] +│ ├── filters: [numbers.number (#1) = 0] +│ ├── estimated rows: 0.00 +│ └── TableScan +│ ├── table: default.system.numbers +│ ├── output columns: [number (#1)] +│ ├── read rows: 1 +│ ├── read size: < 1 KiB +│ ├── partitions total: 1 +│ ├── partitions scanned: 1 +│ ├── push downs: [filters: [numbers.number (#1) = 0], limit: NONE] +│ └── estimated rows: 1.00 └── TableScan(Probe) ├── table: default.system.numbers ├── output columns: [number (#0)] diff --git a/tests/sqllogictests/suites/query/window_function/window_with_subquery.test b/tests/sqllogictests/suites/query/window_function/window_with_subquery.test new file mode 100644 index 000000000000..8465ba2268c0 --- /dev/null +++ b/tests/sqllogictests/suites/query/window_function/window_with_subquery.test @@ -0,0 +1,20 @@ +statement ok +create or replace table t1(a int); + +statement ok +insert into t1 values(1), (2), (2), (3); + +statement ok +create or replace table t2(b int); + +statement ok +insert into t2 values(1), (2), (3); + +query error 1001.*Scalar subquery can't return more than one row +select count(distinct a) over (partition by (select b from t2)) from t1; + +statement ok +drop table t1; + +statement ok +drop table t2;