This is an automated email from the ASF dual-hosted git repository.
abhishek pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git
The following commit(s) were added to refs/heads/master by this push:
new 3bf1e699ff GREATEST/LEAST function is incorrectly specifying that it
cannot return null (#12804)
3bf1e699ff is described below
commit 3bf1e699ff09ef13807cc05f00eec032912a1206
Author: Maytas Monsereenusorn <[email protected]>
AuthorDate: Wed Jul 20 02:11:24 2022 -0700
GREATEST/LEAST function is incorrectly specifying that it cannot return
null (#12804)
---
.../builtin/ReductionOperatorConversionHelper.java | 12 ++-
.../apache/druid/sql/calcite/CalciteQueryTest.java | 110 +++++++++++++++++++++
2 files changed, 120 insertions(+), 2 deletions(-)
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/expression/builtin/ReductionOperatorConversionHelper.java
b/sql/src/main/java/org/apache/druid/sql/calcite/expression/builtin/ReductionOperatorConversionHelper.java
index 4a457b7ad7..a747e9d27d 100644
---
a/sql/src/main/java/org/apache/druid/sql/calcite/expression/builtin/ReductionOperatorConversionHelper.java
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/expression/builtin/ReductionOperatorConversionHelper.java
@@ -23,6 +23,7 @@ import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.sql.type.SqlReturnTypeInference;
import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.druid.common.config.NullHandling;
import org.apache.druid.java.util.common.IAE;
import org.apache.druid.math.expr.ExpressionTypeConversion;
import org.apache.druid.segment.column.ColumnType;
@@ -53,7 +54,7 @@ class ReductionOperatorConversionHelper
SqlTypeName returnSqlTypeName = SqlTypeName.NULL;
boolean hasDouble = false;
-
+ boolean isString = false;
for (int i = 0; i < n; i++) {
RelDataType type = opBinding.getOperandType(i);
SqlTypeName sqlTypeName = type.getSqlTypeName();
@@ -63,6 +64,7 @@ class ReductionOperatorConversionHelper
if (valueType != null) {
if (valueType.is(ValueType.STRING)) {
returnSqlTypeName = sqlTypeName;
+ isString = true;
break;
} else if (valueType.anyOf(ValueType.DOUBLE, ValueType.FLOAT)) {
returnSqlTypeName = SqlTypeName.DOUBLE;
@@ -75,6 +77,12 @@ class ReductionOperatorConversionHelper
}
}
- return typeFactory.createSqlType(returnSqlTypeName);
+ if (isString || NullHandling.sqlCompatible()) {
+ // String can be null in both modes
+ return
typeFactory.createTypeWithNullability(typeFactory.createSqlType(returnSqlTypeName),
true);
+ } else {
+ return typeFactory.createSqlType(returnSqlTypeName);
+ }
};
}
+
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java
index 77e6ca22d2..666967c410 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java
@@ -39,6 +39,7 @@ import org.apache.druid.query.Druids;
import org.apache.druid.query.InlineDataSource;
import org.apache.druid.query.JoinDataSource;
import org.apache.druid.query.LookupDataSource;
+import org.apache.druid.query.Query;
import org.apache.druid.query.QueryContext;
import org.apache.druid.query.QueryContexts;
import org.apache.druid.query.QueryDataSource;
@@ -13902,4 +13903,113 @@ public class CalciteQueryTest extends
BaseCalciteQueryTest
null
);
}
+
+ @Test
+ public void testGreatestFunctionForNumberWithIsNull() throws Exception
+ {
+ String query = "SELECT dim1, MAX(GREATEST(l1, l2)) IS NULL FROM
druid.numfoo GROUP BY dim1";
+
+ List<Object[]> expectedResult;
+ List<Query> expectedQueries;
+
+ if (NullHandling.replaceWithDefault()) {
+ expectedResult = ImmutableList.of(
+ new Object[]{"", false},
+ new Object[]{"1", false},
+ new Object[]{"10.1", false},
+ new Object[]{"2", false},
+ new Object[]{"abc", false},
+ new Object[]{"def", false}
+ );
+ expectedQueries = ImmutableList.of(
+ GroupByQuery.builder()
+ .setDataSource(CalciteTests.DATASOURCE3)
+ .setInterval(querySegmentSpec(Intervals.ETERNITY))
+ .setGranularity(Granularities.ALL)
+ .addDimension(new DefaultDimensionSpec("dim1", "_d0"))
+ .setPostAggregatorSpecs(ImmutableList.of(
+ expressionPostAgg("p0", "0")
+ ))
+ .build()
+ );
+ } else {
+ cannotVectorize();
+ expectedResult = ImmutableList.of(
+ new Object[]{"", false},
+ new Object[]{"1", true},
+ new Object[]{"10.1", false},
+ new Object[]{"2", false},
+ new Object[]{"abc", true},
+ new Object[]{"def", true}
+ );
+ expectedQueries = ImmutableList.of(
+ GroupByQuery.builder()
+ .setDataSource(CalciteTests.DATASOURCE3)
+ .setInterval(querySegmentSpec(Intervals.ETERNITY))
+ .setVirtualColumns(
+ expressionVirtualColumn(
+ "v0",
+ "greatest(\"l1\",\"l2\")",
+ ColumnType.LONG
+ )
+ )
+ .setGranularity(Granularities.ALL)
+ .addDimension(new DefaultDimensionSpec("dim1", "_d0"))
+ .addAggregator(new LongMaxAggregatorFactory("a0", "v0"))
+ .setPostAggregatorSpecs(ImmutableList.of(
+ expressionPostAgg("p0", "isnull(\"a0\")")
+ ))
+ .build()
+ );
+ }
+
+ testQuery(
+ query,
+ expectedQueries,
+ expectedResult
+ );
+ }
+
+ @Test
+ public void testGreatestFunctionForStringWithIsNull() throws Exception
+ {
+ cannotVectorize();
+
+ String query = "SELECT l1, LATEST(GREATEST(dim1, dim2)) IS NULL FROM
druid.numfoo GROUP BY l1";
+
+ testQuery(
+ query,
+ ImmutableList.of(
+ GroupByQuery.builder()
+ .setDataSource(CalciteTests.DATASOURCE3)
+ .setInterval(querySegmentSpec(Intervals.ETERNITY))
+ .setVirtualColumns(
+ expressionVirtualColumn(
+ "v0",
+ "CAST(greatest(\"dim1\",\"dim2\"), 'DOUBLE')",
+ ColumnType.DOUBLE
+ )
+ )
+ .setGranularity(Granularities.ALL)
+ .addDimension(new DefaultDimensionSpec("l1", "_d0",
ColumnType.LONG))
+ .addAggregator(new DoubleLastAggregatorFactory("a0",
"v0", null))
+ .setPostAggregatorSpecs(ImmutableList.of(
+ expressionPostAgg("p0", "isnull(\"a0\")")
+ ))
+ .build()
+ ),
+ NullHandling.replaceWithDefault() ?
+ ImmutableList.of(
+ new Object[]{0L, false},
+ new Object[]{7L, false},
+ new Object[]{325323L, false}
+ ) :
+ ImmutableList.of(
+ new Object[]{null, true},
+ new Object[]{0L, false},
+ new Object[]{7L, true},
+ new Object[]{325323L, false}
+ )
+ );
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]