15
15
use common_ast:: ast:: Identifier ;
16
16
use common_ast:: ast:: TableAlias ;
17
17
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 ;
19
22
use common_exception:: ErrorCode ;
20
23
use common_exception:: Result ;
21
24
22
25
use super :: AggregateInfo ;
23
26
use crate :: sql:: common:: IndexType ;
27
+ use crate :: sql:: plans:: Scalar ;
24
28
25
29
#[ derive( Clone , PartialEq , Eq , Debug ) ]
26
30
pub struct ColumnBinding {
@@ -41,6 +45,12 @@ pub struct ColumnBinding {
41
45
pub visible_in_unqualified_wildcard : bool ,
42
46
}
43
47
48
+ #[ derive( Debug , Clone ) ]
49
+ pub enum NameResolutionResult {
50
+ Column ( ColumnBinding ) ,
51
+ Alias { alias : String , scalar : Scalar } ,
52
+ }
53
+
44
54
/// `BindContext` stores all the free variables in a query and tracks the context of binding procedure.
45
55
#[ derive( Clone , Default , Debug ) ]
46
56
pub struct BindContext {
@@ -118,20 +128,37 @@ impl BindContext {
118
128
119
129
/// Try to find a column binding with given table name and column name.
120
130
/// This method will return error if the given names are ambiguous or invalid.
121
- pub fn resolve_column (
131
+ pub fn resolve_name (
122
132
& self ,
123
133
database : Option < & str > ,
124
134
table : Option < & str > ,
125
135
column : & Identifier ,
126
- ) -> Result < ColumnBinding > {
136
+ available_aliases : & [ ( String , Scalar ) ] ,
137
+ ) -> Result < NameResolutionResult > {
127
138
let mut result = vec ! [ ] ;
128
139
129
140
let mut bind_context: & BindContext = self ;
130
- // Lookup parent context to support correlated subquery
141
+ // Lookup parent context to resolve outer reference.
131
142
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
+
132
159
for column_binding in bind_context. columns . iter ( ) {
133
160
if Self :: match_column_binding ( database, table, column, column_binding) {
134
- result. push ( column_binding. clone ( ) ) ;
161
+ result. push ( NameResolutionResult :: Column ( column_binding. clone ( ) ) ) ;
135
162
}
136
163
}
137
164
if !result. is_empty ( ) {
0 commit comments