@@ -39,7 +39,7 @@ use sqlparser::ast::{
3939 Statement , TableObject ,
4040} ;
4141use sqlparser:: tokenizer:: Span ;
42- use std:: collections:: { BTreeMap , HashMap , HashSet } ;
42+ use std:: collections:: { BTreeMap , HashMap } ;
4343use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
4444use std:: sync:: Arc ;
4545
@@ -54,6 +54,7 @@ use crate::planner::{LogicalPlan, SchemaOutput};
5454use crate :: storage:: { TableCache , Transaction , ViewCache } ;
5555use crate :: types:: tuple:: SchemaRef ;
5656use crate :: types:: value:: DataValue ;
57+ use crate :: types:: LogicalType ;
5758
5859pub enum InputRefType {
5960 AggCall ,
@@ -204,6 +205,69 @@ impl BoundSource<'_> {
204205 }
205206}
206207
208+ #[ derive( Clone ) ]
209+ pub ( crate ) struct UsingColumn {
210+ join_type : JoinType ,
211+ left_column : ColumnRef ,
212+ left_position : usize ,
213+ right_column : ColumnRef ,
214+ right_position : usize ,
215+ }
216+
217+ impl UsingColumn {
218+ fn new (
219+ join_type : JoinType ,
220+ left_column : ColumnRef ,
221+ left_position : usize ,
222+ right_column : ColumnRef ,
223+ right_position : usize ,
224+ ) -> Self {
225+ Self {
226+ join_type,
227+ left_column,
228+ left_position,
229+ right_column,
230+ right_position,
231+ }
232+ }
233+
234+ fn left_expr ( & self ) -> ScalarExpression {
235+ ScalarExpression :: column_expr ( self . left_column . clone ( ) , self . left_position )
236+ }
237+
238+ fn right_expr ( & self ) -> ScalarExpression {
239+ ScalarExpression :: column_expr ( self . right_column . clone ( ) , self . right_position )
240+ }
241+
242+ pub ( crate ) fn visible_expr ( & self ) -> Result < ScalarExpression , DatabaseError > {
243+ match self . join_type {
244+ JoinType :: RightOuter => Ok ( self . right_expr ( ) ) ,
245+ JoinType :: Full => {
246+ let left_expr = self . left_expr ( ) ;
247+ let right_expr = self . right_expr ( ) ;
248+ let left_ty = left_expr. return_type ( ) ;
249+ let right_ty = right_expr. return_type ( ) ;
250+ let ty = LogicalType :: max_logical_type ( & left_ty, & right_ty) ?. into_owned ( ) ;
251+
252+ Ok ( ScalarExpression :: Coalesce {
253+ exprs : vec ! [ left_expr, right_expr] ,
254+ ty,
255+ } )
256+ }
257+ JoinType :: Inner | JoinType :: LeftOuter | JoinType :: Cross => Ok ( self . left_expr ( ) ) ,
258+ }
259+ }
260+
261+ pub ( crate ) fn hides_column ( & self , column : & ColumnRef ) -> bool {
262+ let hidden_column = if self . join_type . is_right ( ) {
263+ & self . left_column
264+ } else {
265+ & self . right_column
266+ } ;
267+ hidden_column. same_column ( column)
268+ }
269+ }
270+
207271#[ derive( Clone ) ]
208272pub struct BinderContext < ' a , T : Transaction > {
209273 pub ( crate ) scala_functions : & ' a ScalaFunctions ,
@@ -221,7 +285,7 @@ pub struct BinderContext<'a, T: Transaction> {
221285 group_by_exprs : Vec < ScalarExpression > ,
222286 pub ( crate ) agg_calls : Vec < ScalarExpression > ,
223287 // join
224- using : HashSet < ColumnRef > ,
288+ using : HashMap < String , UsingColumn > ,
225289
226290 bind_step : QueryBindStep ,
227291 sub_queries : HashMap < QueryBindStep , Vec < SubQueryType > > ,
@@ -471,15 +535,27 @@ impl<'a, T: Transaction> BinderContext<'a, T> {
471535
472536 pub fn add_using (
473537 & mut self ,
538+ name : String ,
474539 join_type : JoinType ,
475- left_expr : & ColumnRef ,
476- right_expr : & ColumnRef ,
477- ) {
478- self . using . insert ( if join_type. is_right ( ) {
479- left_expr. clone ( )
480- } else {
481- right_expr. clone ( )
482- } ) ;
540+ left_column : & ColumnRef ,
541+ left_position : usize ,
542+ right_column : & ColumnRef ,
543+ right_position : usize ,
544+ ) -> Result < ( ) , DatabaseError > {
545+ if self . using . contains_key ( & name) {
546+ return Err ( DatabaseError :: UnsupportedStmt ( format ! (
547+ "duplicate `USING({name})` across joins is not supported"
548+ ) ) ) ;
549+ }
550+ let using_column = UsingColumn :: new (
551+ join_type,
552+ left_column. clone ( ) ,
553+ left_position,
554+ right_column. clone ( ) ,
555+ right_position,
556+ ) ;
557+ self . using . insert ( name, using_column) ;
558+ Ok ( ( ) )
483559 }
484560
485561 pub fn add_alias (
0 commit comments