diff --git a/omnioperator/omniop-spark-extension/java/src/main/scala/com/huawei/boostkit/spark/expression/OmniExpressionAdaptor.scala b/omnioperator/omniop-spark-extension/java/src/main/scala/com/huawei/boostkit/spark/expression/OmniExpressionAdaptor.scala index f2fce985433969813197d3fecfd9964991802d46..2e14bae22d35df4ea4fc147084160d66e4354878 100644 --- a/omnioperator/omniop-spark-extension/java/src/main/scala/com/huawei/boostkit/spark/expression/OmniExpressionAdaptor.scala +++ b/omnioperator/omniop-spark-extension/java/src/main/scala/com/huawei/boostkit/spark/expression/OmniExpressionAdaptor.scala @@ -34,6 +34,9 @@ import org.apache.spark.sql.catalyst.plans.{FullOuter, InnerLike, JoinType, Left import org.apache.spark.sql.catalyst.util.CharVarcharUtils.getRawTypeString import org.apache.spark.sql.types.{BooleanType, DataType, DateType, Decimal, DecimalType, DoubleType, IntegerType, LongType, Metadata, ShortType, StringType} +import scala.collection.mutable +import scala.collection.mutable.ArrayBuffer + object OmniExpressionAdaptor extends Logging { def getRealExprId(expr: Expression): ExprId = { @@ -448,6 +451,11 @@ object OmniExpressionAdaptor extends Logging { sparkTypeToOmniExpJsonType(BooleanType), rewriteToOmniJsonExpressionLiteral(isnotnull.child, exprsIndexMap)) + case isNull: IsNull => + "{\"exprType\":\"IS_NULL\",\"returnType\":%s,\"arguments\":[%s]}".format( + sparkTypeToOmniExpJsonType(BooleanType), + rewriteToOmniJsonExpressionLiteral(isNull.child, exprsIndexMap)) + // Substring case subString: Substring => ("{\"exprType\":\"FUNCTION\",\"returnType\":%s," + @@ -516,15 +524,13 @@ object OmniExpressionAdaptor extends Logging { rewriteToOmniJsonExpressionLiteral(ifExp.trueValue, exprsIndexMap), rewriteToOmniJsonExpressionLiteral(ifExp.falseValue, exprsIndexMap)) - // only support with one case condition, for omni rewrite to if(A, B, C) case caseWhen: CaseWhen => - "{\"exprType\":\"IF\",\"returnType\":%s,\"condition\":%s,\"if_true\":%s,\"if_false\":%s}" - .format(sparkTypeToOmniExpJsonType(caseWhen.dataType), - rewriteToOmniJsonExpressionLiteral(caseWhen.branches(0)._1, exprsIndexMap), - rewriteToOmniJsonExpressionLiteral(caseWhen.branches(0)._2, exprsIndexMap), - rewriteToOmniJsonExpressionLiteral(caseWhen.elseValue.get, exprsIndexMap)) + procCaseWhenExpression(caseWhen, exprsIndexMap) case coalesce: Coalesce => + if (coalesce.children.length > 2) { + throw new UnsupportedOperationException(s"Number of parameters is ${coalesce.children.length}. Exceeds the maximum number of parameters, coalesce only supports up to 2 parameters") + } "{\"exprType\":\"COALESCE\",\"returnType\":%s, \"value1\":%s,\"value2\":%s}".format( sparkTypeToOmniExpJsonType(coalesce.dataType), rewriteToOmniJsonExpressionLiteral(coalesce.children(0), exprsIndexMap), @@ -743,6 +749,163 @@ object OmniExpressionAdaptor extends Logging { width } + def procCaseWhenExpression(caseWhen: CaseWhen, + exprsIndexMap: Map[ExprId, Int]): String = { + val exprStr = "{\"exprType\":\"IF\",\"returnType\":%s,\"condition\":%s,\"if_true\":%s,\"if_false\":%s}" + var exprStrRes = exprStr + for (i <- caseWhen.branches.indices) { + var ifFalseStr = "" + if (i != caseWhen.branches.length - 1) { + ifFalseStr = exprStr + } else { + var elseValue = caseWhen.elseValue + if (elseValue.isEmpty) { + elseValue = Some(Literal(null, caseWhen.dataType)) + } + ifFalseStr = rewriteToOmniJsonExpressionLiteral(elseValue.get, exprsIndexMap) + } + exprStrRes = exprStrRes.format(sparkTypeToOmniExpJsonType(caseWhen.dataType), + rewriteToOmniJsonExpressionLiteral(caseWhen.branches(i)._1, exprsIndexMap), + rewriteToOmniJsonExpressionLiteral(caseWhen.branches(i)._2, exprsIndexMap), + ifFalseStr) + } + exprStrRes + } + + def procLikeExpression(likeExpr: Expression, + exprsIndexMap: Map[ExprId, Int]): String = { + likeExpr match { + case like: Like => + val dataType = like.right.dataType + like.right match { + case literal: Literal => + ("{\"exprType\":\"FUNCTION\",\"returnType\":%s," + + "\"function_name\":\"LIKE\", \"arguments\":[%s, %s]}") + .format(sparkTypeToOmniExpJsonType(like.dataType), + rewriteToOmniJsonExpressionLiteral(like.left, exprsIndexMap), + generateLikeArg(literal,"")) + case _ => + throw new UnsupportedOperationException(s"Unsupported datatype in like expression: $dataType") + } + case startsWith: StartsWith => + val dataType = startsWith.right.dataType + startsWith.right match { + case literal: Literal => + ("{\"exprType\":\"FUNCTION\",\"returnType\":%s," + + "\"function_name\":\"LIKE\", \"arguments\":[%s, %s]}") + .format(sparkTypeToOmniExpJsonType(startsWith.dataType), + rewriteToOmniJsonExpressionLiteral(startsWith.left, exprsIndexMap), + generateLikeArg(literal, "startsWith")) + case _ => + throw new UnsupportedOperationException(s"Unsupported datatype in like expression: $dataType") + } + case endsWith: EndsWith => + val dataType = endsWith.right.dataType + endsWith.right match { + case literal: Literal => + ("{\"exprType\":\"FUNCTION\",\"returnType\":%s," + + "\"function_name\":\"LIKE\", \"arguments\":[%s, %s]}") + .format(sparkTypeToOmniExpJsonType(endsWith.dataType), + rewriteToOmniJsonExpressionLiteral(endsWith.left, exprsIndexMap), + generateLikeArg(literal, "endsWith")) + case _ => + throw new UnsupportedOperationException(s"Unsupported datatype in like expression: $dataType") + } + case contains: Contains => + val dataType = contains.right.dataType + contains.right match { + case literal: Literal => + ("{\"exprType\":\"FUNCTION\",\"returnType\":%s," + + "\"function_name\":\"LIKE\", \"arguments\":[%s, %s]}") + .format(sparkTypeToOmniExpJsonType(contains.dataType), + rewriteToOmniJsonExpressionLiteral(contains.left, exprsIndexMap), + generateLikeArg(literal, "contains")) + case _ => + throw new UnsupportedOperationException(s"Unsupported datatype in like expression: $dataType") + } + } + } + + def generateLikeArg(literal: Literal, exprFormat: String) : String = { + val value = literal.value + if (value == null) { + return "{\"exprType\":\"LITERAL\",\"dataType\":%s,\"isNull\":%b}".format(sparkTypeToOmniExpJsonType(literal.dataType), true) + } + var inputValue = value.toString + exprFormat match { + case "startsWith" => + inputValue = inputValue + "%" + case "endsWith" => + inputValue = "%" + inputValue + case "contains" => + inputValue = "%" + inputValue + "%" + case _ => + inputValue = value.toString + } + + val omniType = sparkTypeToOmniExpType(literal.dataType) + literal.dataType match { + case StringType => + val likeRegExpr = generateLikeRegExpr(inputValue) + ("{\"exprType\":\"LITERAL\",\"dataType\":%s," + + "\"isNull\":%b, \"value\":\"%s\",\"width\":%d}") + .format(omniType, false, likeRegExpr, likeRegExpr.length) + case dt: DecimalType => + toOmniJsonLiteral(literal) + case _ => + toOmniJsonLiteral(literal) + } + } + + def generateLikeRegExpr(value : String) : String = { + val regexString = new mutable.StringBuilder + regexString.append('^') + val valueArr = value.toCharArray + for (i <- 0 until valueArr.length) { + valueArr(i) match { + case '%' => + if (i - 1 < 0 || valueArr(i - 1) != '\\') { + regexString.append(".*") + } else { + regexString.append(valueArr(i)) + } + + case '_' => + if (i - 1 < 0 || valueArr(i - 1) != '\\') { + regexString.append(".") + } else { + regexString.append(valueArr(i)) + } + + case '\\' => + regexString.append("\\") + regexString.append(valueArr(i)) + + case '^' => + regexString.append("\\") + regexString.append(valueArr(i)) + + case '$' => + regexString.append("\\") + regexString.append(valueArr(i)) + + case '.' => + regexString.append("\\") + regexString.append(valueArr(i)) + + case '*' => + regexString.append("\\") + regexString.append(valueArr(i)) + + case _ => + regexString.append(valueArr(i)) + + } + } + regexString.append('$') + regexString.toString() + } + def toOmniJoinType(joinType: JoinType): nova.hetu.omniruntime.constants.JoinType = { joinType match { case FullOuter => diff --git a/omnioperator/omniop-spark-extension/java/src/test/scala/com/huawei/boostkit/spark/expression/OmniExpressionAdaptorSuite.scala b/omnioperator/omniop-spark-extension/java/src/test/scala/com/huawei/boostkit/spark/expression/OmniExpressionAdaptorSuite.scala index 76c8cfc455f54e77a12194702a2ec9b978cad0ec..dae771f6dd4025a2957da93272cd8e3a7851fede 100644 --- a/omnioperator/omniop-spark-extension/java/src/test/scala/com/huawei/boostkit/spark/expression/OmniExpressionAdaptorSuite.scala +++ b/omnioperator/omniop-spark-extension/java/src/test/scala/com/huawei/boostkit/spark/expression/OmniExpressionAdaptorSuite.scala @@ -18,7 +18,7 @@ package com.huawei.boostkit.spark.expression -import com.huawei.boostkit.spark.expression.OmniExpressionAdaptor.{getExprIdMap, rewriteToOmniExpressionLiteral, rewriteToOmniJsonExpressionLiteral} +import com.huawei.boostkit.spark.expression.OmniExpressionAdaptor.{getExprIdMap, procCaseWhenExpression, procLikeExpression, rewriteToOmniExpressionLiteral, rewriteToOmniJsonExpressionLiteral} import org.apache.spark.SparkFunSuite import org.apache.spark.sql.catalyst.expressions._ import org.apache.spark.sql.catalyst.expressions.aggregate.{Average, Max, Min, Sum} @@ -268,4 +268,125 @@ class OmniExpressionAdaptorSuite extends SparkFunSuite { s"running value:$runResult") } } + + test("json expression rewrite support Chinese") { + val cnAttribute = Seq(AttributeReference("char_1", StringType)(), AttributeReference("char_20", StringType)(), + AttributeReference("varchar_1", StringType)(), AttributeReference("varchar_20", StringType)()) + + val like = Like(cnAttribute(2), Literal("我_"), '\\'); + val likeResult = procLikeExpression(like, getExprIdMap(cnAttribute)) + val likeExp = "{\"exprType\":\"FUNCTION\",\"returnType\":4,\"function_name\":\"LIKE\", \"arguments\":[{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":15,\"colVal\":2,\"width\":2000}, {\"exprType\":\"LITERAL\",\"dataType\":15,\"isNull\":false, \"value\":\"^我.$\",\"width\":4}]}" + if (!likeExp.equals(likeResult)) { + fail(s"expression($like) not match with expected value:$likeExp," + + s"running value:$likeResult") + } + + val startsWith = StartsWith(cnAttribute(2), Literal("我")); + val startsWithResult = procLikeExpression(startsWith, getExprIdMap(cnAttribute)) + val startsWithExp = "{\"exprType\":\"FUNCTION\",\"returnType\":4,\"function_name\":\"LIKE\", \"arguments\":[{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":15,\"colVal\":2,\"width\":2000}, {\"exprType\":\"LITERAL\",\"dataType\":15,\"isNull\":false, \"value\":\"^我.*$\",\"width\":5}]}" + if (!startsWithExp.equals(startsWithResult)) { + fail(s"expression($startsWith) not match with expected value:$startsWithExp," + + s"running value:$startsWithResult") + } + + val endsWith = EndsWith(cnAttribute(2), Literal("我")); + val endsWithResult = procLikeExpression(endsWith, getExprIdMap(cnAttribute)) + val endsWithExp = "{\"exprType\":\"FUNCTION\",\"returnType\":4,\"function_name\":\"LIKE\", \"arguments\":[{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":15,\"colVal\":2,\"width\":2000}, {\"exprType\":\"LITERAL\",\"dataType\":15,\"isNull\":false, \"value\":\"^.*我$\",\"width\":5}]}" + if (!endsWithExp.equals(endsWithResult)) { + fail(s"expression($endsWith) not match with expected value:$endsWithExp," + + s"running value:$endsWithResult") + } + + val contains = Contains(cnAttribute(2), Literal("我")); + val containsResult = procLikeExpression(contains, getExprIdMap(cnAttribute)) + val containsExp = "{\"exprType\":\"FUNCTION\",\"returnType\":4,\"function_name\":\"LIKE\", \"arguments\":[{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":15,\"colVal\":2,\"width\":2000}, {\"exprType\":\"LITERAL\",\"dataType\":15,\"isNull\":false, \"value\":\"^.*我.*$\",\"width\":7}]}" + if (!containsExp.equals(containsResult)) { + fail(s"expression($contains) not match with expected value:$containsExp," + + s"running value:$containsResult") + } + + val t1 = new Tuple2(Not(EqualTo(cnAttribute(0), Literal("新"))), Not(EqualTo(cnAttribute(1), Literal("官方爸爸")))) + val t2 = new Tuple2(Not(EqualTo(cnAttribute(2), Literal("爱你三千遍"))), Not(EqualTo(cnAttribute(2), Literal("新")))) + val branch = Seq(t1, t2) + val elseValue = Some(Not(EqualTo(cnAttribute(3), Literal("啊水水水水")))) + val caseWhen = CaseWhen(branch, elseValue); + val caseWhenResult = rewriteToOmniJsonExpressionLiteral(caseWhen, getExprIdMap(cnAttribute)) + val caseWhenExp = "{\"exprType\":\"IF\",\"returnType\":4,\"condition\":{\"exprType\":\"UNARY\",\"returnType\":4,\"operator\":\"not\",\"expr\":{\"exprType\":\"BINARY\",\"returnType\":4,\"operator\":\"EQUAL\",\"left\":{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":15,\"colVal\":0,\"width\":2000},\"right\":{\"exprType\":\"LITERAL\",\"dataType\":15,\"isNull\":false, \"value\":\"新\",\"width\":1}}},\"if_true\":{\"exprType\":\"UNARY\",\"returnType\":4,\"operator\":\"not\",\"expr\":{\"exprType\":\"BINARY\",\"returnType\":4,\"operator\":\"EQUAL\",\"left\":{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":15,\"colVal\":1,\"width\":2000},\"right\":{\"exprType\":\"LITERAL\",\"dataType\":15,\"isNull\":false, \"value\":\"官方爸爸\",\"width\":4}}},\"if_false\":{\"exprType\":\"IF\",\"returnType\":4,\"condition\":{\"exprType\":\"UNARY\",\"returnType\":4,\"operator\":\"not\",\"expr\":{\"exprType\":\"BINARY\",\"returnType\":4,\"operator\":\"EQUAL\",\"left\":{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":15,\"colVal\":2,\"width\":2000},\"right\":{\"exprType\":\"LITERAL\",\"dataType\":15,\"isNull\":false, \"value\":\"爱你三千遍\",\"width\":5}}},\"if_true\":{\"exprType\":\"UNARY\",\"returnType\":4,\"operator\":\"not\",\"expr\":{\"exprType\":\"BINARY\",\"returnType\":4,\"operator\":\"EQUAL\",\"left\":{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":15,\"colVal\":2,\"width\":2000},\"right\":{\"exprType\":\"LITERAL\",\"dataType\":15,\"isNull\":false, \"value\":\"新\",\"width\":1}}},\"if_false\":{\"exprType\":\"UNARY\",\"returnType\":4,\"operator\":\"not\",\"expr\":{\"exprType\":\"BINARY\",\"returnType\":4,\"operator\":\"EQUAL\",\"left\":{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":15,\"colVal\":3,\"width\":2000},\"right\":{\"exprType\":\"LITERAL\",\"dataType\":15,\"isNull\":false, \"value\":\"啊水水水水\",\"width\":5}}}}}" + if (!caseWhenExp.equals(caseWhenResult)) { + fail(s"expression($caseWhen) not match with expected value:$caseWhenExp," + + s"running value:$caseWhenResult") + } + + val isNull = IsNull(cnAttribute(0)); + val isNullResult = rewriteToOmniJsonExpressionLiteral(isNull, getExprIdMap(cnAttribute)) + val isNullExp = "{\"exprType\":\"IS_NULL\",\"returnType\":4,\"arguments\":[{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":15,\"colVal\":0,\"width\":2000}]}" + if (!isNullExp.equals(isNullResult)) { + fail(s"expression($isNull) not match with expected value:$isNullExp," + + s"running value:$isNullResult") + } + + val children = Seq(cnAttribute(0), cnAttribute(1)) + val coalesce = Coalesce(children); + val coalesceResult = rewriteToOmniJsonExpressionLiteral(coalesce, getExprIdMap(cnAttribute)) + val coalesceExp = "{\"exprType\":\"COALESCE\",\"returnType\":15,\"width\":2000, \"value1\":{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":15,\"colVal\":0,\"width\":2000},\"value2\":{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":15,\"colVal\":1,\"width\":2000}}" + if (!coalesceExp.equals(coalesceResult)) { + fail(s"expression($coalesce) not match with expected value:$coalesceExp," + + s"running value:$coalesceResult") + } + + val children2 = Seq(cnAttribute(0), cnAttribute(1), cnAttribute(2)) + val coalesce2 = Coalesce(children2); + try { + rewriteToOmniJsonExpressionLiteral(coalesce2, getExprIdMap(cnAttribute)) + } catch { + case ex: UnsupportedOperationException => { + println(ex) + } + } + + } + + test("procCaseWhenExpression") { + val caseWhenAttribute = Seq(AttributeReference("char_1", StringType)(), AttributeReference("char_20", StringType)(), + AttributeReference("varchar_1", StringType)(), AttributeReference("varchar_20", StringType)(), + AttributeReference("a", IntegerType)(), AttributeReference("b", IntegerType)()) + + val t1 = new Tuple2(Not(EqualTo(caseWhenAttribute(0), Literal("新"))), Not(EqualTo(caseWhenAttribute(1), Literal("官方爸爸")))) + val t2 = new Tuple2(Not(EqualTo(caseWhenAttribute(2), Literal("爱你三千遍"))), Not(EqualTo(caseWhenAttribute(2), Literal("新")))) + val branch = Seq(t1, t2) + val elseValue = Some(Not(EqualTo(caseWhenAttribute(3), Literal("啊水水水水")))) + val expression = CaseWhen(branch, elseValue); + val runResult = procCaseWhenExpression(expression, getExprIdMap(caseWhenAttribute)) + val filterExp = "{\"exprType\":\"IF\",\"returnType\":4,\"condition\":{\"exprType\":\"UNARY\",\"returnType\":4,\"operator\":\"not\",\"expr\":{\"exprType\":\"BINARY\",\"returnType\":4,\"operator\":\"EQUAL\",\"left\":{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":15,\"colVal\":0,\"width\":2000},\"right\":{\"exprType\":\"LITERAL\",\"dataType\":15,\"isNull\":false, \"value\":\"新\",\"width\":1}}},\"if_true\":{\"exprType\":\"UNARY\",\"returnType\":4,\"operator\":\"not\",\"expr\":{\"exprType\":\"BINARY\",\"returnType\":4,\"operator\":\"EQUAL\",\"left\":{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":15,\"colVal\":1,\"width\":2000},\"right\":{\"exprType\":\"LITERAL\",\"dataType\":15,\"isNull\":false, \"value\":\"官方爸爸\",\"width\":4}}},\"if_false\":{\"exprType\":\"IF\",\"returnType\":4,\"condition\":{\"exprType\":\"UNARY\",\"returnType\":4,\"operator\":\"not\",\"expr\":{\"exprType\":\"BINARY\",\"returnType\":4,\"operator\":\"EQUAL\",\"left\":{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":15,\"colVal\":2,\"width\":2000},\"right\":{\"exprType\":\"LITERAL\",\"dataType\":15,\"isNull\":false, \"value\":\"爱你三千遍\",\"width\":5}}},\"if_true\":{\"exprType\":\"UNARY\",\"returnType\":4,\"operator\":\"not\",\"expr\":{\"exprType\":\"BINARY\",\"returnType\":4,\"operator\":\"EQUAL\",\"left\":{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":15,\"colVal\":2,\"width\":2000},\"right\":{\"exprType\":\"LITERAL\",\"dataType\":15,\"isNull\":false, \"value\":\"新\",\"width\":1}}},\"if_false\":{\"exprType\":\"UNARY\",\"returnType\":4,\"operator\":\"not\",\"expr\":{\"exprType\":\"BINARY\",\"returnType\":4,\"operator\":\"EQUAL\",\"left\":{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":15,\"colVal\":3,\"width\":2000},\"right\":{\"exprType\":\"LITERAL\",\"dataType\":15,\"isNull\":false, \"value\":\"啊水水水水\",\"width\":5}}}}}" + if (!filterExp.equals(runResult)) { + fail(s"expression($expression) not match with expected value:$filterExp," + + s"running value:$runResult") + } + + val t3 = new Tuple2(Not(EqualTo(caseWhenAttribute(4), Literal(5))), Not(EqualTo(caseWhenAttribute(5), Literal(10)))) + val t4 = new Tuple2(LessThan(caseWhenAttribute(4), Literal(15)), GreaterThan(caseWhenAttribute(5), Literal(20))) + val branch2 = Seq(t3, t4) + val elseValue2 = Some(Not(EqualTo(caseWhenAttribute(5), Literal(25)))) + val numExpression = CaseWhen(branch2, elseValue2); + val numResult = procCaseWhenExpression(numExpression, getExprIdMap(caseWhenAttribute)) + val numFilterExp = "{\"exprType\":\"IF\",\"returnType\":4,\"condition\":{\"exprType\":\"UNARY\",\"returnType\":4,\"operator\":\"not\",\"expr\":{\"exprType\":\"BINARY\",\"returnType\":4,\"operator\":\"EQUAL\",\"left\":{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":1,\"colVal\":4},\"right\":{\"exprType\":\"LITERAL\",\"dataType\":1, \"isNull\":false, \"value\":5}}},\"if_true\":{\"exprType\":\"UNARY\",\"returnType\":4,\"operator\":\"not\",\"expr\":{\"exprType\":\"BINARY\",\"returnType\":4,\"operator\":\"EQUAL\",\"left\":{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":1,\"colVal\":5},\"right\":{\"exprType\":\"LITERAL\",\"dataType\":1, \"isNull\":false, \"value\":10}}},\"if_false\":{\"exprType\":\"IF\",\"returnType\":4,\"condition\":{\"exprType\":\"BINARY\",\"returnType\":4,\"operator\":\"LESS_THAN\",\"left\":{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":1,\"colVal\":4},\"right\":{\"exprType\":\"LITERAL\",\"dataType\":1, \"isNull\":false, \"value\":15}},\"if_true\":{\"exprType\":\"BINARY\",\"returnType\":4,\"operator\":\"GREATER_THAN\",\"left\":{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":1,\"colVal\":5},\"right\":{\"exprType\":\"LITERAL\",\"dataType\":1, \"isNull\":false, \"value\":20}},\"if_false\":{\"exprType\":\"UNARY\",\"returnType\":4,\"operator\":\"not\",\"expr\":{\"exprType\":\"BINARY\",\"returnType\":4,\"operator\":\"EQUAL\",\"left\":{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":1,\"colVal\":5},\"right\":{\"exprType\":\"LITERAL\",\"dataType\":1, \"isNull\":false, \"value\":25}}}}}" + if (!numFilterExp.equals(numResult)) { + fail(s"expression($numExpression) not match with expected value:$numFilterExp," + + s"running value:$numResult") + } + + val t5 = new Tuple2(Not(EqualTo(caseWhenAttribute(4), Literal(5))), Not(EqualTo(caseWhenAttribute(5), Literal(10)))) + val t6 = new Tuple2(LessThan(caseWhenAttribute(4), Literal(15)), GreaterThan(caseWhenAttribute(5), Literal(20))) + val branch3 = Seq(t5, t6) + val elseValue3 = None + val noneExpression = CaseWhen(branch3, elseValue3); + val noneResult = procCaseWhenExpression(noneExpression, getExprIdMap(caseWhenAttribute)) + val noneFilterExp = "{\"exprType\":\"IF\",\"returnType\":4,\"condition\":{\"exprType\":\"UNARY\",\"returnType\":4,\"operator\":\"not\",\"expr\":{\"exprType\":\"BINARY\",\"returnType\":4,\"operator\":\"EQUAL\",\"left\":{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":1,\"colVal\":4},\"right\":{\"exprType\":\"LITERAL\",\"dataType\":1, \"isNull\":false, \"value\":5}}},\"if_true\":{\"exprType\":\"UNARY\",\"returnType\":4,\"operator\":\"not\",\"expr\":{\"exprType\":\"BINARY\",\"returnType\":4,\"operator\":\"EQUAL\",\"left\":{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":1,\"colVal\":5},\"right\":{\"exprType\":\"LITERAL\",\"dataType\":1, \"isNull\":false, \"value\":10}}},\"if_false\":{\"exprType\":\"IF\",\"returnType\":4,\"condition\":{\"exprType\":\"BINARY\",\"returnType\":4,\"operator\":\"LESS_THAN\",\"left\":{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":1,\"colVal\":4},\"right\":{\"exprType\":\"LITERAL\",\"dataType\":1, \"isNull\":false, \"value\":15}},\"if_true\":{\"exprType\":\"BINARY\",\"returnType\":4,\"operator\":\"GREATER_THAN\",\"left\":{\"exprType\":\"FIELD_REFERENCE\",\"dataType\":1,\"colVal\":5},\"right\":{\"exprType\":\"LITERAL\",\"dataType\":1, \"isNull\":false, \"value\":20}},\"if_false\":{\"exprType\":\"LITERAL\",\"dataType\":4,\"isNull\":true}}}" + if (!noneFilterExp.equals(noneResult)) { + fail(s"expression($noneExpression) not match with expected value:$noneFilterExp," + + s"running value:$noneResult") + } + } + + }