@@ -1059,6 +1059,12 @@ impl Planner {
1059
1059
high,
1060
1060
negated,
1061
1061
} => self . plan_between ( ctx, expr, low, high, * negated, plan) ,
1062
+ ASTNode :: SQLCase {
1063
+ operand,
1064
+ conditions,
1065
+ results,
1066
+ else_result,
1067
+ } => self . plan_case ( ctx, operand, conditions, results, else_result, plan) ,
1062
1068
ASTNode :: SQLNested ( expr) => self . plan_expr ( ctx, expr, plan) ,
1063
1069
ASTNode :: SQLFunction {
1064
1070
name,
@@ -1311,6 +1317,72 @@ impl Planner {
1311
1317
self . plan_expr ( ctx, & both, plan)
1312
1318
}
1313
1319
1320
+ fn plan_case < ' a > (
1321
+ & self ,
1322
+ ctx : & ExprContext ,
1323
+ operand : & ' a Option < Box < ASTNode > > ,
1324
+ conditions : & ' a [ ASTNode ] ,
1325
+ results : & ' a [ ASTNode ] ,
1326
+ else_result : & ' a Option < Box < ASTNode > > ,
1327
+ plan : & SQLPlan ,
1328
+ ) -> Result < ( Expr , Type ) , failure:: Error > {
1329
+ let mut case_exprs = Vec :: new ( ) ;
1330
+ let mut result_type: Option < Type > = None ;
1331
+ for ( c, r) in conditions. iter ( ) . zip ( results) {
1332
+ let c = match operand {
1333
+ Some ( operand) => ASTNode :: SQLBinaryExpr {
1334
+ left : operand. clone ( ) ,
1335
+ op : SQLOperator :: Eq ,
1336
+ right : Box :: new ( c. clone ( ) ) ,
1337
+ } ,
1338
+ None => c. clone ( ) ,
1339
+ } ;
1340
+ let ( cexpr, ctype) = self . plan_expr ( ctx, & c, plan) ?;
1341
+ if ctype. ftype != FType :: Bool {
1342
+ bail ! ( "CASE expression has non-boolean type {:?}" , ctype. ftype) ;
1343
+ }
1344
+ let ( rexpr, rtype) = self . plan_expr ( ctx, r, plan) ?;
1345
+ match & result_type {
1346
+ Some ( result_type) => {
1347
+ if result_type. ftype != rtype. ftype {
1348
+ bail ! (
1349
+ "CASE expression does not have uniform result type: {:?} vs {:?}" ,
1350
+ result_type. ftype,
1351
+ rtype. ftype
1352
+ ) ;
1353
+ }
1354
+ }
1355
+ None => result_type = Some ( rtype) ,
1356
+ }
1357
+ case_exprs. push ( ( cexpr, rexpr) ) ;
1358
+ }
1359
+ // conditions and results must be non-empty, which implies that
1360
+ // result_type must be non-None.
1361
+ let result_type = result_type. unwrap ( ) ;
1362
+ let mut expr = match else_result {
1363
+ Some ( else_result) => {
1364
+ let ( expr, typ) = self . plan_expr ( ctx, else_result, plan) ?;
1365
+ if typ. ftype != result_type. ftype {
1366
+ bail ! (
1367
+ "CASE expression does not have uniform result type: {:?} vs {:?}" ,
1368
+ result_type. ftype,
1369
+ typ. ftype
1370
+ ) ;
1371
+ }
1372
+ expr
1373
+ }
1374
+ None => Expr :: Literal ( Datum :: Null ) ,
1375
+ } ;
1376
+ for ( cexpr, rexpr) in case_exprs. into_iter ( ) . rev ( ) {
1377
+ expr = Expr :: If {
1378
+ cond : Box :: new ( cexpr) ,
1379
+ then : Box :: new ( rexpr) ,
1380
+ els : Box :: new ( expr) ,
1381
+ }
1382
+ }
1383
+ Ok ( ( expr, result_type) )
1384
+ }
1385
+
1314
1386
fn plan_literal < ' a > ( & self , l : & ' a Value ) -> Result < ( Expr , Type ) , failure:: Error > {
1315
1387
let ( datum, ftype) = match l {
1316
1388
Value :: Long ( i) => ( Datum :: Int64 ( * i) , FType :: Int64 ) ,
0 commit comments