diff --git a/processing/src/main/java/org/apache/druid/query/rowsandcols/column/accessor/DoubleColumnAccessorBase.java b/processing/src/main/java/org/apache/druid/query/rowsandcols/column/accessor/DoubleColumnAccessorBase.java index b1a04a95a05..50c818dd1f1 100644 --- a/processing/src/main/java/org/apache/druid/query/rowsandcols/column/accessor/DoubleColumnAccessorBase.java +++ b/processing/src/main/java/org/apache/druid/query/rowsandcols/column/accessor/DoubleColumnAccessorBase.java @@ -36,7 +36,11 @@ public abstract class DoubleColumnAccessorBase implements ColumnAccessor @Override public Object getObject(int rowNum) { - return getDouble(rowNum); + if (isNull(rowNum)) { + return null; + } else { + return getDouble(rowNum); + } } @Override diff --git a/processing/src/main/java/org/apache/druid/query/rowsandcols/column/accessor/FloatColumnAccessorBase.java b/processing/src/main/java/org/apache/druid/query/rowsandcols/column/accessor/FloatColumnAccessorBase.java index 1c8892876cd..66cbbbfea42 100644 --- a/processing/src/main/java/org/apache/druid/query/rowsandcols/column/accessor/FloatColumnAccessorBase.java +++ b/processing/src/main/java/org/apache/druid/query/rowsandcols/column/accessor/FloatColumnAccessorBase.java @@ -36,7 +36,11 @@ public abstract class FloatColumnAccessorBase implements ColumnAccessor @Override public Object getObject(int rowNum) { - return getFloat(rowNum); + if (isNull(rowNum)) { + return null; + } else { + return getFloat(rowNum); + } } @Override diff --git a/processing/src/main/java/org/apache/druid/query/rowsandcols/column/accessor/LongColumnAccessorBase.java b/processing/src/main/java/org/apache/druid/query/rowsandcols/column/accessor/LongColumnAccessorBase.java index 595ab9eb4d6..ae2b3f1f7ec 100644 --- a/processing/src/main/java/org/apache/druid/query/rowsandcols/column/accessor/LongColumnAccessorBase.java +++ b/processing/src/main/java/org/apache/druid/query/rowsandcols/column/accessor/LongColumnAccessorBase.java @@ -34,9 +34,13 @@ public abstract class LongColumnAccessorBase implements ColumnAccessor @Nullable @Override - public Object getObject(int rowNum) + public final Object getObject(int rowNum) { - return getLong(rowNum); + if (isNull(rowNum)) { + return null; + } else { + return getLong(rowNum); + } } @Override diff --git a/processing/src/test/java/org/apache/druid/query/rowsandcols/column/ColumnAccessorsTest.java b/processing/src/test/java/org/apache/druid/query/rowsandcols/column/ColumnAccessorsTest.java new file mode 100644 index 00000000000..2f721a51e3b --- /dev/null +++ b/processing/src/test/java/org/apache/druid/query/rowsandcols/column/ColumnAccessorsTest.java @@ -0,0 +1,188 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.druid.query.rowsandcols.column; + +import org.apache.druid.query.rowsandcols.column.accessor.DoubleColumnAccessorBase; +import org.apache.druid.query.rowsandcols.column.accessor.FloatColumnAccessorBase; +import org.apache.druid.query.rowsandcols.column.accessor.LongColumnAccessorBase; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +@RunWith(Parameterized.class) +public class ColumnAccessorsTest +{ + private TestAccessorShim testAccessor; + + @Parameters + public static List getParameters() + { + List ret = new ArrayList<>(); + + for (TestAccessorShim accessor : TestAccessorShim.values()) { + ret.add(new Object[] {accessor}); + } + + return ret; + } + + enum TestAccessorShim + { + LONG { + @Override + ColumnAccessor getColumnAccessor(Object value) + { + Long val = (Long) value; + return new LongColumnAccessorBase() + { + @Override + public int numRows() + { + return 1; + } + + @Override + public boolean isNull(int rowNum) + { + return val == null; + } + + @Override + public long getLong(int rowNum) + { + return val; + } + }; + } + + @Override + protected Object getSomeValue() + { + return 42L; + } + + + }, + FLOAT { + @Override + ColumnAccessor getColumnAccessor(Object value) + { + Float val = (Float) value; + return new FloatColumnAccessorBase() + { + + @Override + public int numRows() + { + return 1; + } + + @Override + public boolean isNull(int rowNum) + { + return val == null; + } + + @Override + public float getFloat(int rowNum) + { + return val; + } + }; + } + + @Override + protected Object getSomeValue() + { + return 42.1F; + } + }, + DOUBLE { + @Override + ColumnAccessor getColumnAccessor(Object value) + { + Double val = (Double) value; + return new DoubleColumnAccessorBase() + { + + @Override + public int numRows() + { + return 1; + } + + @Override + public boolean isNull(int rowNum) + { + return val == null; + } + + @Override + public double getDouble(int rowNum) + { + return val; + } + }; + } + + @Override + protected Object getSomeValue() + { + return 42.1D; + } + }; + + abstract ColumnAccessor getColumnAccessor(Object val); + + protected abstract Object getSomeValue(); + } + + public ColumnAccessorsTest(TestAccessorShim accessor) + { + this.testAccessor = accessor; + } + + @Test + public void testSomeValue() + { + Object expectedValue = testAccessor.getSomeValue(); + ColumnAccessor acc = testAccessor.getColumnAccessor(expectedValue); + + assertFalse(acc.isNull(0)); + assertEquals(expectedValue, acc.getObject(0)); + } + + @Test + public void testNull() + { + ColumnAccessor acc = testAccessor.getColumnAccessor(null); + + assertTrue(acc.isNull(0)); + assertEquals(null, acc.getObject(0)); + } +} diff --git a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteWindowQueryTest.java b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteWindowQueryTest.java index e4c07d188e7..b0172fcd0c8 100644 --- a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteWindowQueryTest.java +++ b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteWindowQueryTest.java @@ -127,6 +127,7 @@ public class CalciteWindowQueryTest extends BaseCalciteQueryTest } Assert.assertEquals(1, results.recordedQueries.size()); + maybeDumpActualResults(results.results); final WindowOperatorQuery query = getWindowOperatorQuery(results.recordedQueries); for (int i = 0; i < input.expectedOperators.size(); ++i) { final OperatorFactory expectedOperator = input.expectedOperators.get(i); @@ -145,7 +146,6 @@ public class CalciteWindowQueryTest extends BaseCalciteQueryTest Assert.assertEquals(types[i], results.signature.getColumnType(i).get()); } - maybeDumpActualResults(results.results); for (Object[] result : input.expectedResults) { for (int i = 0; i < result.length; i++) { // Jackson deserializes numbers as the minimum size required to diff --git a/sql/src/test/java/org/apache/druid/sql/calcite/DrillWindowQueryTest.java b/sql/src/test/java/org/apache/druid/sql/calcite/DrillWindowQueryTest.java index 8097377d09c..969b59b5037 100644 --- a/sql/src/test/java/org/apache/druid/sql/calcite/DrillWindowQueryTest.java +++ b/sql/src/test/java/org/apache/druid/sql/calcite/DrillWindowQueryTest.java @@ -6209,7 +6209,6 @@ public class DrillWindowQueryTest extends BaseCalciteQueryTest windowQueryTest(); } - @NotYetSupported(Modes.RESULT_MISMATCH) @DrillTest("aggregates/aggOWnFn_17") @Test public void test_aggregates_aggOWnFn_17() @@ -6728,7 +6727,6 @@ public class DrillWindowQueryTest extends BaseCalciteQueryTest windowQueryTest(); } - @NotYetSupported(Modes.RESULT_MISMATCH) @DrillTest("frameclause/defaultFrame/RBUPACR_bgint_6") @Test public void test_frameclause_defaultFrame_RBUPACR_bgint_6() @@ -6784,7 +6782,6 @@ public class DrillWindowQueryTest extends BaseCalciteQueryTest windowQueryTest(); } - @NotYetSupported(Modes.RESULT_MISMATCH) @DrillTest("frameclause/defaultFrame/RBUPACR_dbl_6") @Test public void test_frameclause_defaultFrame_RBUPACR_dbl_6() @@ -6840,7 +6837,6 @@ public class DrillWindowQueryTest extends BaseCalciteQueryTest windowQueryTest(); } - @NotYetSupported(Modes.RESULT_MISMATCH) @DrillTest("frameclause/defaultFrame/RBUPACR_int13") @Test public void test_frameclause_defaultFrame_RBUPACR_int13() @@ -7120,7 +7116,6 @@ public class DrillWindowQueryTest extends BaseCalciteQueryTest windowQueryTest(); } - @NotYetSupported(Modes.RESULT_MISMATCH) @DrillTest("frameclause/RBUPACR/RBUPACR_bgint_6") @Test public void test_frameclause_RBUPACR_RBUPACR_bgint_6() @@ -7176,7 +7171,6 @@ public class DrillWindowQueryTest extends BaseCalciteQueryTest windowQueryTest(); } - @NotYetSupported(Modes.RESULT_MISMATCH) @DrillTest("frameclause/RBUPACR/RBUPACR_dbl_6") @Test public void test_frameclause_RBUPACR_RBUPACR_dbl_6() @@ -7200,7 +7194,6 @@ public class DrillWindowQueryTest extends BaseCalciteQueryTest windowQueryTest(); } - @NotYetSupported(Modes.RESULT_MISMATCH) @DrillTest("frameclause/RBUPACR/RBUPACR_int13") @Test public void test_frameclause_RBUPACR_RBUPACR_int13() @@ -7240,7 +7233,6 @@ public class DrillWindowQueryTest extends BaseCalciteQueryTest windowQueryTest(); } - @NotYetSupported(Modes.RESULT_MISMATCH) @DrillTest("frameclause/RBUPAUF/RBUPAUF_bgint_6") @Test public void test_frameclause_RBUPAUF_RBUPAUF_bgint_6() @@ -7256,7 +7248,6 @@ public class DrillWindowQueryTest extends BaseCalciteQueryTest windowQueryTest(); } - @NotYetSupported(Modes.RESULT_MISMATCH) @DrillTest("frameclause/RBUPAUF/RBUPAUF_dbl_6") @Test public void test_frameclause_RBUPAUF_RBUPAUF_dbl_6() @@ -7264,7 +7255,6 @@ public class DrillWindowQueryTest extends BaseCalciteQueryTest windowQueryTest(); } - @NotYetSupported(Modes.RESULT_MISMATCH) @DrillTest("frameclause/RBUPAUF/RBUPAUF_dbl_7") @Test public void test_frameclause_RBUPAUF_RBUPAUF_dbl_7() @@ -7304,7 +7294,6 @@ public class DrillWindowQueryTest extends BaseCalciteQueryTest windowQueryTest(); } - @NotYetSupported(Modes.RESULT_MISMATCH) @DrillTest("frameclause/RBUPAUF/RBUPAUF_int_13") @Test public void test_frameclause_RBUPAUF_RBUPAUF_int_13() diff --git a/sql/src/test/resources/calcite/tests/window/windowed_long_null.sqlTest b/sql/src/test/resources/calcite/tests/window/windowed_long_null.sqlTest new file mode 100644 index 00000000000..65d6265769a --- /dev/null +++ b/sql/src/test/resources/calcite/tests/window/windowed_long_null.sqlTest @@ -0,0 +1,30 @@ +type: "operatorValidation" + +sql: | + SELECT + l2, + MIN(l2) OVER(partition by l2) + FROM druid.numfoo + WHERE l2 is null or l2 = -1111 or l2 = 0 + + +expectedOperators: + - type: "naiveSort" + columns: + - column: "l2" + direction: "ASC" + - type: "naivePartition" + partitionColumns: [ "l2" ] + - type: "window" + processor: + type: "framedAgg" + frame: { peerType: "ROWS", lowUnbounded: true, lowOffset: 0, uppUnbounded: true, uppOffset: 0 } + aggregations: + - { type: "longMin", name: "w0", fieldName: "l2" } + +expectedResults: + - [null,null] + - [null,null] + - [null,null] + - [null,null] + - [0,0] \ No newline at end of file