From cf30bd56ecb8059af55c7a566010e6abc618fad7 Mon Sep 17 00:00:00 2001 From: Laksh Singla Date: Tue, 30 Apr 2024 15:13:14 +0530 Subject: [PATCH] Improve code flow in the First/Last vector aggregators and unify the numeric aggregators with the String implementations (#16230) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR fixes the first and last vector aggregators and improves their readability. Following changes are introduced The folding is broken in the vectorized versions. We consider time before checking the folded object. If the numerical aggregator gets passed any other object type for some other reason (like String), then the aggregator considers it to be folded, even though it shouldn’t be. We should convert these objects to the desired type, and aggregate them properly. The aggregators must properly use generics. This would minimize the ClassCastException issues that can happen with mixed segment types. We are unifying the string first/last aggregators with numeric versions as well. The aggregators must aggregate null values (https://github.com/apache/druid/blob/master/processing/src/main/java/org/apache/druid/query/aggregation/first/StringFirstLastUtils.java#L55-L56 ). The aggregator should only ignore pairs with time == null, and not value == null Time nullity is ignored when trying to vectorize the data. String versions initialized with DateTimes.MIN that is equal to Long.MIN / 2. This can cause incorrect results in case the user enters a custom time column. NOTE: This is still present because it would require a larger refactor in all of the versions. There is a difference in what users might expect from the results because the code flow is changed (for example, the direction of the for loops, etc), however, this will only change the results, and not the contract set by first/last aggregators, which is that if multiple values have the same timestamp, then any of them can get picked. If the column is non-existent, the users might expect a change in the timestamp from DateTime.MAX to Long.MAX, because the code incorrectly used DateTime.MAX to initialize the aggregator, however, in case of a custom timestamp column, this might not be the case. The SQL query might be prohibited from using any Long since it requires a cast to the timestamp function that can fail, but AFAICT native queries don't have such limitations. --- .../common/task/CompactionTaskTest.java | 4 +- .../druid/jackson/AggregatorsModule.java | 20 +- .../any/StringAnyAggregatorFactory.java | 2 +- .../aggregation/first/FirstLastUtils.java | 69 ----- .../first/NumericFirstVectorAggregator.java | 225 --------------- ...eStringFirstDimensionVectorAggregator.java | 125 -------- .../first/StringFirstVectorAggregator.java | 184 ------------ .../DoubleFirstLastVectorAggregator.java | 123 ++++++++ .../aggregation/firstlast/FirstLastUtils.java | 155 ++++++++++ .../firstlast/FirstLastVectorAggregator.java | 266 ++++++++++++++++++ .../FloatFirstLastVectorAggregator.java | 122 ++++++++ .../LongFirstLastVectorAggregator.java | 121 ++++++++ .../firstlast/SelectionPredicate.java | 70 +++++ ...ingFirstLastDimensionVectorAggregator.java | 185 ++++++++++++ .../StringFirstLastUtils.java | 24 +- .../StringFirstLastVectorAggregator.java | 110 ++++++++ .../first/DoubleFirstAggregator.java | 2 +- .../first/DoubleFirstAggregatorFactory.java | 3 +- .../first/DoubleFirstBufferAggregator.java | 2 +- .../first/DoubleFirstVectorAggregator.java | 40 +-- .../first/FloatFirstAggregator.java | 2 +- .../first/FloatFirstAggregatorFactory.java | 3 +- .../first/FloatFirstBufferAggregator.java | 2 +- .../first/FloatFirstVectorAggregator.java | 39 +-- .../first/GenericFirstAggregateCombiner.java | 2 +- .../first/LongFirstAggregator.java | 2 +- .../first/LongFirstAggregatorFactory.java | 3 +- .../first/LongFirstBufferAggregator.java | 2 +- .../first/LongFirstVectorAggregator.java | 38 +-- .../first/NumericFirstAggregator.java | 2 +- .../first/NumericFirstBufferAggregator.java | 2 +- ...eStringFirstDimensionVectorAggregator.java | 38 +++ .../first/StringFirstAggregator.java | 3 +- .../first/StringFirstAggregatorFactory.java | 12 +- .../first/StringFirstBufferAggregator.java | 3 +- .../StringFirstFoldingAggregatorFactory.java | 2 +- .../first/StringFirstVectorAggregator.java | 39 +++ .../last/DoubleLastAggregator.java | 2 +- .../last/DoubleLastAggregatorFactory.java | 6 +- .../last/DoubleLastBufferAggregator.java | 2 +- .../last/DoubleLastVectorAggregator.java | 43 +-- .../last/FloatLastAggregator.java | 2 +- .../last/FloatLastAggregatorFactory.java | 6 +- .../last/FloatLastBufferAggregator.java | 2 +- .../last/FloatLastVectorAggregator.java | 44 +-- .../last/GenericLastAggregateCombiner.java | 2 +- .../last/LongLastAggregator.java | 2 +- .../last/LongLastAggregatorFactory.java | 10 +- .../last/LongLastBufferAggregator.java | 2 +- .../last/LongLastVectorAggregator.java | 38 +++ .../last/NumericLastAggregator.java | 4 +- .../last/NumericLastBufferAggregator.java | 4 +- ...leStringLastDimensionVectorAggregator.java | 38 +++ .../last/StringLastAggregator.java | 4 +- .../last/StringLastAggregatorFactory.java | 12 +- .../last/StringLastBufferAggregator.java | 4 +- .../StringLastFoldingAggregatorFactory.java | 2 +- .../last/StringLastVectorAggregator.java | 39 +++ .../last/LongLastVectorAggregator.java | 72 ----- .../last/NumericLastVectorAggregator.java | 228 --------------- ...leStringLastDimensionVectorAggregator.java | 124 -------- .../last/StringLastVectorAggregator.java | 200 ------------- .../aggregation/AggregatorFactoryTest.java | 16 +- .../first/DoubleFirstAggregationTest.java | 2 +- .../DoubleFirstVectorAggregatorTest.java} | 48 +++- .../first/FloatFirstAggregationTest.java | 2 +- .../FloatFirstVectorAggregatorTest.java} | 26 +- .../first/LongFirstAggregationTest.java | 2 +- .../first/LongFirstVectorAggregatorTest.java} | 24 +- .../first/StringFirstAggregationTest.java | 2 +- .../StringFirstBufferAggregatorTest.java | 2 +- .../first/StringFirstLastUtilsTest.java | 3 +- .../first/StringFirstTimeseriesQueryTest.java | 2 +- .../StringFirstVectorAggregatorTest.java | 15 +- .../last/DoubleLastAggregationTest.java | 2 +- .../last/DoubleLastVectorAggregatorTest.java | 46 ++- .../last/FloatLastAggregationTest.java | 2 +- .../last/FloatLastVectorAggregatorTest.java | 23 +- .../last/LongLastAggregationTest.java | 2 +- .../last/LongLastVectorAggregatorTest.java | 84 +++++- .../last/StringLastAggregationTest.java | 2 +- .../last/StringLastBufferAggregatorTest.java | 2 +- .../last/StringLastTimeseriesQueryTest.java | 2 +- .../last/StringLastVectorAggregatorTest.java | 25 +- ...nalizingFieldAccessPostAggregatorTest.java | 2 +- .../GroupByQueryQueryToolChestTest.java | 8 +- .../query/groupby/GroupByQueryRunnerTest.java | 4 +- .../TimeseriesQueryQueryToolChestTest.java | 2 +- .../timeseries/TimeseriesQueryRunnerTest.java | 4 +- .../topn/TopNQueryQueryToolChestTest.java | 8 +- .../druid/query/topn/TopNQueryRunnerTest.java | 10 +- .../query/topn/UnnestTopNQueryRunnerTest.java | 2 +- .../druid/segment/IndexMergerRollupTest.java | 16 +- .../segment/column/SchemaPayloadPlusTest.java | 2 +- .../segment/column/SchemaPayloadTest.java | 2 +- .../column/SegmentSchemaMappingTest.java | 2 +- .../metadata/FingerprintGeneratorTest.java | 2 +- .../SegmentSchemaBackFillQueueTest.java | 2 +- .../metadata/SegmentSchemaManagerTest.java | 2 +- .../EarliestLatestAnySqlAggregator.java | 16 +- .../druid/sql/calcite/CalciteQueryTest.java | 16 +- .../sql/calcite/CalciteSimpleQueryTest.java | 4 +- .../sql/calcite/util/TestDataBuilder.java | 10 +- 103 files changed, 1744 insertions(+), 1642 deletions(-) delete mode 100644 processing/src/main/java/org/apache/druid/query/aggregation/first/FirstLastUtils.java delete mode 100644 processing/src/main/java/org/apache/druid/query/aggregation/first/NumericFirstVectorAggregator.java delete mode 100644 processing/src/main/java/org/apache/druid/query/aggregation/first/SingleStringFirstDimensionVectorAggregator.java delete mode 100644 processing/src/main/java/org/apache/druid/query/aggregation/first/StringFirstVectorAggregator.java create mode 100644 processing/src/main/java/org/apache/druid/query/aggregation/firstlast/DoubleFirstLastVectorAggregator.java create mode 100644 processing/src/main/java/org/apache/druid/query/aggregation/firstlast/FirstLastUtils.java create mode 100644 processing/src/main/java/org/apache/druid/query/aggregation/firstlast/FirstLastVectorAggregator.java create mode 100644 processing/src/main/java/org/apache/druid/query/aggregation/firstlast/FloatFirstLastVectorAggregator.java create mode 100644 processing/src/main/java/org/apache/druid/query/aggregation/firstlast/LongFirstLastVectorAggregator.java create mode 100644 processing/src/main/java/org/apache/druid/query/aggregation/firstlast/SelectionPredicate.java create mode 100644 processing/src/main/java/org/apache/druid/query/aggregation/firstlast/SingleStringFirstLastDimensionVectorAggregator.java rename processing/src/main/java/org/apache/druid/query/aggregation/{first => firstlast}/StringFirstLastUtils.java (90%) create mode 100644 processing/src/main/java/org/apache/druid/query/aggregation/firstlast/StringFirstLastVectorAggregator.java rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/first/DoubleFirstAggregator.java (96%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/first/DoubleFirstAggregatorFactory.java (98%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/first/DoubleFirstBufferAggregator.java (97%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/first/DoubleFirstVectorAggregator.java (50%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/first/FloatFirstAggregator.java (96%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/first/FloatFirstAggregatorFactory.java (98%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/first/FloatFirstBufferAggregator.java (97%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/first/FloatFirstVectorAggregator.java (51%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/first/GenericFirstAggregateCombiner.java (96%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/first/LongFirstAggregator.java (96%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/first/LongFirstAggregatorFactory.java (98%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/first/LongFirstBufferAggregator.java (97%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/first/LongFirstVectorAggregator.java (51%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/first/NumericFirstAggregator.java (98%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/first/NumericFirstBufferAggregator.java (98%) create mode 100644 processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/SingleStringFirstDimensionVectorAggregator.java rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/first/StringFirstAggregator.java (96%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/first/StringFirstAggregatorFactory.java (96%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/first/StringFirstBufferAggregator.java (97%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/first/StringFirstFoldingAggregatorFactory.java (96%) create mode 100644 processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstVectorAggregator.java rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/last/DoubleLastAggregator.java (96%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/last/DoubleLastAggregatorFactory.java (97%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/last/DoubleLastBufferAggregator.java (97%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/last/DoubleLastVectorAggregator.java (50%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/last/FloatLastAggregator.java (96%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/last/FloatLastAggregatorFactory.java (97%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/last/FloatLastBufferAggregator.java (97%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/last/FloatLastVectorAggregator.java (50%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/last/GenericLastAggregateCombiner.java (96%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/last/LongLastAggregator.java (96%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/last/LongLastAggregatorFactory.java (96%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/last/LongLastBufferAggregator.java (97%) create mode 100644 processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/LongLastVectorAggregator.java rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/last/NumericLastAggregator.java (95%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/last/NumericLastBufferAggregator.java (96%) create mode 100644 processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/SingleStringLastDimensionVectorAggregator.java rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/last/StringLastAggregator.java (96%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/last/StringLastAggregatorFactory.java (94%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/last/StringLastBufferAggregator.java (97%) rename processing/src/main/java/org/apache/druid/query/aggregation/{ => firstlast}/last/StringLastFoldingAggregatorFactory.java (96%) create mode 100644 processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastVectorAggregator.java delete mode 100644 processing/src/main/java/org/apache/druid/query/aggregation/last/LongLastVectorAggregator.java delete mode 100644 processing/src/main/java/org/apache/druid/query/aggregation/last/NumericLastVectorAggregator.java delete mode 100644 processing/src/main/java/org/apache/druid/query/aggregation/last/SingleStringLastDimensionVectorAggregator.java delete mode 100644 processing/src/main/java/org/apache/druid/query/aggregation/last/StringLastVectorAggregator.java rename processing/src/test/java/org/apache/druid/query/aggregation/{ => firstlast}/first/DoubleFirstAggregationTest.java (99%) rename processing/src/test/java/org/apache/druid/query/aggregation/{first/DoubleFirstVectorAggregationTest.java => firstlast/first/DoubleFirstVectorAggregatorTest.java} (86%) rename processing/src/test/java/org/apache/druid/query/aggregation/{ => firstlast}/first/FloatFirstAggregationTest.java (99%) rename processing/src/test/java/org/apache/druid/query/aggregation/{first/FloatFirstVectorAggregationTest.java => firstlast/first/FloatFirstVectorAggregatorTest.java} (92%) rename processing/src/test/java/org/apache/druid/query/aggregation/{ => firstlast}/first/LongFirstAggregationTest.java (99%) rename processing/src/test/java/org/apache/druid/query/aggregation/{first/LongFirstVectorAggregationTest.java => firstlast/first/LongFirstVectorAggregatorTest.java} (92%) rename processing/src/test/java/org/apache/druid/query/aggregation/{ => firstlast}/first/StringFirstAggregationTest.java (99%) rename processing/src/test/java/org/apache/druid/query/aggregation/{ => firstlast}/first/StringFirstBufferAggregatorTest.java (99%) rename processing/src/test/java/org/apache/druid/query/aggregation/{ => firstlast}/first/StringFirstLastUtilsTest.java (94%) rename processing/src/test/java/org/apache/druid/query/aggregation/{ => firstlast}/first/StringFirstTimeseriesQueryTest.java (99%) rename processing/src/test/java/org/apache/druid/query/aggregation/{ => firstlast}/first/StringFirstVectorAggregatorTest.java (96%) rename processing/src/test/java/org/apache/druid/query/aggregation/{ => firstlast}/last/DoubleLastAggregationTest.java (99%) rename processing/src/test/java/org/apache/druid/query/aggregation/{ => firstlast}/last/DoubleLastVectorAggregatorTest.java (87%) rename processing/src/test/java/org/apache/druid/query/aggregation/{ => firstlast}/last/FloatLastAggregationTest.java (99%) rename processing/src/test/java/org/apache/druid/query/aggregation/{ => firstlast}/last/FloatLastVectorAggregatorTest.java (92%) rename processing/src/test/java/org/apache/druid/query/aggregation/{ => firstlast}/last/LongLastAggregationTest.java (99%) rename processing/src/test/java/org/apache/druid/query/aggregation/{ => firstlast}/last/LongLastVectorAggregatorTest.java (80%) rename processing/src/test/java/org/apache/druid/query/aggregation/{ => firstlast}/last/StringLastAggregationTest.java (99%) rename processing/src/test/java/org/apache/druid/query/aggregation/{ => firstlast}/last/StringLastBufferAggregatorTest.java (99%) rename processing/src/test/java/org/apache/druid/query/aggregation/{ => firstlast}/last/StringLastTimeseriesQueryTest.java (99%) rename processing/src/test/java/org/apache/druid/query/aggregation/{ => firstlast}/last/StringLastVectorAggregatorTest.java (95%) diff --git a/indexing-service/src/test/java/org/apache/druid/indexing/common/task/CompactionTaskTest.java b/indexing-service/src/test/java/org/apache/druid/indexing/common/task/CompactionTaskTest.java index ee49a0dc0b6c..4ccd3f498118 100644 --- a/indexing-service/src/test/java/org/apache/druid/indexing/common/task/CompactionTaskTest.java +++ b/indexing-service/src/test/java/org/apache/druid/indexing/common/task/CompactionTaskTest.java @@ -95,8 +95,8 @@ import org.apache.druid.query.aggregation.FloatMinAggregatorFactory; import org.apache.druid.query.aggregation.LongMaxAggregatorFactory; import org.apache.druid.query.aggregation.LongSumAggregatorFactory; -import org.apache.druid.query.aggregation.first.FloatFirstAggregatorFactory; -import org.apache.druid.query.aggregation.last.DoubleLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.FloatFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.DoubleLastAggregatorFactory; import org.apache.druid.query.filter.SelectorDimFilter; import org.apache.druid.segment.DoubleDimensionHandler; import org.apache.druid.segment.IndexIO; diff --git a/processing/src/main/java/org/apache/druid/jackson/AggregatorsModule.java b/processing/src/main/java/org/apache/druid/jackson/AggregatorsModule.java index dddf39956edb..f7aca511e17d 100644 --- a/processing/src/main/java/org/apache/druid/jackson/AggregatorsModule.java +++ b/processing/src/main/java/org/apache/druid/jackson/AggregatorsModule.java @@ -49,20 +49,20 @@ import org.apache.druid.query.aggregation.any.LongAnyAggregatorFactory; import org.apache.druid.query.aggregation.any.StringAnyAggregatorFactory; import org.apache.druid.query.aggregation.cardinality.CardinalityAggregatorFactory; -import org.apache.druid.query.aggregation.first.DoubleFirstAggregatorFactory; -import org.apache.druid.query.aggregation.first.FloatFirstAggregatorFactory; -import org.apache.druid.query.aggregation.first.LongFirstAggregatorFactory; -import org.apache.druid.query.aggregation.first.StringFirstAggregatorFactory; -import org.apache.druid.query.aggregation.first.StringFirstFoldingAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.DoubleFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.FloatFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.LongFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.StringFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.StringFirstFoldingAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.DoubleLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.FloatLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.LongLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.StringLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.StringLastFoldingAggregatorFactory; import org.apache.druid.query.aggregation.hyperloglog.HyperUniqueFinalizingPostAggregator; import org.apache.druid.query.aggregation.hyperloglog.HyperUniquesAggregatorFactory; import org.apache.druid.query.aggregation.hyperloglog.HyperUniquesSerde; import org.apache.druid.query.aggregation.hyperloglog.PreComputedHyperUniquesSerde; -import org.apache.druid.query.aggregation.last.DoubleLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.FloatLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.LongLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.StringLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.StringLastFoldingAggregatorFactory; import org.apache.druid.query.aggregation.mean.DoubleMeanAggregatorFactory; import org.apache.druid.query.aggregation.mean.DoubleMeanHolder; import org.apache.druid.query.aggregation.post.ArithmeticPostAggregator; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/any/StringAnyAggregatorFactory.java b/processing/src/main/java/org/apache/druid/query/aggregation/any/StringAnyAggregatorFactory.java index f137af7e7fd3..418bb32f64eb 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/any/StringAnyAggregatorFactory.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/any/StringAnyAggregatorFactory.java @@ -27,7 +27,7 @@ import org.apache.druid.query.aggregation.AggregatorFactory; import org.apache.druid.query.aggregation.AggregatorUtil; import org.apache.druid.query.aggregation.BufferAggregator; -import org.apache.druid.query.aggregation.first.StringFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.StringFirstAggregatorFactory; import org.apache.druid.query.cache.CacheKeyBuilder; import org.apache.druid.query.dimension.DefaultDimensionSpec; import org.apache.druid.segment.ColumnInspector; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/FirstLastUtils.java b/processing/src/main/java/org/apache/druid/query/aggregation/first/FirstLastUtils.java deleted file mode 100644 index b9ef88dfdcf9..000000000000 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/FirstLastUtils.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.aggregation.first; - -import org.apache.druid.segment.BaseObjectColumnValueSelector; -import org.apache.druid.segment.NilColumnValueSelector; -import org.apache.druid.segment.column.ColumnCapabilities; -import org.apache.druid.segment.column.ValueType; - -import javax.annotation.Nullable; - -public class FirstLastUtils -{ - - /** - * Returns whether a given value selector *might* contain object assignable from pairClass (SerializablePairLong*). - */ - public static boolean selectorNeedsFoldCheck( - final BaseObjectColumnValueSelector valueSelector, - @Nullable final ColumnCapabilities valueSelectorCapabilities, - Class pairClass - ) - { - if (valueSelectorCapabilities != null && !valueSelectorCapabilities.is(ValueType.COMPLEX)) { - // Known, non-complex type. - return false; - } - - if (valueSelector instanceof NilColumnValueSelector) { - // Nil column, definitely no SerializablePairLongObject. - return false; - } - - // Check if the selector class could possibly be of pairClass* (either a superclass or subclass). - final Class clazz = valueSelector.classOfObject(); - return clazz.isAssignableFrom(pairClass) - || pairClass.isAssignableFrom(clazz); - } - - /** - * Returns whether an object *might* is assignable to/from the pairClass. - */ - public static boolean objectNeedsFoldCheck(Object obj, Class pairClass) - { - if (obj == null) { - return false; - } - final Class clazz = obj.getClass(); - return clazz.isAssignableFrom(pairClass) - || pairClass.isAssignableFrom(clazz); - } -} diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/NumericFirstVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/first/NumericFirstVectorAggregator.java deleted file mode 100644 index 6f6bfec014c1..000000000000 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/NumericFirstVectorAggregator.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * 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.aggregation.first; - -import org.apache.druid.collections.SerializablePair; -import org.apache.druid.common.config.NullHandling; -import org.apache.druid.query.aggregation.VectorAggregator; -import org.apache.druid.segment.vector.VectorObjectSelector; -import org.apache.druid.segment.vector.VectorValueSelector; - -import javax.annotation.Nullable; -import java.nio.ByteBuffer; - -/** - * Class for vectorized version of first/earliest aggregator over numeric types - */ -public abstract class NumericFirstVectorAggregator implements VectorAggregator -{ - static final int NULL_OFFSET = Long.BYTES; - static final int VALUE_OFFSET = NULL_OFFSET + Byte.BYTES; - final VectorObjectSelector objectSelector; - final VectorValueSelector valueSelector; - private final boolean useDefault = NullHandling.replaceWithDefault(); - private final VectorValueSelector timeSelector; - private long firstTime; - - NumericFirstVectorAggregator(VectorValueSelector timeSelector, VectorValueSelector valueSelector, VectorObjectSelector objectSelector) - { - this.timeSelector = timeSelector; - this.objectSelector = objectSelector; - this.valueSelector = valueSelector; - firstTime = Long.MAX_VALUE; - } - - @Override - public void init(ByteBuffer buf, int position) - { - buf.putLong(position, Long.MAX_VALUE); - buf.put(position + NULL_OFFSET, useDefault ? NullHandling.IS_NOT_NULL_BYTE : NullHandling.IS_NULL_BYTE); - initValue(buf, position + VALUE_OFFSET); - } - - @Override - public void aggregate(ByteBuffer buf, int position, int startRow, int endRow) - { - final long[] timeVector = timeSelector.getLongVector(); - final boolean[] nullTimeVector = timeSelector.getNullVector(); - - Object[] objectsWhichMightBeNumeric = null; - boolean[] nullValueVector = null; - - if (objectSelector != null) { - objectsWhichMightBeNumeric = objectSelector.getObjectVector(); - } else if (valueSelector != null) { - nullValueVector = valueSelector.getNullVector(); - } - - firstTime = buf.getLong(position); - - // the time vector is already sorted - // if earliest is on the default time dimension - // but if earliest uses earliest_by it might use a secondary timestamp - // which is not sorted. For correctness, we need to go over all elements. - // A possible optimization here is to have 2 paths one for earliest where - // we can take advantage of the sorted nature of time - // and the earliest_by where we have to go over all elements. - - int index; - for (int i = startRow; i < endRow; i++) { - if (nullTimeVector != null && nullTimeVector[i]) { - continue; - } - - if (timeVector[i] >= firstTime) { - continue; - } - index = i; - - if (objectsWhichMightBeNumeric != null) { - final SerializablePair inPair = (SerializablePair) objectsWhichMightBeNumeric[index]; - if (inPair != null && inPair.lhs != null && inPair.lhs < firstTime) { - firstTime = inPair.lhs; - if (useDefault || inPair.rhs != null) { - updateTimeWithValue(buf, position, firstTime, index); - } else { - updateTimeWithNull(buf, position, firstTime); - } - } - } else { - final long earliestTime = timeVector[index]; - - if (earliestTime < firstTime) { - firstTime = earliestTime; - if (useDefault || nullValueVector == null || !nullValueVector[index]) { - updateTimeWithValue(buf, position, earliestTime, index); - } else { - updateTimeWithNull(buf, position, earliestTime); - } - } - } - } - } - - /** - * - * Checks if the aggregated value at a position in the buffer is null or not - * - * @param buf byte buffer storing the byte array representation of the aggregate - * @param position offset within the byte buffer at which the current aggregate value is stored - * @return - */ - boolean isValueNull(ByteBuffer buf, int position) - { - return buf.get(position + NULL_OFFSET) == NullHandling.IS_NULL_BYTE; - } - - @Override - public void aggregate( - ByteBuffer buf, - int numRows, - int[] positions, - @Nullable int[] rows, - int positionOffset - ) - { - final long[] timeVector = timeSelector.getLongVector(); - - Object[] objectsWhichMightBeNumeric = null; - boolean[] nulls = null; - if (objectSelector != null) { - objectsWhichMightBeNumeric = objectSelector.getObjectVector(); - } else if (valueSelector != null) { - nulls = useDefault ? null : valueSelector.getNullVector(); - } - - for (int i = 0; i < numRows; i++) { - int position = positions[i] + positionOffset; - int row = rows == null ? i : rows[i]; - firstTime = buf.getLong(position); - - if (objectsWhichMightBeNumeric != null) { - final SerializablePair inPair = (SerializablePair) objectsWhichMightBeNumeric[row]; - if (useDefault || inPair != null) { - if (inPair.lhs != null && inPair.lhs < firstTime) { - if (inPair.rhs != null) { - updateTimeWithValue(buf, position, inPair.lhs, row); - } else { - updateTimeWithNull(buf, position, inPair.lhs); - } - } - } - } else { - if (timeVector[row] < firstTime) { - if (useDefault || nulls == null || !nulls[row]) { - updateTimeWithValue(buf, position, timeVector[row], row); - } else { - updateTimeWithNull(buf, position, timeVector[row]); - } - } - } - } - } - - /** - * Updates the time and the non null values to the appropriate position in buffer - * - * @param buf byte buffer storing the byte array representation of the aggregate - * @param position offset within the byte buffer at which the current aggregate value is stored - * @param time the time to be updated in the buffer as the first time - * @param index he index of the vectorized vector which is the first value - */ - void updateTimeWithValue(ByteBuffer buf, int position, long time, int index) - { - buf.putLong(position, time); - buf.put(position + NULL_OFFSET, NullHandling.IS_NOT_NULL_BYTE); - putValue(buf, position + VALUE_OFFSET, index); - } - - /** - * Updates the time only to the appropriate position in buffer as the value is null - * - * @param buf byte buffer storing the byte array representation of the aggregate - * @param position offset within the byte buffer at which the current aggregate value is stored - * @param time the time to be updated in the buffer as the last time - */ - void updateTimeWithNull(ByteBuffer buf, int position, long time) - { - buf.putLong(position, time); - buf.put(position + NULL_OFFSET, NullHandling.IS_NULL_BYTE); - } - - /** - *Abstract function which needs to be overridden by subclasses to set the initial value - */ - abstract void initValue(ByteBuffer buf, int position); - - /** - * Abstract function which needs to be overridden by subclasses to set the - * latest value in the buffer depending on the datatype - */ - abstract void putValue(ByteBuffer buf, int position, int index); - - @Override - public void close() - { - // no resources to cleanup - } -} diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/SingleStringFirstDimensionVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/first/SingleStringFirstDimensionVectorAggregator.java deleted file mode 100644 index 119e13464a09..000000000000 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/SingleStringFirstDimensionVectorAggregator.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * 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.aggregation.first; - -import org.apache.druid.common.config.NullHandling; -import org.apache.druid.java.util.common.StringUtils; -import org.apache.druid.query.aggregation.SerializablePairLongString; -import org.apache.druid.query.aggregation.VectorAggregator; -import org.apache.druid.segment.vector.SingleValueDimensionVectorSelector; -import org.apache.druid.segment.vector.VectorValueSelector; - -import javax.annotation.Nullable; -import java.nio.ByteBuffer; - -public class SingleStringFirstDimensionVectorAggregator implements VectorAggregator -{ - private final VectorValueSelector timeSelector; - private final SingleValueDimensionVectorSelector valueDimensionVectorSelector; - private long firstTime; - private final int maxStringBytes; - private final boolean useDefault = NullHandling.replaceWithDefault(); - - public SingleStringFirstDimensionVectorAggregator( - VectorValueSelector timeSelector, - SingleValueDimensionVectorSelector valueDimensionVectorSelector, - int maxStringBytes - ) - { - this.timeSelector = timeSelector; - this.valueDimensionVectorSelector = valueDimensionVectorSelector; - this.maxStringBytes = maxStringBytes; - this.firstTime = Long.MAX_VALUE; - } - - @Override - public void init(ByteBuffer buf, int position) - { - buf.putLong(position, Long.MAX_VALUE); - buf.put( - position + NumericFirstVectorAggregator.NULL_OFFSET, - useDefault ? NullHandling.IS_NOT_NULL_BYTE : NullHandling.IS_NULL_BYTE - ); - buf.putInt(position + NumericFirstVectorAggregator.VALUE_OFFSET, 0); - } - - @Override - public void aggregate(ByteBuffer buf, int position, int startRow, int endRow) - { - final long[] timeVector = timeSelector.getLongVector(); - final boolean[] nullTimeVector = timeSelector.getNullVector(); - final int[] valueVector = valueDimensionVectorSelector.getRowVector(); - firstTime = buf.getLong(position); - int index; - - long earliestTime; - for (index = startRow; index < endRow; index++) { - if (nullTimeVector != null && nullTimeVector[index]) { - continue; - } - earliestTime = timeVector[index]; - if (earliestTime < firstTime) { - firstTime = earliestTime; - buf.putLong(position, firstTime); - buf.put(position + NumericFirstVectorAggregator.NULL_OFFSET, NullHandling.IS_NOT_NULL_BYTE); - buf.putInt(position + NumericFirstVectorAggregator.VALUE_OFFSET, valueVector[index]); - } - } - } - - @Override - public void aggregate(ByteBuffer buf, int numRows, int[] positions, @Nullable int[] rows, int positionOffset) - { - final long[] timeVector = timeSelector.getLongVector(); - final boolean[] nullTimeVector = timeSelector.getNullVector(); - final int[] values = valueDimensionVectorSelector.getRowVector(); - for (int i = 0; i < numRows; i++) { - if (nullTimeVector != null && nullTimeVector[i]) { - continue; - } - int position = positions[i] + positionOffset; - int row = rows == null ? i : rows[i]; - long firstTime = buf.getLong(position); - if (timeVector[row] < firstTime) { - firstTime = timeVector[row]; - buf.putLong(position, firstTime); - buf.put(position + NumericFirstVectorAggregator.NULL_OFFSET, NullHandling.IS_NOT_NULL_BYTE); - buf.putInt(position + NumericFirstVectorAggregator.VALUE_OFFSET, values[row]); - } - } - - } - - @Nullable - @Override - public Object get(ByteBuffer buf, int position) - { - int index = buf.getInt(position + NumericFirstVectorAggregator.VALUE_OFFSET); - long earliest = buf.getLong(position); - String strValue = valueDimensionVectorSelector.lookupName(index); - return new SerializablePairLongString(earliest, StringUtils.chop(strValue, maxStringBytes)); - } - - @Override - public void close() - { - // nothing to close - } -} diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/StringFirstVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/first/StringFirstVectorAggregator.java deleted file mode 100644 index fd2260b8d665..000000000000 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/StringFirstVectorAggregator.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * 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.aggregation.first; - -import org.apache.druid.java.util.common.DateTimes; -import org.apache.druid.query.aggregation.SerializablePairLongString; -import org.apache.druid.query.aggregation.VectorAggregator; -import org.apache.druid.segment.DimensionHandlerUtils; -import org.apache.druid.segment.vector.VectorObjectSelector; -import org.apache.druid.segment.vector.VectorValueSelector; - -import javax.annotation.Nullable; -import java.nio.ByteBuffer; - -public class StringFirstVectorAggregator implements VectorAggregator -{ - private static final SerializablePairLongString INIT = new SerializablePairLongString( - DateTimes.MAX.getMillis(), - null - ); - private final VectorValueSelector timeSelector; - private final VectorObjectSelector valueSelector; - private final int maxStringBytes; - - - public StringFirstVectorAggregator( - VectorValueSelector timeSelector, - VectorObjectSelector valueSelector, - int maxStringBytes - ) - { - this.timeSelector = timeSelector; - this.valueSelector = valueSelector; - this.maxStringBytes = maxStringBytes; - } - - @Override - public void init(ByteBuffer buf, int position) - { - StringFirstLastUtils.writePair(buf, position, INIT, maxStringBytes); - } - - @Override - public void aggregate(ByteBuffer buf, int position, int startRow, int endRow) - { - if (timeSelector == null) { - return; - } - final long[] times = timeSelector.getLongVector(); - final boolean[] nullTimeVector = timeSelector.getNullVector(); - final Object[] objectsWhichMightBeStrings = valueSelector.getObjectVector(); - long firstTime = buf.getLong(position); - int index; - for (int i = startRow; i < endRow; i++) { - if (times[i] > firstTime) { - continue; - } - if (nullTimeVector != null && nullTimeVector[i]) { - continue; - } - index = i; - final boolean foldNeeded = FirstLastUtils.objectNeedsFoldCheck(objectsWhichMightBeStrings[index], SerializablePairLongString.class); - if (foldNeeded) { - final SerializablePairLongString inPair = StringFirstLastUtils.readPairFromVectorSelectorsAtIndex( - timeSelector, - valueSelector, - index - ); - if (inPair != null) { - firstTime = buf.getLong(position); - if (inPair.lhs < firstTime) { - StringFirstLastUtils.writePair( - buf, - position, - new SerializablePairLongString(inPair.lhs, inPair.rhs), - maxStringBytes - ); - } - } - } else { - final long time = times[index]; - if (time < firstTime) { - final String value = DimensionHandlerUtils.convertObjectToString(objectsWhichMightBeStrings[index]); - firstTime = time; - StringFirstLastUtils.writePair( - buf, - position, - new SerializablePairLongString(time, value), - maxStringBytes - ); - } - } - } - - } - - @Override - public void aggregate(ByteBuffer buf, int numRows, int[] positions, @Nullable int[] rows, int positionOffset) - { - final long[] timeVector = timeSelector.getLongVector(); - final boolean[] nullTimeVector = timeSelector.getNullVector(); - final Object[] objectsWhichMightBeStrings = valueSelector.getObjectVector(); - - // iterate once over the object vector to find first non null element and - // determine if the type is Pair or not - boolean foldNeeded = false; - for (Object obj : objectsWhichMightBeStrings) { - if (obj == null) { - continue; - } else { - foldNeeded = FirstLastUtils.objectNeedsFoldCheck(obj, SerializablePairLongString.class); - break; - } - } - - for (int i = 0; i < numRows; i++) { - if (nullTimeVector != null && nullTimeVector[i]) { - continue; - } - int position = positions[i] + positionOffset; - int row = rows == null ? i : rows[i]; - long firstTime = buf.getLong(position); - if (timeVector[row] < firstTime) { - if (foldNeeded) { - final SerializablePairLongString inPair = StringFirstLastUtils.readPairFromVectorSelectorsAtIndex( - timeSelector, - valueSelector, - row - ); - if (inPair != null) { - if (inPair.lhs < firstTime) { - StringFirstLastUtils.writePair( - buf, - position, - new SerializablePairLongString(inPair.lhs, inPair.rhs), - maxStringBytes - ); - } - } - } else { - final String value = DimensionHandlerUtils.convertObjectToString(objectsWhichMightBeStrings[row]); - firstTime = timeVector[row]; - StringFirstLastUtils.writePair( - buf, - position, - new SerializablePairLongString(firstTime, value), - maxStringBytes - ); - } - } - } - - } - - @Nullable - @Override - public Object get(ByteBuffer buf, int position) - { - return StringFirstLastUtils.readPair(buf, position); - } - - @Override - public void close() - { - // nothing to close - } -} diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/DoubleFirstLastVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/DoubleFirstLastVectorAggregator.java new file mode 100644 index 000000000000..728018691550 --- /dev/null +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/DoubleFirstLastVectorAggregator.java @@ -0,0 +1,123 @@ +/* + * 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.aggregation.firstlast; + +import org.apache.druid.common.config.NullHandling; +import org.apache.druid.query.aggregation.SerializablePairLongDouble; +import org.apache.druid.segment.vector.VectorObjectSelector; +import org.apache.druid.segment.vector.VectorValueSelector; + +import javax.annotation.Nullable; +import java.nio.ByteBuffer; + +/** + * Vectorized version of on heap aggregator for column selectors with type DOUBLE. + */ +public class DoubleFirstLastVectorAggregator extends FirstLastVectorAggregator +{ + private final SelectionPredicate selectionPredicate; + + protected DoubleFirstLastVectorAggregator( + VectorValueSelector timeSelector, + VectorObjectSelector objectSelector, + SelectionPredicate selectionPredicate + ) + { + super(timeSelector, null, objectSelector, selectionPredicate); + this.selectionPredicate = selectionPredicate; + } + + protected DoubleFirstLastVectorAggregator( + VectorValueSelector timeSelector, + VectorValueSelector valueSelector, + SelectionPredicate selectionPredicate + ) + { + super(timeSelector, valueSelector, null, selectionPredicate); + this.selectionPredicate = selectionPredicate; + } + + @Override + public void init(ByteBuffer buf, int position) + { + buf.putLong(position, selectionPredicate.initValue()); + buf.put( + position + NULLITY_OFFSET, + NullHandling.replaceWithDefault() ? NullHandling.IS_NOT_NULL_BYTE : NullHandling.IS_NULL_BYTE + ); + buf.putDouble(position + VALUE_OFFSET, 0.0D); + } + + @Nullable + @Override + public Object get(ByteBuffer buf, int position) + { + long time = buf.getLong(position); + if (buf.get(position + NULLITY_OFFSET) == NullHandling.IS_NULL_BYTE) { + return new SerializablePairLongDouble(time, null); + } + return new SerializablePairLongDouble(time, buf.getDouble(position + VALUE_OFFSET)); + } + + @Override + protected void putValue(ByteBuffer buf, int position, long time, Double value) + { + buf.putLong(position, time); + buf.put(position + NULLITY_OFFSET, NullHandling.IS_NOT_NULL_BYTE); + buf.putDouble(position + VALUE_OFFSET, value); + } + + @Override + protected void putValue(ByteBuffer buf, int position, long time, VectorValueSelector valueSelector, int index) + { + buf.putLong(position, time); + buf.put(position + NULLITY_OFFSET, NullHandling.IS_NOT_NULL_BYTE); + buf.putDouble(position + VALUE_OFFSET, valueSelector.getDoubleVector()[index]); + } + + @Override + protected void putNull(ByteBuffer buf, int position, long time) + { + buf.putLong(position, time); + buf.put(position + NULLITY_OFFSET, NullHandling.IS_NULL_BYTE); + buf.putDouble(position + VALUE_OFFSET, 0.0D); + + } + + @Override + protected void putDefaultValue(ByteBuffer buf, int position, long time) + { + buf.putLong(position, time); + buf.put(position + NULLITY_OFFSET, NullHandling.IS_NOT_NULL_BYTE); + buf.putDouble(position, 0.0D); + } + + @Override + protected SerializablePairLongDouble readPairFromVectorSelectors( + boolean[] timeNullityVector, + long[] timeVector, + Object[] maybeFoldedObjects, + int index + ) + { + return FirstLastUtils.readDoublePairFromVectorSelectors(timeNullityVector, timeVector, maybeFoldedObjects, index); + } +} + diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/FirstLastUtils.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/FirstLastUtils.java new file mode 100644 index 000000000000..1dce1472126d --- /dev/null +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/FirstLastUtils.java @@ -0,0 +1,155 @@ +/* + * 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.aggregation.firstlast; + +import org.apache.druid.query.aggregation.SerializablePairLongDouble; +import org.apache.druid.query.aggregation.SerializablePairLongFloat; +import org.apache.druid.query.aggregation.SerializablePairLongLong; +import org.apache.druid.segment.BaseObjectColumnValueSelector; +import org.apache.druid.segment.DimensionHandlerUtils; +import org.apache.druid.segment.NilColumnValueSelector; +import org.apache.druid.segment.column.ColumnCapabilities; +import org.apache.druid.segment.column.ValueType; + +import javax.annotation.Nullable; + +public class FirstLastUtils +{ + + /** + * Returns whether a given value selector *might* contain object assignable from pairClass (SerializablePairLong*). + */ + public static boolean selectorNeedsFoldCheck( + final BaseObjectColumnValueSelector valueSelector, + @Nullable final ColumnCapabilities valueSelectorCapabilities, + Class pairClass + ) + { + if (valueSelectorCapabilities != null && !valueSelectorCapabilities.is(ValueType.COMPLEX)) { + // Known, non-complex type. + return false; + } + + if (valueSelector instanceof NilColumnValueSelector) { + // Nil column, definitely no SerializablePairLongObject. + return false; + } + + // Check if the selector class could possibly be of pairClass* (either a superclass or subclass). + final Class clazz = valueSelector.classOfObject(); + return clazz.isAssignableFrom(pairClass) + || pairClass.isAssignableFrom(clazz); + } + + @Nullable + public static SerializablePairLongDouble readDoublePairFromVectorSelectors( + @Nullable boolean[] timeNullityVector, + long[] timeVector, + Object[] objectVector, + int index + ) + { + final long time; + final Double value; + + final Object object = objectVector[index]; + + if (object instanceof SerializablePairLongDouble) { + // We got a folded object, ignore timeSelector completely, the object has all the info it requires + final SerializablePairLongDouble pair = (SerializablePairLongDouble) object; + // if time == null, don't aggregate + if (pair.lhs == null) { + return null; + } + return pair; + } else { + if (timeNullityVector != null && timeNullityVector[index]) { + // Donot aggregate pairs where time is unknown + return null; + } + time = timeVector[index]; + value = DimensionHandlerUtils.convertObjectToDouble(object); + } + return new SerializablePairLongDouble(time, value); + } + + @Nullable + public static SerializablePairLongFloat readFloatPairFromVectorSelectors( + @Nullable boolean[] timeNullityVector, + long[] timeVector, + Object[] objectVector, + int index + ) + { + final long time; + final Float value; + + final Object object = objectVector[index]; + + if (object instanceof SerializablePairLongFloat) { + // We got a folded object, ignore timeSelector completely, the object has all the info it requires + final SerializablePairLongFloat pair = (SerializablePairLongFloat) object; + // if time == null, don't aggregate + if (pair.lhs == null) { + return null; + } + return pair; + } else { + if (timeNullityVector != null && timeNullityVector[index]) { + // Donot aggregate pairs where time is unknown + return null; + } + time = timeVector[index]; + value = DimensionHandlerUtils.convertObjectToFloat(object); + } + return new SerializablePairLongFloat(time, value); + } + @Nullable + public static SerializablePairLongLong readLongPairFromVectorSelectors( + @Nullable boolean[] timeNullityVector, + long[] timeVector, + Object[] objectVector, + int index + ) + { + final long time; + final Long value; + + final Object object = objectVector[index]; + + if (object instanceof SerializablePairLongLong) { + // We got a folded object, ignore timeSelector completely, the object has all the info it requires + final SerializablePairLongLong pair = (SerializablePairLongLong) object; + // if time == null, don't aggregate + if (pair.lhs == null) { + return null; + } + return pair; + } else { + if (timeNullityVector != null && timeNullityVector[index]) { + // Donot aggregate pairs where time is unknown + return null; + } + time = timeVector[index]; + value = DimensionHandlerUtils.convertObjectToLong(object); + } + return new SerializablePairLongLong(time, value); + } +} diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/FirstLastVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/FirstLastVectorAggregator.java new file mode 100644 index 000000000000..129465a6d591 --- /dev/null +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/FirstLastVectorAggregator.java @@ -0,0 +1,266 @@ +/* + * 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.aggregation.firstlast; + +import com.google.common.base.Preconditions; +import org.apache.druid.collections.SerializablePair; +import org.apache.druid.common.config.NullHandling; +import org.apache.druid.query.aggregation.VectorAggregator; +import org.apache.druid.segment.vector.VectorObjectSelector; +import org.apache.druid.segment.vector.VectorValueSelector; + +import javax.annotation.Nullable; +import java.nio.ByteBuffer; + +/** + * Base type for vectorized version of on heap 'last' aggregator for primitive numeric column selectors.. + */ +public abstract class FirstLastVectorAggregator> + implements VectorAggregator +{ + public static final int NULLITY_OFFSET = Long.BYTES; + public static final int VALUE_OFFSET = NULLITY_OFFSET + Byte.BYTES; + + @Nullable + private final VectorValueSelector timeSelector; + @Nullable + private final VectorValueSelector valueSelector; + @Nullable + private final VectorObjectSelector objectSelector; + private final SelectionPredicate selectionPredicate; + private final boolean useDefault = NullHandling.replaceWithDefault(); + + + /** + * timeSelector can be null, however aggregate functions are no-op then. + */ + public FirstLastVectorAggregator( + @Nullable VectorValueSelector timeSelector, + @Nullable VectorValueSelector valueSelector, + @Nullable VectorObjectSelector objectSelector, + SelectionPredicate selectionPredicate + ) + { + if (timeSelector != null) { + Preconditions.checkArgument( + (valueSelector != null && objectSelector == null) || (valueSelector == null && objectSelector != null), + "exactly one of 'valueSelector' and 'objectSelector' must be provided" + ); + } + this.timeSelector = timeSelector; + this.valueSelector = valueSelector; + this.objectSelector = objectSelector; + this.selectionPredicate = selectionPredicate; + } + + @Override + public void aggregate(ByteBuffer buf, int position, int startRow, int endRow) + { + // Not a normal case, and this doesn't affect the folding. timeSelectors should be present (albeit irrelevent) when folding. + // timeSelector == null means that the aggregating column's capabilities aren't known, and it only happens for a special case + // while building string aggregator + if (timeSelector == null) { + return; + } + + // If objectSelector isn't null, then the objects might be folded up. If that's the case, whatever's represented by + // the timeSelector doesn't hold any relevance. + if (objectSelector != null) { + final Object[] maybeFoldedObjects = objectSelector.getObjectVector(); + final boolean[] timeNullityVector = timeSelector.getNullVector(); + final long[] timeVector = timeSelector.getLongVector(); + + PairType selectedPair = null; + + for (int index = startRow; index < endRow; ++index) { + + PairType pair = readPairFromVectorSelectors(timeNullityVector, timeVector, maybeFoldedObjects, index); + if (pair != null) { + if (selectedPair == null) { + selectedPair = pair; + } else if (selectionPredicate.apply(pair.lhs, selectedPair.lhs)) { + selectedPair = pair; + } + } + } + // Something's been selected of the row vector + if (selectedPair != null) { + // Compare the latest value of the folded up row vector to the latest value in the buffer + if (selectionPredicate.apply(selectedPair.lhs, buf.getLong(position))) { + if (selectedPair.rhs != null) { + putValue(buf, position, selectedPair.lhs, selectedPair.rhs); + } else if (useDefault) { + putDefaultValue(buf, position, selectedPair.lhs); + } else { + putNull(buf, position, selectedPair.lhs); + } + } + } + + } else { + // No object selector, no folding present. Check the timeSelector before checking the valueSelector + final boolean[] timeNullityVector = timeSelector.getNullVector(); + final long[] timeVector = timeSelector.getLongVector(); + final boolean[] valueNullityVector = valueSelector.getNullVector(); + Integer selectedIndex = null; + + for (int index = startRow; index < endRow; ++index) { + if (timeNullityVector != null && timeNullityVector[index]) { + // Don't aggregate values where time isn't present + continue; + } + // Find the latest time inside the vector objects + if (selectedIndex == null) { + selectedIndex = index; + } else { + if (selectionPredicate.apply(timeVector[index], timeVector[selectedIndex])) { + selectedIndex = index; + } + } + } + // Compare the selectedIndex's value to the value on the buffer. This way, we write to the buffer only once + // Weeds out empty vectors, where endRow == startRow + if (selectedIndex != null) { + if (selectionPredicate.apply(timeVector[selectedIndex], buf.getLong(position))) { + // Write the value here + if (valueNullityVector == null || !valueNullityVector[selectedIndex]) { + putValue(buf, position, timeVector[selectedIndex], valueSelector, selectedIndex); + } else if (useDefault) { + putDefaultValue(buf, position, timeVector[selectedIndex]); + } else { + putNull(buf, position, timeVector[selectedIndex]); + } + } + } + } + } + + @Override + public void aggregate( + ByteBuffer buf, + int numRows, + int[] positions, + @Nullable int[] rows, + int positionOffset + ) + { + // Not a normal case, and this doesn't affect the folding. timeSelectors should be present (albeit irrelevent) when folding. + // timeSelector == null means that the aggregating column's capabilities aren't known, and it only happens for a special case + // while building string aggregator + if (timeSelector == null) { + return; + } + + // If objectSelector isn't null, then the objects might be folded up. If that's the case, whatever's represented by + // the timeSelector doesn't hold any relevance. We should check for folded objects BEFORE even thinking about looking + // at the timeSelector + if (objectSelector != null) { + final Object[] maybeFoldedObjects = objectSelector.getObjectVector(); + final boolean[] timeNullityVector = timeSelector.getNullVector(); + final long[] timeVector = timeSelector.getLongVector(); + for (int i = 0; i < numRows; ++i) { + int position = positions[i] + positionOffset; + int row = rows == null ? i : rows[i]; + // All the information about the object would be in the single selector. This method will check the folding of the object selector, + // casting, and everything........ + PairType pair = readPairFromVectorSelectors(timeNullityVector, timeVector, maybeFoldedObjects, row); + if (pair != null) { + long lastTime = buf.getLong(position); + if (selectionPredicate.apply(pair.lhs, lastTime)) { + if (pair.rhs != null) { + putValue(buf, position, pair.lhs, pair.rhs); + } else if (useDefault) { + putDefaultValue(buf, position, pair.lhs); + } else { + putNull(buf, position, pair.lhs); + } + } + } + } + } else { + // No object selector, no folding present. Check the timeSelector before checking the valueSelector + final boolean[] timeNullityVector = timeSelector.getNullVector(); + final long[] timeVector = timeSelector.getLongVector(); + final boolean[] valueNullityVector = valueSelector.getNullVector(); + + for (int i = 0; i < numRows; ++i) { + int position = positions[i] + positionOffset; + int row = rows == null ? i : rows[i]; + long lastTime = buf.getLong(position); + if (timeNullityVector != null && timeNullityVector[row]) { + // Don't aggregate values where time isn't present + continue; + } + if (selectionPredicate.apply(timeVector[row], lastTime)) { + if (valueNullityVector == null || !valueNullityVector[row]) { + putValue(buf, position, timeVector[row], valueSelector, row); + } else if (useDefault) { + putDefaultValue(buf, position, timeVector[row]); + } else { + putNull(buf, position, timeVector[row]); + } + } + } + } + } + + /** + * Sets the value at the position. Subclasses can assume that the value isn't null + * + * 'position' refers to the location where the value of the pair will get updated (as opposed to the beginning of + * the serialized pair) + * + * It is only used if objectSelector is supplied + */ + protected abstract void putValue(ByteBuffer buf, int position, long time, RhsType value); + + /** + * Sets the value represented by the valueSelector at the given index. A slightly redundant method to {@link #putValue(ByteBuffer, int, long, Object)} + * to avoid autoboxing for the numeric types. Subclasses can assume that valueSelector.getNullVector[index] is false (i.e. + * the value represented at the index isn't null) + * + * It is used if valueSelector is supplied + */ + protected abstract void putValue(ByteBuffer buf, int position, long time, VectorValueSelector valueSelector, int index); + + /** + * Sets the default value for the type in the byte buffer at the given position. It is only used when replaceNullWithDefault = true, + * therefore the callers don't need to handle any other case. + * + * 'position' refers to the location where the value of the pair will get updated (as opposed to the beginning of + * the serialized pair) + */ + protected abstract void putDefaultValue(ByteBuffer buf, int position, long time); + + protected abstract void putNull(ByteBuffer buf, int position, long time); + + protected abstract PairType readPairFromVectorSelectors( + boolean[] timeNullityVector, + long[] timeVector, + Object[] maybeFoldedObjects, + int index + ); + + @Override + public void close() + { + // no resources to cleanup + } +} diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/FloatFirstLastVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/FloatFirstLastVectorAggregator.java new file mode 100644 index 000000000000..2edebc307823 --- /dev/null +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/FloatFirstLastVectorAggregator.java @@ -0,0 +1,122 @@ +/* + * 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.aggregation.firstlast; + +import org.apache.druid.common.config.NullHandling; +import org.apache.druid.query.aggregation.SerializablePairLongFloat; +import org.apache.druid.segment.vector.VectorObjectSelector; +import org.apache.druid.segment.vector.VectorValueSelector; + +import javax.annotation.Nullable; +import java.nio.ByteBuffer; + +/** + * Vectorized version of on heap 'last' aggregator for column selectors with type FLOAT. + */ +public class FloatFirstLastVectorAggregator extends FirstLastVectorAggregator +{ + private final SelectionPredicate selectionPredicate; + + protected FloatFirstLastVectorAggregator( + VectorValueSelector timeSelector, + VectorObjectSelector objectSelector, + SelectionPredicate selectionPredicate + ) + { + super(timeSelector, null, objectSelector, selectionPredicate); + this.selectionPredicate = selectionPredicate; + } + + protected FloatFirstLastVectorAggregator( + VectorValueSelector timeSelector, + VectorValueSelector valueSelector, + SelectionPredicate selectionPredicate + ) + { + super(timeSelector, valueSelector, null, selectionPredicate); + this.selectionPredicate = selectionPredicate; + } + + @Override + public void init(ByteBuffer buf, int position) + { + buf.putLong(position, selectionPredicate.initValue()); + buf.put( + position + NULLITY_OFFSET, + NullHandling.replaceWithDefault() ? NullHandling.IS_NOT_NULL_BYTE : NullHandling.IS_NULL_BYTE + ); + buf.putFloat(position + VALUE_OFFSET, 0.0F); + } + + @Nullable + @Override + public Object get(ByteBuffer buf, int position) + { + long time = buf.getLong(position); + if (buf.get(position + NULLITY_OFFSET) == NullHandling.IS_NULL_BYTE) { + return new SerializablePairLongFloat(time, null); + } + return new SerializablePairLongFloat(time, buf.getFloat(position + VALUE_OFFSET)); + } + + @Override + protected void putValue(ByteBuffer buf, int position, long time, Float value) + { + buf.putLong(position, time); + buf.put(position + NULLITY_OFFSET, NullHandling.IS_NOT_NULL_BYTE); + buf.putFloat(position + VALUE_OFFSET, value); + } + + @Override + protected void putValue(ByteBuffer buf, int position, long time, VectorValueSelector valueSelector, int index) + { + buf.putLong(position, time); + buf.put(position + NULLITY_OFFSET, NullHandling.IS_NOT_NULL_BYTE); + buf.putFloat(position + VALUE_OFFSET, valueSelector.getFloatVector()[index]); + } + + @Override + protected void putNull(ByteBuffer buf, int position, long time) + { + buf.putLong(position, time); + buf.put(position + NULLITY_OFFSET, NullHandling.IS_NULL_BYTE); + buf.putFloat(position + VALUE_OFFSET, 0.0F); + } + + @Override + protected void putDefaultValue(ByteBuffer buf, int position, long time) + { + buf.putLong(position, time); + buf.put(position + NULLITY_OFFSET, NullHandling.IS_NOT_NULL_BYTE); + buf.putFloat(position + VALUE_OFFSET, 0.0F); + } + + @Override + protected SerializablePairLongFloat readPairFromVectorSelectors( + boolean[] timeNullityVector, + long[] timeVector, + Object[] maybeFoldedObjects, + int index + ) + { + return FirstLastUtils.readFloatPairFromVectorSelectors(timeNullityVector, timeVector, maybeFoldedObjects, index); + } +} + diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/LongFirstLastVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/LongFirstLastVectorAggregator.java new file mode 100644 index 000000000000..9b77426dfee3 --- /dev/null +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/LongFirstLastVectorAggregator.java @@ -0,0 +1,121 @@ +/* + * 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.aggregation.firstlast; + +import org.apache.druid.common.config.NullHandling; +import org.apache.druid.query.aggregation.SerializablePairLongLong; +import org.apache.druid.segment.vector.VectorObjectSelector; +import org.apache.druid.segment.vector.VectorValueSelector; + +import javax.annotation.Nullable; +import java.nio.ByteBuffer; + +/** + * Vectorized version of on heap 'last' aggregator for column selectors with type LONG.. + */ +public class LongFirstLastVectorAggregator extends FirstLastVectorAggregator +{ + private final SelectionPredicate selectionPredicate; + + protected LongFirstLastVectorAggregator( + VectorValueSelector timeSelector, + VectorObjectSelector objectSelector, + SelectionPredicate selectionPredicate + ) + { + super(timeSelector, null, objectSelector, selectionPredicate); + this.selectionPredicate = selectionPredicate; + } + + protected LongFirstLastVectorAggregator( + VectorValueSelector timeSelector, + VectorValueSelector valueSelector, + SelectionPredicate selectionPredicate + ) + { + super(timeSelector, valueSelector, null, selectionPredicate); + this.selectionPredicate = selectionPredicate; + } + + @Override + public void init(ByteBuffer buf, int position) + { + buf.putLong(position, selectionPredicate.initValue()); + buf.put( + position + NULLITY_OFFSET, + NullHandling.replaceWithDefault() ? NullHandling.IS_NOT_NULL_BYTE : NullHandling.IS_NULL_BYTE + ); + buf.putLong(position + VALUE_OFFSET, 0L); + } + + @Nullable + @Override + public Object get(ByteBuffer buf, int position) + { + long time = buf.getLong(position); + if (buf.get(position + NULLITY_OFFSET) == NullHandling.IS_NULL_BYTE) { + return new SerializablePairLongLong(time, null); + } + return new SerializablePairLongLong(time, buf.getLong(position + VALUE_OFFSET)); + } + + @Override + protected void putValue(ByteBuffer buf, int position, long time, Long value) + { + buf.putLong(position, time); + buf.put(position + NULLITY_OFFSET, NullHandling.IS_NOT_NULL_BYTE); + buf.putLong(position + VALUE_OFFSET, value); + } + + @Override + protected void putValue(ByteBuffer buf, int position, long time, VectorValueSelector valueSelector, int index) + { + buf.putLong(position, time); + buf.put(position + NULLITY_OFFSET, NullHandling.IS_NOT_NULL_BYTE); + buf.putLong(position + VALUE_OFFSET, valueSelector.getLongVector()[index]); + } + + @Override + protected void putNull(ByteBuffer buf, int position, long time) + { + buf.putLong(position, time); + buf.put(position + NULLITY_OFFSET, NullHandling.IS_NULL_BYTE); + buf.putLong(position + VALUE_OFFSET, 0L); + } + + @Override + protected void putDefaultValue(ByteBuffer buf, int position, long time) + { + buf.putLong(position, time); + buf.put(position + NULLITY_OFFSET, NullHandling.IS_NOT_NULL_BYTE); + buf.putLong(position + VALUE_OFFSET, 0L); + } + + @Override + protected SerializablePairLongLong readPairFromVectorSelectors( + boolean[] timeNullityVector, + long[] timeVector, + Object[] maybeFoldedObjects, + int index + ) + { + return FirstLastUtils.readLongPairFromVectorSelectors(timeNullityVector, timeVector, maybeFoldedObjects, index); + } +} diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/SelectionPredicate.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/SelectionPredicate.java new file mode 100644 index 000000000000..fd1ca915b473 --- /dev/null +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/SelectionPredicate.java @@ -0,0 +1,70 @@ +/* + * 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.aggregation.firstlast; + +import org.apache.druid.java.util.common.DateTimes; + +/** + * Differentiating factor between the first and the last aggregator. Specifies the + */ +public interface SelectionPredicate +{ + /** + * @return Time value to initialize the aggregation with + */ + long initValue(); + + /** + * @param currentTime Time of the current row + * @param selectedTime Aggregated time value + * @return true if the current row should be selected over the aggregated value, else false + */ + boolean apply(long currentTime, long selectedTime); + + SelectionPredicate FIRST_PREDICATE = new SelectionPredicate() + { + @Override + public long initValue() + { + return DateTimes.MAX.getMillis(); + } + + @Override + public boolean apply(long currentTime, long selectedTime) + { + return currentTime < selectedTime; + } + }; + + SelectionPredicate LAST_PREDICATE = new SelectionPredicate() + { + @Override + public long initValue() + { + return DateTimes.MIN.getMillis(); + } + + @Override + public boolean apply(long currentTime, long selectedTime) + { + return currentTime >= selectedTime; + } + }; +} diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/SingleStringFirstLastDimensionVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/SingleStringFirstLastDimensionVectorAggregator.java new file mode 100644 index 000000000000..031140e4f6c5 --- /dev/null +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/SingleStringFirstLastDimensionVectorAggregator.java @@ -0,0 +1,185 @@ +/* + * 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.aggregation.firstlast; + +import org.apache.druid.common.config.NullHandling; +import org.apache.druid.error.DruidException; +import org.apache.druid.java.util.common.StringUtils; +import org.apache.druid.query.aggregation.SerializablePairLongString; +import org.apache.druid.segment.vector.SingleValueDimensionVectorSelector; +import org.apache.druid.segment.vector.VectorValueSelector; + +import javax.annotation.Nullable; +import java.nio.ByteBuffer; + +public class SingleStringFirstLastDimensionVectorAggregator + extends FirstLastVectorAggregator +{ + private final SingleValueDimensionVectorSelector singleValueDimensionVectorSelector; + private final int maxStringBytes; + private final SelectionPredicate selectionPredicate; + + protected SingleStringFirstLastDimensionVectorAggregator( + VectorValueSelector timeSelector, + SingleValueDimensionVectorSelector singleValueDimensionVectorSelector, + int maxStringBytes, + SelectionPredicate selectionPredicate + ) + { + super( + timeSelector, + new SingleValueDimensionVectorSelectorAdapter(singleValueDimensionVectorSelector), + null, + selectionPredicate + ); + this.singleValueDimensionVectorSelector = singleValueDimensionVectorSelector; + this.maxStringBytes = maxStringBytes; + this.selectionPredicate = selectionPredicate; + } + + @Override + public void init(ByteBuffer buf, int position) + { + buf.putLong(position, selectionPredicate.initValue()); + buf.put( + position + NULLITY_OFFSET, + NullHandling.replaceWithDefault() ? NullHandling.IS_NOT_NULL_BYTE : NullHandling.IS_NULL_BYTE + ); + buf.putInt(position + VALUE_OFFSET, 0); + } + + /** + * Doesnt need to handle the null handling because that is taken care of while inserting the value, therefore in + * replaceWithDefault mode, it is always going to be non-null + */ + @Nullable + @Override + public Object get(ByteBuffer buf, int position) + { + long time = buf.getLong(position); + if (buf.get(position + NULLITY_OFFSET) == NullHandling.IS_NULL_BYTE) { + return new SerializablePairLongString(time, null); + } + int index = buf.getInt(position + VALUE_OFFSET); + String value = singleValueDimensionVectorSelector.lookupName(index); + return new SerializablePairLongString(time, StringUtils.chop(value, maxStringBytes)); + } + + @Override + protected void putValue(ByteBuffer buf, int position, long time, String value) + { + throw DruidException.defensive("This method is not applicable to the SingleStringFirstLastDimensionVectorAggregator"); + } + + @Override + protected void putValue(ByteBuffer buf, int position, long time, VectorValueSelector valueSelector, int index) + { + buf.putLong(position, time); + buf.put(position + NULLITY_OFFSET, NullHandling.IS_NOT_NULL_BYTE); + buf.putInt( + position + VALUE_OFFSET, + ((SingleValueDimensionVectorSelectorAdapter) valueSelector).singleValueDimensionVectorSelector.getRowVector()[index] + ); + } + + @Override + protected void putDefaultValue(ByteBuffer buf, int position, long time) + { + buf.putLong(position, time); + buf.put(position + NULLITY_OFFSET, NullHandling.IS_NOT_NULL_BYTE); + buf.putInt(position + VALUE_OFFSET, 0); + } + + @Override + protected void putNull(ByteBuffer buf, int position, long time) + { + buf.putLong(position, time); + buf.put(position + NULLITY_OFFSET, NullHandling.IS_NULL_BYTE); + buf.putInt(position + VALUE_OFFSET, 0); + } + + @Override + protected SerializablePairLongString readPairFromVectorSelectors( + boolean[] timeNullityVector, + long[] timeVector, + Object[] maybeFoldedObjects, + int index + ) + { + throw DruidException.defensive("This method is not applicable to the SingleStringFirstLastDimensionVectorAggregator"); + } + + /** + * Adapter class to from {@link SingleValueDimensionVectorSelector} to {@link VectorValueSelector}, to pass to the parent + * class. The parent class only uses the passed in selector for the null check, therefore {@link #getNullVector()} is + * the only relevant method implemented by the adapter. Each string value (even null) is assigned an id that will get stored, + * therefore fetching the nullVector returns null (i.e. no null values) + */ + private static class SingleValueDimensionVectorSelectorAdapter implements VectorValueSelector + { + + private final SingleValueDimensionVectorSelector singleValueDimensionVectorSelector; + + public SingleValueDimensionVectorSelectorAdapter(SingleValueDimensionVectorSelector singleValueDimensionVectorSelector) + { + this.singleValueDimensionVectorSelector = singleValueDimensionVectorSelector; + } + + @Override + public int getMaxVectorSize() + { + throw DruidException.defensive("Unexpected call"); + } + + @Override + public int getCurrentVectorSize() + { + throw DruidException.defensive("Unexpected call"); + } + + @Override + public long[] getLongVector() + { + throw DruidException.defensive("Unexpected call"); + } + + @Override + public float[] getFloatVector() + { + throw DruidException.defensive("Unexpected call"); + } + + @Override + public double[] getDoubleVector() + { + throw DruidException.defensive("Unexpected call"); + } + + /** + * This is the only useful method, that will get used by the parent class. + */ + @Nullable + @Override + public boolean[] getNullVector() + { + return null; + } + } +} diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/StringFirstLastUtils.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/StringFirstLastUtils.java similarity index 90% rename from processing/src/main/java/org/apache/druid/query/aggregation/first/StringFirstLastUtils.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/StringFirstLastUtils.java index ff1113c91132..afbb94faf8f3 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/StringFirstLastUtils.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/StringFirstLastUtils.java @@ -17,15 +17,13 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast; import org.apache.druid.java.util.common.StringUtils; import org.apache.druid.query.aggregation.SerializablePairLongString; import org.apache.druid.segment.BaseLongColumnValueSelector; import org.apache.druid.segment.BaseObjectColumnValueSelector; import org.apache.druid.segment.DimensionHandlerUtils; -import org.apache.druid.segment.vector.VectorObjectSelector; -import org.apache.druid.segment.vector.VectorValueSelector; import javax.annotation.Nullable; import java.nio.ByteBuffer; @@ -38,25 +36,29 @@ public class StringFirstLastUtils * Return the object at a particular index from the vector selectors. * index of bounds issues is the responsibility of the caller */ + @Nullable public static SerializablePairLongString readPairFromVectorSelectorsAtIndex( - VectorValueSelector timeSelector, - VectorObjectSelector valueSelector, + boolean[] timeNullityVector, + long[] timeVector, + Object[] maybeFoldedObjects, int index ) { final long time; final String string; - final Object object = valueSelector.getObjectVector()[index]; + final Object object = maybeFoldedObjects[index]; + if (object instanceof SerializablePairLongString) { final SerializablePairLongString pair = (SerializablePairLongString) object; time = pair.lhs; string = pair.rhs; - } else if (object != null) { - time = timeSelector.getLongVector()[index]; - string = DimensionHandlerUtils.convertObjectToString(object); } else { - // Don't aggregate nulls. - return null; + if (timeNullityVector != null && timeNullityVector[index]) { + // Donot aggregate pairs where time is unknown + return null; + } + time = timeVector[index]; + string = DimensionHandlerUtils.convertObjectToString(object); } return new SerializablePairLongString(time, string); diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/StringFirstLastVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/StringFirstLastVectorAggregator.java new file mode 100644 index 000000000000..118d28e0c366 --- /dev/null +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/StringFirstLastVectorAggregator.java @@ -0,0 +1,110 @@ +/* + * 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.aggregation.firstlast; + +import org.apache.druid.common.config.NullHandling; +import org.apache.druid.error.DruidException; +import org.apache.druid.query.aggregation.SerializablePairLongString; +import org.apache.druid.segment.vector.VectorObjectSelector; +import org.apache.druid.segment.vector.VectorValueSelector; + +import javax.annotation.Nullable; +import java.nio.ByteBuffer; + +public class StringFirstLastVectorAggregator extends FirstLastVectorAggregator +{ + private final int maxStringBytes; + private final SelectionPredicate selectionPredicate; + + protected StringFirstLastVectorAggregator( + @Nullable final VectorValueSelector timeSelector, + final VectorObjectSelector objectSelector, + final int maxStringBytes, + final SelectionPredicate selectionPredicate + ) + { + super(timeSelector, null, objectSelector, selectionPredicate); + this.maxStringBytes = maxStringBytes; + this.selectionPredicate = selectionPredicate; + } + + @Override + public void init(ByteBuffer buf, int position) + { + StringFirstLastUtils.writePair( + buf, + position, + new SerializablePairLongString(selectionPredicate.initValue(), null), + maxStringBytes + ); + } + + @Nullable + @Override + public Object get(ByteBuffer buf, int position) + { + return StringFirstLastUtils.readPair(buf, position); + } + + @Override + protected void putValue(ByteBuffer buf, int position, long time, String value) + { + StringFirstLastUtils.writePair(buf, position, new SerializablePairLongString(time, value), maxStringBytes); + } + + @Override + protected void putValue(ByteBuffer buf, int position, long time, VectorValueSelector valueSelector, int index) + { + throw DruidException.defensive("This variant is not applicable to the StringFirstLastVectorAggregator"); + } + + @Override + protected void putDefaultValue(ByteBuffer buf, int position, long time) + { + StringFirstLastUtils.writePair( + buf, + position, + new SerializablePairLongString(time, NullHandling.defaultStringValue()), + maxStringBytes + ); + } + + @Override + protected void putNull(ByteBuffer buf, int position, long time) + { + StringFirstLastUtils.writePair(buf, position, new SerializablePairLongString(time, null), maxStringBytes); + } + + @Override + protected SerializablePairLongString readPairFromVectorSelectors( + boolean[] timeNullityVector, + long[] timeVector, + Object[] maybeFoldedObjects, + int index + ) + { + return StringFirstLastUtils.readPairFromVectorSelectorsAtIndex( + timeNullityVector, + timeVector, + maybeFoldedObjects, + index + ); + } +} diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/DoubleFirstAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/DoubleFirstAggregator.java similarity index 96% rename from processing/src/main/java/org/apache/druid/query/aggregation/first/DoubleFirstAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/DoubleFirstAggregator.java index cf121f72fc98..3861b580c170 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/DoubleFirstAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/DoubleFirstAggregator.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import org.apache.druid.query.aggregation.SerializablePairLongDouble; import org.apache.druid.segment.BaseLongColumnValueSelector; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/DoubleFirstAggregatorFactory.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/DoubleFirstAggregatorFactory.java similarity index 98% rename from processing/src/main/java/org/apache/druid/query/aggregation/first/DoubleFirstAggregatorFactory.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/DoubleFirstAggregatorFactory.java index 92880be84573..f0157512167a 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/DoubleFirstAggregatorFactory.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/DoubleFirstAggregatorFactory.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -32,6 +32,7 @@ import org.apache.druid.query.aggregation.SerializablePairLongDouble; import org.apache.druid.query.aggregation.SerializablePairLongDoubleComplexMetricSerde; import org.apache.druid.query.aggregation.VectorAggregator; +import org.apache.druid.query.aggregation.firstlast.FirstLastUtils; import org.apache.druid.query.cache.CacheKeyBuilder; import org.apache.druid.segment.ColumnInspector; import org.apache.druid.segment.ColumnSelectorFactory; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/DoubleFirstBufferAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/DoubleFirstBufferAggregator.java similarity index 97% rename from processing/src/main/java/org/apache/druid/query/aggregation/first/DoubleFirstBufferAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/DoubleFirstBufferAggregator.java index c00472e923c9..2a2fc229145b 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/DoubleFirstBufferAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/DoubleFirstBufferAggregator.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import org.apache.druid.query.aggregation.SerializablePairLongDouble; import org.apache.druid.segment.BaseLongColumnValueSelector; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/DoubleFirstVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/DoubleFirstVectorAggregator.java similarity index 50% rename from processing/src/main/java/org/apache/druid/query/aggregation/first/DoubleFirstVectorAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/DoubleFirstVectorAggregator.java index 0fdd06231feb..11cfa3b5366e 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/DoubleFirstVectorAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/DoubleFirstVectorAggregator.java @@ -17,51 +17,23 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; -import org.apache.druid.query.aggregation.SerializablePairLongDouble; +import org.apache.druid.query.aggregation.firstlast.DoubleFirstLastVectorAggregator; +import org.apache.druid.query.aggregation.firstlast.SelectionPredicate; import org.apache.druid.segment.vector.VectorObjectSelector; import org.apache.druid.segment.vector.VectorValueSelector; -import javax.annotation.Nullable; -import java.nio.ByteBuffer; - -public class DoubleFirstVectorAggregator extends NumericFirstVectorAggregator +public class DoubleFirstVectorAggregator extends DoubleFirstLastVectorAggregator { public DoubleFirstVectorAggregator(VectorValueSelector timeSelector, VectorObjectSelector objectSelector) { - super(timeSelector, null, objectSelector); + super(timeSelector, objectSelector, SelectionPredicate.FIRST_PREDICATE); } public DoubleFirstVectorAggregator(VectorValueSelector timeSelector, VectorValueSelector valueSelector) { - super(timeSelector, valueSelector, null); - } - - @Override - public void initValue(ByteBuffer buf, int position) - { - buf.putDouble(position, 0); - } - - - @Override - void putValue(ByteBuffer buf, int position, int index) - { - double firstValue = valueSelector != null ? valueSelector.getDoubleVector()[index] : ((SerializablePairLongDouble) (objectSelector.getObjectVector()[index])).getRhs(); - buf.putDouble(position, firstValue); - } - - - /** - * @return The object as a pair with the position and the value stored at the position in the buffer. - */ - @Nullable - @Override - public Object get(ByteBuffer buf, int position) - { - final boolean rhsNull = isValueNull(buf, position); - return new SerializablePairLongDouble(buf.getLong(position), rhsNull ? null : buf.getDouble(position + VALUE_OFFSET)); + super(timeSelector, valueSelector, SelectionPredicate.FIRST_PREDICATE); } } diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/FloatFirstAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/FloatFirstAggregator.java similarity index 96% rename from processing/src/main/java/org/apache/druid/query/aggregation/first/FloatFirstAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/FloatFirstAggregator.java index 987937c2ba87..b1340b5dfc54 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/FloatFirstAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/FloatFirstAggregator.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import org.apache.druid.query.aggregation.SerializablePairLongFloat; import org.apache.druid.segment.BaseLongColumnValueSelector; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/FloatFirstAggregatorFactory.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/FloatFirstAggregatorFactory.java similarity index 98% rename from processing/src/main/java/org/apache/druid/query/aggregation/first/FloatFirstAggregatorFactory.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/FloatFirstAggregatorFactory.java index 5faf04607df7..d35782533748 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/FloatFirstAggregatorFactory.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/FloatFirstAggregatorFactory.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -32,6 +32,7 @@ import org.apache.druid.query.aggregation.SerializablePairLongFloat; import org.apache.druid.query.aggregation.SerializablePairLongFloatComplexMetricSerde; import org.apache.druid.query.aggregation.VectorAggregator; +import org.apache.druid.query.aggregation.firstlast.FirstLastUtils; import org.apache.druid.query.cache.CacheKeyBuilder; import org.apache.druid.segment.ColumnInspector; import org.apache.druid.segment.ColumnSelectorFactory; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/FloatFirstBufferAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/FloatFirstBufferAggregator.java similarity index 97% rename from processing/src/main/java/org/apache/druid/query/aggregation/first/FloatFirstBufferAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/FloatFirstBufferAggregator.java index b8881ee9500f..9b04b0d1a51f 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/FloatFirstBufferAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/FloatFirstBufferAggregator.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import org.apache.druid.query.aggregation.SerializablePairLongFloat; import org.apache.druid.segment.BaseLongColumnValueSelector; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/FloatFirstVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/FloatFirstVectorAggregator.java similarity index 51% rename from processing/src/main/java/org/apache/druid/query/aggregation/first/FloatFirstVectorAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/FloatFirstVectorAggregator.java index 82a679095946..9d4b5bc71932 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/FloatFirstVectorAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/FloatFirstVectorAggregator.java @@ -17,50 +17,23 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; -import org.apache.druid.query.aggregation.SerializablePairLongFloat; +import org.apache.druid.query.aggregation.firstlast.FloatFirstLastVectorAggregator; +import org.apache.druid.query.aggregation.firstlast.SelectionPredicate; import org.apache.druid.segment.vector.VectorObjectSelector; import org.apache.druid.segment.vector.VectorValueSelector; -import javax.annotation.Nullable; -import java.nio.ByteBuffer; - -public class FloatFirstVectorAggregator extends NumericFirstVectorAggregator +public class FloatFirstVectorAggregator extends FloatFirstLastVectorAggregator { public FloatFirstVectorAggregator(VectorValueSelector timeSelector, VectorObjectSelector objectSelector) { - super(timeSelector, null, objectSelector); + super(timeSelector, objectSelector, SelectionPredicate.FIRST_PREDICATE); } public FloatFirstVectorAggregator(VectorValueSelector timeSelector, VectorValueSelector valueSelector) { - super(timeSelector, valueSelector, null); - } - - @Override - public void initValue(ByteBuffer buf, int position) - { - buf.putFloat(position, 0); - } - - @Override - void putValue(ByteBuffer buf, int position, int index) - { - float firstValue = valueSelector != null ? valueSelector.getFloatVector()[index] : ((SerializablePairLongFloat) objectSelector.getObjectVector()[index]).getRhs(); - buf.putFloat(position, firstValue); - } - - - /** - * @return The object as a pair with the position and the value stored at the position in the buffer. - */ - @Nullable - @Override - public Object get(ByteBuffer buf, int position) - { - final boolean rhsNull = isValueNull(buf, position); - return new SerializablePairLongFloat(buf.getLong(position), rhsNull ? null : buf.getFloat(position + VALUE_OFFSET)); + super(timeSelector, valueSelector, SelectionPredicate.FIRST_PREDICATE); } } diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/GenericFirstAggregateCombiner.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/GenericFirstAggregateCombiner.java similarity index 96% rename from processing/src/main/java/org/apache/druid/query/aggregation/first/GenericFirstAggregateCombiner.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/GenericFirstAggregateCombiner.java index cd72c306b798..f6a39aafc3ba 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/GenericFirstAggregateCombiner.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/GenericFirstAggregateCombiner.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import com.google.common.primitives.Longs; import org.apache.druid.collections.SerializablePair; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/LongFirstAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/LongFirstAggregator.java similarity index 96% rename from processing/src/main/java/org/apache/druid/query/aggregation/first/LongFirstAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/LongFirstAggregator.java index d229819382e9..ad56e379563c 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/LongFirstAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/LongFirstAggregator.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import org.apache.druid.query.aggregation.SerializablePairLongLong; import org.apache.druid.segment.BaseLongColumnValueSelector; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/LongFirstAggregatorFactory.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/LongFirstAggregatorFactory.java similarity index 98% rename from processing/src/main/java/org/apache/druid/query/aggregation/first/LongFirstAggregatorFactory.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/LongFirstAggregatorFactory.java index 6b8836050ef5..791ca1a02d30 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/LongFirstAggregatorFactory.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/LongFirstAggregatorFactory.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -32,6 +32,7 @@ import org.apache.druid.query.aggregation.SerializablePairLongLong; import org.apache.druid.query.aggregation.SerializablePairLongLongComplexMetricSerde; import org.apache.druid.query.aggregation.VectorAggregator; +import org.apache.druid.query.aggregation.firstlast.FirstLastUtils; import org.apache.druid.query.cache.CacheKeyBuilder; import org.apache.druid.segment.ColumnInspector; import org.apache.druid.segment.ColumnSelectorFactory; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/LongFirstBufferAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/LongFirstBufferAggregator.java similarity index 97% rename from processing/src/main/java/org/apache/druid/query/aggregation/first/LongFirstBufferAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/LongFirstBufferAggregator.java index 426d4c64816d..694d5903d1de 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/LongFirstBufferAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/LongFirstBufferAggregator.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import org.apache.druid.query.aggregation.SerializablePairLongLong; import org.apache.druid.segment.BaseLongColumnValueSelector; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/LongFirstVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/LongFirstVectorAggregator.java similarity index 51% rename from processing/src/main/java/org/apache/druid/query/aggregation/first/LongFirstVectorAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/LongFirstVectorAggregator.java index 8c7631db3c12..135946f61557 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/LongFirstVectorAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/LongFirstVectorAggregator.java @@ -17,48 +17,22 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; -import org.apache.druid.query.aggregation.SerializablePairLongLong; +import org.apache.druid.query.aggregation.firstlast.LongFirstLastVectorAggregator; +import org.apache.druid.query.aggregation.firstlast.SelectionPredicate; import org.apache.druid.segment.vector.VectorObjectSelector; import org.apache.druid.segment.vector.VectorValueSelector; -import javax.annotation.Nullable; -import java.nio.ByteBuffer; - -public class LongFirstVectorAggregator extends NumericFirstVectorAggregator +public class LongFirstVectorAggregator extends LongFirstLastVectorAggregator { public LongFirstVectorAggregator(VectorValueSelector timeSelector, VectorObjectSelector objectSelector) { - super(timeSelector, null, objectSelector); + super(timeSelector, objectSelector, SelectionPredicate.FIRST_PREDICATE); } public LongFirstVectorAggregator(VectorValueSelector timeSelector, VectorValueSelector valueSelector) { - super(timeSelector, valueSelector, null); - } - - @Override - public void initValue(ByteBuffer buf, int position) - { - buf.putLong(position, 0); - } - - @Override - void putValue(ByteBuffer buf, int position, int index) - { - long firstValue = valueSelector != null ? valueSelector.getLongVector()[index] : ((SerializablePairLongLong) objectSelector.getObjectVector()[index]).getRhs(); - buf.putLong(position, firstValue); - } - - /** - * @return The object as a pair with the position and the value stored at the position in the buffer. - */ - @Nullable - @Override - public Object get(ByteBuffer buf, int position) - { - final boolean rhsNull = isValueNull(buf, position); - return new SerializablePairLongLong(buf.getLong(position), rhsNull ? null : buf.getLong(position + VALUE_OFFSET)); + super(timeSelector, valueSelector, SelectionPredicate.FIRST_PREDICATE); } } diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/NumericFirstAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/NumericFirstAggregator.java similarity index 98% rename from processing/src/main/java/org/apache/druid/query/aggregation/first/NumericFirstAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/NumericFirstAggregator.java index 6b32996b4f2f..bc5f939c8b1c 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/NumericFirstAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/NumericFirstAggregator.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import org.apache.druid.collections.SerializablePair; import org.apache.druid.common.config.NullHandling; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/NumericFirstBufferAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/NumericFirstBufferAggregator.java similarity index 98% rename from processing/src/main/java/org/apache/druid/query/aggregation/first/NumericFirstBufferAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/NumericFirstBufferAggregator.java index f20456d31223..e85e470fb613 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/NumericFirstBufferAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/NumericFirstBufferAggregator.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import org.apache.druid.collections.SerializablePair; import org.apache.druid.common.config.NullHandling; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/SingleStringFirstDimensionVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/SingleStringFirstDimensionVectorAggregator.java new file mode 100644 index 000000000000..e098aaddd95d --- /dev/null +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/SingleStringFirstDimensionVectorAggregator.java @@ -0,0 +1,38 @@ +/* + * 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.aggregation.firstlast.first; + +import org.apache.druid.query.aggregation.firstlast.SelectionPredicate; +import org.apache.druid.query.aggregation.firstlast.SingleStringFirstLastDimensionVectorAggregator; +import org.apache.druid.segment.vector.SingleValueDimensionVectorSelector; +import org.apache.druid.segment.vector.VectorValueSelector; + +public class SingleStringFirstDimensionVectorAggregator extends SingleStringFirstLastDimensionVectorAggregator +{ + + public SingleStringFirstDimensionVectorAggregator( + VectorValueSelector timeSelector, + SingleValueDimensionVectorSelector singleValueDimensionVectorSelector, + int maxStringBytes + ) + { + super(timeSelector, singleValueDimensionVectorSelector, maxStringBytes, SelectionPredicate.FIRST_PREDICATE); + } +} diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/StringFirstAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstAggregator.java similarity index 96% rename from processing/src/main/java/org/apache/druid/query/aggregation/first/StringFirstAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstAggregator.java index 0d05833378c6..72ce511ae788 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/StringFirstAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstAggregator.java @@ -17,12 +17,13 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import org.apache.druid.java.util.common.DateTimes; import org.apache.druid.java.util.common.StringUtils; import org.apache.druid.query.aggregation.Aggregator; import org.apache.druid.query.aggregation.SerializablePairLongString; +import org.apache.druid.query.aggregation.firstlast.StringFirstLastUtils; import org.apache.druid.segment.BaseLongColumnValueSelector; import org.apache.druid.segment.BaseObjectColumnValueSelector; import org.apache.druid.segment.DimensionHandlerUtils; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/StringFirstAggregatorFactory.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstAggregatorFactory.java similarity index 96% rename from processing/src/main/java/org/apache/druid/query/aggregation/first/StringFirstAggregatorFactory.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstAggregatorFactory.java index 61486e0936ad..8ff45a27380b 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/StringFirstAggregatorFactory.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstAggregatorFactory.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -33,6 +33,7 @@ import org.apache.druid.query.aggregation.BufferAggregator; import org.apache.druid.query.aggregation.SerializablePairLongString; import org.apache.druid.query.aggregation.VectorAggregator; +import org.apache.druid.query.aggregation.firstlast.FirstLastUtils; import org.apache.druid.query.cache.CacheKeyBuilder; import org.apache.druid.query.dimension.DefaultDimensionSpec; import org.apache.druid.segment.BaseObjectColumnValueSelector; @@ -208,10 +209,11 @@ public VectorAggregator factorizeVector(VectorColumnSelectorFactory selectorFact // For multivalue string we need to iterate a list of indexedInts which is also similar to iterating // over elements for an ARRAY typed column. These two which requires an iteration will be done together. if (!capabilities.hasMultipleValues().isTrue()) { - SingleValueDimensionVectorSelector sSelector = selectorFactory.makeSingleValueDimensionSelector( - DefaultDimensionSpec.of( - fieldName)); - return new SingleStringFirstDimensionVectorAggregator(timeSelector, sSelector, maxStringBytes); + SingleValueDimensionVectorSelector sSelector = + selectorFactory.makeSingleValueDimensionSelector(DefaultDimensionSpec.of(fieldName)); + if (sSelector.nameLookupPossibleInAdvance()) { + return new SingleStringFirstDimensionVectorAggregator(timeSelector, sSelector, maxStringBytes); + } } } } diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/StringFirstBufferAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstBufferAggregator.java similarity index 97% rename from processing/src/main/java/org/apache/druid/query/aggregation/first/StringFirstBufferAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstBufferAggregator.java index 563455c9eefa..1f0a70bd1fe3 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/StringFirstBufferAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstBufferAggregator.java @@ -17,11 +17,12 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import org.apache.druid.java.util.common.DateTimes; import org.apache.druid.query.aggregation.BufferAggregator; import org.apache.druid.query.aggregation.SerializablePairLongString; +import org.apache.druid.query.aggregation.firstlast.StringFirstLastUtils; import org.apache.druid.query.monomorphicprocessing.RuntimeShapeInspector; import org.apache.druid.segment.BaseLongColumnValueSelector; import org.apache.druid.segment.BaseObjectColumnValueSelector; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/first/StringFirstFoldingAggregatorFactory.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstFoldingAggregatorFactory.java similarity index 96% rename from processing/src/main/java/org/apache/druid/query/aggregation/first/StringFirstFoldingAggregatorFactory.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstFoldingAggregatorFactory.java index 8c6c06856d8e..ebb74746f020 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/first/StringFirstFoldingAggregatorFactory.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstFoldingAggregatorFactory.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import com.fasterxml.jackson.annotation.JsonCreator; import org.apache.druid.query.aggregation.AggregatorFactory; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstVectorAggregator.java new file mode 100644 index 000000000000..a99332332b4e --- /dev/null +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstVectorAggregator.java @@ -0,0 +1,39 @@ +/* + * 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.aggregation.firstlast.first; + +import org.apache.druid.query.aggregation.firstlast.SelectionPredicate; +import org.apache.druid.query.aggregation.firstlast.StringFirstLastVectorAggregator; +import org.apache.druid.segment.vector.VectorObjectSelector; +import org.apache.druid.segment.vector.VectorValueSelector; + +import javax.annotation.Nullable; + +public class StringFirstVectorAggregator extends StringFirstLastVectorAggregator +{ + public StringFirstVectorAggregator( + @Nullable VectorValueSelector timeSelector, + VectorObjectSelector objectSelector, + int maxStringBytes + ) + { + super(timeSelector, objectSelector, maxStringBytes, SelectionPredicate.FIRST_PREDICATE); + } +} diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/DoubleLastAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/DoubleLastAggregator.java similarity index 96% rename from processing/src/main/java/org/apache/druid/query/aggregation/last/DoubleLastAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/DoubleLastAggregator.java index 009e9c82333f..4f5a39851d2f 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/DoubleLastAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/DoubleLastAggregator.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import org.apache.druid.query.aggregation.SerializablePairLongDouble; import org.apache.druid.segment.BaseLongColumnValueSelector; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/DoubleLastAggregatorFactory.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/DoubleLastAggregatorFactory.java similarity index 97% rename from processing/src/main/java/org/apache/druid/query/aggregation/last/DoubleLastAggregatorFactory.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/DoubleLastAggregatorFactory.java index 56b58a33896e..3d22508c1cdb 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/DoubleLastAggregatorFactory.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/DoubleLastAggregatorFactory.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -32,8 +32,8 @@ import org.apache.druid.query.aggregation.SerializablePairLongDouble; import org.apache.druid.query.aggregation.SerializablePairLongDoubleComplexMetricSerde; import org.apache.druid.query.aggregation.VectorAggregator; -import org.apache.druid.query.aggregation.first.DoubleFirstAggregatorFactory; -import org.apache.druid.query.aggregation.first.FirstLastUtils; +import org.apache.druid.query.aggregation.firstlast.FirstLastUtils; +import org.apache.druid.query.aggregation.firstlast.first.DoubleFirstAggregatorFactory; import org.apache.druid.query.cache.CacheKeyBuilder; import org.apache.druid.segment.ColumnInspector; import org.apache.druid.segment.ColumnSelectorFactory; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/DoubleLastBufferAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/DoubleLastBufferAggregator.java similarity index 97% rename from processing/src/main/java/org/apache/druid/query/aggregation/last/DoubleLastBufferAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/DoubleLastBufferAggregator.java index d605180951c4..8e8fcd9b9cc0 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/DoubleLastBufferAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/DoubleLastBufferAggregator.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import org.apache.druid.query.aggregation.SerializablePairLongDouble; import org.apache.druid.segment.BaseLongColumnValueSelector; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/DoubleLastVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/DoubleLastVectorAggregator.java similarity index 50% rename from processing/src/main/java/org/apache/druid/query/aggregation/last/DoubleLastVectorAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/DoubleLastVectorAggregator.java index d40ba750476b..cf033b805cdf 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/DoubleLastVectorAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/DoubleLastVectorAggregator.java @@ -17,54 +17,23 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; -import org.apache.druid.query.aggregation.SerializablePairLongDouble; +import org.apache.druid.query.aggregation.firstlast.DoubleFirstLastVectorAggregator; +import org.apache.druid.query.aggregation.firstlast.SelectionPredicate; import org.apache.druid.segment.vector.VectorObjectSelector; import org.apache.druid.segment.vector.VectorValueSelector; -import javax.annotation.Nullable; -import java.nio.ByteBuffer; - -/** - * Vectorized version of on heap 'last' aggregator for column selectors with type DOUBLE.. - */ -public class DoubleLastVectorAggregator extends NumericLastVectorAggregator +public class DoubleLastVectorAggregator extends DoubleFirstLastVectorAggregator { - double lastValue; public DoubleLastVectorAggregator(VectorValueSelector timeSelector, VectorObjectSelector objectSelector) { - super(timeSelector, null, objectSelector); - lastValue = 0; + super(timeSelector, objectSelector, SelectionPredicate.LAST_PREDICATE); } public DoubleLastVectorAggregator(VectorValueSelector timeSelector, VectorValueSelector valueSelector) { - super(timeSelector, valueSelector, null); - lastValue = 0; - } - - @Override - void putValue(ByteBuffer buf, int position, int index) - { - lastValue = valueSelector != null ? valueSelector.getDoubleVector()[index] : ((SerializablePairLongDouble) objectSelector.getObjectVector()[index]).getRhs(); - buf.putDouble(position, lastValue); - } - - - @Override - public void initValue(ByteBuffer buf, int position) - { - buf.putDouble(position, 0); - } - - @Nullable - @Override - public Object get(ByteBuffer buf, int position) - { - final boolean rhsNull = isValueNull(buf, position); - return new SerializablePairLongDouble(buf.getLong(position), rhsNull ? null : buf.getDouble(position + VALUE_OFFSET)); + super(timeSelector, valueSelector, SelectionPredicate.LAST_PREDICATE); } } - diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/FloatLastAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/FloatLastAggregator.java similarity index 96% rename from processing/src/main/java/org/apache/druid/query/aggregation/last/FloatLastAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/FloatLastAggregator.java index 63147a92db77..29117c61c9d1 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/FloatLastAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/FloatLastAggregator.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import org.apache.druid.query.aggregation.SerializablePairLongFloat; import org.apache.druid.segment.BaseLongColumnValueSelector; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/FloatLastAggregatorFactory.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/FloatLastAggregatorFactory.java similarity index 97% rename from processing/src/main/java/org/apache/druid/query/aggregation/last/FloatLastAggregatorFactory.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/FloatLastAggregatorFactory.java index 0eefc4586452..ac1ebfa4ae35 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/FloatLastAggregatorFactory.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/FloatLastAggregatorFactory.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -32,8 +32,8 @@ import org.apache.druid.query.aggregation.SerializablePairLongFloat; import org.apache.druid.query.aggregation.SerializablePairLongFloatComplexMetricSerde; import org.apache.druid.query.aggregation.VectorAggregator; -import org.apache.druid.query.aggregation.first.FirstLastUtils; -import org.apache.druid.query.aggregation.first.FloatFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.FirstLastUtils; +import org.apache.druid.query.aggregation.firstlast.first.FloatFirstAggregatorFactory; import org.apache.druid.query.cache.CacheKeyBuilder; import org.apache.druid.segment.ColumnInspector; import org.apache.druid.segment.ColumnSelectorFactory; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/FloatLastBufferAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/FloatLastBufferAggregator.java similarity index 97% rename from processing/src/main/java/org/apache/druid/query/aggregation/last/FloatLastBufferAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/FloatLastBufferAggregator.java index 68affc9cba90..cc798d806519 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/FloatLastBufferAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/FloatLastBufferAggregator.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import org.apache.druid.query.aggregation.SerializablePairLongFloat; import org.apache.druid.segment.BaseLongColumnValueSelector; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/FloatLastVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/FloatLastVectorAggregator.java similarity index 50% rename from processing/src/main/java/org/apache/druid/query/aggregation/last/FloatLastVectorAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/FloatLastVectorAggregator.java index a5500c19cbe8..45f941e68722 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/FloatLastVectorAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/FloatLastVectorAggregator.java @@ -17,55 +17,23 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; -import org.apache.druid.query.aggregation.SerializablePairLongFloat; +import org.apache.druid.query.aggregation.firstlast.FloatFirstLastVectorAggregator; +import org.apache.druid.query.aggregation.firstlast.SelectionPredicate; import org.apache.druid.segment.vector.VectorObjectSelector; import org.apache.druid.segment.vector.VectorValueSelector; -import javax.annotation.Nullable; -import java.nio.ByteBuffer; - -/** - * Vectorized version of on heap 'last' aggregator for column selectors with type FLOAT.. - */ -public class FloatLastVectorAggregator extends NumericLastVectorAggregator +public class FloatLastVectorAggregator extends FloatFirstLastVectorAggregator { - float lastValue; public FloatLastVectorAggregator(VectorValueSelector timeSelector, VectorObjectSelector objectSelector) { - super(timeSelector, null, objectSelector); - lastValue = 0; + super(timeSelector, objectSelector, SelectionPredicate.LAST_PREDICATE); } public FloatLastVectorAggregator(VectorValueSelector timeSelector, VectorValueSelector valueSelector) { - super(timeSelector, valueSelector, null); - lastValue = 0; - } - - @Override - void putValue(ByteBuffer buf, int position, int index) - { - lastValue = valueSelector != null ? valueSelector.getFloatVector()[index] : ((SerializablePairLongFloat) objectSelector.getObjectVector()[index]).getRhs(); - buf.putFloat(position, lastValue); - } - - - @Override - public void initValue(ByteBuffer buf, int position) - { - buf.putFloat(position, 0); - } - - - @Nullable - @Override - public Object get(ByteBuffer buf, int position) - { - final boolean rhsNull = isValueNull(buf, position); - return new SerializablePairLongFloat(buf.getLong(position), rhsNull ? null : buf.getFloat(position + VALUE_OFFSET)); + super(timeSelector, valueSelector, SelectionPredicate.LAST_PREDICATE); } } - diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/GenericLastAggregateCombiner.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/GenericLastAggregateCombiner.java similarity index 96% rename from processing/src/main/java/org/apache/druid/query/aggregation/last/GenericLastAggregateCombiner.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/GenericLastAggregateCombiner.java index 1b1e2dbd128b..dca26332557e 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/GenericLastAggregateCombiner.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/GenericLastAggregateCombiner.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import com.google.common.primitives.Longs; import org.apache.druid.collections.SerializablePair; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/LongLastAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/LongLastAggregator.java similarity index 96% rename from processing/src/main/java/org/apache/druid/query/aggregation/last/LongLastAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/LongLastAggregator.java index f5f5791da960..5b35c76c38cd 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/LongLastAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/LongLastAggregator.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import org.apache.druid.query.aggregation.SerializablePairLongLong; import org.apache.druid.segment.BaseLongColumnValueSelector; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/LongLastAggregatorFactory.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/LongLastAggregatorFactory.java similarity index 96% rename from processing/src/main/java/org/apache/druid/query/aggregation/last/LongLastAggregatorFactory.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/LongLastAggregatorFactory.java index 492df2136492..bae205cded3e 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/LongLastAggregatorFactory.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/LongLastAggregatorFactory.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -32,8 +32,8 @@ import org.apache.druid.query.aggregation.SerializablePairLongLong; import org.apache.druid.query.aggregation.SerializablePairLongLongComplexMetricSerde; import org.apache.druid.query.aggregation.VectorAggregator; -import org.apache.druid.query.aggregation.first.FirstLastUtils; -import org.apache.druid.query.aggregation.first.LongFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.FirstLastUtils; +import org.apache.druid.query.aggregation.firstlast.first.LongFirstAggregatorFactory; import org.apache.druid.query.cache.CacheKeyBuilder; import org.apache.druid.segment.ColumnInspector; import org.apache.druid.segment.ColumnSelectorFactory; @@ -149,9 +149,7 @@ public boolean canVectorize(ColumnInspector columnInspector) } @Override - public VectorAggregator factorizeVector( - VectorColumnSelectorFactory columnSelectorFactory - ) + public VectorAggregator factorizeVector(VectorColumnSelectorFactory columnSelectorFactory) { VectorValueSelector timeSelector = columnSelectorFactory.makeValueSelector(timeColumn); ColumnCapabilities capabilities = columnSelectorFactory.getColumnCapabilities(fieldName); diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/LongLastBufferAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/LongLastBufferAggregator.java similarity index 97% rename from processing/src/main/java/org/apache/druid/query/aggregation/last/LongLastBufferAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/LongLastBufferAggregator.java index a4a318329b77..0aaf00e7f13a 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/LongLastBufferAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/LongLastBufferAggregator.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import org.apache.druid.query.aggregation.SerializablePairLongLong; import org.apache.druid.segment.BaseLongColumnValueSelector; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/LongLastVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/LongLastVectorAggregator.java new file mode 100644 index 000000000000..97c7eecaacdf --- /dev/null +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/LongLastVectorAggregator.java @@ -0,0 +1,38 @@ +/* + * 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.aggregation.firstlast.last; + +import org.apache.druid.query.aggregation.firstlast.LongFirstLastVectorAggregator; +import org.apache.druid.query.aggregation.firstlast.SelectionPredicate; +import org.apache.druid.segment.vector.VectorObjectSelector; +import org.apache.druid.segment.vector.VectorValueSelector; + +public class LongLastVectorAggregator extends LongFirstLastVectorAggregator +{ + public LongLastVectorAggregator(VectorValueSelector timeSelector, VectorObjectSelector objectSelector) + { + super(timeSelector, objectSelector, SelectionPredicate.LAST_PREDICATE); + } + + public LongLastVectorAggregator(VectorValueSelector timeSelector, VectorValueSelector valueSelector) + { + super(timeSelector, valueSelector, SelectionPredicate.LAST_PREDICATE); + } +} diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/NumericLastAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/NumericLastAggregator.java similarity index 95% rename from processing/src/main/java/org/apache/druid/query/aggregation/last/NumericLastAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/NumericLastAggregator.java index 50d4470fa54a..be2904d34d7d 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/NumericLastAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/NumericLastAggregator.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import org.apache.druid.collections.SerializablePair; import org.apache.druid.common.config.NullHandling; @@ -28,7 +28,7 @@ /** * Base type for on heap 'last' aggregator for primitive numeric column selectors.. * - * This could probably share a base class with {@link org.apache.druid.query.aggregation.first.NumericFirstAggregator} + * This could probably share a base class with {@link org.apache.druid.query.aggregation.firstlast.first.NumericFirstAggregator} */ public abstract class NumericLastAggregator implements Aggregator { diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/NumericLastBufferAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/NumericLastBufferAggregator.java similarity index 96% rename from processing/src/main/java/org/apache/druid/query/aggregation/last/NumericLastBufferAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/NumericLastBufferAggregator.java index 2ba15a7929d3..cc1190fce0ec 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/NumericLastBufferAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/NumericLastBufferAggregator.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import org.apache.druid.collections.SerializablePair; import org.apache.druid.common.config.NullHandling; @@ -32,7 +32,7 @@ * Base type for buffer based 'last' aggregator for primitive numeric column selectors * * This could probably share a base type with - * {@link org.apache.druid.query.aggregation.first.NumericFirstBufferAggregator} ... + * {@link org.apache.druid.query.aggregation.firstlast.first.NumericFirstBufferAggregator} ... */ public abstract class NumericLastBufferAggregator implements BufferAggregator { diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/SingleStringLastDimensionVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/SingleStringLastDimensionVectorAggregator.java new file mode 100644 index 000000000000..aaaeb2039bdc --- /dev/null +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/SingleStringLastDimensionVectorAggregator.java @@ -0,0 +1,38 @@ +/* + * 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.aggregation.firstlast.last; + +import org.apache.druid.query.aggregation.firstlast.SelectionPredicate; +import org.apache.druid.query.aggregation.firstlast.SingleStringFirstLastDimensionVectorAggregator; +import org.apache.druid.segment.vector.SingleValueDimensionVectorSelector; +import org.apache.druid.segment.vector.VectorValueSelector; + +public class SingleStringLastDimensionVectorAggregator extends SingleStringFirstLastDimensionVectorAggregator +{ + + public SingleStringLastDimensionVectorAggregator( + VectorValueSelector timeSelector, + SingleValueDimensionVectorSelector singleValueDimensionVectorSelector, + int maxStringBytes + ) + { + super(timeSelector, singleValueDimensionVectorSelector, maxStringBytes, SelectionPredicate.LAST_PREDICATE); + } +} diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/StringLastAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastAggregator.java similarity index 96% rename from processing/src/main/java/org/apache/druid/query/aggregation/last/StringLastAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastAggregator.java index f1dbab60938b..da6c474f8022 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/StringLastAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastAggregator.java @@ -17,13 +17,13 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import org.apache.druid.java.util.common.DateTimes; import org.apache.druid.java.util.common.StringUtils; import org.apache.druid.query.aggregation.Aggregator; import org.apache.druid.query.aggregation.SerializablePairLongString; -import org.apache.druid.query.aggregation.first.StringFirstLastUtils; +import org.apache.druid.query.aggregation.firstlast.StringFirstLastUtils; import org.apache.druid.segment.BaseLongColumnValueSelector; import org.apache.druid.segment.BaseObjectColumnValueSelector; import org.apache.druid.segment.DimensionHandlerUtils; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/StringLastAggregatorFactory.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastAggregatorFactory.java similarity index 94% rename from processing/src/main/java/org/apache/druid/query/aggregation/last/StringLastAggregatorFactory.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastAggregatorFactory.java index a9bb2f0bbd6f..8e69d7018924 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/StringLastAggregatorFactory.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastAggregatorFactory.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -32,8 +32,8 @@ import org.apache.druid.query.aggregation.BufferAggregator; import org.apache.druid.query.aggregation.SerializablePairLongString; import org.apache.druid.query.aggregation.VectorAggregator; -import org.apache.druid.query.aggregation.first.FirstLastUtils; -import org.apache.druid.query.aggregation.first.StringFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.FirstLastUtils; +import org.apache.druid.query.aggregation.firstlast.first.StringFirstAggregatorFactory; import org.apache.druid.query.cache.CacheKeyBuilder; import org.apache.druid.query.dimension.DefaultDimensionSpec; import org.apache.druid.segment.BaseObjectColumnValueSelector; @@ -182,7 +182,11 @@ public VectorAggregator factorizeVector(VectorColumnSelectorFactory selectorFact SingleValueDimensionVectorSelector sSelector = selectorFactory.makeSingleValueDimensionSelector( DefaultDimensionSpec.of( fieldName)); - return new SingleStringLastDimensionVectorAggregator(timeSelector, sSelector, maxStringBytes); + // Relies on storing the id, and possibly retrieving it at a later stage, therefore name lookup should be + // possible for non current rows + if (sSelector.nameLookupPossibleInAdvance()) { + return new SingleStringLastDimensionVectorAggregator(timeSelector, sSelector, maxStringBytes); + } } } } diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/StringLastBufferAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastBufferAggregator.java similarity index 97% rename from processing/src/main/java/org/apache/druid/query/aggregation/last/StringLastBufferAggregator.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastBufferAggregator.java index 3f78745f5fad..878cd36025c9 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/StringLastBufferAggregator.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastBufferAggregator.java @@ -17,12 +17,12 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import org.apache.druid.java.util.common.DateTimes; import org.apache.druid.query.aggregation.BufferAggregator; import org.apache.druid.query.aggregation.SerializablePairLongString; -import org.apache.druid.query.aggregation.first.StringFirstLastUtils; +import org.apache.druid.query.aggregation.firstlast.StringFirstLastUtils; import org.apache.druid.query.monomorphicprocessing.RuntimeShapeInspector; import org.apache.druid.segment.BaseLongColumnValueSelector; import org.apache.druid.segment.BaseObjectColumnValueSelector; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/StringLastFoldingAggregatorFactory.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastFoldingAggregatorFactory.java similarity index 96% rename from processing/src/main/java/org/apache/druid/query/aggregation/last/StringLastFoldingAggregatorFactory.java rename to processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastFoldingAggregatorFactory.java index ad18eeebadc4..5abc2083b186 100644 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/StringLastFoldingAggregatorFactory.java +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastFoldingAggregatorFactory.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import com.fasterxml.jackson.annotation.JsonCreator; import org.apache.druid.query.aggregation.AggregatorFactory; diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastVectorAggregator.java new file mode 100644 index 000000000000..d0529d96e7ba --- /dev/null +++ b/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastVectorAggregator.java @@ -0,0 +1,39 @@ +/* + * 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.aggregation.firstlast.last; + +import org.apache.druid.query.aggregation.firstlast.SelectionPredicate; +import org.apache.druid.query.aggregation.firstlast.StringFirstLastVectorAggregator; +import org.apache.druid.segment.vector.VectorObjectSelector; +import org.apache.druid.segment.vector.VectorValueSelector; + +import javax.annotation.Nullable; + +public class StringLastVectorAggregator extends StringFirstLastVectorAggregator +{ + public StringLastVectorAggregator( + @Nullable VectorValueSelector timeSelector, + VectorObjectSelector objectSelector, + int maxStringBytes + ) + { + super(timeSelector, objectSelector, maxStringBytes, SelectionPredicate.LAST_PREDICATE); + } +} diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/LongLastVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/last/LongLastVectorAggregator.java deleted file mode 100644 index 65fadf549a76..000000000000 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/LongLastVectorAggregator.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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.aggregation.last; - -import org.apache.druid.query.aggregation.SerializablePairLongLong; -import org.apache.druid.segment.vector.VectorObjectSelector; -import org.apache.druid.segment.vector.VectorValueSelector; - -import javax.annotation.Nullable; -import java.nio.ByteBuffer; - -/** - * Vectorized version of on heap 'last' aggregator for column selectors with type LONG.. - */ -public class LongLastVectorAggregator extends NumericLastVectorAggregator -{ - long lastValue; - - public LongLastVectorAggregator(VectorValueSelector timeSelector, VectorObjectSelector objectSelector) - { - super(timeSelector, null, objectSelector); - lastValue = 0; - } - - public LongLastVectorAggregator(VectorValueSelector timeSelector, VectorValueSelector valueSelector) - { - super(timeSelector, valueSelector, null); - lastValue = 0; - } - - @Override - public void initValue(ByteBuffer buf, int position) - { - buf.putLong(position, 0); - } - - @Override - void putValue(ByteBuffer buf, int position, int index) - { - lastValue = valueSelector != null ? valueSelector.getLongVector()[index] : ((SerializablePairLongLong) objectSelector.getObjectVector()[index]).getRhs(); - buf.putLong(position, lastValue); - } - - - /** - * @return The primitive object stored at the position in the buffer. - */ - @Nullable - @Override - public Object get(ByteBuffer buf, int position) - { - final boolean rhsNull = isValueNull(buf, position); - return new SerializablePairLongLong(buf.getLong(position), rhsNull ? null : buf.getLong(position + VALUE_OFFSET)); - } -} diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/NumericLastVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/last/NumericLastVectorAggregator.java deleted file mode 100644 index a556c3fea186..000000000000 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/NumericLastVectorAggregator.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * 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.aggregation.last; - -import org.apache.druid.collections.SerializablePair; -import org.apache.druid.common.config.NullHandling; -import org.apache.druid.query.aggregation.VectorAggregator; -import org.apache.druid.segment.vector.VectorObjectSelector; -import org.apache.druid.segment.vector.VectorValueSelector; - -import javax.annotation.Nullable; -import java.nio.ByteBuffer; - -/** - * Base type for vectorized version of on heap 'last' aggregator for primitive numeric column selectors.. - */ -public abstract class NumericLastVectorAggregator implements VectorAggregator -{ - static final int NULL_OFFSET = Long.BYTES; - static final int VALUE_OFFSET = NULL_OFFSET + Byte.BYTES; - final VectorValueSelector valueSelector; - final VectorObjectSelector objectSelector; - private final boolean useDefault = NullHandling.replaceWithDefault(); - private final VectorValueSelector timeSelector; - private long lastTime; - - - NumericLastVectorAggregator(VectorValueSelector timeSelector, VectorValueSelector valueSelector, VectorObjectSelector objectSelector) - { - this.timeSelector = timeSelector; - this.valueSelector = valueSelector; - this.objectSelector = objectSelector; - lastTime = Long.MIN_VALUE; - } - - @Override - public void init(ByteBuffer buf, int position) - { - buf.putLong(position, Long.MIN_VALUE); - buf.put(position + NULL_OFFSET, useDefault ? NullHandling.IS_NOT_NULL_BYTE : NullHandling.IS_NULL_BYTE); - initValue(buf, position + VALUE_OFFSET); - } - - @Override - public void aggregate(ByteBuffer buf, int position, int startRow, int endRow) - { - if (timeSelector == null) { - return; - } - - final long[] timeVector = timeSelector.getLongVector(); - Object[] objectsWhichMightBeNumeric = null; - boolean[] nullValueVector = null; - boolean nullAbsent = false; - - if (objectSelector != null) { - objectsWhichMightBeNumeric = objectSelector.getObjectVector(); - } else if (valueSelector != null) { - nullValueVector = valueSelector.getNullVector(); - } - - lastTime = buf.getLong(position); - - if (nullValueVector == null) { - nullAbsent = true; - } - - //the time vector is already sorted so the last element would be the latest - //traverse the value vector from the back (for latest) - int index = endRow - 1; - if (!useDefault && !nullAbsent) { - for (int i = endRow - 1; i >= startRow; i--) { - if (!nullValueVector[i]) { - index = i; - break; - } - } - } - - if (objectsWhichMightBeNumeric != null) { - final SerializablePair inPair = (SerializablePair) objectsWhichMightBeNumeric[index]; - if (inPair != null && inPair.lhs != null && inPair.lhs >= lastTime) { - lastTime = inPair.lhs; - if (useDefault || inPair.rhs != null) { - updateTimeWithValue(buf, position, lastTime, index); - } else { - updateTimeWithNull(buf, position, lastTime); - } - } - } else { - final long latestTime = timeVector[index]; - if (latestTime >= lastTime) { - lastTime = latestTime; - if (useDefault || nullValueVector == null || !nullValueVector[index]) { - updateTimeWithValue(buf, position, lastTime, index); - } else { - updateTimeWithNull(buf, position, lastTime); - } - } - } - } - - /** - * - * Checks if the aggregated value at a position in the buffer is null or not - * - * @param buf byte buffer storing the byte array representation of the aggregate - * @param position offset within the byte buffer at which the current aggregate value is stored - * @return - */ - boolean isValueNull(ByteBuffer buf, int position) - { - return buf.get(position + NULL_OFFSET) == NullHandling.IS_NULL_BYTE; - } - - @Override - public void aggregate( - ByteBuffer buf, - int numRows, - int[] positions, - @Nullable int[] rows, - int positionOffset - ) - { - if (timeSelector == null) { - return; - } - - final long[] timeVector = timeSelector.getLongVector(); - Object[] objectsWhichMightBeNumeric = null; - boolean[] nulls = null; - - if (objectSelector != null) { - objectsWhichMightBeNumeric = objectSelector.getObjectVector(); - } else if (valueSelector != null) { - nulls = useDefault ? null : valueSelector.getNullVector(); - } - - - - for (int i = 0; i < numRows; i++) { - int position = positions[i] + positionOffset; - int row = rows == null ? i : rows[i]; - long lastTime = buf.getLong(position); - - if (objectsWhichMightBeNumeric != null) { - final SerializablePair inPair = (SerializablePair) objectsWhichMightBeNumeric[row]; - if (useDefault || inPair != null) { - if (inPair.lhs != null && inPair.lhs >= lastTime) { - if (inPair.rhs != null) { - updateTimeWithValue(buf, position, inPair.lhs, row); - } else { - updateTimeWithNull(buf, position, inPair.lhs); - } - } - } - } else { - if (timeVector[row] >= lastTime) { - if (useDefault || nulls == null || !nulls[row]) { - updateTimeWithValue(buf, position, timeVector[row], row); - } else { - updateTimeWithNull(buf, position, timeVector[row]); - } - } - } - } - } - - /** - * - * @param buf byte buffer storing the byte array representation of the aggregate - * @param position offset within the byte buffer at which the current aggregate value is stored - * @param time the time to be updated in the buffer as the last time - * @param index he index of the vectorized vector which is the last value - */ - void updateTimeWithValue(ByteBuffer buf, int position, long time, int index) - { - buf.putLong(position, time); - buf.put(position + NULL_OFFSET, NullHandling.IS_NOT_NULL_BYTE); - putValue(buf, position + VALUE_OFFSET, index); - } - - /** - * - * @param buf byte buffer storing the byte array representation of the aggregate - * @param position offset within the byte buffer at which the current aggregate value is stored - * @param time the time to be updated in the buffer as the last time - */ - void updateTimeWithNull(ByteBuffer buf, int position, long time) - { - buf.putLong(position, time); - buf.put(position + NULL_OFFSET, NullHandling.IS_NULL_BYTE); - } - - /** - *Abstract function which needs to be overridden by subclasses to set the initial value - */ - abstract void initValue(ByteBuffer buf, int position); - - /** - *Abstract function which needs to be overridden by subclasses to set the - * latest value in the buffer depending on the datatype - */ - abstract void putValue(ByteBuffer buf, int position, int index); - - @Override - public void close() - { - // no resources to cleanup - } -} diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/SingleStringLastDimensionVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/last/SingleStringLastDimensionVectorAggregator.java deleted file mode 100644 index 6b39088faa2e..000000000000 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/SingleStringLastDimensionVectorAggregator.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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.aggregation.last; - -import org.apache.druid.common.config.NullHandling; -import org.apache.druid.java.util.common.StringUtils; -import org.apache.druid.query.aggregation.SerializablePairLongString; -import org.apache.druid.query.aggregation.VectorAggregator; -import org.apache.druid.segment.vector.SingleValueDimensionVectorSelector; -import org.apache.druid.segment.vector.VectorValueSelector; - -import javax.annotation.Nullable; -import java.nio.ByteBuffer; - -public class SingleStringLastDimensionVectorAggregator implements VectorAggregator -{ - private final VectorValueSelector timeSelector; - private final SingleValueDimensionVectorSelector valueDimensionVectorSelector; - private long lastTime; - private final int maxStringBytes; - private final boolean useDefault = NullHandling.replaceWithDefault(); - - public SingleStringLastDimensionVectorAggregator( - VectorValueSelector timeSelector, - SingleValueDimensionVectorSelector valueDimensionVectorSelector, - int maxStringBytes - ) - { - this.timeSelector = timeSelector; - this.valueDimensionVectorSelector = valueDimensionVectorSelector; - this.maxStringBytes = maxStringBytes; - this.lastTime = Long.MIN_VALUE; - } - - @Override - public void init(ByteBuffer buf, int position) - { - buf.putLong(position, Long.MIN_VALUE); - buf.put( - position + NumericLastVectorAggregator.NULL_OFFSET, - useDefault ? NullHandling.IS_NOT_NULL_BYTE : NullHandling.IS_NULL_BYTE - ); - buf.putInt(position + NumericLastVectorAggregator.VALUE_OFFSET, 0); - } - - @Override - public void aggregate(ByteBuffer buf, int position, int startRow, int endRow) - { - final long[] timeVector = timeSelector.getLongVector(); - final boolean[] nullTimeVector = timeSelector.getNullVector(); - final int[] valueVector = valueDimensionVectorSelector.getRowVector(); - lastTime = buf.getLong(position); - int index; - - long latestTime; - for (index = endRow - 1; index >= startRow; index--) { - if (nullTimeVector != null && nullTimeVector[index]) { - continue; - } - latestTime = timeVector[index]; - if (latestTime > lastTime) { - lastTime = latestTime; - buf.putLong(position, lastTime); - buf.put(position + NumericLastVectorAggregator.NULL_OFFSET, NullHandling.IS_NOT_NULL_BYTE); - buf.putInt(position + NumericLastVectorAggregator.VALUE_OFFSET, valueVector[index]); - } - } - } - - @Override - public void aggregate(ByteBuffer buf, int numRows, int[] positions, @Nullable int[] rows, int positionOffset) - { - final long[] timeVector = timeSelector.getLongVector(); - final boolean[] nullTimeVector = timeSelector.getNullVector(); - final int[] values = valueDimensionVectorSelector.getRowVector(); - for (int i = numRows - 1; i >= 0; i--) { - if (nullTimeVector != null && nullTimeVector[i]) { - continue; - } - int position = positions[i] + positionOffset; - int row = rows == null ? i : rows[i]; - lastTime = buf.getLong(position); - if (timeVector[row] > lastTime) { - lastTime = timeVector[row]; - buf.putLong(position, lastTime); - buf.put(position + NumericLastVectorAggregator.NULL_OFFSET, NullHandling.IS_NOT_NULL_BYTE); - buf.putInt(position + NumericLastVectorAggregator.VALUE_OFFSET, values[row]); - } - } - } - - @Nullable - @Override - public Object get(ByteBuffer buf, int position) - { - int index = buf.getInt(position + NumericLastVectorAggregator.VALUE_OFFSET); - long earliest = buf.getLong(position); - String strValue = valueDimensionVectorSelector.lookupName(index); - return new SerializablePairLongString(earliest, StringUtils.chop(strValue, maxStringBytes)); - } - - @Override - public void close() - { - // nothing to close - } -} diff --git a/processing/src/main/java/org/apache/druid/query/aggregation/last/StringLastVectorAggregator.java b/processing/src/main/java/org/apache/druid/query/aggregation/last/StringLastVectorAggregator.java deleted file mode 100644 index 09ef10572b59..000000000000 --- a/processing/src/main/java/org/apache/druid/query/aggregation/last/StringLastVectorAggregator.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * 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.aggregation.last; - -import org.apache.druid.java.util.common.DateTimes; -import org.apache.druid.query.aggregation.SerializablePairLongString; -import org.apache.druid.query.aggregation.VectorAggregator; -import org.apache.druid.query.aggregation.first.FirstLastUtils; -import org.apache.druid.query.aggregation.first.StringFirstLastUtils; -import org.apache.druid.segment.DimensionHandlerUtils; -import org.apache.druid.segment.vector.VectorObjectSelector; -import org.apache.druid.segment.vector.VectorValueSelector; - -import javax.annotation.Nullable; -import java.nio.ByteBuffer; - -public class StringLastVectorAggregator implements VectorAggregator -{ - private static final SerializablePairLongString INIT = new SerializablePairLongString( - DateTimes.MIN.getMillis(), - null - ); - private final VectorValueSelector timeSelector; - private final VectorObjectSelector valueSelector; - private final int maxStringBytes; - protected long lastTime; - - public StringLastVectorAggregator( - @Nullable final VectorValueSelector timeSelector, - final VectorObjectSelector valueSelector, - final int maxStringBytes - ) - { - this.timeSelector = timeSelector; - this.valueSelector = valueSelector; - this.maxStringBytes = maxStringBytes; - } - - @Override - public void init(ByteBuffer buf, int position) - { - StringFirstLastUtils.writePair(buf, position, INIT, maxStringBytes); - } - - @Override - public void aggregate(ByteBuffer buf, int position, int startRow, int endRow) - { - if (timeSelector == null) { - return; - } - final long[] times = timeSelector.getLongVector(); - final boolean[] nullTimeVector = timeSelector.getNullVector(); - final Object[] objectsWhichMightBeStrings = valueSelector.getObjectVector(); - - lastTime = buf.getLong(position); - int index; - for (int i = endRow - 1; i >= startRow; i--) { - if (objectsWhichMightBeStrings[i] == null) { - continue; - } - if (times[i] <= lastTime) { - continue; - } - if (nullTimeVector != null && nullTimeVector[i]) { - continue; - } - index = i; - final boolean foldNeeded = FirstLastUtils.objectNeedsFoldCheck(objectsWhichMightBeStrings[index], SerializablePairLongString.class); - if (foldNeeded) { - // Less efficient code path when folding is a possibility (we must read the value selector first just in case - // it's a foldable object). - final SerializablePairLongString inPair = StringFirstLastUtils.readPairFromVectorSelectorsAtIndex( - timeSelector, - valueSelector, - index - ); - if (inPair != null) { - final long lastTime = buf.getLong(position); - if (inPair.lhs >= lastTime) { - StringFirstLastUtils.writePair( - buf, - position, - new SerializablePairLongString(inPair.lhs, inPair.rhs), - maxStringBytes - ); - } - } - } else { - final long time = times[index]; - - if (time >= lastTime) { - final String value = DimensionHandlerUtils.convertObjectToString(objectsWhichMightBeStrings[index]); - lastTime = time; - StringFirstLastUtils.writePair( - buf, - position, - new SerializablePairLongString(time, value), - maxStringBytes - ); - } - } - } - - } - - @Override - public void aggregate( - ByteBuffer buf, - int numRows, - int[] positions, - @Nullable int[] rows, - int positionOffset - ) - { - if (timeSelector == null) { - return; - } - final long[] timeVector = timeSelector.getLongVector(); - final boolean[] nullTimeVector = timeSelector.getNullVector(); - final Object[] objectsWhichMightBeStrings = valueSelector.getObjectVector(); - - // iterate once over the object vector to find first non null element and - // determine if the type is Pair or not - boolean foldNeeded = false; - for (Object obj : objectsWhichMightBeStrings) { - if (obj != null) { - foldNeeded = FirstLastUtils.objectNeedsFoldCheck(obj, SerializablePairLongString.class); - break; - } - } - - for (int i = 0; i < numRows; i++) { - if (nullTimeVector != null && nullTimeVector[i]) { - continue; - } - int position = positions[i] + positionOffset; - int row = rows == null ? i : rows[i]; - long lastTime = buf.getLong(position); - if (timeVector[row] >= lastTime) { - if (foldNeeded) { - final SerializablePairLongString inPair = StringFirstLastUtils.readPairFromVectorSelectorsAtIndex( - timeSelector, - valueSelector, - row - ); - if (inPair != null) { - if (inPair.lhs >= lastTime) { - StringFirstLastUtils.writePair( - buf, - position, - new SerializablePairLongString(inPair.lhs, inPair.rhs), - maxStringBytes - ); - } - } - } else { - final String value = DimensionHandlerUtils.convertObjectToString(objectsWhichMightBeStrings[row]); - lastTime = timeVector[row]; - StringFirstLastUtils.writePair( - buf, - position, - new SerializablePairLongString(lastTime, value), - maxStringBytes - ); - } - } - } - } - - @Nullable - @Override - public Object get(ByteBuffer buf, int position) - { - return StringFirstLastUtils.readPair(buf, position); - } - - @Override - public void close() - { - // nothing to close - } -} - diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/AggregatorFactoryTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/AggregatorFactoryTest.java index 44c998cd89cd..ff7b18c3dca2 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/AggregatorFactoryTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/AggregatorFactoryTest.java @@ -28,15 +28,15 @@ import org.apache.druid.query.aggregation.any.LongAnyAggregatorFactory; import org.apache.druid.query.aggregation.any.StringAnyAggregatorFactory; import org.apache.druid.query.aggregation.cardinality.CardinalityAggregatorFactory; -import org.apache.druid.query.aggregation.first.DoubleFirstAggregatorFactory; -import org.apache.druid.query.aggregation.first.FloatFirstAggregatorFactory; -import org.apache.druid.query.aggregation.first.LongFirstAggregatorFactory; -import org.apache.druid.query.aggregation.first.StringFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.DoubleFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.FloatFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.LongFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.StringFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.DoubleLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.FloatLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.LongLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.StringLastAggregatorFactory; import org.apache.druid.query.aggregation.hyperloglog.HyperUniquesAggregatorFactory; -import org.apache.druid.query.aggregation.last.DoubleLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.FloatLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.LongLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.StringLastAggregatorFactory; import org.apache.druid.query.aggregation.mean.DoubleMeanAggregatorFactory; import org.apache.druid.query.aggregation.post.FinalizingFieldAccessPostAggregator; import org.apache.druid.query.dimension.DefaultDimensionSpec; diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/first/DoubleFirstAggregationTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/DoubleFirstAggregationTest.java similarity index 99% rename from processing/src/test/java/org/apache/druid/query/aggregation/first/DoubleFirstAggregationTest.java rename to processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/DoubleFirstAggregationTest.java index 7109a0a47961..1d521d1a5c95 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/first/DoubleFirstAggregationTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/DoubleFirstAggregationTest.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import org.apache.druid.jackson.DefaultObjectMapper; import org.apache.druid.java.util.common.Pair; diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/first/DoubleFirstVectorAggregationTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/DoubleFirstVectorAggregatorTest.java similarity index 86% rename from processing/src/test/java/org/apache/druid/query/aggregation/first/DoubleFirstVectorAggregationTest.java rename to processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/DoubleFirstVectorAggregatorTest.java index e055930a2169..734d7e3d6e8c 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/first/DoubleFirstVectorAggregationTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/DoubleFirstVectorAggregatorTest.java @@ -17,15 +17,18 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; +import org.apache.druid.java.util.common.DateTimes; import org.apache.druid.java.util.common.Pair; import org.apache.druid.query.aggregation.SerializablePairLongDouble; import org.apache.druid.query.aggregation.VectorAggregator; +import org.apache.druid.query.aggregation.firstlast.FirstLastVectorAggregator; import org.apache.druid.query.dimension.DimensionSpec; import org.apache.druid.segment.column.ColumnCapabilities; import org.apache.druid.segment.column.ColumnCapabilitiesImpl; import org.apache.druid.segment.column.ColumnType; +import org.apache.druid.segment.vector.BaseDoubleVectorValueSelector; import org.apache.druid.segment.vector.BaseLongVectorValueSelector; import org.apache.druid.segment.vector.MultiValueDimensionVectorSelector; import org.apache.druid.segment.vector.NoFilterVectorOffset; @@ -43,7 +46,7 @@ import java.nio.ByteBuffer; import java.util.concurrent.ThreadLocalRandom; -public class DoubleFirstVectorAggregationTest extends InitializedNullHandlingTest +public class DoubleFirstVectorAggregatorTest extends InitializedNullHandlingTest { private static final double EPSILON = 1e-5; private static final double[] VALUES = new double[]{7.8d, 11, 23.67, 60}; @@ -69,7 +72,8 @@ public class DoubleFirstVectorAggregationTest extends InitializedNullHandlingTes private DoubleFirstAggregatorFactory doubleFirstAggregatorFactory; private VectorColumnSelectorFactory selectorFactory; - private VectorValueSelector nonLongValueSelector; + private VectorValueSelector longValueSelector; + private VectorValueSelector doubleValueSelector; @Before public void setup() @@ -115,7 +119,7 @@ public int getCurrentVectorSize() } }; - nonLongValueSelector = new BaseLongVectorValueSelector(new NoFilterVectorOffset( + longValueSelector = new BaseLongVectorValueSelector(new NoFilterVectorOffset( LONG_VALUES.length, 0, LONG_VALUES.length @@ -159,6 +163,22 @@ public int getCurrentVectorSize() } }; + doubleValueSelector = new BaseDoubleVectorValueSelector(new NoFilterVectorOffset(VALUES.length, 0, VALUES.length)) + { + @Override + public double[] getDoubleVector() + { + return VALUES; + } + + @Nullable + @Override + public boolean[] getNullVector() + { + return null; + } + }; + selectorFactory = new VectorColumnSelectorFactory() { @Override @@ -185,7 +205,9 @@ public VectorValueSelector makeValueSelector(String column) if (TIME_COL.equals(column)) { return timeSelector; } else if (FIELD_NAME_LONG.equals(column)) { - return nonLongValueSelector; + return longValueSelector; + } else if (FIELD_NAME.equals(column)) { + return doubleValueSelector; } return null; } @@ -230,15 +252,15 @@ public void testFactory() } @Test - public void initValueShouldInitZero() + public void testInit() { - target.initValue(buf, 0); - double initVal = buf.getDouble(0); - Assert.assertEquals(0, initVal, EPSILON); + target.init(buf, 0); + Assert.assertEquals(DateTimes.MAX.getMillis(), buf.getLong(0)); + Assert.assertEquals(0, buf.getDouble(FirstLastVectorAggregator.VALUE_OFFSET), EPSILON); } @Test - public void aggregate() + public void testAggregate() { target.aggregate(buf, 0, 0, pairs.length); Pair result = (Pair) target.get(buf, 0); @@ -247,7 +269,7 @@ public void aggregate() } @Test - public void aggregateWithNulls() + public void testAggregateWithNulls() { target.aggregate(buf, 0, 0, pairs.length); Pair result = (Pair) target.get(buf, 0); @@ -256,7 +278,7 @@ public void aggregateWithNulls() } @Test - public void aggregateBatchWithoutRows() + public void testAggregateBatchWithoutRows() { int[] positions = new int[]{0, 43, 70}; int positionOffset = 2; @@ -270,7 +292,7 @@ public void aggregateBatchWithoutRows() } @Test - public void aggregateBatchWithRows() + public void testAggregateBatchWithRows() { int[] positions = new int[]{0, 43, 70}; int[] rows = new int[]{3, 0, 2}; diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/first/FloatFirstAggregationTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/FloatFirstAggregationTest.java similarity index 99% rename from processing/src/test/java/org/apache/druid/query/aggregation/first/FloatFirstAggregationTest.java rename to processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/FloatFirstAggregationTest.java index 0df142677437..e1d8ee4c7409 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/first/FloatFirstAggregationTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/FloatFirstAggregationTest.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import org.apache.druid.jackson.DefaultObjectMapper; import org.apache.druid.java.util.common.Pair; diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/first/FloatFirstVectorAggregationTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/FloatFirstVectorAggregatorTest.java similarity index 92% rename from processing/src/test/java/org/apache/druid/query/aggregation/first/FloatFirstVectorAggregationTest.java rename to processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/FloatFirstVectorAggregatorTest.java index a95e89bd32af..660fdc91e856 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/first/FloatFirstVectorAggregationTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/FloatFirstVectorAggregatorTest.java @@ -17,12 +17,14 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import org.apache.druid.common.config.NullHandling; +import org.apache.druid.java.util.common.DateTimes; import org.apache.druid.java.util.common.Pair; import org.apache.druid.query.aggregation.SerializablePairLongFloat; import org.apache.druid.query.aggregation.VectorAggregator; +import org.apache.druid.query.aggregation.firstlast.FirstLastVectorAggregator; import org.apache.druid.query.dimension.DimensionSpec; import org.apache.druid.segment.column.ColumnCapabilities; import org.apache.druid.segment.column.ColumnCapabilitiesImpl; @@ -44,7 +46,7 @@ import java.nio.ByteBuffer; import java.util.concurrent.ThreadLocalRandom; -public class FloatFirstVectorAggregationTest extends InitializedNullHandlingTest +public class FloatFirstVectorAggregatorTest extends InitializedNullHandlingTest { private static final double EPSILON = 1e-5; private static final float[] VALUES = new float[]{7.2f, 15.6f, 2.1f, 150.0f}; @@ -261,15 +263,15 @@ public void testFactory() } @Test - public void initValueShouldBeZero() + public void testInit() { - target.initValue(buf, 0); - float initVal = buf.getFloat(0); - Assert.assertEquals(0.0f, initVal, EPSILON); + target.init(buf, 0); + Assert.assertEquals(DateTimes.MAX.getMillis(), buf.getLong(0)); + Assert.assertEquals(0.0f, buf.getDouble(FirstLastVectorAggregator.VALUE_OFFSET), EPSILON); } @Test - public void aggregate() + public void testAggregate() { target.init(buf, 0); target.aggregate(buf, 0, 0, VALUES.length); @@ -279,17 +281,17 @@ public void aggregate() } @Test - public void aggregateNulls1() + public void testAggregateNulls1() { target1.init(buf, 0); target1.aggregate(buf, 0, 0, VALUES.length); Pair result = (Pair) target1.get(buf, 0); - Assert.assertEquals(Long.MAX_VALUE, result.lhs.longValue()); + Assert.assertEquals(pairs[0].lhs.longValue(), result.lhs.longValue()); Assert.assertEquals(NullHandling.defaultFloatValue(), result.rhs); } @Test - public void aggregateWithNulls() + public void testAggregateWithNulls() { target.aggregate(buf, 0, 0, VALUES.length); Pair result = (Pair) target.get(buf, 0); @@ -298,7 +300,7 @@ public void aggregateWithNulls() } @Test - public void aggregateBatchWithoutRows() + public void testAggregateBatchWithoutRows() { int[] positions = new int[]{0, 43, 70}; int positionOffset = 2; @@ -316,7 +318,7 @@ public void aggregateBatchWithoutRows() } @Test - public void aggregateBatchWithRows() + public void testAggregateBatchWithRows() { int[] positions = new int[]{0, 43, 70}; int[] rows = new int[]{3, 2, 0}; diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/first/LongFirstAggregationTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/LongFirstAggregationTest.java similarity index 99% rename from processing/src/test/java/org/apache/druid/query/aggregation/first/LongFirstAggregationTest.java rename to processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/LongFirstAggregationTest.java index 104dbcfa60dd..e11c27c38c77 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/first/LongFirstAggregationTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/LongFirstAggregationTest.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import org.apache.druid.jackson.DefaultObjectMapper; import org.apache.druid.java.util.common.Pair; diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/first/LongFirstVectorAggregationTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/LongFirstVectorAggregatorTest.java similarity index 92% rename from processing/src/test/java/org/apache/druid/query/aggregation/first/LongFirstVectorAggregationTest.java rename to processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/LongFirstVectorAggregatorTest.java index a45e0f25563d..24dd37dd0c24 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/first/LongFirstVectorAggregationTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/LongFirstVectorAggregatorTest.java @@ -17,12 +17,14 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import org.apache.druid.common.config.NullHandling; +import org.apache.druid.java.util.common.DateTimes; import org.apache.druid.java.util.common.Pair; import org.apache.druid.query.aggregation.SerializablePairLongLong; import org.apache.druid.query.aggregation.VectorAggregator; +import org.apache.druid.query.aggregation.firstlast.FirstLastVectorAggregator; import org.apache.druid.query.dimension.DimensionSpec; import org.apache.druid.segment.column.ColumnCapabilities; import org.apache.druid.segment.column.ColumnCapabilitiesImpl; @@ -45,7 +47,7 @@ import java.util.concurrent.ThreadLocalRandom; -public class LongFirstVectorAggregationTest extends InitializedNullHandlingTest +public class LongFirstVectorAggregatorTest extends InitializedNullHandlingTest { private static final double EPSILON = 1e-5; private static final long[] VALUES = new long[]{7, 15, 2, 150}; @@ -188,7 +190,7 @@ public VectorValueSelector makeValueSelector(String column) { if (TIME_COL.equals(column)) { return timeSelector; - } else if (FIELD_NAME_LONG.equals(column)) { + } else if (FIELD_NAME_LONG.equals(column) || FIELD_NAME.equals(column)) { return nonLongValueSelector; } return null; @@ -234,15 +236,15 @@ public void testFactory() } @Test - public void initValueShouldInitZero() + public void testInit() { - target.initValue(buf, 0); - long initVal = buf.getLong(0); - Assert.assertEquals(0, initVal); + target.init(buf, 0); + Assert.assertEquals(DateTimes.MAX.getMillis(), buf.getLong(0)); + Assert.assertEquals(0, buf.getLong(FirstLastVectorAggregator.VALUE_OFFSET)); } @Test - public void aggregate() + public void testAggregate() { target.aggregate(buf, 0, 0, pairs.length); Pair result = (Pair) target.get(buf, 0); @@ -251,7 +253,7 @@ public void aggregate() } @Test - public void aggregateWithNulls() + public void testAggregateWithNulls() { target.aggregate(buf, 0, 0, pairs.length); Pair result = (Pair) target.get(buf, 0); @@ -260,7 +262,7 @@ public void aggregateWithNulls() } @Test - public void aggregateBatchWithoutRows() + public void testAggregateBatchWithoutRows() { int[] positions = new int[]{0, 43, 70}; int positionOffset = 2; @@ -278,7 +280,7 @@ public void aggregateBatchWithoutRows() } @Test - public void aggregateBatchWithRows() + public void testAggregateBatchWithRows() { int[] positions = new int[]{0, 43, 70}; int[] rows = new int[]{3, 2, 0}; diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/first/StringFirstAggregationTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstAggregationTest.java similarity index 99% rename from processing/src/test/java/org/apache/druid/query/aggregation/first/StringFirstAggregationTest.java rename to processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstAggregationTest.java index d2f332f0bb85..6f6bd41f6bc1 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/first/StringFirstAggregationTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstAggregationTest.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import org.apache.druid.common.config.NullHandling; import org.apache.druid.java.util.common.Pair; diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/first/StringFirstBufferAggregatorTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstBufferAggregatorTest.java similarity index 99% rename from processing/src/test/java/org/apache/druid/query/aggregation/first/StringFirstBufferAggregatorTest.java rename to processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstBufferAggregatorTest.java index 2653940ae389..9f72ff8fd313 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/first/StringFirstBufferAggregatorTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstBufferAggregatorTest.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import org.apache.druid.query.aggregation.BufferAggregator; import org.apache.druid.query.aggregation.SerializablePairLongString; diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/first/StringFirstLastUtilsTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstLastUtilsTest.java similarity index 94% rename from processing/src/test/java/org/apache/druid/query/aggregation/first/StringFirstLastUtilsTest.java rename to processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstLastUtilsTest.java index b4e4088535cb..d6b95a89a995 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/first/StringFirstLastUtilsTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstLastUtilsTest.java @@ -17,10 +17,11 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import org.apache.druid.java.util.common.DateTimes; import org.apache.druid.query.aggregation.SerializablePairLongString; +import org.apache.druid.query.aggregation.firstlast.StringFirstLastUtils; import org.junit.Assert; import org.junit.Test; diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/first/StringFirstTimeseriesQueryTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstTimeseriesQueryTest.java similarity index 99% rename from processing/src/test/java/org/apache/druid/query/aggregation/first/StringFirstTimeseriesQueryTest.java rename to processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstTimeseriesQueryTest.java index 267fa52ab639..2e960e6186e3 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/first/StringFirstTimeseriesQueryTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstTimeseriesQueryTest.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/first/StringFirstVectorAggregatorTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstVectorAggregatorTest.java similarity index 96% rename from processing/src/test/java/org/apache/druid/query/aggregation/first/StringFirstVectorAggregatorTest.java rename to processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstVectorAggregatorTest.java index e3b461da5687..2652431e083c 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/first/StringFirstVectorAggregatorTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstVectorAggregatorTest.java @@ -17,8 +17,9 @@ * under the License. */ -package org.apache.druid.query.aggregation.first; +package org.apache.druid.query.aggregation.firstlast.first; +import org.apache.druid.common.config.NullHandling; import org.apache.druid.java.util.common.DateTimes; import org.apache.druid.java.util.common.Pair; import org.apache.druid.query.aggregation.SerializablePairLongString; @@ -295,7 +296,7 @@ public void testFactory() } @Test - public void initValueShouldBeMaxDate() + public void testInit() { target.init(buf, 0); long initVal = buf.getLong(0); @@ -303,7 +304,7 @@ public void initValueShouldBeMaxDate() } @Test - public void aggregate() + public void testAggregate() { target.aggregate(buf, 0, 0, VALUES.length); Pair result = (Pair) target.get(buf, 0); @@ -325,7 +326,7 @@ public void testStringEarliestOnNonStringColumns() } @Test - public void aggregateBatchWithoutRows() + public void testAggregateBatchWithoutRows() { int[] positions = new int[]{0, 43, 70}; int positionOffset = 2; @@ -334,12 +335,12 @@ public void aggregateBatchWithoutRows() for (int i = 0; i < positions.length; i++) { Pair result = (Pair) target.get(buf, positions[i] + positionOffset); Assert.assertEquals(times[i], result.lhs.longValue()); - Assert.assertEquals(VALUES[i], result.rhs); + Assert.assertEquals(NullHandling.nullToEmptyIfNeeded(VALUES[i]), result.rhs); } } @Test - public void aggregateBatchWithRows() + public void testAggregateBatchWithRows() { int[] positions = new int[]{0, 43, 70}; int[] rows = new int[]{3, 2, 0}; @@ -349,7 +350,7 @@ public void aggregateBatchWithRows() for (int i = 0; i < positions.length; i++) { Pair result = (Pair) target.get(buf, positions[i] + positionOffset); Assert.assertEquals(times[rows[i]], result.lhs.longValue()); - Assert.assertEquals(VALUES[rows[i]], result.rhs); + Assert.assertEquals(NullHandling.nullToEmptyIfNeeded(VALUES[rows[i]]), result.rhs); } } diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/last/DoubleLastAggregationTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/DoubleLastAggregationTest.java similarity index 99% rename from processing/src/test/java/org/apache/druid/query/aggregation/last/DoubleLastAggregationTest.java rename to processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/DoubleLastAggregationTest.java index bbcf9be37a2b..1135fb76ca6f 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/last/DoubleLastAggregationTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/DoubleLastAggregationTest.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import org.apache.druid.jackson.DefaultObjectMapper; import org.apache.druid.java.util.common.Pair; diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/last/DoubleLastVectorAggregatorTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/DoubleLastVectorAggregatorTest.java similarity index 87% rename from processing/src/test/java/org/apache/druid/query/aggregation/last/DoubleLastVectorAggregatorTest.java rename to processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/DoubleLastVectorAggregatorTest.java index d3125f190e1c..16e1bdb43892 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/last/DoubleLastVectorAggregatorTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/DoubleLastVectorAggregatorTest.java @@ -17,15 +17,18 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; +import org.apache.druid.java.util.common.DateTimes; import org.apache.druid.java.util.common.Pair; import org.apache.druid.query.aggregation.SerializablePairLongDouble; import org.apache.druid.query.aggregation.VectorAggregator; +import org.apache.druid.query.aggregation.firstlast.FirstLastVectorAggregator; import org.apache.druid.query.dimension.DimensionSpec; import org.apache.druid.segment.column.ColumnCapabilities; import org.apache.druid.segment.column.ColumnCapabilitiesImpl; import org.apache.druid.segment.column.ColumnType; +import org.apache.druid.segment.vector.BaseDoubleVectorValueSelector; import org.apache.druid.segment.vector.BaseLongVectorValueSelector; import org.apache.druid.segment.vector.MultiValueDimensionVectorSelector; import org.apache.druid.segment.vector.NoFilterVectorOffset; @@ -70,7 +73,8 @@ public class DoubleLastVectorAggregatorTest extends InitializedNullHandlingTest private DoubleLastAggregatorFactory doubleLastAggregatorFactory; private VectorColumnSelectorFactory selectorFactory; - private VectorValueSelector nonLongValueSelector; + private VectorValueSelector longValueSelector; + private VectorValueSelector doubleValueSelector; @Before public void setup() @@ -116,7 +120,7 @@ public int getCurrentVectorSize() } }; - nonLongValueSelector = new BaseLongVectorValueSelector(new NoFilterVectorOffset( + longValueSelector = new BaseLongVectorValueSelector(new NoFilterVectorOffset( LONG_VALUES.length, 0, LONG_VALUES.length @@ -160,6 +164,22 @@ public int getCurrentVectorSize() } }; + doubleValueSelector = new BaseDoubleVectorValueSelector(new NoFilterVectorOffset(VALUES.length, 0, VALUES.length)) + { + @Override + public double[] getDoubleVector() + { + return VALUES; + } + + @Nullable + @Override + public boolean[] getNullVector() + { + return null; + } + }; + selectorFactory = new VectorColumnSelectorFactory() { @Override @@ -186,7 +206,9 @@ public VectorValueSelector makeValueSelector(String column) if (TIME_COL.equals(column)) { return timeSelector; } else if (FIELD_NAME_LONG.equals(column)) { - return nonLongValueSelector; + return longValueSelector; + } else if (FIELD_NAME.equals(column)) { + return doubleValueSelector; } return null; } @@ -231,15 +253,15 @@ public void testFactory() } @Test - public void initValueShouldInitZero() + public void testInit() { - target.initValue(buf, 0); - double initVal = buf.getDouble(0); - Assert.assertEquals(0, initVal, EPSILON); + target.init(buf, 0); + Assert.assertEquals(DateTimes.MIN.getMillis(), buf.getLong(0)); + Assert.assertEquals(0, buf.getDouble(FirstLastVectorAggregator.VALUE_OFFSET), EPSILON); } @Test - public void aggregate() + public void testAggregate() { target.aggregate(buf, 0, 0, pairs.length); Pair result = (Pair) target.get(buf, 0); @@ -248,7 +270,7 @@ public void aggregate() } @Test - public void aggregateWithNulls() + public void testAggregateWithNulls() { target.aggregate(buf, 0, 0, pairs.length); Pair result = (Pair) target.get(buf, 0); @@ -257,7 +279,7 @@ public void aggregateWithNulls() } @Test - public void aggregateBatchWithoutRows() + public void testAggregateBatchWithoutRows() { int[] positions = new int[]{0, 43, 70}; int positionOffset = 2; @@ -271,7 +293,7 @@ public void aggregateBatchWithoutRows() } @Test - public void aggregateBatchWithRows() + public void testAggregateBatchWithRows() { int[] positions = new int[]{0, 43, 70}; int[] rows = new int[]{3, 2, 0}; diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/last/FloatLastAggregationTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/FloatLastAggregationTest.java similarity index 99% rename from processing/src/test/java/org/apache/druid/query/aggregation/last/FloatLastAggregationTest.java rename to processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/FloatLastAggregationTest.java index 7030f6671e1b..77ac1083f454 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/last/FloatLastAggregationTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/FloatLastAggregationTest.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import org.apache.druid.jackson.DefaultObjectMapper; import org.apache.druid.java.util.common.Pair; diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/last/FloatLastVectorAggregatorTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/FloatLastVectorAggregatorTest.java similarity index 92% rename from processing/src/test/java/org/apache/druid/query/aggregation/last/FloatLastVectorAggregatorTest.java rename to processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/FloatLastVectorAggregatorTest.java index 957d585e5fd9..b19767a4ae9c 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/last/FloatLastVectorAggregatorTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/FloatLastVectorAggregatorTest.java @@ -17,12 +17,15 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import org.apache.druid.common.config.NullHandling; +import org.apache.druid.java.util.common.DateTimes; import org.apache.druid.java.util.common.Pair; import org.apache.druid.query.aggregation.SerializablePairLongFloat; import org.apache.druid.query.aggregation.VectorAggregator; +import org.apache.druid.query.aggregation.firstlast.FirstLastVectorAggregator; +import org.apache.druid.query.aggregation.firstlast.FloatFirstLastVectorAggregator; import org.apache.druid.query.dimension.DimensionSpec; import org.apache.druid.segment.column.ColumnCapabilities; import org.apache.druid.segment.column.ColumnCapabilitiesImpl; @@ -69,7 +72,7 @@ public class FloatLastVectorAggregatorTest extends InitializedNullHandlingTest private VectorObjectSelector selector; private BaseLongVectorValueSelector timeSelector; private ByteBuffer buf; - private FloatLastVectorAggregator target; + private FloatFirstLastVectorAggregator target; private FloatLastAggregatorFactory floatLastAggregatorFactory; private VectorColumnSelectorFactory selectorFactory; @@ -235,15 +238,15 @@ public void testFactory() } @Test - public void initValueShouldBeZero() + public void testInit() { - target.initValue(buf, 0); - float initVal = buf.getFloat(0); - Assert.assertEquals(0.0f, initVal, EPSILON); + target.init(buf, 0); + Assert.assertEquals(DateTimes.MIN.getMillis(), buf.getLong(0)); + Assert.assertEquals(0.0f, buf.getFloat(FirstLastVectorAggregator.VALUE_OFFSET), EPSILON); } @Test - public void aggregate() + public void testAggregate() { target.init(buf, 0); target.aggregate(buf, 0, 0, VALUES.length); @@ -253,7 +256,7 @@ public void aggregate() } @Test - public void aggregateWithNulls() + public void testAggregateWithNulls() { target.aggregate(buf, 0, 0, VALUES.length); Pair result = (Pair) target.get(buf, 0); @@ -262,7 +265,7 @@ public void aggregateWithNulls() } @Test - public void aggregateBatchWithoutRows() + public void testAggregateBatchWithoutRows() { int[] positions = new int[]{0, 43, 70}; int positionOffset = 2; @@ -280,7 +283,7 @@ public void aggregateBatchWithoutRows() } @Test - public void aggregateBatchWithRows() + public void testAggregateBatchWithRows() { int[] positions = new int[]{0, 43, 70}; int[] rows = new int[]{3, 2, 0}; diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/last/LongLastAggregationTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/LongLastAggregationTest.java similarity index 99% rename from processing/src/test/java/org/apache/druid/query/aggregation/last/LongLastAggregationTest.java rename to processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/LongLastAggregationTest.java index 111f86884251..6a922b63d5c6 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/last/LongLastAggregationTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/LongLastAggregationTest.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import org.apache.druid.jackson.DefaultObjectMapper; import org.apache.druid.java.util.common.Pair; diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/last/LongLastVectorAggregatorTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/LongLastVectorAggregatorTest.java similarity index 80% rename from processing/src/test/java/org/apache/druid/query/aggregation/last/LongLastVectorAggregatorTest.java rename to processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/LongLastVectorAggregatorTest.java index 6cc8bfa9f5a2..04fffcd7d94d 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/last/LongLastVectorAggregatorTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/LongLastVectorAggregatorTest.java @@ -17,12 +17,14 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import org.apache.druid.common.config.NullHandling; +import org.apache.druid.java.util.common.DateTimes; import org.apache.druid.java.util.common.Pair; import org.apache.druid.query.aggregation.SerializablePairLongLong; import org.apache.druid.query.aggregation.VectorAggregator; +import org.apache.druid.query.aggregation.firstlast.FirstLastVectorAggregator; import org.apache.druid.query.dimension.DimensionSpec; import org.apache.druid.segment.column.ColumnCapabilities; import org.apache.druid.segment.column.ColumnCapabilitiesImpl; @@ -187,7 +189,7 @@ public VectorValueSelector makeValueSelector(String column) { if (TIME_COL.equals(column)) { return timeSelector; - } else if (FIELD_NAME_LONG.equals(column)) { + } else if (FIELD_NAME_LONG.equals(column) || FIELD_NAME.equals(column)) { return nonLongValueSelector; } return null; @@ -233,16 +235,17 @@ public void testFactory() } @Test - public void initValueShouldInitZero() + public void testInit() { - target.initValue(buf, 0); - long initVal = buf.getLong(0); - Assert.assertEquals(0, initVal); + target.init(buf, 0); + Assert.assertEquals(DateTimes.MIN.getMillis(), buf.getLong(0)); + Assert.assertEquals(0, buf.getLong(FirstLastVectorAggregator.VALUE_OFFSET)); } @Test - public void aggregate() + public void testAggregate() { + target.init(buf, 0); target.aggregate(buf, 0, 0, pairs.length); Pair result = (Pair) target.get(buf, 0); Assert.assertEquals(pairs[3].lhs.longValue(), result.lhs.longValue()); @@ -250,7 +253,7 @@ public void aggregate() } @Test - public void aggregateWithNulls() + public void testAggregateWithNulls() { target.aggregate(buf, 0, 0, pairs.length); Pair result = (Pair) target.get(buf, 0); @@ -259,7 +262,7 @@ public void aggregateWithNulls() } @Test - public void aggregateBatchWithoutRows() + public void testAggregateBatchWithoutRows() { int[] positions = new int[]{0, 43, 70}; int positionOffset = 2; @@ -277,7 +280,7 @@ public void aggregateBatchWithoutRows() } @Test - public void aggregateBatchWithRows() + public void testAggregateBatchWithRows() { int[] positions = new int[]{0, 43, 70}; int[] rows = new int[]{3, 2, 0}; @@ -295,6 +298,67 @@ public void aggregateBatchWithRows() } } + @Test + public void testAggregateWithStringifiedLongs() + { + VectorObjectSelector objectSelector = new VectorObjectSelector() + { + @Override + public Object[] getObjectVector() + { + return new Object[]{"1000", "2000", "3000"}; + } + + @Override + public int getMaxVectorSize() + { + return 3; + } + + @Override + public int getCurrentVectorSize() + { + return 3; + } + }; + LongLastVectorAggregator ll = new LongLastVectorAggregator(createLongSelector(new Long[]{1L, 2L, 3L}), objectSelector); + clearBufferForPositions(0, 0); + ll.aggregate(buf, 0, 0, 3); + Pair val = (Pair) ll.get(buf, 0); + Assert.assertEquals(3, (long) val.lhs); + Assert.assertEquals(3000, (long) val.rhs); + } + + private VectorValueSelector createLongSelector(Long[] times) + { + return new BaseLongVectorValueSelector(new NoFilterVectorOffset(times.length, 0, times.length)) + { + @Override + public long[] getLongVector() + { + long[] timesCasted = new long[times.length]; + for (int i = 0; i < times.length; ++i) { + timesCasted[i] = times[i] == null ? 0 : times[i]; + } + return timesCasted; + } + + @Nullable + @Override + public boolean[] getNullVector() + { + if (NullHandling.replaceWithDefault()) { + return null; + } + boolean[] nulls = new boolean[times.length]; + for (int i = 0; i < times.length; ++i) { + nulls[i] = times[i] == null; + } + return nulls; + } + }; + } + private void clearBufferForPositions(int offset, int... positions) { for (int position : positions) { diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/last/StringLastAggregationTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/StringLastAggregationTest.java similarity index 99% rename from processing/src/test/java/org/apache/druid/query/aggregation/last/StringLastAggregationTest.java rename to processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/StringLastAggregationTest.java index 6a6aa1e6509d..974d668b9818 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/last/StringLastAggregationTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/StringLastAggregationTest.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import org.apache.druid.common.config.NullHandling; import org.apache.druid.java.util.common.Pair; diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/last/StringLastBufferAggregatorTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/StringLastBufferAggregatorTest.java similarity index 99% rename from processing/src/test/java/org/apache/druid/query/aggregation/last/StringLastBufferAggregatorTest.java rename to processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/StringLastBufferAggregatorTest.java index 37a1c417e198..4c3d7fea39e8 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/last/StringLastBufferAggregatorTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/StringLastBufferAggregatorTest.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import org.apache.druid.query.aggregation.BufferAggregator; import org.apache.druid.query.aggregation.SerializablePairLongString; diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/last/StringLastTimeseriesQueryTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/StringLastTimeseriesQueryTest.java similarity index 99% rename from processing/src/test/java/org/apache/druid/query/aggregation/last/StringLastTimeseriesQueryTest.java rename to processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/StringLastTimeseriesQueryTest.java index 318a2a47fd68..6bbada405b93 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/last/StringLastTimeseriesQueryTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/StringLastTimeseriesQueryTest.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/last/StringLastVectorAggregatorTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/StringLastVectorAggregatorTest.java similarity index 95% rename from processing/src/test/java/org/apache/druid/query/aggregation/last/StringLastVectorAggregatorTest.java rename to processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/StringLastVectorAggregatorTest.java index da79faae3c15..68aea948d6b1 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/last/StringLastVectorAggregatorTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/firstlast/last/StringLastVectorAggregatorTest.java @@ -17,8 +17,9 @@ * under the License. */ -package org.apache.druid.query.aggregation.last; +package org.apache.druid.query.aggregation.firstlast.last; +import org.apache.druid.common.config.NullHandling; import org.apache.druid.java.util.common.DateTimes; import org.apache.druid.java.util.common.Pair; import org.apache.druid.query.aggregation.SerializablePairLongString; @@ -358,7 +359,7 @@ public void testStringLastOnNonStringColumns() } @Test - public void initValueShouldBeMinDate() + public void testInit() { target.init(buf, 0); long initVal = buf.getLong(0); @@ -366,7 +367,7 @@ public void initValueShouldBeMinDate() } @Test - public void aggregate() + public void testAggregate() { target.aggregate(buf, 0, 0, VALUES.length); Pair result = (Pair) target.get(buf, 0); @@ -375,7 +376,7 @@ public void aggregate() } @Test - public void aggregateNoOp() + public void testAggregateNoOp() { // Test that aggregates run just fine when the input field does not exist StringLastVectorAggregator aggregator = new StringLastVectorAggregator(null, selector, 10); @@ -383,7 +384,7 @@ public void aggregateNoOp() } @Test - public void aggregateBatchNoOp() + public void testAggregateBatchNoOp() { // Test that aggregates run just fine when the input field does not exist StringLastVectorAggregator aggregator = new StringLastVectorAggregator(null, selector, 10); @@ -394,7 +395,7 @@ public void aggregateBatchNoOp() } @Test - public void aggregateBatchWithoutRows() + public void testAggregateBatchWithoutRows() { int[] positions = new int[]{0, 43, 70}; int positionOffset = 2; @@ -403,12 +404,12 @@ public void aggregateBatchWithoutRows() for (int i = 0; i < positions.length; i++) { Pair result = (Pair) target.get(buf, positions[i] + positionOffset); Assert.assertEquals(times[i], result.lhs.longValue()); - Assert.assertEquals(VALUES[i], result.rhs); + Assert.assertEquals(NullHandling.nullToEmptyIfNeeded(VALUES[i]), result.rhs); } } @Test - public void aggregateBatchWithRows() + public void testAggregateBatchWithRows() { int[] positions = new int[]{0, 43, 70}; int[] rows = new int[]{3, 2, 0}; @@ -418,12 +419,12 @@ public void aggregateBatchWithRows() for (int i = 0; i < positions.length; i++) { Pair result = (Pair) target.get(buf, positions[i] + positionOffset); Assert.assertEquals(times[rows[i]], result.lhs.longValue()); - Assert.assertEquals(VALUES[rows[i]], result.rhs); + Assert.assertEquals(NullHandling.nullToEmptyIfNeeded(VALUES[rows[i]]), result.rhs); } } @Test - public void aggregateSingleDim() + public void testAggregateSingleDim() { targetSingleDim.aggregate(buf, 0, 0, VALUES.length); Pair result = (Pair) targetSingleDim.get(buf, 0); @@ -432,7 +433,7 @@ public void aggregateSingleDim() } @Test - public void aggregateBatchWithoutRowsSingleDim() + public void testAggregateBatchWithoutRowsSingleDim() { int[] positions = new int[]{0, 43, 70}; int positionOffset = 2; @@ -446,7 +447,7 @@ public void aggregateBatchWithoutRowsSingleDim() } @Test - public void aggregateBatchWithRowsSingleDim() + public void testAggregateBatchWithRowsSingleDim() { int[] positions = new int[]{0, 43, 70}; int[] rows = new int[]{3, 2, 0}; diff --git a/processing/src/test/java/org/apache/druid/query/aggregation/post/FinalizingFieldAccessPostAggregatorTest.java b/processing/src/test/java/org/apache/druid/query/aggregation/post/FinalizingFieldAccessPostAggregatorTest.java index ceea41d427bc..f5a19119b84c 100644 --- a/processing/src/test/java/org/apache/druid/query/aggregation/post/FinalizingFieldAccessPostAggregatorTest.java +++ b/processing/src/test/java/org/apache/druid/query/aggregation/post/FinalizingFieldAccessPostAggregatorTest.java @@ -34,7 +34,7 @@ import org.apache.druid.query.aggregation.CountAggregator; import org.apache.druid.query.aggregation.CountAggregatorFactory; import org.apache.druid.query.aggregation.PostAggregator; -import org.apache.druid.query.aggregation.first.StringFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.StringFirstAggregatorFactory; import org.apache.druid.query.groupby.GroupByQueryRunnerTest; import org.apache.druid.query.groupby.ResultRow; import org.apache.druid.query.timeseries.TimeseriesQuery; diff --git a/processing/src/test/java/org/apache/druid/query/groupby/GroupByQueryQueryToolChestTest.java b/processing/src/test/java/org/apache/druid/query/groupby/GroupByQueryQueryToolChestTest.java index 0c89afb75e23..d2b599049944 100644 --- a/processing/src/test/java/org/apache/druid/query/groupby/GroupByQueryQueryToolChestTest.java +++ b/processing/src/test/java/org/apache/druid/query/groupby/GroupByQueryQueryToolChestTest.java @@ -51,10 +51,10 @@ import org.apache.druid.query.aggregation.SerializablePairLongFloat; import org.apache.druid.query.aggregation.SerializablePairLongLong; import org.apache.druid.query.aggregation.SerializablePairLongString; -import org.apache.druid.query.aggregation.last.DoubleLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.FloatLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.LongLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.StringLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.DoubleLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.FloatLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.LongLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.StringLastAggregatorFactory; import org.apache.druid.query.aggregation.post.ConstantPostAggregator; import org.apache.druid.query.aggregation.post.ExpressionPostAggregator; import org.apache.druid.query.dimension.DefaultDimensionSpec; diff --git a/processing/src/test/java/org/apache/druid/query/groupby/GroupByQueryRunnerTest.java b/processing/src/test/java/org/apache/druid/query/groupby/GroupByQueryRunnerTest.java index 54cdcf129e92..080d5d5d4ba3 100644 --- a/processing/src/test/java/org/apache/druid/query/groupby/GroupByQueryRunnerTest.java +++ b/processing/src/test/java/org/apache/druid/query/groupby/GroupByQueryRunnerTest.java @@ -76,10 +76,10 @@ import org.apache.druid.query.aggregation.LongMaxAggregatorFactory; import org.apache.druid.query.aggregation.LongSumAggregatorFactory; import org.apache.druid.query.aggregation.cardinality.CardinalityAggregatorFactory; -import org.apache.druid.query.aggregation.first.LongFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.LongFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.LongLastAggregatorFactory; import org.apache.druid.query.aggregation.hyperloglog.HyperUniqueFinalizingPostAggregator; import org.apache.druid.query.aggregation.hyperloglog.HyperUniquesAggregatorFactory; -import org.apache.druid.query.aggregation.last.LongLastAggregatorFactory; import org.apache.druid.query.aggregation.mean.DoubleMeanAggregatorFactory; import org.apache.druid.query.aggregation.post.ArithmeticPostAggregator; import org.apache.druid.query.aggregation.post.ConstantPostAggregator; diff --git a/processing/src/test/java/org/apache/druid/query/timeseries/TimeseriesQueryQueryToolChestTest.java b/processing/src/test/java/org/apache/druid/query/timeseries/TimeseriesQueryQueryToolChestTest.java index b672798b1ba6..f1afabe9c75e 100644 --- a/processing/src/test/java/org/apache/druid/query/timeseries/TimeseriesQueryQueryToolChestTest.java +++ b/processing/src/test/java/org/apache/druid/query/timeseries/TimeseriesQueryQueryToolChestTest.java @@ -36,7 +36,7 @@ import org.apache.druid.query.aggregation.CountAggregatorFactory; import org.apache.druid.query.aggregation.LongSumAggregatorFactory; import org.apache.druid.query.aggregation.SerializablePairLongString; -import org.apache.druid.query.aggregation.last.StringLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.StringLastAggregatorFactory; import org.apache.druid.query.aggregation.post.ArithmeticPostAggregator; import org.apache.druid.query.aggregation.post.ConstantPostAggregator; import org.apache.druid.query.aggregation.post.FieldAccessPostAggregator; diff --git a/processing/src/test/java/org/apache/druid/query/timeseries/TimeseriesQueryRunnerTest.java b/processing/src/test/java/org/apache/druid/query/timeseries/TimeseriesQueryRunnerTest.java index aefad5c6dde9..8f0ffadef8a0 100644 --- a/processing/src/test/java/org/apache/druid/query/timeseries/TimeseriesQueryRunnerTest.java +++ b/processing/src/test/java/org/apache/druid/query/timeseries/TimeseriesQueryRunnerTest.java @@ -54,9 +54,9 @@ import org.apache.druid.query.aggregation.FloatSumAggregatorFactory; import org.apache.druid.query.aggregation.LongSumAggregatorFactory; import org.apache.druid.query.aggregation.cardinality.CardinalityAggregatorFactory; -import org.apache.druid.query.aggregation.first.DoubleFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.DoubleFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.DoubleLastAggregatorFactory; import org.apache.druid.query.aggregation.hyperloglog.HyperUniquesAggregatorFactory; -import org.apache.druid.query.aggregation.last.DoubleLastAggregatorFactory; import org.apache.druid.query.aggregation.post.FieldAccessPostAggregator; import org.apache.druid.query.dimension.DefaultDimensionSpec; import org.apache.druid.query.expression.TestExprMacroTable; diff --git a/processing/src/test/java/org/apache/druid/query/topn/TopNQueryQueryToolChestTest.java b/processing/src/test/java/org/apache/druid/query/topn/TopNQueryQueryToolChestTest.java index 23d202c72be0..f53fc77cb216 100644 --- a/processing/src/test/java/org/apache/druid/query/topn/TopNQueryQueryToolChestTest.java +++ b/processing/src/test/java/org/apache/druid/query/topn/TopNQueryQueryToolChestTest.java @@ -48,11 +48,11 @@ import org.apache.druid.query.aggregation.SerializablePairLongLong; import org.apache.druid.query.aggregation.SerializablePairLongString; import org.apache.druid.query.aggregation.cardinality.CardinalityAggregator; +import org.apache.druid.query.aggregation.firstlast.last.DoubleLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.FloatLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.LongLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.StringLastAggregatorFactory; import org.apache.druid.query.aggregation.hyperloglog.HyperUniquesAggregatorFactory; -import org.apache.druid.query.aggregation.last.DoubleLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.FloatLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.LongLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.StringLastAggregatorFactory; import org.apache.druid.query.aggregation.post.ArithmeticPostAggregator; import org.apache.druid.query.aggregation.post.ConstantPostAggregator; import org.apache.druid.query.aggregation.post.FieldAccessPostAggregator; diff --git a/processing/src/test/java/org/apache/druid/query/topn/TopNQueryRunnerTest.java b/processing/src/test/java/org/apache/druid/query/topn/TopNQueryRunnerTest.java index 4163afb997fa..79adf89fb86b 100644 --- a/processing/src/test/java/org/apache/druid/query/topn/TopNQueryRunnerTest.java +++ b/processing/src/test/java/org/apache/druid/query/topn/TopNQueryRunnerTest.java @@ -59,13 +59,13 @@ import org.apache.druid.query.aggregation.FloatMinAggregatorFactory; import org.apache.druid.query.aggregation.LongSumAggregatorFactory; import org.apache.druid.query.aggregation.cardinality.CardinalityAggregatorFactory; -import org.apache.druid.query.aggregation.first.DoubleFirstAggregatorFactory; -import org.apache.druid.query.aggregation.first.FloatFirstAggregatorFactory; -import org.apache.druid.query.aggregation.first.LongFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.DoubleFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.FloatFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.LongFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.FloatLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.LongLastAggregatorFactory; import org.apache.druid.query.aggregation.hyperloglog.HyperUniqueFinalizingPostAggregator; import org.apache.druid.query.aggregation.hyperloglog.HyperUniquesAggregatorFactory; -import org.apache.druid.query.aggregation.last.FloatLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.LongLastAggregatorFactory; import org.apache.druid.query.aggregation.post.ExpressionPostAggregator; import org.apache.druid.query.context.ResponseContext; import org.apache.druid.query.dimension.DefaultDimensionSpec; diff --git a/processing/src/test/java/org/apache/druid/query/topn/UnnestTopNQueryRunnerTest.java b/processing/src/test/java/org/apache/druid/query/topn/UnnestTopNQueryRunnerTest.java index ba0025490fa1..cb4ee3b942b1 100644 --- a/processing/src/test/java/org/apache/druid/query/topn/UnnestTopNQueryRunnerTest.java +++ b/processing/src/test/java/org/apache/druid/query/topn/UnnestTopNQueryRunnerTest.java @@ -38,7 +38,7 @@ import org.apache.druid.query.aggregation.AggregatorFactory; import org.apache.druid.query.aggregation.DoubleMaxAggregatorFactory; import org.apache.druid.query.aggregation.DoubleMinAggregatorFactory; -import org.apache.druid.query.aggregation.first.DoubleFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.DoubleFirstAggregatorFactory; import org.apache.druid.query.context.ResponseContext; import org.apache.druid.query.expression.TestExprMacroTable; import org.apache.druid.query.ordering.StringComparators; diff --git a/processing/src/test/java/org/apache/druid/segment/IndexMergerRollupTest.java b/processing/src/test/java/org/apache/druid/segment/IndexMergerRollupTest.java index ddea2cbf62b0..c0b8cceb24b6 100644 --- a/processing/src/test/java/org/apache/druid/segment/IndexMergerRollupTest.java +++ b/processing/src/test/java/org/apache/druid/segment/IndexMergerRollupTest.java @@ -23,14 +23,14 @@ import com.google.common.collect.ImmutableMap; import org.apache.druid.data.input.MapBasedInputRow; import org.apache.druid.query.aggregation.AggregatorFactory; -import org.apache.druid.query.aggregation.first.DoubleFirstAggregatorFactory; -import org.apache.druid.query.aggregation.first.FloatFirstAggregatorFactory; -import org.apache.druid.query.aggregation.first.LongFirstAggregatorFactory; -import org.apache.druid.query.aggregation.first.StringFirstAggregatorFactory; -import org.apache.druid.query.aggregation.last.DoubleLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.FloatLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.LongLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.StringLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.DoubleFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.FloatFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.LongFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.StringFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.DoubleLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.FloatLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.LongLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.StringLastAggregatorFactory; import org.apache.druid.segment.data.IncrementalIndexTest; import org.apache.druid.segment.incremental.IncrementalIndex; import org.apache.druid.segment.writeout.OffHeapMemorySegmentWriteOutMediumFactory; diff --git a/processing/src/test/java/org/apache/druid/segment/column/SchemaPayloadPlusTest.java b/processing/src/test/java/org/apache/druid/segment/column/SchemaPayloadPlusTest.java index ac501c1524e8..9fb08fb74ff9 100644 --- a/processing/src/test/java/org/apache/druid/segment/column/SchemaPayloadPlusTest.java +++ b/processing/src/test/java/org/apache/druid/segment/column/SchemaPayloadPlusTest.java @@ -21,7 +21,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.druid.common.config.NullHandling; -import org.apache.druid.query.aggregation.last.StringLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.StringLastAggregatorFactory; import org.apache.druid.segment.SchemaPayload; import org.apache.druid.segment.SchemaPayloadPlus; import org.apache.druid.segment.TestHelper; diff --git a/processing/src/test/java/org/apache/druid/segment/column/SchemaPayloadTest.java b/processing/src/test/java/org/apache/druid/segment/column/SchemaPayloadTest.java index 0878e92d2d8c..dfb352775638 100644 --- a/processing/src/test/java/org/apache/druid/segment/column/SchemaPayloadTest.java +++ b/processing/src/test/java/org/apache/druid/segment/column/SchemaPayloadTest.java @@ -21,7 +21,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.druid.common.config.NullHandling; -import org.apache.druid.query.aggregation.last.StringLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.StringLastAggregatorFactory; import org.apache.druid.segment.SchemaPayload; import org.apache.druid.segment.TestHelper; import org.junit.Assert; diff --git a/processing/src/test/java/org/apache/druid/segment/column/SegmentSchemaMappingTest.java b/processing/src/test/java/org/apache/druid/segment/column/SegmentSchemaMappingTest.java index 38c9362a11ce..4272e67433cc 100644 --- a/processing/src/test/java/org/apache/druid/segment/column/SegmentSchemaMappingTest.java +++ b/processing/src/test/java/org/apache/druid/segment/column/SegmentSchemaMappingTest.java @@ -21,7 +21,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.druid.common.config.NullHandling; -import org.apache.druid.query.aggregation.last.StringLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.StringLastAggregatorFactory; import org.apache.druid.segment.SchemaPayload; import org.apache.druid.segment.SchemaPayloadPlus; import org.apache.druid.segment.SegmentMetadata; diff --git a/server/src/test/java/org/apache/druid/segment/metadata/FingerprintGeneratorTest.java b/server/src/test/java/org/apache/druid/segment/metadata/FingerprintGeneratorTest.java index 3d35691c7fb4..093585508029 100644 --- a/server/src/test/java/org/apache/druid/segment/metadata/FingerprintGeneratorTest.java +++ b/server/src/test/java/org/apache/druid/segment/metadata/FingerprintGeneratorTest.java @@ -22,7 +22,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.druid.common.config.NullHandling; import org.apache.druid.query.aggregation.AggregatorFactory; -import org.apache.druid.query.aggregation.first.LongFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.LongFirstAggregatorFactory; import org.apache.druid.segment.SchemaPayload; import org.apache.druid.segment.TestHelper; import org.apache.druid.segment.column.ColumnType; diff --git a/server/src/test/java/org/apache/druid/segment/metadata/SegmentSchemaBackFillQueueTest.java b/server/src/test/java/org/apache/druid/segment/metadata/SegmentSchemaBackFillQueueTest.java index e014c21e961b..238b5acc5442 100644 --- a/server/src/test/java/org/apache/druid/segment/metadata/SegmentSchemaBackFillQueueTest.java +++ b/server/src/test/java/org/apache/druid/segment/metadata/SegmentSchemaBackFillQueueTest.java @@ -28,7 +28,7 @@ import org.apache.druid.java.util.common.concurrent.ScheduledExecutors; import org.apache.druid.metadata.TestDerbyConnector; import org.apache.druid.query.aggregation.AggregatorFactory; -import org.apache.druid.query.aggregation.first.LongFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.LongFirstAggregatorFactory; import org.apache.druid.segment.SchemaPayload; import org.apache.druid.segment.TestHelper; import org.apache.druid.segment.column.ColumnType; diff --git a/server/src/test/java/org/apache/druid/segment/metadata/SegmentSchemaManagerTest.java b/server/src/test/java/org/apache/druid/segment/metadata/SegmentSchemaManagerTest.java index a79b89f79b39..ed6a567644d4 100644 --- a/server/src/test/java/org/apache/druid/segment/metadata/SegmentSchemaManagerTest.java +++ b/server/src/test/java/org/apache/druid/segment/metadata/SegmentSchemaManagerTest.java @@ -28,7 +28,7 @@ import org.apache.druid.metadata.MetadataStorageTablesConfig; import org.apache.druid.metadata.TestDerbyConnector; import org.apache.druid.query.aggregation.AggregatorFactory; -import org.apache.druid.query.aggregation.first.LongFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.LongFirstAggregatorFactory; import org.apache.druid.segment.SchemaPayload; import org.apache.druid.segment.SchemaPayloadPlus; import org.apache.druid.segment.TestHelper; diff --git a/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/builtin/EarliestLatestAnySqlAggregator.java b/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/builtin/EarliestLatestAnySqlAggregator.java index b47985ea95a9..73209a76a987 100644 --- a/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/builtin/EarliestLatestAnySqlAggregator.java +++ b/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/builtin/EarliestLatestAnySqlAggregator.java @@ -51,14 +51,14 @@ import org.apache.druid.query.aggregation.any.FloatAnyAggregatorFactory; import org.apache.druid.query.aggregation.any.LongAnyAggregatorFactory; import org.apache.druid.query.aggregation.any.StringAnyAggregatorFactory; -import org.apache.druid.query.aggregation.first.DoubleFirstAggregatorFactory; -import org.apache.druid.query.aggregation.first.FloatFirstAggregatorFactory; -import org.apache.druid.query.aggregation.first.LongFirstAggregatorFactory; -import org.apache.druid.query.aggregation.first.StringFirstAggregatorFactory; -import org.apache.druid.query.aggregation.last.DoubleLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.FloatLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.LongLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.StringLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.DoubleFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.FloatFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.LongFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.StringFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.DoubleLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.FloatLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.LongLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.StringLastAggregatorFactory; import org.apache.druid.query.aggregation.post.FinalizingFieldAccessPostAggregator; import org.apache.druid.segment.column.ColumnHolder; import org.apache.druid.segment.column.ColumnType; 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 661785cb9db5..ba0ce0539e5c 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 @@ -65,16 +65,16 @@ import org.apache.druid.query.aggregation.any.LongAnyAggregatorFactory; import org.apache.druid.query.aggregation.any.StringAnyAggregatorFactory; import org.apache.druid.query.aggregation.cardinality.CardinalityAggregatorFactory; -import org.apache.druid.query.aggregation.first.DoubleFirstAggregatorFactory; -import org.apache.druid.query.aggregation.first.FloatFirstAggregatorFactory; -import org.apache.druid.query.aggregation.first.LongFirstAggregatorFactory; -import org.apache.druid.query.aggregation.first.StringFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.DoubleFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.FloatFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.LongFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.StringFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.DoubleLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.FloatLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.LongLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.StringLastAggregatorFactory; import org.apache.druid.query.aggregation.hyperloglog.HyperUniqueFinalizingPostAggregator; import org.apache.druid.query.aggregation.hyperloglog.HyperUniquesAggregatorFactory; -import org.apache.druid.query.aggregation.last.DoubleLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.FloatLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.LongLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.StringLastAggregatorFactory; import org.apache.druid.query.aggregation.post.ArithmeticPostAggregator; import org.apache.druid.query.aggregation.post.FieldAccessPostAggregator; import org.apache.druid.query.aggregation.post.FinalizingFieldAccessPostAggregator; diff --git a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteSimpleQueryTest.java b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteSimpleQueryTest.java index 6fe2205a7ae0..3d7d2a2de33e 100644 --- a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteSimpleQueryTest.java +++ b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteSimpleQueryTest.java @@ -24,8 +24,8 @@ import org.apache.druid.java.util.common.Intervals; import org.apache.druid.java.util.common.granularity.Granularities; import org.apache.druid.query.aggregation.LongSumAggregatorFactory; -import org.apache.druid.query.aggregation.first.StringFirstAggregatorFactory; -import org.apache.druid.query.aggregation.last.StringLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.StringFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.StringLastAggregatorFactory; import org.apache.druid.query.dimension.DefaultDimensionSpec; import org.apache.druid.query.filter.LikeDimFilter; import org.apache.druid.query.groupby.GroupByQuery; diff --git a/sql/src/test/java/org/apache/druid/sql/calcite/util/TestDataBuilder.java b/sql/src/test/java/org/apache/druid/sql/calcite/util/TestDataBuilder.java index f1aba574448a..c914532a3b90 100644 --- a/sql/src/test/java/org/apache/druid/sql/calcite/util/TestDataBuilder.java +++ b/sql/src/test/java/org/apache/druid/sql/calcite/util/TestDataBuilder.java @@ -49,12 +49,12 @@ import org.apache.druid.query.aggregation.DoubleSumAggregatorFactory; import org.apache.druid.query.aggregation.FloatSumAggregatorFactory; import org.apache.druid.query.aggregation.LongSumAggregatorFactory; -import org.apache.druid.query.aggregation.first.DoubleFirstAggregatorFactory; -import org.apache.druid.query.aggregation.first.LongFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.DoubleFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.first.LongFirstAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.DoubleLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.FloatLastAggregatorFactory; +import org.apache.druid.query.aggregation.firstlast.last.LongLastAggregatorFactory; import org.apache.druid.query.aggregation.hyperloglog.HyperUniquesAggregatorFactory; -import org.apache.druid.query.aggregation.last.DoubleLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.FloatLastAggregatorFactory; -import org.apache.druid.query.aggregation.last.LongLastAggregatorFactory; import org.apache.druid.query.groupby.GroupByQueryConfig; import org.apache.druid.query.lookup.LookupExtractorFactoryContainerProvider; import org.apache.druid.segment.IndexBuilder;