@@ -1617,23 +1617,38 @@ impl Expr {
16171617 pub fn infer_placeholder_types ( self , schema : & DFSchema ) -> Result < ( Expr , bool ) > {
16181618 let mut has_placeholder = false ;
16191619 self . transform ( |mut expr| {
1620- // Default to assuming the arguments are the same type
1621- if let Expr :: BinaryExpr ( BinaryExpr { left, op : _, right } ) = & mut expr {
1622- rewrite_placeholder ( left. as_mut ( ) , right. as_ref ( ) , schema) ?;
1623- rewrite_placeholder ( right. as_mut ( ) , left. as_ref ( ) , schema) ?;
1624- } ;
1625- if let Expr :: Between ( Between {
1626- expr,
1627- negated : _,
1628- low,
1629- high,
1630- } ) = & mut expr
1631- {
1632- rewrite_placeholder ( low. as_mut ( ) , expr. as_ref ( ) , schema) ?;
1633- rewrite_placeholder ( high. as_mut ( ) , expr. as_ref ( ) , schema) ?;
1634- }
1635- if let Expr :: Placeholder ( _) = & expr {
1636- has_placeholder = true ;
1620+ match & mut expr {
1621+ // Default to assuming the arguments are the same type
1622+ Expr :: BinaryExpr ( BinaryExpr { left, op : _, right } ) => {
1623+ rewrite_placeholder ( left. as_mut ( ) , right. as_ref ( ) , schema) ?;
1624+ rewrite_placeholder ( right. as_mut ( ) , left. as_ref ( ) , schema) ?;
1625+ }
1626+ Expr :: Between ( Between {
1627+ expr,
1628+ negated : _,
1629+ low,
1630+ high,
1631+ } ) => {
1632+ rewrite_placeholder ( low. as_mut ( ) , expr. as_ref ( ) , schema) ?;
1633+ rewrite_placeholder ( high. as_mut ( ) , expr. as_ref ( ) , schema) ?;
1634+ }
1635+ Expr :: InList ( InList {
1636+ expr,
1637+ list,
1638+ negated : _,
1639+ } ) => {
1640+ for item in list. iter_mut ( ) {
1641+ rewrite_placeholder ( item, expr. as_ref ( ) , schema) ?;
1642+ }
1643+ }
1644+ Expr :: Like ( Like { expr, pattern, .. } )
1645+ | Expr :: SimilarTo ( Like { expr, pattern, .. } ) => {
1646+ rewrite_placeholder ( pattern. as_mut ( ) , expr. as_ref ( ) , schema) ?;
1647+ }
1648+ Expr :: Placeholder ( _) => {
1649+ has_placeholder = true ;
1650+ }
1651+ _ => { }
16371652 }
16381653 Ok ( Transformed :: yes ( expr) )
16391654 } )
@@ -2839,10 +2854,117 @@ mod test {
28392854 case, lit, qualified_wildcard, wildcard, wildcard_with_options, ColumnarValue ,
28402855 ScalarFunctionArgs , ScalarUDF , ScalarUDFImpl , Volatility ,
28412856 } ;
2857+ use arrow:: datatypes:: { Field , Schema } ;
28422858 use sqlparser:: ast;
28432859 use sqlparser:: ast:: { Ident , IdentWithAlias } ;
28442860 use std:: any:: Any ;
28452861
2862+ #[ test]
2863+ fn infer_placeholder_in_clause ( ) {
2864+ // SELECT * FROM employees WHERE department_id IN ($1, $2, $3);
2865+ let column = col ( "department_id" ) ;
2866+ let param_placeholders = vec ! [
2867+ Expr :: Placeholder ( Placeholder {
2868+ id: "$1" . to_string( ) ,
2869+ data_type: None ,
2870+ } ) ,
2871+ Expr :: Placeholder ( Placeholder {
2872+ id: "$2" . to_string( ) ,
2873+ data_type: None ,
2874+ } ) ,
2875+ Expr :: Placeholder ( Placeholder {
2876+ id: "$3" . to_string( ) ,
2877+ data_type: None ,
2878+ } ) ,
2879+ ] ;
2880+ let in_list = Expr :: InList ( InList {
2881+ expr : Box :: new ( column) ,
2882+ list : param_placeholders,
2883+ negated : false ,
2884+ } ) ;
2885+
2886+ let schema = Arc :: new ( Schema :: new ( vec ! [
2887+ Field :: new( "name" , DataType :: Utf8 , true ) ,
2888+ Field :: new( "department_id" , DataType :: Int32 , true ) ,
2889+ ] ) ) ;
2890+ let df_schema = DFSchema :: try_from ( schema) . unwrap ( ) ;
2891+
2892+ let ( inferred_expr, contains_placeholder) =
2893+ in_list. infer_placeholder_types ( & df_schema) . unwrap ( ) ;
2894+
2895+ assert ! ( contains_placeholder) ;
2896+
2897+ match inferred_expr {
2898+ Expr :: InList ( in_list) => {
2899+ for expr in in_list. list {
2900+ match expr {
2901+ Expr :: Placeholder ( placeholder) => {
2902+ assert_eq ! (
2903+ placeholder. data_type,
2904+ Some ( DataType :: Int32 ) ,
2905+ "Placeholder {} should infer Int32" ,
2906+ placeholder. id
2907+ ) ;
2908+ }
2909+ _ => panic ! ( "Expected Placeholder expression" ) ,
2910+ }
2911+ }
2912+ }
2913+ _ => panic ! ( "Expected InList expression" ) ,
2914+ }
2915+ }
2916+
2917+ #[ test]
2918+ fn infer_placeholder_like_and_similar_to ( ) {
2919+ // name LIKE $1
2920+ let schema =
2921+ Arc :: new ( Schema :: new ( vec ! [ Field :: new( "name" , DataType :: Utf8 , true ) ] ) ) ;
2922+ let df_schema = DFSchema :: try_from ( schema) . unwrap ( ) ;
2923+
2924+ let like = Like {
2925+ expr : Box :: new ( col ( "name" ) ) ,
2926+ pattern : Box :: new ( Expr :: Placeholder ( Placeholder {
2927+ id : "$1" . to_string ( ) ,
2928+ data_type : None ,
2929+ } ) ) ,
2930+ negated : false ,
2931+ case_insensitive : false ,
2932+ escape_char : None ,
2933+ } ;
2934+
2935+ let expr = Expr :: Like ( like. clone ( ) ) ;
2936+
2937+ let ( inferred_expr, _) = expr. infer_placeholder_types ( & df_schema) . unwrap ( ) ;
2938+ match inferred_expr {
2939+ Expr :: Like ( like) => match * like. pattern {
2940+ Expr :: Placeholder ( placeholder) => {
2941+ assert_eq ! ( placeholder. data_type, Some ( DataType :: Utf8 ) ) ;
2942+ }
2943+ _ => panic ! ( "Expected Placeholder" ) ,
2944+ } ,
2945+ _ => panic ! ( "Expected Like" ) ,
2946+ }
2947+
2948+ // name SIMILAR TO $1
2949+ let expr = Expr :: SimilarTo ( like) ;
2950+
2951+ let ( inferred_expr, _) = expr. infer_placeholder_types ( & df_schema) . unwrap ( ) ;
2952+ match inferred_expr {
2953+ Expr :: SimilarTo ( like) => match * like. pattern {
2954+ Expr :: Placeholder ( placeholder) => {
2955+ assert_eq ! (
2956+ placeholder. data_type,
2957+ Some ( DataType :: Utf8 ) ,
2958+ "Placeholder {} should infer Utf8" ,
2959+ placeholder. id
2960+ ) ;
2961+ }
2962+ _ => panic ! ( "Expected Placeholder expression" ) ,
2963+ } ,
2964+ _ => panic ! ( "Expected SimilarTo expression" ) ,
2965+ }
2966+ }
2967+
28462968 #[ test]
28472969 #[ allow( deprecated) ]
28482970 fn format_case_when ( ) -> Result < ( ) > {
0 commit comments