@@ -36,6 +36,7 @@ use crate::types::tuple::{Schema, SchemaRef};
3636use crate :: types:: value:: Utf8Type ;
3737use crate :: types:: { ColumnId , LogicalType } ;
3838use itertools:: Itertools ;
39+ use sqlparser:: ast:: CharLengthUnits :: Characters ;
3940use sqlparser:: ast:: {
4041 CharLengthUnits , Distinct , Expr , Ident , Join , JoinConstraint , JoinOperator , Offset ,
4142 OrderByExpr , Query , Select , SelectInto , SelectItem , SetExpr , SetOperator , SetQuantifier ,
@@ -156,6 +157,55 @@ impl<'a: 'b, 'b, T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'
156157 Ok ( plan)
157158 }
158159
160+ fn bind_set_cast (
161+ & self ,
162+ mut left_plan : LogicalPlan ,
163+ mut right_plan : LogicalPlan ,
164+ ) -> Result < ( LogicalPlan , LogicalPlan ) , DatabaseError > {
165+ let mut left_cast = vec ! [ ] ;
166+ let mut right_cast = vec ! [ ] ;
167+
168+ let left_schema = left_plan. output_schema ( ) ;
169+ let right_schema = right_plan. output_schema ( ) ;
170+
171+ for ( left_schema, right_schema) in left_schema. iter ( ) . zip ( right_schema. iter ( ) ) {
172+ let cast_type =
173+ LogicalType :: max_logical_type ( left_schema. datatype ( ) , right_schema. datatype ( ) ) ?;
174+ if & cast_type != left_schema. datatype ( ) {
175+ left_cast. push ( ScalarExpression :: TypeCast {
176+ expr : Box :: new ( ScalarExpression :: ColumnRef ( left_schema. clone ( ) ) ) ,
177+ ty : cast_type. clone ( ) ,
178+ } ) ;
179+ } else {
180+ left_cast. push ( ScalarExpression :: ColumnRef ( left_schema. clone ( ) ) ) ;
181+ }
182+ if & cast_type != right_schema. datatype ( ) {
183+ right_cast. push ( ScalarExpression :: TypeCast {
184+ expr : Box :: new ( ScalarExpression :: ColumnRef ( right_schema. clone ( ) ) ) ,
185+ ty : cast_type. clone ( ) ,
186+ } ) ;
187+ } else {
188+ right_cast. push ( ScalarExpression :: ColumnRef ( right_schema. clone ( ) ) ) ;
189+ }
190+ }
191+
192+ if left_cast. len ( ) > 0 {
193+ left_plan = LogicalPlan :: new (
194+ Operator :: Project ( ProjectOperator { exprs : left_cast } ) ,
195+ Childrens :: Only ( left_plan) ,
196+ ) ;
197+ }
198+
199+ if right_cast. len ( ) > 0 {
200+ right_plan = LogicalPlan :: new (
201+ Operator :: Project ( ProjectOperator { exprs : right_cast } ) ,
202+ Childrens :: Only ( right_plan) ,
203+ ) ;
204+ }
205+
206+ Ok ( ( left_plan, right_plan) )
207+ }
208+
159209 pub ( crate ) fn bind_set_operation (
160210 & mut self ,
161211 op : & SetOperator ,
@@ -169,30 +219,29 @@ impl<'a: 'b, 'b, T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'
169219 } ;
170220 let mut left_plan = self . bind_set_expr ( left) ?;
171221 let mut right_plan = self . bind_set_expr ( right) ?;
172- let fn_eq = |left_schema : & Schema , right_schema : & Schema | {
173- let left_len = left_schema. len ( ) ;
174222
175- if left_len != right_schema. len ( ) {
176- return false ;
177- }
178- for i in 0 ..left_len {
179- if left_schema[ i] . datatype ( ) != right_schema[ i] . datatype ( ) {
180- return false ;
181- }
182- }
183- true
184- } ;
223+ let mut left_schema = left_plan. output_schema ( ) ;
224+ let mut right_schema = right_plan. output_schema ( ) ;
185225
186- let left_schema = left_plan. output_schema ( ) ;
187- let right_schema = right_plan. output_schema ( ) ;
226+ let left_len = left_schema. len ( ) ;
188227
189- if ! fn_eq ( left_schema , right_schema) {
228+ if left_len != right_schema. len ( ) {
190229 return Err ( DatabaseError :: MisMatch (
191- "the output types on the left" ,
192- "the output types on the right" ,
230+ "the lens on the left" ,
231+ "the lens on the right" ,
193232 ) ) ;
194233 }
195234
235+ if !left_schema
236+ . iter ( )
237+ . zip ( right_schema. iter ( ) )
238+ . all ( |( left, right) | left. datatype ( ) == right. datatype ( ) )
239+ {
240+ ( left_plan, right_plan) = self . bind_set_cast ( left_plan, right_plan) ?;
241+ left_schema = left_plan. output_schema ( ) ;
242+ right_schema = right_plan. output_schema ( ) ;
243+ }
244+
196245 match op {
197246 SetOperator :: Union => {
198247 if is_all {
0 commit comments