diff --git a/src/query/sql/src/planner/semantic/type_check.rs b/src/query/sql/src/planner/semantic/type_check.rs index 632a466a21369..c3bf1bfec3702 100644 --- a/src/query/sql/src/planner/semantic/type_check.rs +++ b/src/query/sql/src/planner/semantic/type_check.rs @@ -2510,34 +2510,18 @@ impl<'a> TypeChecker<'a> { ) } ("ifnull", &[arg_x, arg_y]) => { - // Rewrite ifnull(x, y) to if(is_null(x), y, x) + // Rewrite ifnull(x, y) to coalesce(x, y) Some( - self.resolve_function(span, "if", vec![], &[ - &Expr::IsNull { - span, - expr: Box::new(arg_x.clone()), - not: false, - }, - arg_y, - arg_x, - ]) - .await, + self.resolve_function(span, "coalesce", vec![], &[arg_x, arg_y]) + .await, ) } ("nvl", &[arg_x, arg_y]) => { - // Rewrite nvl(x, y) to if(is_not_null(x), x, y) + // Rewrite nvl(x, y) to coalesce(x, y) // nvl is essentially an alias for ifnull. Some( - self.resolve_function(span, "if", vec![], &[ - &Expr::IsNull { - span, - expr: Box::new(arg_x.clone()), - not: true, - }, - arg_x, - arg_y, - ]) - .await, + self.resolve_function(span, "coalesce", vec![], &[arg_x, arg_y]) + .await, ) } ("nvl2", &[arg_x, arg_y, arg_z]) => { @@ -2620,6 +2604,14 @@ impl<'a> TypeChecker<'a> { span, lit: Literal::Null, }); + new_args.push(Expr::Literal { + span, + lit: Literal::Null, + }); + new_args.push(Expr::Literal { + span, + lit: Literal::Null, + }); let args_ref: Vec<&Expr> = new_args.iter().collect(); Some(self.resolve_function(span, "if", vec![], &args_ref).await) } diff --git a/tests/sqllogictests/suites/mode/standalone/explain/push_down_filter.test b/tests/sqllogictests/suites/mode/standalone/explain/push_down_filter.test index d0ede503ab0ec..9a26f18a33d6c 100644 --- a/tests/sqllogictests/suites/mode/standalone/explain/push_down_filter.test +++ b/tests/sqllogictests/suites/mode/standalone/explain/push_down_filter.test @@ -146,7 +146,7 @@ AggregateFinal ├── estimated rows: 0.00 ├── EvalScalar │ ├── output columns: [t.id (#0), de (#8)] - │ ├── expressions: [if(CAST(is_not_null(sum(tb.de) (#7)) AS Boolean NULL), CAST(assume_not_null(sum(tb.de) (#7)) AS Int64 NULL), true, 0, NULL)] + │ ├── expressions: [if(CAST(is_not_null(sum(tb.de) (#7)) AS Boolean NULL), CAST(assume_not_null(sum(tb.de) (#7)) AS Int64 NULL), true, 0, NULL, NULL, NULL)] │ ├── estimated rows: 0.00 │ └── AggregateFinal │ ├── output columns: [sum(tb.de) (#7), t.id (#0)] @@ -177,7 +177,7 @@ AggregateFinal │ │ ├── estimated rows: 0.00 │ │ └── EvalScalar │ │ ├── output columns: [t2.sid (#1), sum_arg_0 (#4)] - │ │ ├── expressions: [if(CAST(is_not_null(t3.val (#2)) AS Boolean NULL), CAST(assume_not_null(t3.val (#2)) AS Int32 NULL), true, 0, NULL)] + │ │ ├── expressions: [if(CAST(is_not_null(t3.val (#2)) AS Boolean NULL), CAST(assume_not_null(t3.val (#2)) AS Int32 NULL), true, 0, NULL, NULL, NULL)] │ │ ├── estimated rows: 0.00 │ │ └── TableScan │ │ ├── table: default.default.t2 diff --git a/tests/sqllogictests/suites/mode/standalone/explain_native/push_down_filter.test b/tests/sqllogictests/suites/mode/standalone/explain_native/push_down_filter.test index 4f3cd9bdc1717..22648067dc47c 100644 --- a/tests/sqllogictests/suites/mode/standalone/explain_native/push_down_filter.test +++ b/tests/sqllogictests/suites/mode/standalone/explain_native/push_down_filter.test @@ -138,7 +138,7 @@ AggregateFinal ├── estimated rows: 0.00 ├── EvalScalar │ ├── output columns: [t.id (#0), de (#8)] - │ ├── expressions: [if(CAST(is_not_null(sum(tb.de) (#7)) AS Boolean NULL), CAST(assume_not_null(sum(tb.de) (#7)) AS Int64 NULL), true, 0, NULL)] + │ ├── expressions: [if(CAST(is_not_null(sum(tb.de) (#7)) AS Boolean NULL), CAST(assume_not_null(sum(tb.de) (#7)) AS Int64 NULL), true, 0, NULL, NULL, NULL)] │ ├── estimated rows: 0.00 │ └── AggregateFinal │ ├── output columns: [sum(tb.de) (#7), t.id (#0)] @@ -169,7 +169,7 @@ AggregateFinal │ │ ├── estimated rows: 0.00 │ │ └── EvalScalar │ │ ├── output columns: [t2.sid (#1), sum_arg_0 (#4)] - │ │ ├── expressions: [if(CAST(is_not_null(t3.val (#2)) AS Boolean NULL), CAST(assume_not_null(t3.val (#2)) AS Int32 NULL), true, 0, NULL)] + │ │ ├── expressions: [if(CAST(is_not_null(t3.val (#2)) AS Boolean NULL), CAST(assume_not_null(t3.val (#2)) AS Int32 NULL), true, 0, NULL, NULL, NULL)] │ │ ├── estimated rows: 0.00 │ │ └── TableScan │ │ ├── table: default.default.t2 diff --git a/tests/sqllogictests/suites/query/02_function/02_0070_function_nvl.test b/tests/sqllogictests/suites/query/02_function/02_0070_function_nvl.test index 54363571e3d77..a001f1d49e51f 100644 --- a/tests/sqllogictests/suites/query/02_function/02_0070_function_nvl.test +++ b/tests/sqllogictests/suites/query/02_function/02_0070_function_nvl.test @@ -1,3 +1,16 @@ +query B +select nvl(nullif(rand()>0.5, true), false) is null from (unnest(range(1,10))); +---- +0 +0 +0 +0 +0 +0 +0 +0 +0 + query I SELECT NVL(1, 1) ----