@@ -878,12 +878,56 @@ impl<'a, S: SimplifyInfo> ExprRewriter for Simplifier<'a, S> {
878878 out_expr. rewrite ( self ) ?
879879 }
880880
881+ // concat
882+ ScalarFunction {
883+ fun : BuiltinScalarFunction :: Concat ,
884+ args,
885+ } => {
886+ let mut new_args = Vec :: with_capacity ( args. len ( ) ) ;
887+ let mut contiguous_scalar = "" . to_string ( ) ;
888+ for e in args {
889+ match e {
890+ // All literals have been converted to Utf8 or LargeUtf8 in type_coercion.
891+ // Concatenate it with `contiguous_scalar`.
892+ Expr :: Literal (
893+ ScalarValue :: Utf8 ( x) | ScalarValue :: LargeUtf8 ( x) ,
894+ ) => {
895+ if let Some ( s) = x {
896+ contiguous_scalar += & s;
897+ }
898+ }
899+ // If the arg is not a literal, we should first push the current `contiguous_scalar`
900+ // to the `new_args` (if it is not empty) and reset it to empty string.
901+ // Then pushing this arg to the `new_args`.
902+ e => {
903+ if !contiguous_scalar. is_empty ( ) {
904+ new_args. push ( Expr :: Literal ( ScalarValue :: Utf8 ( Some (
905+ contiguous_scalar. clone ( ) ,
906+ ) ) ) ) ;
907+ contiguous_scalar = "" . to_string ( ) ;
908+ }
909+ new_args. push ( e) ;
910+ }
911+ }
912+ }
913+ if !contiguous_scalar. is_empty ( ) {
914+ new_args
915+ . push ( Expr :: Literal ( ScalarValue :: Utf8 ( Some ( contiguous_scalar) ) ) ) ;
916+ }
917+
918+ ScalarFunction {
919+ fun : BuiltinScalarFunction :: Concat ,
920+ args : new_args,
921+ }
922+ }
923+
881924 // concat_ws
882925 ScalarFunction {
883926 fun : BuiltinScalarFunction :: ConcatWithSeparator ,
884927 args,
885928 } => {
886929 match & args[ ..] {
930+ // concat_ws(null, ..) --> null
887931 [ Expr :: Literal ( sp) , ..] if sp. is_null ( ) => {
888932 Expr :: Literal ( ScalarValue :: Utf8 ( None ) )
889933 }
@@ -1352,6 +1396,30 @@ mod tests {
13521396 }
13531397 }
13541398
1399+ #[ test]
1400+ fn test_simplify_concat ( ) {
1401+ fn build_concat_expr ( args : & [ Expr ] ) -> Expr {
1402+ Expr :: ScalarFunction {
1403+ fun : BuiltinScalarFunction :: Concat ,
1404+ args : args. to_vec ( ) ,
1405+ }
1406+ }
1407+
1408+ let null = Expr :: Literal ( ScalarValue :: Utf8 ( None ) ) ;
1409+ let expr = build_concat_expr ( & [
1410+ null. clone ( ) ,
1411+ col ( "c0" ) ,
1412+ lit ( "hello " ) ,
1413+ null. clone ( ) ,
1414+ lit ( "rust" ) ,
1415+ col ( "c1" ) ,
1416+ lit ( "" ) ,
1417+ null,
1418+ ] ) ;
1419+ let expected = build_concat_expr ( & [ col ( "c0" ) , lit ( "hello rust" ) , col ( "c1" ) ] ) ;
1420+ assert_eq ! ( simplify( expr) , expected)
1421+ }
1422+
13551423 // ------------------------------
13561424 // --- ConstEvaluator tests -----
13571425 // ------------------------------
0 commit comments