@@ -1970,6 +1970,27 @@ impl Expr {
19701970 | Expr :: SimilarTo ( Like { expr, pattern, .. } ) => {
19711971 rewrite_placeholder ( pattern. as_mut ( ) , expr. as_ref ( ) , schema) ?;
19721972 }
1973+ Expr :: InSubquery ( InSubquery {
1974+ expr,
1975+ subquery,
1976+ negated : _,
1977+ } ) => {
1978+ let subquery_schema = subquery. subquery . schema ( ) ;
1979+ let fields = subquery_schema. fields ( ) ;
1980+
1981+ // only supports subquery with exactly 1 field
1982+ if let [ first_field] = & fields[ ..] {
1983+ rewrite_placeholder (
1984+ expr. as_mut ( ) ,
1985+ & Expr :: Column ( Column {
1986+ relation : None ,
1987+ name : first_field. name ( ) . clone ( ) ,
1988+ spans : Spans :: new ( ) ,
1989+ } ) ,
1990+ schema,
1991+ ) ?;
1992+ }
1993+ }
19731994 Expr :: Placeholder ( _) => {
19741995 has_placeholder = true ;
19751996 }
@@ -3421,7 +3442,8 @@ mod test {
34213442 use crate :: expr_fn:: col;
34223443 use crate :: {
34233444 case, lit, qualified_wildcard, wildcard, wildcard_with_options, ColumnarValue ,
3424- ScalarFunctionArgs , ScalarUDF , ScalarUDFImpl , Volatility ,
3445+ LogicalPlan , LogicalTableSource , Projection , ScalarFunctionArgs , ScalarUDF ,
3446+ ScalarUDFImpl , TableScan , Volatility ,
34253447 } ;
34263448 use arrow:: datatypes:: { Field , Schema } ;
34273449 use sqlparser:: ast;
@@ -3483,6 +3505,87 @@ mod test {
34833505 }
34843506 }
34853507
3508+ #[ test]
3509+ fn infer_placeholder_in_subquery ( ) -> Result < ( ) > {
3510+ // Schema for my_table: A (Int32), B (Int32)
3511+ let schema = Arc :: new ( Schema :: new ( vec ! [
3512+ Field :: new( "A" , DataType :: Int32 , true ) ,
3513+ Field :: new( "B" , DataType :: Int32 , true ) ,
3514+ ] ) ) ;
3515+
3516+ let source = Arc :: new ( LogicalTableSource :: new ( schema. clone ( ) ) ) ;
3517+
3518+ // Simulate: SELECT * FROM my_table WHERE $1 IN (SELECT A FROM my_table WHERE B > 3);
3519+ let placeholder = Expr :: Placeholder ( Placeholder {
3520+ id : "$1" . to_string ( ) ,
3521+ data_type : None ,
3522+ } ) ;
3523+
3524+ // Subquery: SELECT A FROM my_table WHERE B > 3
3525+ let subquery_filter = Expr :: BinaryExpr ( BinaryExpr {
3526+ left : Box :: new ( col ( "B" ) ) ,
3527+ op : Operator :: Gt ,
3528+ right : Box :: new ( Expr :: Literal ( ScalarValue :: Int32 ( Some ( 3 ) ) ) ) ,
3529+ } ) ;
3530+
3531+ let subquery_scan = LogicalPlan :: TableScan ( TableScan {
3532+ table_name : TableReference :: from ( "my_table" ) ,
3533+ source,
3534+ projected_schema : Arc :: new ( DFSchema :: try_from ( schema. clone ( ) ) ?) ,
3535+ projection : None ,
3536+ filters : vec ! [ subquery_filter. clone( ) ] ,
3537+ fetch : None ,
3538+ } ) ;
3539+
3540+ let projected_fields = vec ! [ Field :: new( "A" , DataType :: Int32 , true ) ] ;
3541+ let projected_schema = Arc :: new ( DFSchema :: from_unqualified_fields (
3542+ projected_fields. into ( ) ,
3543+ Default :: default ( ) ,
3544+ ) ?) ;
3545+
3546+ let subquery = Subquery {
3547+ subquery : Arc :: new ( LogicalPlan :: Projection ( Projection {
3548+ expr : vec ! [ col( "A" ) ] ,
3549+ input : Arc :: new ( subquery_scan) ,
3550+ schema : projected_schema,
3551+ } ) ) ,
3552+ outer_ref_columns : vec ! [ ] ,
3553+ spans : Spans :: new ( ) ,
3554+ } ;
3555+
3556+ let in_subquery = Expr :: InSubquery ( InSubquery {
3557+ expr : Box :: new ( placeholder) ,
3558+ subquery,
3559+ negated : false ,
3560+ } ) ;
3561+
3562+ let df_schema = DFSchema :: try_from ( schema) ?;
3563+
3564+ let ( inferred_expr, contains_placeholder) =
3565+ in_subquery. infer_placeholder_types ( & df_schema) ?;
3566+
3567+ assert ! (
3568+ contains_placeholder,
3569+ "Expression should contain a placeholder"
3570+ ) ;
3571+
3572+ match inferred_expr {
3573+ Expr :: InSubquery ( in_subquery) => match * in_subquery. expr {
3574+ Expr :: Placeholder ( placeholder) => {
3575+ assert_eq ! (
3576+ placeholder. data_type,
3577+ Some ( DataType :: Int32 ) ,
3578+ "Placeholder $1 should infer Int32"
3579+ ) ;
3580+ }
3581+ _ => panic ! ( "Expected Placeholder expression in InSubquery" ) ,
3582+ } ,
3583+ _ => panic ! ( "Expected InSubquery expression" ) ,
3584+ }
3585+
3586+ Ok ( ( ) )
3587+ }
3588+
34863589 #[ test]
34873590 fn infer_placeholder_like_and_similar_to ( ) {
34883591 // name LIKE $1
0 commit comments