This is an automated email from the ASF dual-hosted git repository. jackie pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/pinot.git
The following commit(s) were added to refs/heads/master by this push: new 2e1e475697 Skip computation incase of Null Literal for case/when transformation (#11444) 2e1e475697 is described below commit 2e1e4756977e272572cce7b53df9902de6167686 Author: Abhishek Sharma <abhishek.sha...@spothero.com> AuthorDate: Tue Aug 29 13:20:03 2023 -0400 Skip computation incase of Null Literal for case/when transformation (#11444) --- .../transform/function/CaseTransformFunction.java | 25 ++++++++++++++++------ .../function/LiteralTransformFunction.java | 4 ++++ .../function/LiteralTransformFunctionTest.java | 19 ++++++++++++++++ .../src/test/resources/queries/Case.json | 5 +++++ 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/CaseTransformFunction.java b/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/CaseTransformFunction.java index f4ff9330b3..aff6b460c9 100644 --- a/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/CaseTransformFunction.java +++ b/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/CaseTransformFunction.java @@ -113,7 +113,7 @@ public class CaseTransformFunction extends ComputeDifferentlyWhenNullHandlingEna _whenStatements.add(arguments.get(i * 2)); _thenStatements.add(arguments.get(i * 2 + 1)); } - if (arguments.size() % 2 != 0) { + if (arguments.size() % 2 != 0 && !isNullLiteralTransformation(arguments.get(arguments.size() - 1))) { _elseStatement = arguments.get(arguments.size() - 1); } } @@ -128,16 +128,21 @@ public class CaseTransformFunction extends ComputeDifferentlyWhenNullHandlingEna for (int i = numWhenStatements; i < numWhenStatements * 2; i++) { _thenStatements.add(arguments.get(i)); } - if (arguments.size() % 2 != 0) { + if (arguments.size() % 2 != 0 && !isNullLiteralTransformation(arguments.get(arguments.size() - 1))) { _elseStatement = arguments.get(arguments.size() - 1); } } private TransformResultMetadata calculateResultMetadata() { - TransformResultMetadata elseStatementResultMetadata = _elseStatement.getResultMetadata(); - DataType dataType = elseStatementResultMetadata.getDataType(); - Preconditions.checkState(elseStatementResultMetadata.isSingleValue(), - "Unsupported multi-value expression in the ELSE clause"); + DataType dataType; + if (_elseStatement == null) { + dataType = DataType.UNKNOWN; + } else { + TransformResultMetadata elseStatementResultMetadata = _elseStatement.getResultMetadata(); + dataType = elseStatementResultMetadata.getDataType(); + Preconditions.checkState(elseStatementResultMetadata.isSingleValue(), + "Unsupported multi-value expression in the ELSE clause"); + } int numThenStatements = _thenStatements.size(); for (int i = 0; i < numThenStatements; i++) { TransformFunction thenStatement = _thenStatements.get(i); @@ -257,6 +262,14 @@ public class CaseTransformFunction extends ComputeDifferentlyWhenNullHandlingEna return _resultMetadata; } + private boolean isNullLiteralTransformation(TransformFunction function) { + if (function instanceof LiteralTransformFunction) { + LiteralTransformFunction literalFunction = (LiteralTransformFunction) function; + return literalFunction.isNull(); + } + return false; + } + /** * Evaluate the ValueBlock for the WHEN statements, returns an array with the index(1 to N) of matched WHEN clause -1 * means there is no match. diff --git a/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/LiteralTransformFunction.java b/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/LiteralTransformFunction.java index ec9f010101..3ce9abba8b 100644 --- a/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/LiteralTransformFunction.java +++ b/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/LiteralTransformFunction.java @@ -269,4 +269,8 @@ public class LiteralTransformFunction implements TransformFunction { bitmap.add(0L, length); return bitmap; } + + public boolean isNull() { + return _dataType == DataType.UNKNOWN; + } } diff --git a/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/LiteralTransformFunctionTest.java b/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/LiteralTransformFunctionTest.java index b1d7d55343..d6f4060e80 100644 --- a/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/LiteralTransformFunctionTest.java +++ b/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/LiteralTransformFunctionTest.java @@ -78,4 +78,23 @@ public class LiteralTransformFunctionTest { } Assert.assertEquals(nullLiteral.getNullBitmap(_projectionBlock), expectedBitmap); } + + @Test + public void testIsNullLiteralTransform() { + LiteralTransformFunction nullLiteral = + new LiteralTransformFunction(new LiteralContext(DataType.UNKNOWN, null)); + Assert.assertTrue(nullLiteral.isNull()); + + LiteralTransformFunction nullLiteralWITHBooleanValue = + new LiteralTransformFunction(new LiteralContext(DataType.UNKNOWN, true)); + Assert.assertTrue(nullLiteralWITHBooleanValue.isNull()); + + LiteralTransformFunction trueLiteral = + new LiteralTransformFunction(new LiteralContext(DataType.BOOLEAN, true)); + Assert.assertFalse(trueLiteral.isNull()); + + LiteralTransformFunction stringNullLiteral = + new LiteralTransformFunction(new LiteralContext(DataType.STRING, null)); + Assert.assertFalse(stringNullLiteral.isNull()); + } } diff --git a/pinot-query-runtime/src/test/resources/queries/Case.json b/pinot-query-runtime/src/test/resources/queries/Case.json index 4375d1b482..196997f4a7 100644 --- a/pinot-query-runtime/src/test/resources/queries/Case.json +++ b/pinot-query-runtime/src/test/resources/queries/Case.json @@ -21,13 +21,18 @@ "queries": [ { "sql": "SELECT intCol, CASE WHEN boolCol = true THEN 'Yes' ELSE 'No' END AS boolVal, strCol FROM {tbl1}"}, { "sql": "SELECT intCol, CASE WHEN boolCol = true THEN 'Yes' END AS boolVal, strCol FROM {tbl1}"}, + { "sql": "SELECT intCol, CASE WHEN boolCol = true THEN 'Yes' ELSE NULL END AS boolVal, strCol FROM {tbl1}"}, { "sql": "SELECT intCol, CASE WHEN intCol % 2 = 0 THEN intCol END AS intVal, strCol FROM {tbl1}"}, + { "sql": "SELECT intCol, CASE WHEN intCol % 2 = 0 THEN intCol ELSE NULL END AS intVal, strCol FROM {tbl1}"}, { "sql": "SELECT intCol, CASE WHEN longCol % 2 = 0 THEN longCol END AS longVal, strCol FROM {tbl1}"}, + { "sql": "SELECT intCol, CASE WHEN longCol % 2 = 0 THEN longCol ELSE NULL END AS longVal, strCol FROM {tbl1}"}, { "sql": "SELECT intCol, CASE WHEN longCol % 2 = 0 THEN longCol ELSE longCol * 2 END AS longVal, strCol FROM {tbl1}"}, { "sql": "SELECT intCol, CASE WHEN doubleCol % 2.343 = 0 THEN doubleCol END AS doubleVal, strCol FROM {tbl1}"}, + { "sql": "SELECT intCol, CASE WHEN doubleCol % 2.343 = 0 THEN doubleCol ELSE NULL END AS doubleVal, strCol FROM {tbl1}"}, { "sql": "SELECT intCol, CASE WHEN doubleCol % 2.343 = 0 THEN doubleCol ELSE doubleCol * 2 END AS doubleVal, strCol FROM {tbl1}"}, { "sql": "SELECT intCol, CASE WHEN intCol % 2 = 0 THEN intCol ELSE intCol * 4 END AS intVal, strCol FROM {tbl1}"}, { "sql": "SELECT intCol, CASE WHEN floatCol > 4.0 THEN floatCol END AS floatVal, strCol FROM {tbl1}"}, + { "sql": "SELECT intCol, CASE WHEN floatCol > 4.0 THEN floatCol ELSE NULL END AS floatVal, strCol FROM {tbl1}"}, { "sql": "SELECT intCol, CASE WHEN floatCol > 4.0 THEN floatCol ELSE floatCol * 4 END AS floatVal, strCol FROM {tbl1}"}, { "sql": "SELECT intCol, CASE WHEN strCol = 'one' THEN strCol END AS strVal FROM {tbl1}"}, { "sql": "SELECT intCol, CASE WHEN strCol = 'one' THEN strCol ELSE 'TWO' END AS strVal FROM {tbl1}"}, --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org For additional commands, e-mail: commits-h...@pinot.apache.org