Skip to content

Commit 59c0007

Browse files
authored
Merge pull request #10533 from xudong963/fix_cte
fix: ambiguous column reference with reused CTE
2 parents 7d28139 + 485a6bf commit 59c0007

File tree

4 files changed

+48
-13
lines changed

4 files changed

+48
-13
lines changed

src/query/sql/src/planner/binder/bind_context.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
use std::hash::Hash;
1616

17+
use common_ast::ast::Query;
1718
use common_ast::ast::TableAlias;
1819
use common_exception::ErrorCode;
1920
use common_exception::Result;
@@ -26,7 +27,6 @@ use dashmap::DashMap;
2627

2728
use super::AggregateInfo;
2829
use crate::normalize_identifier;
29-
use crate::optimizer::SExpr;
3030
use crate::plans::ScalarExpr;
3131
use crate::IndexType;
3232
use crate::NameResolutionContext;
@@ -101,8 +101,7 @@ pub struct BindContext {
101101
#[derive(Clone, Debug)]
102102
pub struct CteInfo {
103103
pub columns_alias: Vec<String>,
104-
pub s_expr: SExpr,
105-
pub bind_context: BindContext,
104+
pub query: Query,
106105
}
107106

108107
impl BindContext {

src/query/sql/src/planner/binder/select.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,9 @@ impl Binder {
203203
"duplicate cte {table_name}"
204204
)));
205205
}
206-
let (s_expr, cte_bind_context) = self.bind_query(bind_context, &cte.query).await?;
207206
let cte_info = CteInfo {
208207
columns_alias: cte.alias.columns.iter().map(|c| c.name.clone()).collect(),
209-
s_expr,
210-
bind_context: cte_bind_context.clone(),
208+
query: cte.query.clone(),
211209
};
212210
bind_context.ctes_map.insert(table_name, cte_info);
213211
}

src/query/sql/src/planner/binder/table.rs

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ use common_storages_result_cache::ResultCacheReader;
5656
use common_storages_result_cache::ResultScan;
5757
use common_storages_view::view_table::QUERY;
5858
use common_users::UserApiProvider;
59+
use dashmap::DashMap;
5960

6061
use crate::binder::copy::parse_stage_location_v2;
6162
use crate::binder::location::parse_uri_location;
@@ -138,7 +139,9 @@ impl Binder {
138139
};
139140
// Check and bind common table expression
140141
if let Some(cte_info) = bind_context.ctes_map.get(&table_name) {
141-
return self.bind_cte(bind_context, &table_name, alias, &cte_info);
142+
return self
143+
.bind_cte(bind_context, &table_name, alias, &cte_info)
144+
.await;
142145
}
143146

144147
if database == "system" {
@@ -153,15 +156,36 @@ impl Binder {
153156
};
154157

155158
// Resolve table with catalog
156-
let table_meta: Arc<dyn Table> = self
159+
let table_meta = match self
157160
.resolve_data_source(
158161
tenant.as_str(),
159162
catalog.as_str(),
160163
database.as_str(),
161164
table_name.as_str(),
162165
&navigation_point,
163166
)
164-
.await?;
167+
.await
168+
{
169+
Ok(table) => table,
170+
Err(_) => {
171+
let mut parent = bind_context.parent.as_ref();
172+
loop {
173+
if parent.is_none() {
174+
break;
175+
}
176+
if let Some(cte_info) = parent.unwrap().ctes_map.get(&table_name) {
177+
return self
178+
.bind_cte(bind_context, &table_name, alias, &cte_info)
179+
.await;
180+
}
181+
parent = parent.unwrap().parent.as_ref();
182+
}
183+
return Err(ErrorCode::UnknownTable(format!(
184+
"Unknown table '{table_name}'"
185+
)));
186+
}
187+
};
188+
165189
match table_meta.engine() {
166190
"VIEW" => {
167191
let query = table_meta
@@ -417,15 +441,23 @@ impl Binder {
417441
}
418442
}
419443

420-
fn bind_cte(
444+
async fn bind_cte(
421445
&mut self,
422446
bind_context: &BindContext,
423447
table_name: &str,
424448
alias: &Option<TableAlias>,
425449
cte_info: &CteInfo,
426450
) -> Result<(SExpr, BindContext)> {
427-
let mut new_bind_context = bind_context.clone();
428-
new_bind_context.columns = cte_info.bind_context.columns.clone();
451+
let new_bind_context = BindContext {
452+
parent: Some(Box::new(bind_context.clone())),
453+
columns: vec![],
454+
aggregate_info: Default::default(),
455+
in_grouping: false,
456+
ctes_map: Box::new(DashMap::new()),
457+
is_view: false,
458+
};
459+
let (s_expr, mut new_bind_context) =
460+
self.bind_query(&new_bind_context, &cte_info.query).await?;
429461
let mut cols_alias = cte_info.columns_alias.clone();
430462
if let Some(alias) = alias {
431463
for (idx, col_alias) in alias.columns.iter().enumerate() {
@@ -455,7 +487,7 @@ impl Binder {
455487
for (index, column_name) in cols_alias.iter().enumerate() {
456488
new_bind_context.columns[index].column_name = column_name.clone();
457489
}
458-
Ok((cte_info.s_expr.clone(), new_bind_context))
490+
Ok((s_expr, new_bind_context))
459491
}
460492

461493
async fn bind_base_table(

tests/sqllogictests/suites/query/cte.test

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,3 +365,9 @@ query II
365365
select * from (WITH source AS (select 1 as e) SELECT * FROM source) A, (WITH source AS (select 2 as e) SELECT * FROM source) B
366366
----
367367
1 2
368+
369+
query II
370+
with v as (select * from numbers(2)) select * from v t1, (select * from v where number = 0) t2 where t1.number = 1 and t2.number = 1
371+
----
372+
373+

0 commit comments

Comments
 (0)