Skip to content

Commit d39a32d

Browse files
authored
Merge pull request #6979 from leiysky/name-resolution-with-alias
feat(planner): Support name resolution for alias
2 parents 5918ef9 + 8030cd3 commit d39a32d

File tree

18 files changed

+185
-75
lines changed

18 files changed

+185
-75
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ impl<'a> Binder {
343343

344344
// Resolve scalar item and alias item
345345
let mut scalar_binder =
346-
ScalarBinder::new(bind_context, self.ctx.clone(), self.metadata.clone());
346+
ScalarBinder::new(bind_context, self.ctx.clone(), self.metadata.clone(), &[]);
347347
let (scalar_expr, data_type) = scalar_binder
348348
.bind(expr)
349349
.await

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

+32-5
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@
1515
use common_ast::ast::Identifier;
1616
use common_ast::ast::TableAlias;
1717
use common_ast::DisplayError;
18-
use common_datavalues::prelude::*;
18+
use common_datavalues::DataField;
19+
use common_datavalues::DataSchemaRef;
20+
use common_datavalues::DataSchemaRefExt;
21+
use common_datavalues::DataTypeImpl;
1922
use common_exception::ErrorCode;
2023
use common_exception::Result;
2124

2225
use super::AggregateInfo;
2326
use crate::sql::common::IndexType;
27+
use crate::sql::plans::Scalar;
2428

2529
#[derive(Clone, PartialEq, Eq, Debug)]
2630
pub struct ColumnBinding {
@@ -41,6 +45,12 @@ pub struct ColumnBinding {
4145
pub visible_in_unqualified_wildcard: bool,
4246
}
4347

48+
#[derive(Debug, Clone)]
49+
pub enum NameResolutionResult {
50+
Column(ColumnBinding),
51+
Alias { alias: String, scalar: Scalar },
52+
}
53+
4454
/// `BindContext` stores all the free variables in a query and tracks the context of binding procedure.
4555
#[derive(Clone, Default, Debug)]
4656
pub struct BindContext {
@@ -118,20 +128,37 @@ impl BindContext {
118128

119129
/// Try to find a column binding with given table name and column name.
120130
/// This method will return error if the given names are ambiguous or invalid.
121-
pub fn resolve_column(
131+
pub fn resolve_name(
122132
&self,
123133
database: Option<&str>,
124134
table: Option<&str>,
125135
column: &Identifier,
126-
) -> Result<ColumnBinding> {
136+
available_aliases: &[(String, Scalar)],
137+
) -> Result<NameResolutionResult> {
127138
let mut result = vec![];
128139

129140
let mut bind_context: &BindContext = self;
130-
// Lookup parent context to support correlated subquery
141+
// Lookup parent context to resolve outer reference.
131142
loop {
143+
// TODO(leiysky): use `Identifier` for alias instead of raw string
144+
for (alias, scalar) in available_aliases {
145+
if database.is_none() && table.is_none() && &column.name.to_lowercase() == alias {
146+
result.push(NameResolutionResult::Alias {
147+
alias: alias.clone(),
148+
scalar: scalar.clone(),
149+
});
150+
}
151+
}
152+
153+
// We will lookup alias first. If there are matched aliases, we will skip
154+
// looking up `BindContext` to avoid ambiguity.
155+
if !result.is_empty() {
156+
break;
157+
}
158+
132159
for column_binding in bind_context.columns.iter() {
133160
if Self::match_column_binding(database, table, column, column_binding) {
134-
result.push(column_binding.clone());
161+
result.push(NameResolutionResult::Column(column_binding.clone()));
135162
}
136163
}
137164
if !result.is_empty() {

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ impl<'a> Binder {
741741
match source {
742742
CreateTableSource::Columns(columns) => {
743743
let mut scalar_binder =
744-
ScalarBinder::new(&bind_context, self.ctx.clone(), self.metadata.clone());
744+
ScalarBinder::new(&bind_context, self.ctx.clone(), self.metadata.clone(), &[]);
745745
let mut fields = Vec::with_capacity(columns.len());
746746
let mut fields_comments = Vec::with_capacity(columns.len());
747747
for column in columns.iter() {
@@ -821,7 +821,7 @@ impl<'a> Binder {
821821
bind_context.columns.push(column);
822822
}
823823
let mut scalar_binder =
824-
ScalarBinder::new(&bind_context, self.ctx.clone(), self.metadata.clone());
824+
ScalarBinder::new(&bind_context, self.ctx.clone(), self.metadata.clone(), &[]);
825825

826826
let mut cluster_keys = Vec::with_capacity(cluster_by.len());
827827
for cluster_by in cluster_by.iter() {

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ impl<'a> Binder {
8181
.await?;
8282

8383
let mut scalar_binder =
84-
ScalarBinder::new(&context, self.ctx.clone(), self.metadata.clone());
84+
ScalarBinder::new(&context, self.ctx.clone(), self.metadata.clone(), &[]);
8585

8686
let mut expression = None;
8787
let mut require_columns: HashSet<String> = HashSet::new();

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

+13-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use common_ast::ast::Expr;
1616
use common_ast::parser::token::Token;
1717
use common_exception::Result;
1818

19+
use super::select::SelectList;
1920
use crate::sql::binder::aggregate::AggregateRewriter;
2021
use crate::sql::binder::split_conjunctions;
2122
use crate::sql::binder::ScalarBinder;
@@ -32,10 +33,20 @@ impl<'a> Binder {
3233
pub(super) async fn analyze_aggregate_having(
3334
&mut self,
3435
bind_context: &mut BindContext,
36+
select_list: &SelectList<'a>,
3537
having: &Expr<'a>,
3638
) -> Result<(Scalar, &'a [Token<'a>])> {
37-
let mut scalar_binder =
38-
ScalarBinder::new(bind_context, self.ctx.clone(), self.metadata.clone());
39+
let aliases = select_list
40+
.items
41+
.iter()
42+
.map(|item| (item.alias.clone(), item.scalar.clone()))
43+
.collect::<Vec<_>>();
44+
let mut scalar_binder = ScalarBinder::new(
45+
bind_context,
46+
self.ctx.clone(),
47+
self.metadata.clone(),
48+
&aliases,
49+
);
3950
let (scalar, _) = scalar_binder.bind(having).await?;
4051
let mut rewriter = AggregateRewriter::new(bind_context, self.metadata.clone());
4152
Ok((rewriter.visit(&scalar)?, having.span()))

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ async fn exprs_to_datavalue<'a>(
427427
}
428428
let mut expressions = Vec::with_capacity(exprs.len());
429429
for (i, expr) in exprs.iter().enumerate() {
430-
let mut scalar_binder = ScalarBinder::new(bind_context, ctx.clone(), metadata.clone());
430+
let mut scalar_binder = ScalarBinder::new(bind_context, ctx.clone(), metadata.clone(), &[]);
431431
let scalar = scalar_binder.bind(expr).await?.0;
432432
let expression_builder = ExpressionBuilderWithRenaming::create(metadata.clone());
433433
let expr = expression_builder.build(&scalar)?;

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

+6-2
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,12 @@ impl<'a> JoinConditionResolver<'a> {
305305
right_join_conditions: &mut Vec<Scalar>,
306306
other_join_conditions: &mut Vec<Scalar>,
307307
) -> Result<()> {
308-
let mut scalar_binder =
309-
ScalarBinder::new(self.join_context, self.ctx.clone(), self.metadata.clone());
308+
let mut scalar_binder = ScalarBinder::new(
309+
self.join_context,
310+
self.ctx.clone(),
311+
self.metadata.clone(),
312+
&[],
313+
);
310314
let (scalar, _) = scalar_binder.bind(condition).await?;
311315
let conjunctions = split_conjunctions(&scalar);
312316

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ impl<'a> Binder {
3131
limit: Option<&Expr<'a>>,
3232
offset: &Option<Expr<'a>>,
3333
) -> Result<SExpr> {
34-
let type_checker = TypeChecker::new(bind_context, self.ctx.clone(), self.metadata.clone());
34+
let type_checker =
35+
TypeChecker::new(bind_context, self.ctx.clone(), self.metadata.clone(), &[]);
3536

3637
let limit_cnt = match limit {
3738
Some(Expr::Literal { span: _, lit: x }) => {

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

+1-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
use std::sync::Arc;
1616

1717
pub use aggregate::AggregateInfo;
18-
pub use bind_context::BindContext;
19-
pub use bind_context::ColumnBinding;
18+
pub use bind_context::*;
2019
use common_ast::ast::Statement;
2120
use common_ast::parser::parse_sql;
2221
use common_ast::parser::tokenize_sql;

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

+15-8
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use common_ast::ast::SelectTarget;
1919
use common_exception::ErrorCode;
2020
use common_exception::Result;
2121

22+
use super::bind_context::NameResolutionResult;
2223
use crate::sql::binder::select::SelectItem;
2324
use crate::sql::binder::select::SelectList;
2425
use crate::sql::optimizer::ColumnSet;
@@ -162,14 +163,16 @@ impl<'a> Binder {
162163
let indirection = &names[0];
163164
match indirection {
164165
Indirection::Identifier(ident) => {
165-
let column_binding =
166-
input_context.resolve_column(None, None, ident)?;
166+
let result = input_context.resolve_name(None, None, ident, &[])?;
167167
output.items.push(SelectItem {
168168
select_target,
169-
scalar: BoundColumnRef {
170-
column: column_binding,
171-
}
172-
.into(),
169+
scalar: match result {
170+
NameResolutionResult::Column(column) => {
171+
BoundColumnRef { column }.into()
172+
}
173+
NameResolutionResult::Alias { scalar, .. } => scalar,
174+
},
175+
173176
alias: ident.name.clone(),
174177
});
175178
}
@@ -197,8 +200,12 @@ impl<'a> Binder {
197200
}
198201
}
199202
SelectTarget::AliasedExpr { expr, alias } => {
200-
let mut scalar_binder =
201-
ScalarBinder::new(input_context, self.ctx.clone(), self.metadata.clone());
203+
let mut scalar_binder = ScalarBinder::new(
204+
input_context,
205+
self.ctx.clone(),
206+
self.metadata.clone(),
207+
&[],
208+
);
202209
let (bound_expr, _) = scalar_binder.bind(expr).await?;
203210

204211
// If alias is not specified, we will generate a name for the scalar expression.

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

+9-2
Original file line numberDiff line numberDiff line change
@@ -29,24 +29,31 @@ pub struct ScalarBinder<'a> {
2929
bind_context: &'a BindContext,
3030
ctx: Arc<QueryContext>,
3131
metadata: MetadataRef,
32+
aliases: &'a [(String, Scalar)],
3233
}
3334

3435
impl<'a> ScalarBinder<'a> {
3536
pub fn new(
3637
bind_context: &'a BindContext,
3738
ctx: Arc<QueryContext>,
3839
metadata: MetadataRef,
40+
aliases: &'a [(String, Scalar)],
3941
) -> Self {
4042
ScalarBinder {
4143
bind_context,
4244
ctx,
4345
metadata,
46+
aliases,
4447
}
4548
}
4649

4750
pub async fn bind(&mut self, expr: &Expr<'a>) -> Result<(Scalar, DataTypeImpl)> {
48-
let mut type_checker =
49-
TypeChecker::new(self.bind_context, self.ctx.clone(), self.metadata.clone());
51+
let mut type_checker = TypeChecker::new(
52+
self.bind_context,
53+
self.ctx.clone(),
54+
self.metadata.clone(),
55+
self.aliases,
56+
);
5057
Ok(*type_checker.resolve(expr, None).await?)
5158
}
5259
}

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ impl<'a> Binder {
100100

101101
let having = if let Some(having) = &stmt.having {
102102
Some(
103-
self.analyze_aggregate_having(&mut from_context, having)
103+
self.analyze_aggregate_having(&mut from_context, &select_list, having)
104104
.await?,
105105
)
106106
} else {
@@ -233,7 +233,7 @@ impl<'a> Binder {
233233
child: SExpr,
234234
) -> Result<SExpr> {
235235
let mut scalar_binder =
236-
ScalarBinder::new(bind_context, self.ctx.clone(), self.metadata.clone());
236+
ScalarBinder::new(bind_context, self.ctx.clone(), self.metadata.clone(), &[]);
237237
let (scalar, _) = scalar_binder.bind(expr).await?;
238238
let filter_plan = Filter {
239239
predicates: split_conjunctions(&scalar),

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ impl<'a> Binder {
3131
variable: &Identifier<'a>,
3232
value: &Literal,
3333
) -> Result<Plan> {
34-
let type_checker = TypeChecker::new(bind_context, self.ctx.clone(), self.metadata.clone());
34+
let type_checker =
35+
TypeChecker::new(bind_context, self.ctx.clone(), self.metadata.clone(), &[]);
3536

3637
let variable = variable.name.clone();
3738

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

+22-10
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use common_ast::DisplayError;
2222
use common_exception::ErrorCode;
2323
use common_exception::Result;
2424

25+
use super::bind_context::NameResolutionResult;
2526
use crate::sessions::TableContext;
2627
use crate::sql::binder::scalar::ScalarBinder;
2728
use crate::sql::binder::select::SelectList;
@@ -104,19 +105,26 @@ impl<'a> Binder {
104105

105106
// If there isn't a matched alias in select list, we will fallback to
106107
// from clause.
107-
let column = from_context.resolve_column(database_name.as_ref().map(|v| v.name.as_str()), table_name.as_ref().map(|v| v.name.as_str()), ident).and_then(|v| {
108+
let result = from_context.resolve_name(database_name.as_ref().map(|v| v.name.as_str()), table_name.as_ref().map(|v| v.name.as_str()), ident, &[]).and_then(|v| {
108109
if distinct {
109110
Err(ErrorCode::SemanticError(order.expr.span().display_error("for SELECT DISTINCT, ORDER BY expressions must appear in select list".to_string())))
110111
} else {
111112
Ok(v)
112113
}
113114
})?;
114-
order_items.push(OrderItem {
115-
expr: order.clone(),
116-
name: column.column_name.clone(),
117-
index: column.index,
118-
need_eval_scalar: false,
119-
});
115+
match result {
116+
NameResolutionResult::Column(column) => {
117+
order_items.push(OrderItem {
118+
expr: order.clone(),
119+
name: column.column_name.clone(),
120+
index: column.index,
121+
need_eval_scalar: false,
122+
});
123+
}
124+
NameResolutionResult::Alias { .. } => {
125+
return Err(ErrorCode::LogicalError("Invalid name resolution result"));
126+
}
127+
}
120128
}
121129
Expr::Literal {
122130
lit: Literal::Integer(index),
@@ -143,8 +151,12 @@ impl<'a> Binder {
143151
}
144152
bind_context.columns.push(column_binding.clone());
145153
}
146-
let mut scalar_binder =
147-
ScalarBinder::new(&bind_context, self.ctx.clone(), self.metadata.clone());
154+
let mut scalar_binder = ScalarBinder::new(
155+
&bind_context,
156+
self.ctx.clone(),
157+
self.metadata.clone(),
158+
&[],
159+
);
148160
let (bound_expr, _) = scalar_binder.bind(&order.expr).await?;
149161
let rewrite_scalar = self
150162
.rewrite_scalar_with_replacement(&bound_expr, &|nest_scalar| {
@@ -259,7 +271,7 @@ impl<'a> Binder {
259271
order_by: &[OrderByExpr<'_>],
260272
) -> Result<SExpr> {
261273
let mut scalar_binder =
262-
ScalarBinder::new(bind_context, self.ctx.clone(), self.metadata.clone());
274+
ScalarBinder::new(bind_context, self.ctx.clone(), self.metadata.clone(), &[]);
263275
let mut order_by_items = Vec::with_capacity(order_by.len());
264276
for order in order_by.iter() {
265277
match order.expr {

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ impl<'a> Binder {
173173
alias,
174174
} => {
175175
let mut scalar_binder =
176-
ScalarBinder::new(bind_context, self.ctx.clone(), self.metadata.clone());
176+
ScalarBinder::new(bind_context, self.ctx.clone(), self.metadata.clone(), &[]);
177177
let mut args = Vec::with_capacity(params.len());
178178
for arg in params.iter() {
179179
args.push(scalar_binder.bind(arg).await?);
@@ -296,7 +296,7 @@ impl<'a> Binder {
296296
TimeTravelPoint::Snapshot(s) => Ok(NavigationPoint::SnapshotID(s.to_owned())),
297297
TimeTravelPoint::Timestamp(expr) => {
298298
let mut type_checker =
299-
TypeChecker::new(bind_context, self.ctx.clone(), self.metadata.clone());
299+
TypeChecker::new(bind_context, self.ctx.clone(), self.metadata.clone(), &[]);
300300
let box (scalar, data_type) = type_checker
301301
.resolve(expr, Some(TimestampType::new_impl(6)))
302302
.await?;

0 commit comments

Comments
 (0)