Skip to content

Commit

Permalink
Merge pull request #5279 from xudong963/table_ref
Browse files Browse the repository at this point in the history
feat(planner): support subquery table reference type for new planner
  • Loading branch information
BohuTANG authored May 14, 2022
2 parents e6d15eb + 90cfc71 commit 1d430b0
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 11 deletions.
8 changes: 2 additions & 6 deletions query/src/sql/planner/binder/bind_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,9 @@ impl BindContext {

/// Apply table alias like `SELECT * FROM t AS t1(a, b, c)`.
/// This method will rename column bindings according to table alias.
pub fn apply_table_alias(&mut self, original_name: &str, alias: &TableAlias) -> Result<()> {
pub fn apply_table_alias(&mut self, alias: &TableAlias) -> Result<()> {
for column in self.columns.iter_mut() {
if let Some(table_name) = &column.table_name {
if table_name.as_str() == original_name {
column.table_name = Some(alias.name.to_string());
}
}
column.table_name = Some(alias.name.to_string());
}

if alias.columns.len() > self.columns.len() {
Expand Down
33 changes: 33 additions & 0 deletions query/src/sql/planner/binder/join.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ impl<'a> Binder {
.bind_table_reference(&left_context, &join.right)
.await?;

check_duplicate_join_tables(&left_context, &right_context)?;

let mut bind_context = BindContext::new();
for column in left_context.all_column_bindings() {
bind_context.add_column_binding(column.clone());
Expand Down Expand Up @@ -125,6 +127,37 @@ impl<'a> Binder {
}
}

pub fn check_duplicate_join_tables(
left_context: &BindContext,
right_context: &BindContext,
) -> Result<()> {
let left_column_bindings = left_context.all_column_bindings();
let left_table_name = if left_column_bindings.is_empty() {
None
} else {
left_column_bindings[0].table_name.as_ref()
};

let right_column_bindings = right_context.all_column_bindings();
let right_table_name = if right_column_bindings.is_empty() {
None
} else {
right_column_bindings[0].table_name.as_ref()
};

if let Some(left) = left_table_name {
if let Some(right) = right_table_name {
if left.eq(right) {
return Err(ErrorCode::SemanticError(format!(
"Duplicated table name {} in the same FROM clause",
left
)));
}
}
}
Ok(())
}

struct JoinConditionResolver<'a> {
ctx: Arc<QueryContext>,

Expand Down
2 changes: 1 addition & 1 deletion query/src/sql/planner/binder/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ impl<'a> Binder {
/// in this function.
pub(super) async fn normalize_select_list(
&mut self,
select_list: &[SelectTarget<'a>],
input_context: &BindContext,
select_list: &[SelectTarget<'a>],
) -> Result<BindContext> {
let mut output_context = BindContext::new();
for select_target in select_list {
Expand Down
14 changes: 10 additions & 4 deletions query/src/sql/planner/binder/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ impl<'a> Binder {

// Output of current `SELECT` statement.
let mut output_context = self
.normalize_select_list(&stmt.select_list, &from_context)
.normalize_select_list(&from_context, &stmt.select_list)
.await?;

let agg_info = self.analyze_aggregate(&output_context)?;
Expand Down Expand Up @@ -206,7 +206,7 @@ impl<'a> Binder {

let (s_expr, mut bind_context) = self.bind_base_table(table_index).await?;
if let Some(alias) = alias {
bind_context.apply_table_alias(&table, alias)?;
bind_context.apply_table_alias(alias)?;
}
Ok((s_expr, bind_context))
}
Expand Down Expand Up @@ -257,12 +257,18 @@ impl<'a> Binder {

let (s_expr, mut bind_context) = self.bind_base_table(table_index).await?;
if let Some(alias) = alias {
bind_context.apply_table_alias(table.name(), alias)?;
bind_context.apply_table_alias(alias)?;
}
Ok((s_expr, bind_context))
}
TableReference::Join(join) => self.bind_join(bind_context, join).await,
_ => Err(ErrorCode::UnImplement("Unsupported table reference type")),
TableReference::Subquery { subquery, alias } => {
let (s_expr, mut bind_context) = self.bind_query(bind_context, subquery).await?;
if let Some(alias) = alias {
bind_context.apply_table_alias(alias)?;
}
Ok((s_expr, bind_context))
}
}
}

Expand Down
14 changes: 14 additions & 0 deletions tests/suites/0_stateless/20+_others/20_0001_planner_v2.result
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ NULL 2 3
0 1 1
1 1 2
2 NULL 3
4950
100
1
99999
1
0
685
0.685
====INNER_JOIN====
1 1
2 2
Expand Down Expand Up @@ -226,5 +234,11 @@ new_planner
18
====Memory Table====
1
=== Test Subquery In From ===
1
2
0 0 5
0 4 5
0 8 5
====Context Function====
default
23 changes: 23 additions & 0 deletions tests/suites/0_stateless/20+_others/20_0001_planner_v2.sql
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,21 @@ SELECT a%2 as a1, to_uint64(c % 3) as c1, count(0) as ct FROM t GROUP BY a1, c1
-- u64, nullable(u8)
SELECT to_uint64(c % 3) as c1, a%2 as a1, count(0) as ct FROM t GROUP BY a1, c1 ORDER BY a1, c1, ct;

-- aggregator combinator
-- distinct
select sum_distinct(number) from ( select number % 100 as number from numbers(100000));
select count_distinct(number) from ( select number % 100 as number from numbers(100000));
select sum_distinct(number) / count_distinct(number) = avg_distinct(number) from ( select number % 100 as number from numbers(100000));

-- if
select sum_if(number, number >= 100000 - 1) from numbers(100000);
select sum_if(number, number > 100) / count_if(number, number > 100) = avg_if(number, number > 100) from numbers(100000);
select count_if(number, number>9) from numbers(10);

-- boolean
select sum(number > 314) from numbers(1000);
select avg(number > 314) from numbers(1000);

drop table t;

-- Inner join
Expand Down Expand Up @@ -147,6 +162,14 @@ insert into temp values (1);
select a from temp;
drop table temp;

-- subquery in from
select '=== Test Subquery In From ===';
create table t(a int, b int);
insert into t values(1, 2),(2, 3);
select t1.a from (select * from t) as t1;
SELECT a,b,count() from (SELECT cast((number%4) AS bigint) as a, cast((number%20) AS bigint) as b from numbers(100)) group by a,b order by a,b limit 3 ;
drop table t;

select '====Context Function====';
use default;
select database();
Expand Down

0 comments on commit 1d430b0

Please sign in to comment.