@@ -1775,6 +1775,27 @@ impl Expr {
17751775 | Expr :: SimilarTo ( Like { expr, pattern, .. } ) => {
17761776 rewrite_placeholder ( pattern. as_mut ( ) , expr. as_ref ( ) , schema) ?;
17771777 }
1778+ Expr :: InSubquery ( InSubquery {
1779+ expr,
1780+ subquery,
1781+ negated : _,
1782+ } ) => {
1783+ let subquery_schema = subquery. subquery . schema ( ) ;
1784+ let fields = subquery_schema. fields ( ) ;
1785+
1786+ // only supports subquery with exactly 1 field
1787+ if let [ first_field] = & fields[ ..] {
1788+ rewrite_placeholder (
1789+ expr. as_mut ( ) ,
1790+ & Expr :: Column ( Column {
1791+ relation : None ,
1792+ name : first_field. name ( ) . clone ( ) ,
1793+ spans : Spans :: new ( ) ,
1794+ } ) ,
1795+ schema,
1796+ ) ?;
1797+ }
1798+ }
17781799 Expr :: Placeholder ( _) => {
17791800 has_placeholder = true ;
17801801 }
@@ -3198,7 +3219,8 @@ mod test {
31983219 use crate :: expr_fn:: col;
31993220 use crate :: {
32003221 case, lit, qualified_wildcard, wildcard, wildcard_with_options, ColumnarValue ,
3201- ScalarFunctionArgs , ScalarUDF , ScalarUDFImpl , Volatility ,
3222+ LogicalPlan , LogicalTableSource , Projection , ScalarFunctionArgs , ScalarUDF ,
3223+ ScalarUDFImpl , TableScan , Volatility ,
32023224 } ;
32033225 use arrow:: datatypes:: { Field , Schema } ;
32043226 use sqlparser:: ast;
@@ -3260,6 +3282,87 @@ mod test {
32603282 }
32613283 }
32623284
3285+ #[ test]
3286+ fn infer_placeholder_in_subquery ( ) -> Result < ( ) > {
3287+ // Schema for my_table: A (Int32), B (Int32)
3288+ let schema = Arc :: new ( Schema :: new ( vec ! [
3289+ Field :: new( "A" , DataType :: Int32 , true ) ,
3290+ Field :: new( "B" , DataType :: Int32 , true ) ,
3291+ ] ) ) ;
3292+
3293+ let source = Arc :: new ( LogicalTableSource :: new ( schema. clone ( ) ) ) ;
3294+
3295+ // Simulate: SELECT * FROM my_table WHERE $1 IN (SELECT A FROM my_table WHERE B > 3);
3296+ let placeholder = Expr :: Placeholder ( Placeholder {
3297+ id : "$1" . to_string ( ) ,
3298+ data_type : None ,
3299+ } ) ;
3300+
3301+ // Subquery: SELECT A FROM my_table WHERE B > 3
3302+ let subquery_filter = Expr :: BinaryExpr ( BinaryExpr {
3303+ left : Box :: new ( col ( "B" ) ) ,
3304+ op : Operator :: Gt ,
3305+ right : Box :: new ( Expr :: Literal ( ScalarValue :: Int32 ( Some ( 3 ) ) ) ) ,
3306+ } ) ;
3307+
3308+ let subquery_scan = LogicalPlan :: TableScan ( TableScan {
3309+ table_name : TableReference :: from ( "my_table" ) ,
3310+ source,
3311+ projected_schema : Arc :: new ( DFSchema :: try_from ( schema. clone ( ) ) ?) ,
3312+ projection : None ,
3313+ filters : vec ! [ subquery_filter. clone( ) ] ,
3314+ fetch : None ,
3315+ } ) ;
3316+
3317+ let projected_fields = vec ! [ Field :: new( "A" , DataType :: Int32 , true ) ] ;
3318+ let projected_schema = Arc :: new ( DFSchema :: from_unqualified_fields (
3319+ projected_fields. into ( ) ,
3320+ Default :: default ( ) ,
3321+ ) ?) ;
3322+
3323+ let subquery = Subquery {
3324+ subquery : Arc :: new ( LogicalPlan :: Projection ( Projection {
3325+ expr : vec ! [ col( "A" ) ] ,
3326+ input : Arc :: new ( subquery_scan) ,
3327+ schema : projected_schema,
3328+ } ) ) ,
3329+ outer_ref_columns : vec ! [ ] ,
3330+ spans : Spans :: new ( ) ,
3331+ } ;
3332+
3333+ let in_subquery = Expr :: InSubquery ( InSubquery {
3334+ expr : Box :: new ( placeholder) ,
3335+ subquery,
3336+ negated : false ,
3337+ } ) ;
3338+
3339+ let df_schema = DFSchema :: try_from ( schema) ?;
3340+
3341+ let ( inferred_expr, contains_placeholder) =
3342+ in_subquery. infer_placeholder_types ( & df_schema) ?;
3343+
3344+ assert ! (
3345+ contains_placeholder,
3346+ "Expression should contain a placeholder"
3347+ ) ;
3348+
3349+ match inferred_expr {
3350+ Expr :: InSubquery ( in_subquery) => match * in_subquery. expr {
3351+ Expr :: Placeholder ( placeholder) => {
3352+ assert_eq ! (
3353+ placeholder. data_type,
3354+ Some ( DataType :: Int32 ) ,
3355+ "Placeholder $1 should infer Int32"
3356+ ) ;
3357+ }
3358+ _ => panic ! ( "Expected Placeholder expression in InSubquery" ) ,
3359+ } ,
3360+ _ => panic ! ( "Expected InSubquery expression" ) ,
3361+ }
3362+
3363+ Ok ( ( ) )
3364+ }
3365+
32633366 #[ test]
32643367 fn infer_placeholder_like_and_similar_to ( ) {
32653368 // name LIKE $1
0 commit comments