@@ -3478,6 +3478,7 @@ impl<'a> TypeChecker<'a> {
34783478 Ascii :: new ( "is_error" ) ,
34793479 Ascii :: new ( "error_or" ) ,
34803480 Ascii :: new ( "coalesce" ) ,
3481+ Ascii :: new ( "decode" ) ,
34813482 Ascii :: new ( "last_query_id" ) ,
34823483 Ascii :: new ( "array_sort" ) ,
34833484 Ascii :: new ( "array_aggregate" ) ,
@@ -3717,6 +3718,79 @@ impl<'a> TypeChecker<'a> {
37173718 let args_ref: Vec < & Expr > = new_args. iter ( ) . collect ( ) ;
37183719 Some ( self . resolve_function ( span, "if" , vec ! [ ] , & args_ref) )
37193720 }
3721+ ( "decode" , args) => {
3722+ // DECODE( <expr> , <search1> , <result1> [ , <search2> , <result2> ... ] [ , <default> ] )
3723+ // Note that, contrary to CASE, a NULL value in the select expression matches a NULL value in the search expressions.
3724+ if args. len ( ) < 3 {
3725+ return Some ( Err ( ErrorCode :: BadArguments (
3726+ "DECODE requires at least 3 arguments" ,
3727+ )
3728+ . set_span ( span) ) ) ;
3729+ }
3730+
3731+ let mut new_args = Vec :: with_capacity ( args. len ( ) * 2 + 1 ) ;
3732+ let search_expr = args[ 0 ] . clone ( ) ;
3733+ let mut i = 1 ;
3734+
3735+ while i < args. len ( ) {
3736+ let search = args[ i] . clone ( ) ;
3737+ let result = if i + 1 < args. len ( ) {
3738+ args[ i + 1 ] . clone ( )
3739+ } else {
3740+ // If we're at the last argument and it's odd, it's the default value
3741+ break ;
3742+ } ;
3743+
3744+ // (a = b) or (a is null and b is null)
3745+ let is_null_a = Expr :: IsNull {
3746+ span,
3747+ expr : Box :: new ( search_expr. clone ( ) ) ,
3748+ not : false ,
3749+ } ;
3750+ let is_null_b = Expr :: IsNull {
3751+ span,
3752+ expr : Box :: new ( search. clone ( ) ) ,
3753+ not : false ,
3754+ } ;
3755+ let and_expr = Expr :: BinaryOp {
3756+ span,
3757+ op : BinaryOperator :: And ,
3758+ left : Box :: new ( is_null_a) ,
3759+ right : Box :: new ( is_null_b) ,
3760+ } ;
3761+
3762+ let eq_expr = Expr :: BinaryOp {
3763+ span,
3764+ op : BinaryOperator :: Eq ,
3765+ left : Box :: new ( search_expr. clone ( ) ) ,
3766+ right : Box :: new ( search) ,
3767+ } ;
3768+
3769+ let or_expr = Expr :: BinaryOp {
3770+ span,
3771+ op : BinaryOperator :: Or ,
3772+ left : Box :: new ( eq_expr) ,
3773+ right : Box :: new ( and_expr) ,
3774+ } ;
3775+
3776+ new_args. push ( or_expr) ;
3777+ new_args. push ( result) ;
3778+ i += 2 ;
3779+ }
3780+
3781+ // Add default value if it exists
3782+ if i + 1 == args. len ( ) {
3783+ new_args. push ( args[ i] . clone ( ) ) ;
3784+ } else {
3785+ new_args. push ( Expr :: Literal {
3786+ span,
3787+ value : Literal :: Null ,
3788+ } ) ;
3789+ }
3790+
3791+ let args_ref: Vec < & Expr > = new_args. iter ( ) . collect ( ) ;
3792+ Some ( self . resolve_function ( span, "if" , vec ! [ ] , & args_ref) )
3793+ }
37203794 ( "last_query_id" , args) => {
37213795 // last_query_id(index) returns query_id in current session by index
37223796 let res: Result < i64 > = try {
0 commit comments