| /* |
| * 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.variance.sql; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.inject.Injector; |
| import org.apache.druid.common.config.NullHandling; |
| import org.apache.druid.data.input.InputRow; |
| import org.apache.druid.data.input.impl.DimensionSchema; |
| import org.apache.druid.data.input.impl.DimensionsSpec; |
| import org.apache.druid.data.input.impl.DoubleDimensionSchema; |
| import org.apache.druid.data.input.impl.FloatDimensionSchema; |
| import org.apache.druid.data.input.impl.LongDimensionSchema; |
| import org.apache.druid.guice.DruidInjectorBuilder; |
| import org.apache.druid.java.util.common.granularity.Granularities; |
| import org.apache.druid.math.expr.ExprMacroTable; |
| import org.apache.druid.query.Druids; |
| import org.apache.druid.query.QueryRunnerFactoryConglomerate; |
| import org.apache.druid.query.aggregation.CountAggregatorFactory; |
| import org.apache.druid.query.aggregation.DoubleSumAggregatorFactory; |
| import org.apache.druid.query.aggregation.FilteredAggregatorFactory; |
| import org.apache.druid.query.aggregation.stats.DruidStatsModule; |
| import org.apache.druid.query.aggregation.variance.StandardDeviationPostAggregator; |
| import org.apache.druid.query.aggregation.variance.VarianceAggregatorCollector; |
| import org.apache.druid.query.aggregation.variance.VarianceAggregatorFactory; |
| import org.apache.druid.query.aggregation.variance.VarianceSerde; |
| import org.apache.druid.query.aggregation.variance.sql.VarianceSqlAggregatorTest.VarianceComponentSupplier; |
| import org.apache.druid.query.dimension.DefaultDimensionSpec; |
| import org.apache.druid.query.groupby.GroupByQuery; |
| import org.apache.druid.query.groupby.orderby.DefaultLimitSpec; |
| import org.apache.druid.query.groupby.orderby.OrderByColumnSpec; |
| import org.apache.druid.query.ordering.StringComparators; |
| import org.apache.druid.query.spec.MultipleIntervalSegmentSpec; |
| import org.apache.druid.segment.IndexBuilder; |
| import org.apache.druid.segment.QueryableIndex; |
| import org.apache.druid.segment.column.ColumnType; |
| import org.apache.druid.segment.incremental.IncrementalIndexSchema; |
| import org.apache.druid.segment.join.JoinableFactoryWrapper; |
| import org.apache.druid.segment.serde.ComplexMetrics; |
| import org.apache.druid.segment.virtual.ExpressionVirtualColumn; |
| import org.apache.druid.segment.writeout.OffHeapMemorySegmentWriteOutMediumFactory; |
| import org.apache.druid.server.SpecificSegmentsQuerySegmentWalker; |
| import org.apache.druid.sql.calcite.BaseCalciteQueryTest; |
| import org.apache.druid.sql.calcite.TempDirProducer; |
| import org.apache.druid.sql.calcite.filtration.Filtration; |
| import org.apache.druid.sql.calcite.util.CalciteTests; |
| import org.apache.druid.sql.calcite.util.SqlTestFramework; |
| import org.apache.druid.sql.calcite.util.SqlTestFramework.StandardComponentSupplier; |
| import org.apache.druid.sql.calcite.util.TestDataBuilder; |
| import org.apache.druid.timeline.DataSegment; |
| import org.apache.druid.timeline.partition.LinearShardSpec; |
| import org.junit.jupiter.api.Test; |
| |
| import java.util.List; |
| |
| @SqlTestFramework.SqlTestFrameWorkModule(VarianceComponentSupplier.class) |
| public class VarianceSqlAggregatorTest extends BaseCalciteQueryTest |
| { |
| public static class VarianceComponentSupplier extends StandardComponentSupplier |
| { |
| public VarianceComponentSupplier(TempDirProducer tempFolderProducer) |
| { |
| super(tempFolderProducer); |
| } |
| |
| @Override |
| public void configureGuice(DruidInjectorBuilder builder) |
| { |
| super.configureGuice(builder); |
| builder.addModule(new DruidStatsModule()); |
| } |
| |
| @Override |
| public SpecificSegmentsQuerySegmentWalker createQuerySegmentWalker( |
| final QueryRunnerFactoryConglomerate conglomerate, |
| final JoinableFactoryWrapper joinableFactory, |
| final Injector injector |
| ) |
| { |
| ComplexMetrics.registerSerde(VarianceSerde.TYPE_NAME, new VarianceSerde()); |
| |
| final QueryableIndex index = |
| IndexBuilder.create(CalciteTests.getJsonMapper().registerModules(new DruidStatsModule().getJacksonModules())) |
| .tmpDir(tempDirProducer.newTempFolder()) |
| .segmentWriteOutMediumFactory(OffHeapMemorySegmentWriteOutMediumFactory.instance()) |
| .schema( |
| new IncrementalIndexSchema.Builder() |
| .withDimensionsSpec( |
| new DimensionsSpec( |
| ImmutableList.<DimensionSchema>builder() |
| .addAll(DimensionsSpec.getDefaultSchemas(ImmutableList.of("dim1", "dim2", "dim3"))) |
| .add(new DoubleDimensionSchema("d1")) |
| .add(new FloatDimensionSchema("f1")) |
| .add(new LongDimensionSchema("l1")) |
| .build() |
| ) |
| ) |
| .withMetrics( |
| new CountAggregatorFactory("cnt"), |
| new DoubleSumAggregatorFactory("m1", "m1"), |
| new VarianceAggregatorFactory("var1", "m1", null, null) |
| ) |
| .withRollup(false) |
| .build() |
| ) |
| .rows(TestDataBuilder.ROWS1_WITH_NUMERIC_DIMS) |
| .buildMMappedIndex(); |
| |
| return SpecificSegmentsQuerySegmentWalker.createWalker(injector, conglomerate).add( |
| DataSegment.builder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .interval(index.getDataInterval()) |
| .version("1") |
| .shardSpec(new LinearShardSpec(0)) |
| .size(0) |
| .build(), |
| index |
| ); |
| } |
| } |
| |
| public void addToHolder(VarianceAggregatorCollector holder, Object raw) |
| { |
| addToHolder(holder, raw, 1); |
| } |
| |
| public void addToHolder(VarianceAggregatorCollector holder, Object raw, int multiply) |
| { |
| if (raw != null) { |
| if (raw instanceof Double) { |
| double v = ((Double) raw).doubleValue() * multiply; |
| holder.add(v); |
| } else if (raw instanceof Float) { |
| float v = ((Float) raw).floatValue() * multiply; |
| holder.add(v); |
| } else if (raw instanceof Long) { |
| long v = ((Long) raw).longValue() * multiply; |
| holder.add(v); |
| } else if (raw instanceof Integer) { |
| int v = ((Integer) raw).intValue() * multiply; |
| holder.add(v); |
| } |
| } else { |
| if (NullHandling.replaceWithDefault()) { |
| holder.add(0.0f); |
| } |
| } |
| } |
| |
| @Test |
| public void testVarPop() |
| { |
| VarianceAggregatorCollector holder1 = new VarianceAggregatorCollector(); |
| VarianceAggregatorCollector holder2 = new VarianceAggregatorCollector(); |
| VarianceAggregatorCollector holder3 = new VarianceAggregatorCollector(); |
| for (InputRow row : TestDataBuilder.ROWS1_WITH_NUMERIC_DIMS) { |
| Object raw1 = row.getRaw("d1"); |
| Object raw2 = row.getRaw("f1"); |
| Object raw3 = row.getRaw("l1"); |
| addToHolder(holder1, raw1); |
| addToHolder(holder2, raw2); |
| addToHolder(holder3, raw3); |
| } |
| |
| final List<Object[]> expectedResults = ImmutableList.of( |
| new Object[]{ |
| holder1.getVariance(true), |
| holder2.getVariance(true), |
| holder3.getVariance(true) |
| } |
| ); |
| testQuery( |
| "SELECT\n" |
| + "VAR_POP(d1),\n" |
| + "VAR_POP(f1),\n" |
| + "VAR_POP(l1)\n" |
| + "FROM numfoo", |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(new MultipleIntervalSegmentSpec(ImmutableList.of(Filtration.eternity()))) |
| .granularity(Granularities.ALL) |
| .aggregators( |
| ImmutableList.of( |
| new VarianceAggregatorFactory("a0:agg", "d1", "population", "double"), |
| new VarianceAggregatorFactory("a1:agg", "f1", "population", "float"), |
| new VarianceAggregatorFactory("a2:agg", "l1", "population", "long") |
| ) |
| ) |
| .context(BaseCalciteQueryTest.QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ResultMatchMode.EQUALS_EPS, |
| expectedResults |
| ); |
| } |
| |
| @Test |
| public void testVarSamp() |
| { |
| VarianceAggregatorCollector holder1 = new VarianceAggregatorCollector(); |
| VarianceAggregatorCollector holder2 = new VarianceAggregatorCollector(); |
| VarianceAggregatorCollector holder3 = new VarianceAggregatorCollector(); |
| for (InputRow row : TestDataBuilder.ROWS1_WITH_NUMERIC_DIMS) { |
| Object raw1 = row.getRaw("d1"); |
| Object raw2 = row.getRaw("f1"); |
| Object raw3 = row.getRaw("l1"); |
| addToHolder(holder1, raw1); |
| addToHolder(holder2, raw2); |
| addToHolder(holder3, raw3); |
| } |
| |
| final List<Object[]> expectedResults = ImmutableList.of( |
| new Object[] { |
| holder1.getVariance(false), |
| holder2.getVariance(false).doubleValue(), |
| holder3.getVariance(false), |
| } |
| ); |
| testQuery( |
| "SELECT\n" |
| + "VAR_SAMP(d1),\n" |
| + "VAR_SAMP(f1),\n" |
| + "VAR_SAMP(l1)\n" |
| + "FROM numfoo", |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(new MultipleIntervalSegmentSpec(ImmutableList.of(Filtration.eternity()))) |
| .granularity(Granularities.ALL) |
| .aggregators( |
| ImmutableList.of( |
| new VarianceAggregatorFactory("a0:agg", "d1", "sample", "double"), |
| new VarianceAggregatorFactory("a1:agg", "f1", "sample", "float"), |
| new VarianceAggregatorFactory("a2:agg", "l1", "sample", "long") |
| ) |
| ) |
| .context(BaseCalciteQueryTest.QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ResultMatchMode.EQUALS_EPS, |
| expectedResults |
| ); |
| } |
| |
| @Test |
| public void testStdDevPop() |
| { |
| VarianceAggregatorCollector holder1 = new VarianceAggregatorCollector(); |
| VarianceAggregatorCollector holder2 = new VarianceAggregatorCollector(); |
| VarianceAggregatorCollector holder3 = new VarianceAggregatorCollector(); |
| for (InputRow row : TestDataBuilder.ROWS1_WITH_NUMERIC_DIMS) { |
| Object raw1 = row.getRaw("d1"); |
| Object raw2 = row.getRaw("f1"); |
| Object raw3 = row.getRaw("l1"); |
| addToHolder(holder1, raw1); |
| addToHolder(holder2, raw2); |
| addToHolder(holder3, raw3); |
| } |
| |
| final List<Object[]> expectedResults = ImmutableList.of( |
| new Object[] { |
| Math.sqrt(holder1.getVariance(true)), |
| Math.sqrt(holder2.getVariance(true)), |
| Math.sqrt(holder3.getVariance(true)), |
| } |
| ); |
| |
| testQuery( |
| "SELECT\n" |
| + "STDDEV_POP(d1),\n" |
| + "STDDEV_POP(f1),\n" |
| + "STDDEV_POP(l1)\n" |
| + "FROM numfoo", |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(new MultipleIntervalSegmentSpec(ImmutableList.of(Filtration.eternity()))) |
| .granularity(Granularities.ALL) |
| .aggregators( |
| ImmutableList.of( |
| new VarianceAggregatorFactory("a0:agg", "d1", "population", "double"), |
| new VarianceAggregatorFactory("a1:agg", "f1", "population", "float"), |
| new VarianceAggregatorFactory("a2:agg", "l1", "population", "long") |
| ) |
| ) |
| .postAggregators( |
| ImmutableList.of( |
| new StandardDeviationPostAggregator("a0", "a0:agg", "population"), |
| new StandardDeviationPostAggregator("a1", "a1:agg", "population"), |
| new StandardDeviationPostAggregator("a2", "a2:agg", "population") |
| ) |
| ) |
| .context(BaseCalciteQueryTest.QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ResultMatchMode.EQUALS_EPS, |
| expectedResults |
| ); |
| } |
| |
| @Test |
| public void testStdDevSamp() |
| { |
| VarianceAggregatorCollector holder1 = new VarianceAggregatorCollector(); |
| VarianceAggregatorCollector holder2 = new VarianceAggregatorCollector(); |
| VarianceAggregatorCollector holder3 = new VarianceAggregatorCollector(); |
| for (InputRow row : TestDataBuilder.ROWS1_WITH_NUMERIC_DIMS) { |
| Object raw1 = row.getRaw("d1"); |
| Object raw2 = row.getRaw("f1"); |
| Object raw3 = row.getRaw("l1"); |
| addToHolder(holder1, raw1); |
| addToHolder(holder2, raw2); |
| addToHolder(holder3, raw3); |
| } |
| |
| final List<Object[]> expectedResults = ImmutableList.of( |
| new Object[]{ |
| Math.sqrt(holder1.getVariance(false)), |
| Math.sqrt(holder2.getVariance(false)), |
| Math.sqrt(holder3.getVariance(false)), |
| } |
| ); |
| |
| testQuery( |
| "SELECT\n" |
| + "STDDEV_SAMP(d1),\n" |
| + "STDDEV_SAMP(f1),\n" |
| + "STDDEV_SAMP(l1)\n" |
| + "FROM numfoo", |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(new MultipleIntervalSegmentSpec(ImmutableList.of(Filtration.eternity()))) |
| .granularity(Granularities.ALL) |
| .aggregators( |
| ImmutableList.of( |
| new VarianceAggregatorFactory("a0:agg", "d1", "sample", "double"), |
| new VarianceAggregatorFactory("a1:agg", "f1", "sample", "float"), |
| new VarianceAggregatorFactory("a2:agg", "l1", "sample", "long") |
| ) |
| ) |
| .postAggregators( |
| new StandardDeviationPostAggregator("a0", "a0:agg", "sample"), |
| new StandardDeviationPostAggregator("a1", "a1:agg", "sample"), |
| new StandardDeviationPostAggregator("a2", "a2:agg", "sample") |
| ) |
| .context(BaseCalciteQueryTest.QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ResultMatchMode.EQUALS_EPS, |
| expectedResults |
| ); |
| } |
| |
| @Test |
| public void testStdDevWithVirtualColumns() |
| { |
| VarianceAggregatorCollector holder1 = new VarianceAggregatorCollector(); |
| VarianceAggregatorCollector holder2 = new VarianceAggregatorCollector(); |
| VarianceAggregatorCollector holder3 = new VarianceAggregatorCollector(); |
| for (InputRow row : TestDataBuilder.ROWS1_WITH_NUMERIC_DIMS) { |
| Object raw1 = row.getRaw("d1"); |
| Object raw2 = row.getRaw("f1"); |
| Object raw3 = row.getRaw("l1"); |
| addToHolder(holder1, raw1, 7); |
| addToHolder(holder2, raw2, 7); |
| addToHolder(holder3, raw3, 7); |
| } |
| |
| final List<Object[]> expectedResults = ImmutableList.of( |
| new Object[]{ |
| Math.sqrt(holder1.getVariance(false)), |
| Math.sqrt(holder2.getVariance(false)), |
| Math.sqrt(holder3.getVariance(false)), |
| } |
| ); |
| |
| testQuery( |
| "SELECT\n" |
| + "STDDEV(d1*7),\n" |
| + "STDDEV(f1*7),\n" |
| + "STDDEV(l1*7)\n" |
| + "FROM numfoo", |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(new MultipleIntervalSegmentSpec(ImmutableList.of(Filtration.eternity()))) |
| .granularity(Granularities.ALL) |
| .virtualColumns( |
| BaseCalciteQueryTest.expressionVirtualColumn("v0", "(\"d1\" * 7)", ColumnType.DOUBLE), |
| BaseCalciteQueryTest.expressionVirtualColumn("v1", "(\"f1\" * 7)", ColumnType.FLOAT), |
| BaseCalciteQueryTest.expressionVirtualColumn("v2", "(\"l1\" * 7)", ColumnType.LONG) |
| ) |
| .aggregators( |
| ImmutableList.of( |
| new VarianceAggregatorFactory("a0:agg", "v0", "sample", "double"), |
| new VarianceAggregatorFactory("a1:agg", "v1", "sample", "float"), |
| new VarianceAggregatorFactory("a2:agg", "v2", "sample", "long") |
| ) |
| ) |
| .postAggregators( |
| new StandardDeviationPostAggregator("a0", "a0:agg", "sample"), |
| new StandardDeviationPostAggregator("a1", "a1:agg", "sample"), |
| new StandardDeviationPostAggregator("a2", "a2:agg", "sample") |
| ) |
| .context(BaseCalciteQueryTest.QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ResultMatchMode.EQUALS_EPS, |
| expectedResults |
| ); |
| } |
| |
| |
| @Test |
| public void testVarianceOrderBy() |
| { |
| List<Object[]> expectedResults = NullHandling.sqlCompatible() |
| ? ImmutableList.of( |
| new Object[]{"a", 0.0}, |
| new Object[]{null, 0.0}, |
| new Object[]{"", 0.0}, |
| new Object[]{"abc", null} |
| ) : ImmutableList.of( |
| new Object[]{"a", 0.5}, |
| new Object[]{"", 0.003333333432674409}, |
| new Object[]{"abc", 0.0} |
| ); |
| |
| testQuery( |
| "select dim2, VARIANCE(f1) from druid.numfoo group by 1 order by 2 desc", |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.DATASOURCE3) |
| .setInterval(new MultipleIntervalSegmentSpec(ImmutableList.of(Filtration.eternity()))) |
| .setGranularity(Granularities.ALL) |
| .setDimensions(new DefaultDimensionSpec("dim2", "_d0")) |
| .setAggregatorSpecs( |
| new VarianceAggregatorFactory("a0:agg", "f1", "sample", "float") |
| ) |
| .setLimitSpec( |
| DefaultLimitSpec |
| .builder() |
| .orderBy( |
| new OrderByColumnSpec( |
| "a0:agg", |
| OrderByColumnSpec.Direction.DESCENDING, |
| StringComparators.NUMERIC |
| ) |
| ) |
| .build() |
| ) |
| .setContext(BaseCalciteQueryTest.QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ResultMatchMode.EQUALS_EPS, |
| expectedResults |
| ); |
| } |
| |
| @Test |
| public void testVariancesOnCastedString() |
| { |
| testQuery( |
| "SELECT\n" |
| + "STDDEV_POP(CAST(dim1 AS DOUBLE)),\n" |
| + "STDDEV_SAMP(CAST(dim1 AS DOUBLE)),\n" |
| + "STDDEV(CAST(dim1 AS DOUBLE)),\n" |
| + "VARIANCE(CAST(dim1 AS DOUBLE))\n" |
| + "FROM numfoo", |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .virtualColumns( |
| new ExpressionVirtualColumn("v0", "CAST(\"dim1\", 'DOUBLE')", ColumnType.DOUBLE, ExprMacroTable.nil()) |
| ) |
| .granularity(Granularities.ALL) |
| .aggregators( |
| new VarianceAggregatorFactory("a0:agg", "v0", "population", "double"), |
| new VarianceAggregatorFactory("a1:agg", "v0", "sample", "double"), |
| new VarianceAggregatorFactory("a2:agg", "v0", "sample", "double"), |
| new VarianceAggregatorFactory("a3:agg", "v0", "sample", "double") |
| ) |
| .postAggregators( |
| new StandardDeviationPostAggregator("a0", "a0:agg", "population"), |
| new StandardDeviationPostAggregator("a1", "a1:agg", "sample"), |
| new StandardDeviationPostAggregator("a2", "a2:agg", "sample") |
| ) |
| .context(BaseCalciteQueryTest.QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ResultMatchMode.EQUALS_EPS, |
| ImmutableList.of( |
| NullHandling.replaceWithDefault() |
| ? new Object[]{3.61497656362466, 3.960008417499471, 3.960008417499471, 15.681666666666667} |
| : new Object[]{4.074582459862878, 4.990323970779185, 4.990323970779185, 24.903333333333332} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testEmptyTimeseriesResults() |
| { |
| testQuery( |
| "SELECT\n" |
| + "STDDEV_POP(d1),\n" |
| + "STDDEV_SAMP(d1),\n" |
| + "STDDEV(d1),\n" |
| + "VARIANCE(d1),\n" |
| + "STDDEV_POP(l1),\n" |
| + "STDDEV_SAMP(l1),\n" |
| + "STDDEV(l1),\n" |
| + "VARIANCE(l1)\n" |
| + "FROM numfoo WHERE dim2 = 0", |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .granularity(Granularities.ALL) |
| .filters(numericEquality("dim2", 0L, ColumnType.LONG)) |
| .aggregators( |
| new VarianceAggregatorFactory("a0:agg", "d1", "population", "double"), |
| new VarianceAggregatorFactory("a1:agg", "d1", "sample", "double"), |
| new VarianceAggregatorFactory("a2:agg", "d1", "sample", "double"), |
| new VarianceAggregatorFactory("a3:agg", "d1", "sample", "double"), |
| new VarianceAggregatorFactory("a4:agg", "l1", "population", "long"), |
| new VarianceAggregatorFactory("a5:agg", "l1", "sample", "long"), |
| new VarianceAggregatorFactory("a6:agg", "l1", "sample", "long"), |
| new VarianceAggregatorFactory("a7:agg", "l1", "sample", "long") |
| |
| ) |
| .postAggregators( |
| new StandardDeviationPostAggregator("a0", "a0:agg", "population"), |
| new StandardDeviationPostAggregator("a1", "a1:agg", "sample"), |
| new StandardDeviationPostAggregator("a2", "a2:agg", "sample"), |
| new StandardDeviationPostAggregator("a4", "a4:agg", "population"), |
| new StandardDeviationPostAggregator("a5", "a5:agg", "sample"), |
| new StandardDeviationPostAggregator("a6", "a6:agg", "sample") |
| ) |
| .context(BaseCalciteQueryTest.QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ResultMatchMode.EQUALS_EPS, |
| ImmutableList.of( |
| NullHandling.replaceWithDefault() |
| ? new Object[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0} |
| : new Object[]{null, null, null, null, null, null, null, null} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testGroupByAggregatorDefaultValues() |
| { |
| testQuery( |
| "SELECT\n" |
| + "dim2,\n" |
| + "STDDEV_POP(d1) FILTER(WHERE dim1 = 'nonexistent'),\n" |
| + "STDDEV_SAMP(d1) FILTER(WHERE dim1 = 'nonexistent'),\n" |
| + "STDDEV(d1) FILTER(WHERE dim1 = 'nonexistent'),\n" |
| + "VARIANCE(d1) FILTER(WHERE dim1 = 'nonexistent'),\n" |
| + "STDDEV_POP(l1) FILTER(WHERE dim1 = 'nonexistent'),\n" |
| + "STDDEV_SAMP(l1) FILTER(WHERE dim1 = 'nonexistent'),\n" |
| + "STDDEV(l1) FILTER(WHERE dim1 = 'nonexistent'),\n" |
| + "VARIANCE(l1) FILTER(WHERE dim1 = 'nonexistent')\n" |
| + "FROM numfoo WHERE dim2 = 'a' GROUP BY dim2", |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.DATASOURCE3) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setDimFilter(equality("dim2", "a", ColumnType.STRING)) |
| .setGranularity(Granularities.ALL) |
| .setVirtualColumns(expressionVirtualColumn("v0", "'a'", ColumnType.STRING)) |
| .setDimensions(new DefaultDimensionSpec("v0", "_d0", ColumnType.STRING)) |
| .setAggregatorSpecs( |
| aggregators( |
| new FilteredAggregatorFactory( |
| new VarianceAggregatorFactory("a0:agg", "d1", "population", "double"), |
| equality("dim1", "nonexistent", ColumnType.STRING) |
| ), |
| new FilteredAggregatorFactory( |
| new VarianceAggregatorFactory("a1:agg", "d1", "sample", "double"), |
| equality("dim1", "nonexistent", ColumnType.STRING) |
| ), |
| new FilteredAggregatorFactory( |
| new VarianceAggregatorFactory("a2:agg", "d1", "sample", "double"), |
| equality("dim1", "nonexistent", ColumnType.STRING) |
| ), |
| new FilteredAggregatorFactory( |
| new VarianceAggregatorFactory("a3:agg", "d1", "sample", "double"), |
| equality("dim1", "nonexistent", ColumnType.STRING) |
| ), |
| new FilteredAggregatorFactory( |
| new VarianceAggregatorFactory("a4:agg", "l1", "population", "long"), |
| equality("dim1", "nonexistent", ColumnType.STRING) |
| ), |
| new FilteredAggregatorFactory( |
| new VarianceAggregatorFactory("a5:agg", "l1", "sample", "long"), |
| equality("dim1", "nonexistent", ColumnType.STRING) |
| ), |
| new FilteredAggregatorFactory( |
| new VarianceAggregatorFactory("a6:agg", "l1", "sample", "long"), |
| equality("dim1", "nonexistent", ColumnType.STRING) |
| ), |
| new FilteredAggregatorFactory( |
| new VarianceAggregatorFactory("a7:agg", "l1", "sample", "long"), |
| equality("dim1", "nonexistent", ColumnType.STRING) |
| ) |
| ) |
| ) |
| .setPostAggregatorSpecs( |
| ImmutableList.of( |
| new StandardDeviationPostAggregator("a0", "a0:agg", "population"), |
| new StandardDeviationPostAggregator("a1", "a1:agg", "sample"), |
| new StandardDeviationPostAggregator("a2", "a2:agg", "sample"), |
| new StandardDeviationPostAggregator("a4", "a4:agg", "population"), |
| new StandardDeviationPostAggregator("a5", "a5:agg", "sample"), |
| new StandardDeviationPostAggregator("a6", "a6:agg", "sample") |
| ) |
| ) |
| .setContext(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ResultMatchMode.EQUALS_EPS, |
| ImmutableList.of( |
| NullHandling.replaceWithDefault() |
| ? new Object[]{"a", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0} |
| : new Object[]{"a", null, null, null, null, null, null, null, null} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testVarianceAggAsInput() |
| { |
| final List<Object[]> expectedResults = ImmutableList.of( |
| new Object[]{ |
| 3.5D, |
| 2.9166666666666665D, |
| 3.5D, |
| 1.8708286933869707D, |
| 1.707825127659933D, |
| 1.8708286933869707D |
| } |
| ); |
| testQuery( |
| "SELECT\n" |
| + "VARIANCE(var1),\n" |
| + "VAR_POP(var1),\n" |
| + "VAR_SAMP(var1),\n" |
| + "STDDEV(var1),\n" |
| + "STDDEV_POP(var1),\n" |
| + "STDDEV_SAMP(var1)\n" |
| + "FROM numfoo", |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(new MultipleIntervalSegmentSpec(ImmutableList.of(Filtration.eternity()))) |
| .granularity(Granularities.ALL) |
| .aggregators( |
| ImmutableList.of( |
| new VarianceAggregatorFactory("a0:agg", "var1", "sample", "variance"), |
| new VarianceAggregatorFactory("a1:agg", "var1", "population", "variance"), |
| new VarianceAggregatorFactory("a2:agg", "var1", "sample", "variance"), |
| new VarianceAggregatorFactory("a3:agg", "var1", "sample", "variance"), |
| new VarianceAggregatorFactory("a4:agg", "var1", "population", "variance"), |
| new VarianceAggregatorFactory("a5:agg", "var1", "sample", "variance") |
| ) |
| ) |
| .postAggregators( |
| new StandardDeviationPostAggregator("a3", "a3:agg", "sample"), |
| new StandardDeviationPostAggregator("a4", "a4:agg", "population"), |
| new StandardDeviationPostAggregator("a5", "a5:agg", "sample") |
| ) |
| .context(BaseCalciteQueryTest.QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ResultMatchMode.EQUALS_EPS, |
| expectedResults |
| ); |
| } |
| } |